Croissant Runtime
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
crsn/crsn/src/asm/mod.rs

83 lines
2.6 KiB

use std::cell::RefCell;
use std::sync::Arc;
use sexp::SourcePosition;
use crate::asm::instr::flatten::jumps_to_skips;
use crate::asm::parse::{ParserContext, ParserState};
use crate::module::{CrsnExtension, CrsnUniq};
use crate::runtime::program::Program;
use crate::builtin::BuiltinOps;
use crate::runtime::run_thread::{RunState, ThreadInfo, ThreadToken};
use crate::runtime::frame::REG_COUNT;
use std::sync::atomic::AtomicU32;
pub mod data;
pub mod error;
pub mod instr;
pub mod parse;
pub mod patches;
/// Parse a program from string and assemble a low level instruction sequence from it.
pub fn assemble(source: &str, uniq : &CrsnUniq, mut parsers: Vec<Box<dyn CrsnExtension>>) -> Result<Arc<Program>, error::CrsnError> {
parsers.insert(0, BuiltinOps::new());
for p in &mut parsers {
p.init(uniq);
}
let parsers_arc = Arc::new(parsers);
// remove first line if it looks like a shebang
let source = if source.starts_with("#!") {
if let Some(nl) = source.find('\n') {
&source[nl + 1..]
} else {
source
}
} else {
source
};
let ti = Arc::new(ThreadInfo {
id: ThreadToken(0),
uniq: Default::default(),
program: Program::new(vec![], parsers_arc.clone()).unwrap(),
cycle_time: Default::default(),
scheduler_interval: Default::default(),
extensions: parsers_arc.clone(),
});
/* numbered labels start with a weird high number
to avoid conflicts with user-defined numbered labels */
let label_num = Arc::new(AtomicU32::new(0x7890_0000));
let pcx = ParserContext {
parsers: &parsers_arc,
state: RefCell::new(ParserState {
reg_aliases: Default::default(),
reg_alias_stack: vec![],
global_reg_aliases: Default::default(),
constants: Default::default(),
// This is a fake thread to pass to constant expressions when evaluating them.
// This allows to evaluate nearly all instructions at compile time.
const_eval: RunState {
thread_info: ti.clone(),
cr: Default::default(),
parked: Default::default(),
global_regs: [0; REG_COUNT],
ext_data: Default::default(),
cr_deadline: None,
critical_section: 0,
},
const_eval_ti: ti,
parsing_expr: false,
label_num: label_num.clone()
}),
};
let ops = parse::parse(source, &SourcePosition::default(), &pcx)?;
let ops = jumps_to_skips(ops)?;
Ok(Program::new(ops, parsers_arc)?)
}