forked from MightyPork/crsn
generalize parsing to allow extensions to add arbitrary syntax; add 'proc' keyword to introduce a routine.
This commit is contained in:
@@ -9,11 +9,11 @@ use crate::builtin::defs::BuiltinOp;
|
|||||||
|
|
||||||
/// A trait for something that can turn into multiple instructions
|
/// A trait for something that can turn into multiple instructions
|
||||||
pub trait Flatten {
|
pub trait Flatten {
|
||||||
fn flatten(self, label_num: &AtomicU32) -> Result<Vec<Op>, CrsnError>;
|
fn flatten(self: Box<Self>, label_num: &AtomicU32) -> Result<Vec<Op>, CrsnError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Flatten for Instr {
|
impl Flatten for Instr {
|
||||||
fn flatten(self, label_num: &AtomicU32) -> Result<Vec<Op>, CrsnError> {
|
fn flatten(self: Box<Self>, label_num: &AtomicU32) -> Result<Vec<Op>, CrsnError> {
|
||||||
let mut ops = vec![self.op];
|
let mut ops = vec![self.op];
|
||||||
|
|
||||||
if let Some(branches) = self.branches {
|
if let Some(branches) = self.branches {
|
||||||
@@ -31,10 +31,7 @@ impl Flatten for Instr {
|
|||||||
Label::unique(label_num)
|
Label::unique(label_num)
|
||||||
};
|
};
|
||||||
ops.push(BuiltinOp::JumpIf(!cond, next_lbl.clone()).into());
|
ops.push(BuiltinOp::JumpIf(!cond, next_lbl.clone()).into());
|
||||||
|
ops.extend(branch.flatten(label_num)?);
|
||||||
for branch_instr in branch {
|
|
||||||
ops.extend(branch_instr.flatten(label_num)?);
|
|
||||||
}
|
|
||||||
|
|
||||||
if cnt != branch_count - 1 {
|
if cnt != branch_count - 1 {
|
||||||
ops.push(BuiltinOp::Jump(end_lbl.clone()).into());
|
ops.push(BuiltinOp::Jump(end_lbl.clone()).into());
|
||||||
@@ -48,15 +45,23 @@ impl Flatten for Instr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Flatten for Vec<Box<dyn Flatten>> {
|
||||||
|
fn flatten(self: Box<Self>, label_num: &AtomicU32) -> Result<Vec<Op>, CrsnError> {
|
||||||
|
let mut ops = vec![];
|
||||||
|
for item in self.into_iter() {
|
||||||
|
ops.extend(item.flatten(label_num)?);
|
||||||
|
}
|
||||||
|
Ok(ops)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Flatten for Routine {
|
impl Flatten for Routine {
|
||||||
fn flatten(self, label_num: &AtomicU32) -> Result<Vec<Op>, CrsnError> {
|
fn flatten(self: Box<Self>, label_num: &AtomicU32) -> Result<Vec<Op>, CrsnError> {
|
||||||
let mut ops = vec![
|
let mut ops = vec![
|
||||||
BuiltinOp::Routine(self.name.clone()).into(),
|
BuiltinOp::Routine(self.name.clone()).into(),
|
||||||
];
|
];
|
||||||
|
|
||||||
for instr in self.body {
|
ops.extend(self.body.flatten(label_num)?);
|
||||||
ops.extend(instr.flatten(label_num)?);
|
|
||||||
}
|
|
||||||
|
|
||||||
ops.push(BuiltinOp::Barrier(Some(format!("Routine \"{}\" overrun", self.name).into())).into());
|
ops.push(BuiltinOp::Barrier(Some(format!("Routine \"{}\" overrun", self.name).into())).into());
|
||||||
|
|
||||||
|
|||||||
@@ -9,15 +9,13 @@ pub mod cond;
|
|||||||
mod flatten;
|
mod flatten;
|
||||||
|
|
||||||
/// A higher-level instruction
|
/// A higher-level instruction
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Instr {
|
pub struct Instr {
|
||||||
pub op: Op,
|
pub op: Op,
|
||||||
pub branches: Option<Vec<(Cond, Vec<Instr>)>>,
|
pub branches: Option<Vec<(Cond, Box<dyn Flatten>)>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A routine
|
/// A routine
|
||||||
pub struct Routine {
|
pub struct Routine {
|
||||||
pub name: RoutineName,
|
pub name: RoutineName,
|
||||||
pub body: Vec<Instr>,
|
pub body: Box<dyn Flatten>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,21 +5,22 @@ use crate::asm::parse::parse_data::{parse_rd, parse_wr};
|
|||||||
use crate::asm::parse::sexp_expect::expect_string_atom;
|
use crate::asm::parse::sexp_expect::expect_string_atom;
|
||||||
|
|
||||||
/// Utility for argument parsing
|
/// Utility for argument parsing
|
||||||
pub struct ArgParser {
|
pub struct TokenParser {
|
||||||
orig_len: usize,
|
orig_len: usize,
|
||||||
args: Vec<Sexp>,
|
args: Vec<Sexp>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoIterator for ArgParser {
|
impl IntoIterator for TokenParser {
|
||||||
type Item = Sexp;
|
type Item = Sexp;
|
||||||
type IntoIter = std::vec::IntoIter<Sexp>;
|
type IntoIter = std::vec::IntoIter<Sexp>;
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
fn into_iter(mut self) -> Self::IntoIter {
|
||||||
|
self.args.reverse();
|
||||||
self.args.into_iter()
|
self.args.into_iter()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ArgParser {
|
impl TokenParser {
|
||||||
/// Create a new argument parser
|
/// Create a new argument parser
|
||||||
pub fn new(mut args: Vec<Sexp>) -> Self {
|
pub fn new(mut args: Vec<Sexp>) -> Self {
|
||||||
args.reverse();
|
args.reverse();
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use std::sync::atomic::AtomicU32;
|
use std::sync::atomic::{AtomicU32, AtomicU64};
|
||||||
|
|
||||||
pub use parse_instr::parse_instructions;
|
pub use parse_instr::parse_instructions;
|
||||||
use parse_routines::parse_routines;
|
|
||||||
|
|
||||||
use crate::asm::error::CrsnError;
|
use crate::asm::error::CrsnError;
|
||||||
use crate::asm::instr::{Flatten, Op, Routine};
|
use crate::asm::instr::{Flatten, Op, Routine};
|
||||||
@@ -11,22 +10,15 @@ use crate::module::CrsnExtension;
|
|||||||
mod parse_cond;
|
mod parse_cond;
|
||||||
mod parse_instr;
|
mod parse_instr;
|
||||||
pub mod parse_data;
|
pub mod parse_data;
|
||||||
mod parse_routines;
|
|
||||||
pub mod sexp_expect;
|
pub mod sexp_expect;
|
||||||
mod parse_op;
|
mod parse_op;
|
||||||
|
|
||||||
pub mod arg_parser;
|
pub mod arg_parser;
|
||||||
|
|
||||||
pub fn parse(source: &str, parsers: &[Box<dyn CrsnExtension>]) -> Result<Vec<Op>, CrsnError> {
|
pub fn parse(source: &str, parsers: &[Box<dyn CrsnExtension>]) -> Result<Vec<Op>, CrsnError> {
|
||||||
let root = sexp::parse(source)?;
|
let items = expect_list(Some(sexp::parse(source)?), true)?;
|
||||||
|
|
||||||
let subs: Vec<Routine> = parse_routines(expect_list(Some(root), true)?, parsers)?;
|
|
||||||
|
|
||||||
let mut combined = vec![];
|
|
||||||
let label_num = AtomicU32::new(0);
|
let label_num = AtomicU32::new(0);
|
||||||
for sub in subs {
|
parse_instructions(items.into_iter(), parsers)?
|
||||||
combined.extend(sub.flatten(&label_num)?);
|
.flatten(&label_num)
|
||||||
}
|
|
||||||
|
|
||||||
Ok(combined)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
use sexp::Sexp;
|
use sexp::Sexp;
|
||||||
|
|
||||||
use crate::asm::error::CrsnError;
|
use crate::asm::error::CrsnError;
|
||||||
use crate::asm::instr::{Cond, cond, Instr};
|
use crate::asm::instr::{Cond, cond, Instr, Flatten};
|
||||||
use crate::asm::parse::parse_instr::parse_instructions;
|
use crate::asm::parse::parse_instr::parse_instructions;
|
||||||
use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom};
|
use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom};
|
||||||
use crate::asm::patches::TryRemove;
|
use crate::asm::patches::TryRemove;
|
||||||
use crate::module::CrsnExtension;
|
use crate::module::CrsnExtension;
|
||||||
|
|
||||||
pub fn parse_cond_branch(tok: Sexp, parsers: &[Box<dyn CrsnExtension>]) -> Result<(Cond, Vec<Instr>), CrsnError> {
|
pub fn parse_cond_branch(tok: Sexp, parsers: &[Box<dyn CrsnExtension>]) -> Result<(Cond, Box<dyn Flatten>), CrsnError> {
|
||||||
let mut list = expect_list(Some(tok), false)?;
|
let mut list = expect_list(Some(tok), false)?;
|
||||||
let kw = expect_string_atom(list.try_remove(0))?;
|
let kw = expect_string_atom(list.try_remove(0))?;
|
||||||
|
|
||||||
@@ -15,6 +15,6 @@ pub fn parse_cond_branch(tok: Sexp, parsers: &[Box<dyn CrsnExtension>]) -> Resul
|
|||||||
return Err(CrsnError::Parse(format!("Condition must end with '?': {}", kw).into()));
|
return Err(CrsnError::Parse(format!("Condition must end with '?': {}", kw).into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((cond::parse_cond(&kw)?, parse_instructions(list, parsers)?))
|
Ok((cond::parse_cond(&kw)?, parse_instructions(list.into_iter(), parsers)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,49 @@
|
|||||||
use sexp::Sexp;
|
use sexp::Sexp;
|
||||||
|
|
||||||
use crate::asm::error::CrsnError;
|
use crate::asm::error::CrsnError;
|
||||||
use crate::asm::instr::Instr;
|
use crate::asm::instr::{Instr, Flatten, Routine};
|
||||||
use crate::asm::parse::arg_parser::ArgParser;
|
use crate::asm::parse::arg_parser::TokenParser;
|
||||||
use crate::asm::parse::parse_cond::parse_cond_branch;
|
use crate::asm::parse::parse_cond::parse_cond_branch;
|
||||||
use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom};
|
use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom};
|
||||||
use crate::asm::patches::SexpIsA;
|
use crate::asm::patches::SexpIsA;
|
||||||
use crate::module::CrsnExtension;
|
use crate::module::{CrsnExtension, ParseRes};
|
||||||
|
|
||||||
use super::parse_op::parse_op;
|
use super::parse_op::parse_op;
|
||||||
|
use crate::asm::data::literal::RoutineName;
|
||||||
|
|
||||||
pub fn parse_instructions(instrs: Vec<Sexp>, parsers: &[Box<dyn CrsnExtension>]) -> Result<Vec<Instr>, CrsnError> {
|
pub fn parse_instructions(items: impl Iterator<Item=Sexp>, parsers: &[Box<dyn CrsnExtension>]) -> Result<Box<dyn Flatten>, CrsnError> {
|
||||||
let mut parsed = vec![];
|
let mut parsed = vec![];
|
||||||
for expr in instrs {
|
for expr in items {
|
||||||
let tokens = expect_list(Some(expr), false)?;
|
let tokens = expect_list(Some(expr), false)?;
|
||||||
|
|
||||||
let mut toki = tokens.into_iter();
|
let mut toki = tokens.into_iter();
|
||||||
let name = expect_string_atom(toki.next())?;
|
let name = expect_string_atom(toki.next())?;
|
||||||
|
|
||||||
let arg_tokens = ArgParser::new(toki.clone().take_while(|e| e.is_atom()).collect());
|
if name == "proc" {
|
||||||
|
parsed.push(parse_routine(toki, parsers)?);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut token_parser = TokenParser::new(toki.collect());
|
||||||
|
for p in parsers {
|
||||||
|
token_parser = match p.parse_syntax(&name, token_parser, parsers) {
|
||||||
|
Ok(ParseRes::Parsed(op)) => return Ok(op),
|
||||||
|
Ok(ParseRes::Unknown(to_reuse)) => {
|
||||||
|
if to_reuse.parsing_started() {
|
||||||
|
panic!("Module \"{}\" started parsing syntax, but returned Unknown!", p.name());
|
||||||
|
}
|
||||||
|
to_reuse
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get back the original iterator
|
||||||
|
let toki = token_parser.into_iter();
|
||||||
|
|
||||||
|
let arg_tokens = TokenParser::new(toki.clone().take_while(|e| e.is_atom()).collect());
|
||||||
let branch_tokens = toki
|
let branch_tokens = toki
|
||||||
.skip_while(|e| e.is_atom())
|
.skip_while(|e| e.is_atom())
|
||||||
.take_while(|e| e.is_list());
|
.take_while(|e| e.is_list());
|
||||||
@@ -35,11 +60,25 @@ pub fn parse_instructions(instrs: Vec<Sexp>, parsers: &[Box<dyn CrsnExtension>])
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
parsed.push(Instr {
|
parsed.push(Box::new(Instr {
|
||||||
op: parse_op(name.as_str(), arg_tokens, parsers)?,
|
op: parse_op(name.as_str(), arg_tokens, parsers)?,
|
||||||
branches,
|
branches,
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
Ok(parsed)
|
Ok(Box::new(parsed))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_routine(mut toki : impl Iterator<Item=Sexp> + Clone, parsers: &[Box<dyn CrsnExtension>]) -> Result<Box<dyn Flatten>, CrsnError> {
|
||||||
|
let name = expect_string_atom(toki.next())?;
|
||||||
|
|
||||||
|
let arg_tokens = TokenParser::new(toki.clone().take_while(|e| e.is_atom()).collect());
|
||||||
|
|
||||||
|
// TODO parse arg tokens
|
||||||
|
|
||||||
|
let body = parse_instructions(toki, parsers)?;
|
||||||
|
|
||||||
|
return Ok(Box::new(Routine {
|
||||||
|
name: RoutineName(name),
|
||||||
|
body
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
use crate::asm::error::CrsnError;
|
use crate::asm::error::CrsnError;
|
||||||
use crate::asm::instr::Op;
|
use crate::asm::instr::Op;
|
||||||
use crate::asm::parse::arg_parser::ArgParser;
|
use crate::asm::parse::arg_parser::TokenParser;
|
||||||
use crate::builtin::parse::BuiltinOps;
|
use crate::builtin::parse::BuiltinOps;
|
||||||
use crate::module::{CrsnExtension, ParseOpRes};
|
use crate::module::{CrsnExtension, ParseRes};
|
||||||
|
|
||||||
pub fn parse_op(keyword: &str, mut arg_tokens: ArgParser, parsers: &[Box<dyn CrsnExtension>]) -> Result<Op, CrsnError> {
|
pub fn parse_op(keyword: &str, mut arg_tokens: TokenParser, parsers: &[Box<dyn CrsnExtension>]) -> Result<Op, CrsnError> {
|
||||||
// Include built-in instructions
|
// Include built-in instructions
|
||||||
let builtins = [BuiltinOps::new()];
|
let builtins = [BuiltinOps::new()];
|
||||||
|
|
||||||
for p in builtins.iter().chain(parsers) {
|
for p in builtins.iter().chain(parsers) {
|
||||||
arg_tokens = match p.parse_op(keyword, arg_tokens) {
|
arg_tokens = match p.parse_op(keyword, arg_tokens) {
|
||||||
Ok(ParseOpRes::Parsed(op)) => return Ok(op),
|
Ok(ParseRes::Parsed(op)) => return Ok(op),
|
||||||
Ok(ParseOpRes::Unknown(to_reuse)) => {
|
Ok(ParseRes::Unknown(to_reuse)) => {
|
||||||
if to_reuse.parsing_started() {
|
if to_reuse.parsing_started() {
|
||||||
panic!("Module \"{}\" started parsing {}, but returned Unknown!", p.name(), keyword);
|
panic!("Module \"{}\" started parsing {}, but returned Unknown!", p.name(), keyword);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
use sexp::Sexp;
|
|
||||||
|
|
||||||
use crate::asm::data::literal::RoutineName;
|
|
||||||
use crate::asm::error::CrsnError;
|
|
||||||
use crate::asm::instr::Routine;
|
|
||||||
use crate::asm::parse::parse_instr::parse_instructions;
|
|
||||||
use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom};
|
|
||||||
use crate::asm::patches::TryRemove;
|
|
||||||
use crate::module::CrsnExtension;
|
|
||||||
|
|
||||||
pub fn parse_routines(routines: Vec<Sexp>, parsers: &[Box<dyn CrsnExtension>]) -> Result<Vec<Routine>, CrsnError> {
|
|
||||||
let mut parsed = vec![];
|
|
||||||
for rt in routines {
|
|
||||||
let mut def = expect_list(Some(rt), false)?;
|
|
||||||
let name = expect_string_atom(def.try_remove(0))?;
|
|
||||||
let body = parse_instructions(def, parsers)?;
|
|
||||||
parsed.push(Routine {
|
|
||||||
name: RoutineName(name),
|
|
||||||
body,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Ok(parsed)
|
|
||||||
}
|
|
||||||
@@ -4,11 +4,11 @@ use crate::asm::data::literal::{Label, RoutineName};
|
|||||||
use crate::asm::error::CrsnError;
|
use crate::asm::error::CrsnError;
|
||||||
use crate::asm::instr::cond::parse_cond;
|
use crate::asm::instr::cond::parse_cond;
|
||||||
use crate::asm::instr::Op;
|
use crate::asm::instr::Op;
|
||||||
use crate::asm::parse::arg_parser::ArgParser;
|
use crate::asm::parse::arg_parser::TokenParser;
|
||||||
use crate::asm::parse::parse_data::{parse_label, parse_rd};
|
use crate::asm::parse::parse_data::{parse_label, parse_rd};
|
||||||
use crate::asm::parse::sexp_expect::expect_string_atom;
|
use crate::asm::parse::sexp_expect::expect_string_atom;
|
||||||
use crate::builtin::defs::BuiltinOp;
|
use crate::builtin::defs::BuiltinOp;
|
||||||
use crate::module::{CrsnExtension, ParseOpRes};
|
use crate::module::{CrsnExtension, ParseRes};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct BuiltinOps {
|
pub struct BuiltinOps {
|
||||||
@@ -28,8 +28,8 @@ impl CrsnExtension for BuiltinOps {
|
|||||||
"builtin"
|
"builtin"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_op(&self, keyword: &str, mut args: ArgParser) -> Result<ParseOpRes<Op>, CrsnError> {
|
fn parse_op(&self, keyword: &str, mut args: TokenParser) -> Result<ParseRes<Op>, CrsnError> {
|
||||||
Ok(ParseOpRes::Parsed(Op::BuiltIn(match keyword {
|
Ok(ParseRes::Parsed(Op::BuiltIn(match keyword {
|
||||||
"nop" => {
|
"nop" => {
|
||||||
BuiltinOp::Nop
|
BuiltinOp::Nop
|
||||||
}
|
}
|
||||||
@@ -142,10 +142,10 @@ impl CrsnExtension for BuiltinOps {
|
|||||||
let label = Label::Named(label.to_string());
|
let label = Label::Named(label.to_string());
|
||||||
BuiltinOp::FarLabel(label)
|
BuiltinOp::FarLabel(label)
|
||||||
} else {
|
} else {
|
||||||
return Ok(ParseOpRes::Unknown(args));
|
return Ok(ParseRes::Unknown(args));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Ok(ParseOpRes::Unknown(args));
|
return Ok(ParseRes::Unknown(args));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,7 +154,7 @@ impl CrsnExtension for BuiltinOps {
|
|||||||
let label = Label::Named(label.to_string());
|
let label = Label::Named(label.to_string());
|
||||||
BuiltinOp::Label(label)
|
BuiltinOp::Label(label)
|
||||||
} else {
|
} else {
|
||||||
return Ok(ParseOpRes::Unknown(args));
|
return Ok(ParseRes::Unknown(args));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})))
|
})))
|
||||||
|
|||||||
+23
-22
@@ -1,3 +1,5 @@
|
|||||||
|
#![allow(unused_variables)]
|
||||||
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
pub use eval_res::EvalRes;
|
pub use eval_res::EvalRes;
|
||||||
@@ -5,8 +7,8 @@ pub use eval_res::EvalRes;
|
|||||||
use crate::asm::data::literal::Value;
|
use crate::asm::data::literal::Value;
|
||||||
use crate::asm::data::Mask;
|
use crate::asm::data::Mask;
|
||||||
use crate::asm::error::CrsnError;
|
use crate::asm::error::CrsnError;
|
||||||
use crate::asm::instr::Op;
|
use crate::asm::instr::{Op, Flatten};
|
||||||
use crate::asm::parse::arg_parser::ArgParser;
|
use crate::asm::parse::arg_parser::TokenParser;
|
||||||
use crate::runtime::fault::Fault;
|
use crate::runtime::fault::Fault;
|
||||||
use crate::runtime::run_thread::state::RunState;
|
use crate::runtime::run_thread::state::RunState;
|
||||||
use crate::runtime::run_thread::ThreadInfo;
|
use crate::runtime::run_thread::ThreadInfo;
|
||||||
@@ -14,14 +16,14 @@ use crate::runtime::run_thread::ThreadInfo;
|
|||||||
mod eval_res;
|
mod eval_res;
|
||||||
|
|
||||||
/// Result type returned from the op parser. This is the Ok variant of a Result.
|
/// Result type returned from the op parser. This is the Ok variant of a Result.
|
||||||
pub enum ParseOpRes<T> {
|
pub enum ParseRes<T> {
|
||||||
/// Parsing successful.
|
/// Parsing successful.
|
||||||
Parsed(T),
|
Parsed(T),
|
||||||
/// Instruction not recognized, but there was no error.
|
/// Instruction not recognized, but there was no error.
|
||||||
Unknown(ArgParser),
|
Unknown(TokenParser),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseOpRes<Op> {
|
impl ParseRes<Op> {
|
||||||
/// Helper to construct an extension op
|
/// Helper to construct an extension op
|
||||||
pub fn ext(op: impl OpTrait) -> Self {
|
pub fn ext(op: impl OpTrait) -> Self {
|
||||||
Self::Parsed(Op::Ext(Box::new(op)))
|
Self::Parsed(Op::Ext(Box::new(op)))
|
||||||
@@ -41,36 +43,35 @@ pub trait CrsnExtension: Debug + Send + Sync + 'static {
|
|||||||
/// the argument list and either return Ok or Err.
|
/// the argument list and either return Ok or Err.
|
||||||
///
|
///
|
||||||
/// If the instruction keyword is not recognized, return Unknown with the unchanged argument list.
|
/// If the instruction keyword is not recognized, return Unknown with the unchanged argument list.
|
||||||
fn parse_op(&self, keyword: &str, arg_tokens: ArgParser) -> Result<ParseOpRes<Op>, CrsnError>;
|
fn parse_op(&self, keyword: &str, arg_tokens: TokenParser) -> Result<ParseRes<Op>, CrsnError>;
|
||||||
|
|
||||||
|
/// Parse a generic S-expression (non-op)
|
||||||
|
fn parse_syntax(&self, keyword: &str, tokens: TokenParser, parsers: &[Box<dyn CrsnExtension>])
|
||||||
|
-> Result<ParseRes<Box<dyn Flatten>>, CrsnError>
|
||||||
|
{
|
||||||
|
Ok(ParseRes::Unknown(tokens))
|
||||||
|
}
|
||||||
|
|
||||||
/// Drop an object referenced by a handle
|
/// Drop an object referenced by a handle
|
||||||
fn drop_obj(&self,
|
fn drop_obj(&self, ti: &ThreadInfo, state: &mut RunState, handle: Value)
|
||||||
#[allow(unused)] ti: &ThreadInfo,
|
-> Result<Option<()>, Fault>
|
||||||
#[allow(unused)] state: &mut RunState,
|
|
||||||
#[allow(unused)] handle: Value) -> Result<Option<()>, Fault>
|
|
||||||
{
|
{
|
||||||
// Default impl - we do not support dropping this object
|
// Default impl - we do not support dropping this object
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run-time method called to read an object (using the object handle syntax)
|
/// Run-time method called to read an object (using the object handle syntax)
|
||||||
fn read_obj(&self,
|
fn read_obj(&self, ti: &ThreadInfo, state: &mut RunState, handle: Value, _mask: Mask)
|
||||||
#[allow(unused)] ti: &ThreadInfo,
|
-> Result<Option<Value>, Fault>
|
||||||
#[allow(unused)] state: &mut RunState,
|
{
|
||||||
#[allow(unused)] handle: Value,
|
|
||||||
#[allow(unused)] mask: Mask,
|
|
||||||
) -> Result<Option<Value>, Fault> {
|
|
||||||
// Default impl - we do not support reading this object
|
// Default impl - we do not support reading this object
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run-time method called to write an object (using the object handle syntax)
|
/// Run-time method called to write an object (using the object handle syntax)
|
||||||
fn write_obj(&self,
|
fn write_obj(&self, ti: &ThreadInfo, state: &mut RunState, handle: Value, mask: Mask)
|
||||||
#[allow(unused)] ti: &ThreadInfo,
|
-> Result<Option<()>, Fault>
|
||||||
#[allow(unused)] state: &mut RunState,
|
{
|
||||||
#[allow(unused)] handle: Value,
|
|
||||||
#[allow(unused)] mask: Mask,
|
|
||||||
) -> Result<Option<()>, Fault> {
|
|
||||||
// Default impl - we do not support writing this object
|
// Default impl - we do not support writing this object
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crsn::asm::error::CrsnError;
|
use crsn::asm::error::CrsnError;
|
||||||
use crsn::asm::instr::Op;
|
use crsn::asm::instr::Op;
|
||||||
use crsn::asm::parse::arg_parser::ArgParser;
|
use crsn::asm::parse::arg_parser::TokenParser;
|
||||||
use crsn::module::{CrsnExtension, ParseOpRes};
|
use crsn::module::{CrsnExtension, ParseRes};
|
||||||
|
|
||||||
mod defs;
|
mod defs;
|
||||||
mod parse;
|
mod parse;
|
||||||
@@ -21,7 +21,7 @@ impl CrsnExtension for ArithOps {
|
|||||||
"arith"
|
"arith"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_op(&self, keyword: &str, args: ArgParser) -> Result<ParseOpRes<Op>, CrsnError> {
|
fn parse_op(&self, keyword: &str, args: TokenParser) -> Result<ParseRes<Op>, CrsnError> {
|
||||||
parse::parse(keyword, args)
|
parse::parse(keyword, args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
use crsn::asm::data::{Rd, Wr};
|
use crsn::asm::data::{Rd, Wr};
|
||||||
use crsn::asm::error::CrsnError;
|
use crsn::asm::error::CrsnError;
|
||||||
use crsn::asm::instr::Op;
|
use crsn::asm::instr::Op;
|
||||||
use crsn::asm::parse::arg_parser::ArgParser;
|
use crsn::asm::parse::arg_parser::TokenParser;
|
||||||
use crsn::module::ParseOpRes;
|
use crsn::module::ParseRes;
|
||||||
|
|
||||||
use crate::defs::ArithOp;
|
use crate::defs::ArithOp;
|
||||||
|
|
||||||
pub(crate) fn parse(keyword: &str, mut args: ArgParser) -> Result<ParseOpRes<Op>, CrsnError> {
|
pub(crate) fn parse(keyword: &str, mut args: TokenParser) -> Result<ParseRes<Op>, CrsnError> {
|
||||||
Ok(ParseOpRes::ext(match keyword {
|
Ok(ParseRes::ext(match keyword {
|
||||||
"cmp" => {
|
"cmp" => {
|
||||||
ArithOp::Compare {
|
ArithOp::Compare {
|
||||||
a: args.next_rd()?,
|
a: args.next_rd()?,
|
||||||
@@ -430,7 +430,7 @@ pub(crate) fn parse(keyword: &str, mut args: ArgParser) -> Result<ParseOpRes<Op>
|
|||||||
}
|
}
|
||||||
|
|
||||||
_other => {
|
_other => {
|
||||||
return Ok(ParseOpRes::Unknown(args));
|
return Ok(ParseRes::Unknown(args));
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ extern crate log;
|
|||||||
|
|
||||||
use crsn::asm::error::CrsnError;
|
use crsn::asm::error::CrsnError;
|
||||||
use crsn::asm::instr::Op;
|
use crsn::asm::instr::Op;
|
||||||
use crsn::asm::parse::arg_parser::ArgParser;
|
use crsn::asm::parse::arg_parser::TokenParser;
|
||||||
use crsn::module::{CrsnExtension, ParseOpRes};
|
use crsn::module::{CrsnExtension, ParseRes};
|
||||||
|
|
||||||
mod defs;
|
mod defs;
|
||||||
mod parse;
|
mod parse;
|
||||||
@@ -24,7 +24,7 @@ impl CrsnExtension for ScreenOps {
|
|||||||
"screen"
|
"screen"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_op(&self, keyword: &str, args: ArgParser) -> Result<ParseOpRes<Op>, CrsnError> {
|
fn parse_op(&self, keyword: &str, args: TokenParser) -> Result<ParseRes<Op>, CrsnError> {
|
||||||
parse::parse(keyword, args)
|
parse::parse(keyword, args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
use crsn::asm::data::Rd;
|
use crsn::asm::data::Rd;
|
||||||
use crsn::asm::error::CrsnError;
|
use crsn::asm::error::CrsnError;
|
||||||
use crsn::asm::instr::Op;
|
use crsn::asm::instr::Op;
|
||||||
use crsn::asm::parse::arg_parser::ArgParser;
|
use crsn::asm::parse::arg_parser::TokenParser;
|
||||||
use crsn::module::ParseOpRes;
|
use crsn::module::ParseRes;
|
||||||
|
|
||||||
use crate::defs::ScreenOp;
|
use crate::defs::ScreenOp;
|
||||||
|
|
||||||
pub(crate) fn parse(keyword: &str, mut args: ArgParser) -> Result<ParseOpRes<Op>, CrsnError> {
|
pub(crate) fn parse(keyword: &str, mut args: TokenParser) -> Result<ParseRes<Op>, CrsnError> {
|
||||||
Ok(ParseOpRes::ext(match keyword {
|
Ok(ParseRes::ext(match keyword {
|
||||||
"sc-init" => {
|
"sc-init" => {
|
||||||
ScreenOp::ScreenInit {
|
ScreenOp::ScreenInit {
|
||||||
width: args.next_rd()?,
|
width: args.next_rd()?,
|
||||||
@@ -41,7 +41,7 @@ pub(crate) fn parse(keyword: &str, mut args: ArgParser) -> Result<ParseOpRes<Op>
|
|||||||
}
|
}
|
||||||
|
|
||||||
_other => {
|
_other => {
|
||||||
return Ok(ParseOpRes::Unknown(args));
|
return Ok(ParseRes::Unknown(args));
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use crsn::asm::data::literal::Value;
|
use crsn::asm::data::literal::Value;
|
||||||
use crsn::asm::error::CrsnError;
|
use crsn::asm::error::CrsnError;
|
||||||
use crsn::asm::instr::Op;
|
use crsn::asm::instr::Op;
|
||||||
use crsn::asm::parse::arg_parser::ArgParser;
|
use crsn::asm::parse::arg_parser::TokenParser;
|
||||||
use crsn::module::{CrsnExtension, ParseOpRes};
|
use crsn::module::{CrsnExtension, ParseRes};
|
||||||
use crsn::runtime::fault::Fault;
|
use crsn::runtime::fault::Fault;
|
||||||
use crsn::runtime::run_thread::{RunState, ThreadInfo};
|
use crsn::runtime::run_thread::{RunState, ThreadInfo};
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ impl CrsnExtension for StackOps {
|
|||||||
"stacks"
|
"stacks"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_op(&self, keyword: &str, args: ArgParser) -> Result<ParseOpRes<Op>, CrsnError> {
|
fn parse_op(&self, keyword: &str, args: TokenParser) -> Result<ParseRes<Op>, CrsnError> {
|
||||||
parse::parse(keyword, args)
|
parse::parse(keyword, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
use crsn::asm::error::CrsnError;
|
use crsn::asm::error::CrsnError;
|
||||||
use crsn::asm::instr::Op;
|
use crsn::asm::instr::Op;
|
||||||
use crsn::asm::parse::arg_parser::ArgParser;
|
use crsn::asm::parse::arg_parser::TokenParser;
|
||||||
use crsn::module::ParseOpRes;
|
use crsn::module::ParseRes;
|
||||||
|
|
||||||
use crate::defs::StackOp;
|
use crate::defs::StackOp;
|
||||||
|
|
||||||
pub(crate) fn parse(keyword: &str, mut args: ArgParser) -> Result<ParseOpRes<Op>, CrsnError> {
|
pub(crate) fn parse(keyword: &str, mut args: TokenParser) -> Result<ParseRes<Op>, CrsnError> {
|
||||||
Ok(ParseOpRes::ext(match keyword {
|
Ok(ParseRes::ext(match keyword {
|
||||||
"stack" => {
|
"stack" => {
|
||||||
StackOp::NewStack {
|
StackOp::NewStack {
|
||||||
dst: args.next_wr()?,
|
dst: args.next_wr()?,
|
||||||
@@ -28,7 +28,7 @@ pub(crate) fn parse(keyword: &str, mut args: ArgParser) -> Result<ParseOpRes<Op>
|
|||||||
}
|
}
|
||||||
|
|
||||||
_other => {
|
_other => {
|
||||||
return Ok(ParseOpRes::Unknown(args));
|
return Ok(ParseRes::Unknown(args));
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
(
|
(
|
||||||
(main
|
(proc main
|
||||||
(call fac 5)
|
(call fac 5)
|
||||||
(ld r0 res0)
|
(ld r0 res0)
|
||||||
(halt)
|
(halt)
|
||||||
)
|
)
|
||||||
(fac
|
(proc fac
|
||||||
(cmp arg0 2
|
(cmp arg0 2
|
||||||
(eq? (ret 2)))
|
(eq? (ret 2)))
|
||||||
(sub r0 arg0 1)
|
(sub r0 arg0 1)
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
; Set log level to "info" or above for the best results!
|
; Set log level to "info" or above for the best results!
|
||||||
|
|
||||||
(
|
(
|
||||||
(main
|
(proc main
|
||||||
(sc-init 800 600)
|
(sc-init 800 600)
|
||||||
(sc-opt 1 0) ; auto blit
|
(sc-opt 1 1) ; auto blit
|
||||||
(sc-opt 2 60) ; frame rate
|
(sc-opt 2 25) ; frame rate
|
||||||
|
|
||||||
(ld r0 5) ; x
|
(ld r0 5) ; x
|
||||||
(ld r1 0) ; y
|
(ld r1 0) ; y
|
||||||
@@ -15,16 +15,12 @@
|
|||||||
(ld r5 0x3300ff)
|
(ld r5 0x3300ff)
|
||||||
|
|
||||||
(:loop)
|
(:loop)
|
||||||
(add r5 0x000001)
|
(add r5 0x000001)
|
||||||
(and r5 0xffffff)
|
(sc-px r0 r1 r5)
|
||||||
(sc-px r0 r1 r5)
|
(add r0 r2)
|
||||||
(add r0 r2)
|
(add r1 r3)
|
||||||
(add r1 r3)
|
(cmp r0 799 (eq? (ld r2 -1)) (ne? (cmp r0 0 (eq? (ld r2 1)))))
|
||||||
(cmp r0 799 (eq? (ld r2 -1)))
|
(cmp r1 599 (eq? (ld r3 -1)) (ne? (cmp r1 0 (eq? (ld r3 1)))))
|
||||||
(cmp r0 0 (eq? (ld r2 1)))
|
|
||||||
(cmp r1 599 (eq? (ld r3 -1)))
|
|
||||||
(cmp r1 0 (eq? (ld r3 1)))
|
|
||||||
(sc-blit 0)
|
|
||||||
(j :loop)
|
(j :loop)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user