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
|
||||
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 {
|
||||
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];
|
||||
|
||||
if let Some(branches) = self.branches {
|
||||
@@ -31,10 +31,7 @@ impl Flatten for Instr {
|
||||
Label::unique(label_num)
|
||||
};
|
||||
ops.push(BuiltinOp::JumpIf(!cond, next_lbl.clone()).into());
|
||||
|
||||
for branch_instr in branch {
|
||||
ops.extend(branch_instr.flatten(label_num)?);
|
||||
}
|
||||
ops.extend(branch.flatten(label_num)?);
|
||||
|
||||
if cnt != branch_count - 1 {
|
||||
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 {
|
||||
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![
|
||||
BuiltinOp::Routine(self.name.clone()).into(),
|
||||
];
|
||||
|
||||
for instr in self.body {
|
||||
ops.extend(instr.flatten(label_num)?);
|
||||
}
|
||||
ops.extend(self.body.flatten(label_num)?);
|
||||
|
||||
ops.push(BuiltinOp::Barrier(Some(format!("Routine \"{}\" overrun", self.name).into())).into());
|
||||
|
||||
|
||||
@@ -9,15 +9,13 @@ pub mod cond;
|
||||
mod flatten;
|
||||
|
||||
/// A higher-level instruction
|
||||
#[derive(Debug)]
|
||||
pub struct Instr {
|
||||
pub op: Op,
|
||||
pub branches: Option<Vec<(Cond, Vec<Instr>)>>,
|
||||
pub branches: Option<Vec<(Cond, Box<dyn Flatten>)>>,
|
||||
}
|
||||
|
||||
/// A routine
|
||||
pub struct Routine {
|
||||
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;
|
||||
|
||||
/// Utility for argument parsing
|
||||
pub struct ArgParser {
|
||||
pub struct TokenParser {
|
||||
orig_len: usize,
|
||||
args: Vec<Sexp>,
|
||||
}
|
||||
|
||||
impl IntoIterator for ArgParser {
|
||||
impl IntoIterator for TokenParser {
|
||||
type Item = 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()
|
||||
}
|
||||
}
|
||||
|
||||
impl ArgParser {
|
||||
impl TokenParser {
|
||||
/// Create a new argument parser
|
||||
pub fn new(mut args: Vec<Sexp>) -> Self {
|
||||
args.reverse();
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use std::sync::atomic::AtomicU32;
|
||||
use std::sync::atomic::{AtomicU32, AtomicU64};
|
||||
|
||||
pub use parse_instr::parse_instructions;
|
||||
use parse_routines::parse_routines;
|
||||
|
||||
use crate::asm::error::CrsnError;
|
||||
use crate::asm::instr::{Flatten, Op, Routine};
|
||||
@@ -11,22 +10,15 @@ use crate::module::CrsnExtension;
|
||||
mod parse_cond;
|
||||
mod parse_instr;
|
||||
pub mod parse_data;
|
||||
mod parse_routines;
|
||||
pub mod sexp_expect;
|
||||
mod parse_op;
|
||||
|
||||
pub mod arg_parser;
|
||||
|
||||
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);
|
||||
for sub in subs {
|
||||
combined.extend(sub.flatten(&label_num)?);
|
||||
}
|
||||
|
||||
Ok(combined)
|
||||
parse_instructions(items.into_iter(), parsers)?
|
||||
.flatten(&label_num)
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use sexp::Sexp;
|
||||
|
||||
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::sexp_expect::{expect_list, expect_string_atom};
|
||||
use crate::asm::patches::TryRemove;
|
||||
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 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()));
|
||||
}
|
||||
|
||||
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 crate::asm::error::CrsnError;
|
||||
use crate::asm::instr::Instr;
|
||||
use crate::asm::parse::arg_parser::ArgParser;
|
||||
use crate::asm::instr::{Instr, Flatten, Routine};
|
||||
use crate::asm::parse::arg_parser::TokenParser;
|
||||
use crate::asm::parse::parse_cond::parse_cond_branch;
|
||||
use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom};
|
||||
use crate::asm::patches::SexpIsA;
|
||||
use crate::module::CrsnExtension;
|
||||
use crate::module::{CrsnExtension, ParseRes};
|
||||
|
||||
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![];
|
||||
for expr in instrs {
|
||||
for expr in items {
|
||||
let tokens = expect_list(Some(expr), false)?;
|
||||
|
||||
let mut toki = tokens.into_iter();
|
||||
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
|
||||
.skip_while(|e| e.is_atom())
|
||||
.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)?,
|
||||
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::instr::Op;
|
||||
use crate::asm::parse::arg_parser::ArgParser;
|
||||
use crate::asm::parse::arg_parser::TokenParser;
|
||||
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
|
||||
let builtins = [BuiltinOps::new()];
|
||||
|
||||
for p in builtins.iter().chain(parsers) {
|
||||
arg_tokens = match p.parse_op(keyword, arg_tokens) {
|
||||
Ok(ParseOpRes::Parsed(op)) => return Ok(op),
|
||||
Ok(ParseOpRes::Unknown(to_reuse)) => {
|
||||
Ok(ParseRes::Parsed(op)) => return Ok(op),
|
||||
Ok(ParseRes::Unknown(to_reuse)) => {
|
||||
if to_reuse.parsing_started() {
|
||||
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::instr::cond::parse_cond;
|
||||
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::sexp_expect::expect_string_atom;
|
||||
use crate::builtin::defs::BuiltinOp;
|
||||
use crate::module::{CrsnExtension, ParseOpRes};
|
||||
use crate::module::{CrsnExtension, ParseRes};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct BuiltinOps {
|
||||
@@ -28,8 +28,8 @@ impl CrsnExtension for BuiltinOps {
|
||||
"builtin"
|
||||
}
|
||||
|
||||
fn parse_op(&self, keyword: &str, mut args: ArgParser) -> Result<ParseOpRes<Op>, CrsnError> {
|
||||
Ok(ParseOpRes::Parsed(Op::BuiltIn(match keyword {
|
||||
fn parse_op(&self, keyword: &str, mut args: TokenParser) -> Result<ParseRes<Op>, CrsnError> {
|
||||
Ok(ParseRes::Parsed(Op::BuiltIn(match keyword {
|
||||
"nop" => {
|
||||
BuiltinOp::Nop
|
||||
}
|
||||
@@ -142,10 +142,10 @@ impl CrsnExtension for BuiltinOps {
|
||||
let label = Label::Named(label.to_string());
|
||||
BuiltinOp::FarLabel(label)
|
||||
} else {
|
||||
return Ok(ParseOpRes::Unknown(args));
|
||||
return Ok(ParseRes::Unknown(args));
|
||||
}
|
||||
} 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());
|
||||
BuiltinOp::Label(label)
|
||||
} else {
|
||||
return Ok(ParseOpRes::Unknown(args));
|
||||
return Ok(ParseRes::Unknown(args));
|
||||
}
|
||||
}
|
||||
})))
|
||||
|
||||
+23
-22
@@ -1,3 +1,5 @@
|
||||
#![allow(unused_variables)]
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
pub use eval_res::EvalRes;
|
||||
@@ -5,8 +7,8 @@ pub use eval_res::EvalRes;
|
||||
use crate::asm::data::literal::Value;
|
||||
use crate::asm::data::Mask;
|
||||
use crate::asm::error::CrsnError;
|
||||
use crate::asm::instr::Op;
|
||||
use crate::asm::parse::arg_parser::ArgParser;
|
||||
use crate::asm::instr::{Op, Flatten};
|
||||
use crate::asm::parse::arg_parser::TokenParser;
|
||||
use crate::runtime::fault::Fault;
|
||||
use crate::runtime::run_thread::state::RunState;
|
||||
use crate::runtime::run_thread::ThreadInfo;
|
||||
@@ -14,14 +16,14 @@ use crate::runtime::run_thread::ThreadInfo;
|
||||
mod eval_res;
|
||||
|
||||
/// 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.
|
||||
Parsed(T),
|
||||
/// Instruction not recognized, but there was no error.
|
||||
Unknown(ArgParser),
|
||||
Unknown(TokenParser),
|
||||
}
|
||||
|
||||
impl ParseOpRes<Op> {
|
||||
impl ParseRes<Op> {
|
||||
/// Helper to construct an extension op
|
||||
pub fn ext(op: impl OpTrait) -> Self {
|
||||
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.
|
||||
///
|
||||
/// 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
|
||||
fn drop_obj(&self,
|
||||
#[allow(unused)] ti: &ThreadInfo,
|
||||
#[allow(unused)] state: &mut RunState,
|
||||
#[allow(unused)] handle: Value) -> Result<Option<()>, Fault>
|
||||
fn drop_obj(&self, ti: &ThreadInfo, state: &mut RunState, handle: Value)
|
||||
-> Result<Option<()>, Fault>
|
||||
{
|
||||
// Default impl - we do not support dropping this object
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// Run-time method called to read an object (using the object handle syntax)
|
||||
fn read_obj(&self,
|
||||
#[allow(unused)] ti: &ThreadInfo,
|
||||
#[allow(unused)] state: &mut RunState,
|
||||
#[allow(unused)] handle: Value,
|
||||
#[allow(unused)] mask: Mask,
|
||||
) -> Result<Option<Value>, Fault> {
|
||||
fn read_obj(&self, ti: &ThreadInfo, state: &mut RunState, handle: Value, _mask: Mask)
|
||||
-> Result<Option<Value>, Fault>
|
||||
{
|
||||
// Default impl - we do not support reading this object
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// Run-time method called to write an object (using the object handle syntax)
|
||||
fn write_obj(&self,
|
||||
#[allow(unused)] ti: &ThreadInfo,
|
||||
#[allow(unused)] state: &mut RunState,
|
||||
#[allow(unused)] handle: Value,
|
||||
#[allow(unused)] mask: Mask,
|
||||
) -> Result<Option<()>, Fault> {
|
||||
fn write_obj(&self, ti: &ThreadInfo, state: &mut RunState, handle: Value, mask: Mask)
|
||||
-> Result<Option<()>, Fault>
|
||||
{
|
||||
// Default impl - we do not support writing this object
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crsn::asm::error::CrsnError;
|
||||
use crsn::asm::instr::Op;
|
||||
use crsn::asm::parse::arg_parser::ArgParser;
|
||||
use crsn::module::{CrsnExtension, ParseOpRes};
|
||||
use crsn::asm::parse::arg_parser::TokenParser;
|
||||
use crsn::module::{CrsnExtension, ParseRes};
|
||||
|
||||
mod defs;
|
||||
mod parse;
|
||||
@@ -21,7 +21,7 @@ impl CrsnExtension for ArithOps {
|
||||
"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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use crsn::asm::data::{Rd, Wr};
|
||||
use crsn::asm::error::CrsnError;
|
||||
use crsn::asm::instr::Op;
|
||||
use crsn::asm::parse::arg_parser::ArgParser;
|
||||
use crsn::module::ParseOpRes;
|
||||
use crsn::asm::parse::arg_parser::TokenParser;
|
||||
use crsn::module::ParseRes;
|
||||
|
||||
use crate::defs::ArithOp;
|
||||
|
||||
pub(crate) fn parse(keyword: &str, mut args: ArgParser) -> Result<ParseOpRes<Op>, CrsnError> {
|
||||
Ok(ParseOpRes::ext(match keyword {
|
||||
pub(crate) fn parse(keyword: &str, mut args: TokenParser) -> Result<ParseRes<Op>, CrsnError> {
|
||||
Ok(ParseRes::ext(match keyword {
|
||||
"cmp" => {
|
||||
ArithOp::Compare {
|
||||
a: args.next_rd()?,
|
||||
@@ -430,7 +430,7 @@ pub(crate) fn parse(keyword: &str, mut args: ArgParser) -> Result<ParseOpRes<Op>
|
||||
}
|
||||
|
||||
_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::instr::Op;
|
||||
use crsn::asm::parse::arg_parser::ArgParser;
|
||||
use crsn::module::{CrsnExtension, ParseOpRes};
|
||||
use crsn::asm::parse::arg_parser::TokenParser;
|
||||
use crsn::module::{CrsnExtension, ParseRes};
|
||||
|
||||
mod defs;
|
||||
mod parse;
|
||||
@@ -24,7 +24,7 @@ impl CrsnExtension for ScreenOps {
|
||||
"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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use crsn::asm::data::Rd;
|
||||
use crsn::asm::error::CrsnError;
|
||||
use crsn::asm::instr::Op;
|
||||
use crsn::asm::parse::arg_parser::ArgParser;
|
||||
use crsn::module::ParseOpRes;
|
||||
use crsn::asm::parse::arg_parser::TokenParser;
|
||||
use crsn::module::ParseRes;
|
||||
|
||||
use crate::defs::ScreenOp;
|
||||
|
||||
pub(crate) fn parse(keyword: &str, mut args: ArgParser) -> Result<ParseOpRes<Op>, CrsnError> {
|
||||
Ok(ParseOpRes::ext(match keyword {
|
||||
pub(crate) fn parse(keyword: &str, mut args: TokenParser) -> Result<ParseRes<Op>, CrsnError> {
|
||||
Ok(ParseRes::ext(match keyword {
|
||||
"sc-init" => {
|
||||
ScreenOp::ScreenInit {
|
||||
width: args.next_rd()?,
|
||||
@@ -41,7 +41,7 @@ pub(crate) fn parse(keyword: &str, mut args: ArgParser) -> Result<ParseOpRes<Op>
|
||||
}
|
||||
|
||||
_other => {
|
||||
return Ok(ParseOpRes::Unknown(args));
|
||||
return Ok(ParseRes::Unknown(args));
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use crsn::asm::data::literal::Value;
|
||||
use crsn::asm::error::CrsnError;
|
||||
use crsn::asm::instr::Op;
|
||||
use crsn::asm::parse::arg_parser::ArgParser;
|
||||
use crsn::module::{CrsnExtension, ParseOpRes};
|
||||
use crsn::asm::parse::arg_parser::TokenParser;
|
||||
use crsn::module::{CrsnExtension, ParseRes};
|
||||
use crsn::runtime::fault::Fault;
|
||||
use crsn::runtime::run_thread::{RunState, ThreadInfo};
|
||||
|
||||
@@ -24,7 +24,7 @@ impl CrsnExtension for StackOps {
|
||||
"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)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
use crsn::asm::error::CrsnError;
|
||||
use crsn::asm::instr::Op;
|
||||
use crsn::asm::parse::arg_parser::ArgParser;
|
||||
use crsn::module::ParseOpRes;
|
||||
use crsn::asm::parse::arg_parser::TokenParser;
|
||||
use crsn::module::ParseRes;
|
||||
|
||||
use crate::defs::StackOp;
|
||||
|
||||
pub(crate) fn parse(keyword: &str, mut args: ArgParser) -> Result<ParseOpRes<Op>, CrsnError> {
|
||||
Ok(ParseOpRes::ext(match keyword {
|
||||
pub(crate) fn parse(keyword: &str, mut args: TokenParser) -> Result<ParseRes<Op>, CrsnError> {
|
||||
Ok(ParseRes::ext(match keyword {
|
||||
"stack" => {
|
||||
StackOp::NewStack {
|
||||
dst: args.next_wr()?,
|
||||
@@ -28,7 +28,7 @@ pub(crate) fn parse(keyword: &str, mut args: ArgParser) -> Result<ParseOpRes<Op>
|
||||
}
|
||||
|
||||
_other => {
|
||||
return Ok(ParseOpRes::Unknown(args));
|
||||
return Ok(ParseRes::Unknown(args));
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
(
|
||||
(main
|
||||
(proc main
|
||||
(call fac 5)
|
||||
(ld r0 res0)
|
||||
(halt)
|
||||
)
|
||||
(fac
|
||||
(proc fac
|
||||
(cmp arg0 2
|
||||
(eq? (ret 2)))
|
||||
(sub r0 arg0 1)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
; Set log level to "info" or above for the best results!
|
||||
|
||||
(
|
||||
(main
|
||||
(proc main
|
||||
(sc-init 800 600)
|
||||
(sc-opt 1 0) ; auto blit
|
||||
(sc-opt 2 60) ; frame rate
|
||||
(sc-opt 1 1) ; auto blit
|
||||
(sc-opt 2 25) ; frame rate
|
||||
|
||||
(ld r0 5) ; x
|
||||
(ld r1 0) ; y
|
||||
@@ -16,15 +16,11 @@
|
||||
|
||||
(:loop)
|
||||
(add r5 0x000001)
|
||||
(and r5 0xffffff)
|
||||
(sc-px r0 r1 r5)
|
||||
(add r0 r2)
|
||||
(add r1 r3)
|
||||
(cmp r0 799 (eq? (ld r2 -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)
|
||||
(cmp r0 799 (eq? (ld r2 -1)) (ne? (cmp r0 0 (eq? (ld r2 1)))))
|
||||
(cmp r1 599 (eq? (ld r3 -1)) (ne? (cmp r1 0 (eq? (ld r3 1)))))
|
||||
(j :loop)
|
||||
)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user