forked from MightyPork/crsn
fix branch parser eating all list tokens
This commit is contained in:
@@ -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![];
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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)"),
|
||||
|
||||
@@ -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>)
|
||||
|
||||
Reference in New Issue
Block a user