-
Aaron Councilman authoredAaron Councilman authored
lib.rs 5.75 KiB
#![feature(exact_size_is_empty)]
#![feature(let_chains)]
use std::fs::File;
use std::io::Read;
use lrlex::DefaultLexerTypes;
use lrpar::NonStreamingLexer;
use hercules_ir::ir::*;
use juno_utils::env::Env;
use juno_utils::stringtab::StringTable;
mod parser;
use crate::parser::lexer;
mod compile;
mod default;
pub mod ir;
pub mod labels;
mod pm;
use crate::compile::*;
use crate::default::*;
use crate::ir::*;
use crate::labels::*;
pub use crate::pm::*;
// Given a schedule's filename parse and process the schedule
fn build_schedule(sched_filename: String) -> Result<ScheduleStmt, String> {
if let Ok(mut file) = File::open(sched_filename) {
let mut contents = String::new();
if let Ok(_) = file.read_to_string(&mut contents) {
let lexerdef = lexer::lexerdef();
let lexer = lexerdef.lexer(&contents);
let (res, errs) = parser::parse(&lexer);
if errs.is_empty() {
match res {
None => Err(format!("No parse errors, but parsing the schedule failed")),
Some(schd) => {
compile_schedule(schd, &lexer).map_err(|e| format!("Schedule Error: {}", e))
}
}
} else {
Err(errs
.iter()
.map(|e| {
format!(
"Schedule Syntax Error: {}",
e.pp(&lexer, &parser::token_epp)
)
})
.collect::<Vec<_>>()
.join("\n"))
}
} else {
Err(format!("Unable to read schedule"))
}
} else {
Err(format!("Unable to open schedule"))
}
}
pub fn process_schedule(sched_filename: Option<String>) -> Result<ScheduleStmt, String> {
if let Some(name) = sched_filename {
build_schedule(name)
} else {
Ok(default_schedule())
}
}
pub fn schedule_juno(
module: Module,
juno_info: JunoInfo,
sched_filename: Option<String>,
output_dir: String,
module_name: String,
) -> Result<(), String> {
let sched = process_schedule(sched_filename)?;
// Prepare the scheduler's string table and environment
// For this, we need to put all of the Juno functions into the environment
// and string table
let mut strings = StringTable::new();
let mut env = Env::new();
env.open_scope();
let JunoInfo {
func_names,
func_info,
} = juno_info;
for (func_name, func_id) in func_names {
let func_name = strings.lookup_string(func_name);
env.insert(func_name, Value::JunoFunction { func: func_id });
}
env.open_scope();
schedule_codegen(
module,
sched,
strings,
env,
func_info,
output_dir,
module_name,
)
.map_err(|e| format!("Scheduling Error: {}", e))
}
pub fn run_schedule_on_hercules(
module: Module,
sched: Option<ScheduleStmt>,
) -> Result<Module, String> {
let sched = if let Some(sched) = sched {
sched
} else {
default_schedule()
};
// Prepare the scheduler's string table and environment
// For this, we put all of the Hercules function names into the environment
// and string table
let mut strings = StringTable::new();
let mut env = Env::new();
env.open_scope();
for (idx, func) in module.functions.iter().enumerate() {
let func_name = strings.lookup_string(func.name.clone());
env.insert(
func_name,
Value::HerculesFunction {
func: FunctionID::new(idx),
},
);
}
env.open_scope();
schedule_module(
module,
sched,
strings,
env,
JunoFunctions { func_ids: vec![] },
)
.map_err(|e| format!("Scheduling Error: {}", e))
}
pub fn run_schedule_from_file_on_hercules(
module: Module,
sched_filename: Option<String>,
) -> Result<Module, String> {
let sched = process_schedule(sched_filename)?;
// Prepare the scheduler's string table and environment
// For this, we put all of the Hercules function names into the environment
// and string table
let mut strings = StringTable::new();
let mut env = Env::new();
env.open_scope();
for (idx, func) in module.functions.iter().enumerate() {
let func_name = strings.lookup_string(func.name.clone());
env.insert(
func_name,
Value::HerculesFunction {
func: FunctionID::new(idx),
},
);
}
env.open_scope();
schedule_module(
module,
sched,
strings,
env,
JunoFunctions { func_ids: vec![] },
)
.map_err(|e| format!("Scheduling Error: {}", e))
}
pub fn schedule_hercules(
module: Module,
sched_filename: Option<String>,
output_dir: String,
module_name: String,
) -> Result<(), String> {
let sched = process_schedule(sched_filename)?;
// Prepare the scheduler's string table and environment
// For this, we put all of the Hercules function names into the environment
// and string table
let mut strings = StringTable::new();
let mut env = Env::new();
env.open_scope();
for (idx, func) in module.functions.iter().enumerate() {
let func_name = strings.lookup_string(func.name.clone());
env.insert(
func_name,
Value::HerculesFunction {
func: FunctionID::new(idx),
},
);
}
env.open_scope();
schedule_codegen(
module,
sched,
strings,
env,
JunoFunctions { func_ids: vec![] },
output_dir,
module_name,
)
.map_err(|e| format!("Scheduling Error: {}", e))
}