fix branch parser eating all list tokens

This commit is contained in:
2020-10-10 12:26:50 +02:00
parent 9aee9ca143
commit aae9db0598
10 changed files with 101 additions and 47 deletions
+20 -6
View File
@@ -1,4 +1,4 @@
use sexp::{Sexp, SourcePosition};
use sexp::{Sexp, SourcePosition, Atom};
use crate::asm::error::CrsnError;
use crate::asm::instr::{Flatten, InstrWithBranches};
@@ -25,6 +25,7 @@ pub fn parse_instructions(items: impl Iterator<Item=Sexp>, pos: &SourcePosition,
continue;
}
// Let extensions parse custom syntax
let mut token_parser = TokenParser::new(toki.collect(), &listpos, pcx);
for p in pcx.parsers {
token_parser = match p.parse_syntax(pos, &name, token_parser) {
@@ -43,12 +44,25 @@ pub fn parse_instructions(items: impl Iterator<Item=Sexp>, pos: &SourcePosition,
}
// Get back the original iterator
let toki = token_parser.into_iter();
let token_count = token_parser.len();
let toki : std::vec::IntoIter<Sexp> = token_parser.into_iter();
let arg_tokens = TokenParser::new(toki.clone().take_while(|e| e.is_atom()).collect(), &listpos, pcx);
let branch_tokens = toki
.skip_while(|e| e.is_atom())
.take_while(|e| e.is_list());
let branch_tokens = toki.clone().rev()
.take_while(|e| {
if let Sexp::List(ref items, _) = e {
if items.len() > 1 {
if let Sexp::Atom(Atom::S(ref kw), _) = items[0] {
if kw.ends_with('?') {
return true;
}
}
}
}
false
})
.collect::<Vec<_>>();
let arg_tokens = TokenParser::new(toki.take(token_count - branch_tokens.len()).collect(), &listpos, pcx);
let branches = {
let mut branches = vec![];
+19 -3
View File
@@ -15,6 +15,21 @@ pub enum Barrier {
Standalone,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum SleepUnit {
Usec, Msec, Sec
}
impl SleepUnit {
pub fn micros(self) -> u64 {
match self {
SleepUnit::Usec => 1,
SleepUnit::Msec => 1000,
SleepUnit::Sec => 1000000,
}
}
}
#[derive(Debug)]
pub enum BuiltinOp {
/// Do nothing (costs one cycle)
@@ -23,7 +38,8 @@ pub enum BuiltinOp {
Halt,
/// Sleep
Sleep {
micros: Rd,
count: Rd,
unit_us: SleepUnit,
},
/// Mark a jump target.
Label(Label),
@@ -57,9 +73,9 @@ pub enum BuiltinOp {
/// Copy value
Move { dst: Wr, src: Rd },
/// Store runtime status to a register
StoreStatus { dst: Wr },
StoreFlags { dst: Wr },
/// Load runtime status from a register
LoadStatus { src: Rd },
LoadFlags { src: Rd },
}
impl BuiltinOp {
+4 -4
View File
@@ -109,16 +109,16 @@ impl OpTrait for BuiltinOp {
state.update_status(val);
state.write(*dst, val)?;
}
BuiltinOp::StoreStatus { dst } => {
BuiltinOp::StoreFlags { dst } => {
let packed = state.frame.status.store();
state.write(*dst, packed)?;
}
BuiltinOp::LoadStatus { src } => {
BuiltinOp::LoadFlags { src } => {
let x = state.read(*src)?;
state.frame.status.load(x);
}
BuiltinOp::Sleep { micros } => {
std::thread::sleep(Duration::from_micros(state.read(*micros)?))
BuiltinOp::Sleep { count: micros, unit_us } => {
std::thread::sleep(Duration::from_micros(state.read(*micros)? * unit_us.micros()))
}
BuiltinOp::Delete(obj) => {
let x = state.read(Rd::new(RdData::Register(obj.reg())))?;
+48 -29
View File
@@ -8,7 +8,7 @@ use crate::asm::parse::arg_parser::TokenParser;
use crate::asm::parse::parse_data::{parse_constant_name, parse_label, parse_label_str, parse_rd, parse_reg_alias, parse_value};
use crate::asm::parse::sexp_expect::{expect_any_string_atom};
use crate::asm::patches::ErrWithPos;
use crate::builtin::defs::{Barrier, BuiltinOp};
use crate::builtin::defs::{Barrier, BuiltinOp, SleepUnit};
use crate::module::ParseRes;
use crate::utils::A;
@@ -24,9 +24,24 @@ pub(crate) fn parse_op<'a>(op_pos: &SourcePosition, keyword: &str, mut args: Tok
BuiltinOp::Halt
}
"sleep" => {
"uslp" => {
BuiltinOp::Sleep {
micros: args.next_rd()?,
count: args.next_rd()?,
unit_us: SleepUnit::Usec,
}
}
"mslp" => {
BuiltinOp::Sleep {
count: args.next_rd()?,
unit_us: SleepUnit::Msec,
}
}
"sslp" => {
BuiltinOp::Sleep {
count: args.next_rd()?,
unit_us: SleepUnit::Sec,
}
}
@@ -126,7 +141,7 @@ pub(crate) fn parse_op<'a>(op_pos: &SourcePosition, keyword: &str, mut args: Tok
BuiltinOp::Routine(parse_routine_name(name.0, &name.1)?)
}
"skip" => {
"s" => {
BuiltinOp::Skip(args.next_rd()?)
}
@@ -168,14 +183,14 @@ pub(crate) fn parse_op<'a>(op_pos: &SourcePosition, keyword: &str, mut args: Tok
}
}
"sst" => {
BuiltinOp::StoreStatus {
"stf" => {
BuiltinOp::StoreFlags {
dst: args.next_wr()?,
}
}
"sld" => {
BuiltinOp::LoadStatus {
"ldf" => {
BuiltinOp::LoadFlags {
src: args.next_rd()?,
}
}
@@ -224,7 +239,9 @@ pub(crate) fn to_sexp(op: &BuiltinOp) -> Sexp {
match op {
BuiltinOp::Nop => sexp::list(&[A("nop")]),
BuiltinOp::Halt => sexp::list(&[A("halt")]),
BuiltinOp::Sleep { micros } => sexp::list(&[A("sleep"), A(micros)]),
BuiltinOp::Sleep { count: micros, unit_us: SleepUnit::Sec } => sexp::list(&[A("sslp"), A(micros)]),
BuiltinOp::Sleep { count: micros, unit_us: SleepUnit::Msec } => sexp::list(&[A("mslp"), A(micros)]),
BuiltinOp::Sleep { count: micros, unit_us: SleepUnit::Usec } => sexp::list(&[A("uslp"), A(micros)]),
BuiltinOp::Label(label) => sexp::list(&[A(label)]),
BuiltinOp::Jump(label) => sexp::list(&[A("j"), A(label)]),
BuiltinOp::FarLabel(label) => sexp::list(&[A("far"), A(label)]),
@@ -248,7 +265,7 @@ pub(crate) fn to_sexp(op: &BuiltinOp) -> Sexp {
}
}
BuiltinOp::Routine(name) => sexp::list(&[A("routine"), A(name)]),
BuiltinOp::Skip(n) => sexp::list(&[A("skip"), A(n)]),
BuiltinOp::Skip(n) => sexp::list(&[A("s"), A(n)]),
BuiltinOp::Barrier { kind, msg } => {
let mut inner = vec![];
match kind {
@@ -279,8 +296,8 @@ pub(crate) fn to_sexp(op: &BuiltinOp) -> Sexp {
}
BuiltinOp::Delete(obj) => sexp::list(&[A("del"), A(obj)]),
BuiltinOp::Move { dst, src } => sexp::list(&[A("ld"), A(dst), A(src)]),
BuiltinOp::StoreStatus { dst } => sexp::list(&[A("sst"), A(dst)]),
BuiltinOp::LoadStatus { src } => sexp::list(&[A("sld"), A(src)])
BuiltinOp::StoreFlags { dst } => sexp::list(&[A("stf"), A(dst)]),
BuiltinOp::LoadFlags { src } => sexp::list(&[A("ldf"), A(src)])
}
}
@@ -302,26 +319,28 @@ mod test {
// jump is translated to a skip
("(nop)", "(nop)"),
("(halt)", "(halt)"),
("(sleep 1000)", "(sleep 1000)"),
("(sleep 1_0_0_0)", "(sleep 1000)"),
("(sleep ' ')", "(sleep 32)"),
("(sleep '\\n')", "(sleep 10)"),
("(sleep 0b111)", "(sleep 7)"),
("(sleep 0xab_cd)", "(sleep 43981)"),
("(sleep #ab_cd)", "(sleep 43981)"),
("(uslp 1000)", "(uslp 1000)"),
("(uslp 1_0_0_0)", "(uslp 1000)"),
("(uslp ' ')", "(uslp 32)"),
("(uslp '\\n')", "(uslp 10)"),
("(uslp 0b111)", "(uslp 7)"),
("(uslp 0xab_cd)", "(uslp 43981)"),
("(uslp #ab_cd)", "(uslp 43981)"),
("(mslp 1000)", "(mslp 1000)"),
("(sslp 1000)", "(sslp 1000)"),
("(:x)", "(:x)"),
("(j :x)", "(j :x)"),
("(:#7)", "(:#7)"),
("(j :#7)", "(j :#7)"),
("(fj :x)", "(fj :x)"),
("(skip 0)", "(skip 0)"),
("(skip r0)", "(skip r0)"),
("(sym banana r0)(unsym banana)(sym banana r1)(skip banana)", "(skip r1)"),
("(def foo 123)(skip foo)", "(skip 123)"),
("(def foo 123)(undef foo)(def foo 444)(skip foo)", "(skip 444)"),
("(def foo -777)(def bar foo)(skip bar)", "(skip -777)"),
("(skip -10)", "(skip -10)"),
("(skip -10000)", "(skip -10000)"),
("(s 0)", "(s 0)"),
("(s r0)", "(s r0)"),
("(sym banana r0)(unsym banana)(sym banana r1)(s banana)", "(s r1)"),
("(def foo 123)(s foo)", "(s 123)"),
("(def foo 123)(undef foo)(def foo 444)(s foo)", "(s 444)"),
("(def foo -777)(def bar foo)(s bar)", "(s -777)"),
("(s -10)", "(s -10)"),
("(s -10000)", "(s -10000)"),
("(call funcname)", "(call funcname)"),
("(call funcname 13)", "(call funcname 13)"),
("(sym haf r0)\
@@ -348,8 +367,8 @@ mod test {
("(ld r0 r0)", "(ld r0 r0)"),
("(ld r0 156)", "(ld r0 156)"),
("(ld _ -32767)", "(ld _ -32767)"),
("(sst r0)", "(sst r0)"),
("(sld r0)", "(sld r0)"),
("(stf r0)", "(stf r0)"),
("(ldf r0)", "(ldf r0)"),
("(far :label)", "(far :label)"),
("(del @r5)", "(del @r5)"),
("(sym cat r0)(del @cat)", "(del @r0)"),
+1 -1
View File
@@ -82,7 +82,7 @@ pub trait CrsnExtension: Debug + Send + Sync + 'static {
/// pcx is available on the arg_tokens parser
fn parse_op<'a>(&self, pos: &SourcePosition, keyword: &str, arg_tokens: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError>;
/// Parse a generic S-expression (non-op)
/// Parse a generic S-expression (non-op) that started with the given keyword
///
/// pcx is available on the arg_tokens parser
fn parse_syntax<'a>(&self, pos: &SourcePosition, keyword: &str, tokens: TokenParser<'a>)