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/builtin/parse.rs

156 lines
4.3 KiB

use sexp::{Atom, Sexp};
use crate::asm::data::literal::{Label, RoutineName};
use crate::asm::error::Error;
use crate::asm::instr::cond::parse_cond;
use crate::asm::instr::Op;
use crate::asm::parse::arg_parser::ArgParser;
use crate::asm::parse::parse_data::{parse_label, parse_rd};
use crate::asm::parse::sexp_expect::expect_string_atom;
use crate::builtin::defs::BuiltinOp;
use crate::module::{CrsnExtension, ParseOpRes};
#[derive(Debug, Clone)]
pub struct BuiltinOps {
_internal: ()
}
impl BuiltinOps {
pub fn new() -> Box<dyn CrsnExtension> {
Box::new(Self {
_internal: ()
})
}
}
impl CrsnExtension for BuiltinOps {
fn name(&self) -> &'static str {
"builtin"
}
fn parse_op(&self, keyword: &str, mut args: ArgParser) -> Result<ParseOpRes, Error> {
Ok(ParseOpRes::Parsed(Op::BuiltIn(match keyword {
"nop" => {
BuiltinOp::Nop
}
"halt" => {
BuiltinOp::Halt
}
"j" => {
let dest = parse_label(args.next())?;
BuiltinOp::Jump(dest)
}
"fj" => {
let dest = parse_label(args.next())?;
BuiltinOp::FarJump(dest)
}
"call" => {
let dest = RoutineName(args.next_string()?);
let mut call_args = vec![];
for t in args {
call_args.push(parse_rd(Some(t))?);
}
BuiltinOp::Call(dest, call_args)
}
"ret" => {
let mut ret_vals = vec![];
for t in args {
ret_vals.push(parse_rd(Some(t))?);
}
BuiltinOp::Ret(ret_vals)
}
"routine" => {
let dest = RoutineName(args.next_string()?);
BuiltinOp::Routine(dest)
}
"s" => {
BuiltinOp::Skip(args.next_rd()?)
}
"sif" => {
let cond = parse_cond(&args.next_string()?)?;
let offs = args.next_rd()?;
BuiltinOp::SkipIf(cond, offs)
}
"jif" => {
let cond = parse_cond(&args.next_string()?)?;
let dest = parse_label(args.next())?;
BuiltinOp::JumpIf(cond, dest)
}
"fjif" => {
let cond = parse_cond(&args.next_string()?)?;
let dest = parse_label(args.next())?;
BuiltinOp::FarJumpIf(cond, dest)
}
"barrier" => {
BuiltinOp::Barrier(match args.next() {
None => None,
Some(s) => Some(expect_string_atom(Some(s))?.into()),
})
}
"fault" => {
BuiltinOp::Fault(match args.next() {
None => None,
Some(s) => Some(expect_string_atom(Some(s))?.into()),
})
}
"ld" => {
BuiltinOp::Move {
dst: args.next_wr()?,
src: args.next_rd()?,
}
}
"sst" => {
BuiltinOp::StoreStatus {
dst: args.next_wr()?,
}
}
"sld" => {
BuiltinOp::LoadStatus {
src: args.next_rd()?,
}
}
"drop" => {
BuiltinOp::Drop(args.next_rdobj()?)
}
"far" => {
if let Some(Sexp::Atom(Atom::S(ref label))) = args.peek() {
if let Some(label) = label.strip_prefix(':') {
let label = Label::Named(label.to_string());
BuiltinOp::FarLabel(label)
} else {
return Ok(ParseOpRes::Unknown(args));
}
} else {
return Ok(ParseOpRes::Unknown(args));
}
}
other => {
if let Some(label) = other.strip_prefix(':') {
let label = Label::Named(label.to_string());
BuiltinOp::Label(label)
} else {
return Ok(ParseOpRes::Unknown(args));
}
}
})))
}
}