fix branch parser eating all list tokens

pull/21/head
Ondřej Hruška 4 years ago
parent 9aee9ca143
commit aae9db0598
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 26
      crsn/src/asm/parse/parse_instr.rs
  2. 22
      crsn/src/builtin/defs.rs
  3. 8
      crsn/src/builtin/exec.rs
  4. 77
      crsn/src/builtin/parse.rs
  5. 2
      crsn/src/module/mod.rs
  6. 1
      crsn_buf/src/defs.rs
  7. 1
      crsn_buf/src/exec.rs
  8. 1
      crsn_buf/src/parse.rs
  9. 2
      examples/mouse.csn
  10. 8
      examples/number_array.csn

@ -1,4 +1,4 @@
use sexp::{Sexp, SourcePosition}; use sexp::{Sexp, SourcePosition, Atom};
use crate::asm::error::CrsnError; use crate::asm::error::CrsnError;
use crate::asm::instr::{Flatten, InstrWithBranches}; use crate::asm::instr::{Flatten, InstrWithBranches};
@ -25,6 +25,7 @@ pub fn parse_instructions(items: impl Iterator<Item=Sexp>, pos: &SourcePosition,
continue; continue;
} }
// Let extensions parse custom syntax
let mut token_parser = TokenParser::new(toki.collect(), &listpos, pcx); let mut token_parser = TokenParser::new(toki.collect(), &listpos, pcx);
for p in pcx.parsers { for p in pcx.parsers {
token_parser = match p.parse_syntax(pos, &name, token_parser) { 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 // 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.clone().rev()
let branch_tokens = toki .take_while(|e| {
.skip_while(|e| e.is_atom()) if let Sexp::List(ref items, _) = e {
.take_while(|e| e.is_list()); 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 branches = {
let mut branches = vec![]; let mut branches = vec![];

@ -15,6 +15,21 @@ pub enum Barrier {
Standalone, 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)] #[derive(Debug)]
pub enum BuiltinOp { pub enum BuiltinOp {
/// Do nothing (costs one cycle) /// Do nothing (costs one cycle)
@ -23,7 +38,8 @@ pub enum BuiltinOp {
Halt, Halt,
/// Sleep /// Sleep
Sleep { Sleep {
micros: Rd, count: Rd,
unit_us: SleepUnit,
}, },
/// Mark a jump target. /// Mark a jump target.
Label(Label), Label(Label),
@ -57,9 +73,9 @@ pub enum BuiltinOp {
/// Copy value /// Copy value
Move { dst: Wr, src: Rd }, Move { dst: Wr, src: Rd },
/// Store runtime status to a register /// Store runtime status to a register
StoreStatus { dst: Wr }, StoreFlags { dst: Wr },
/// Load runtime status from a register /// Load runtime status from a register
LoadStatus { src: Rd }, LoadFlags { src: Rd },
} }
impl BuiltinOp { impl BuiltinOp {

@ -109,16 +109,16 @@ impl OpTrait for BuiltinOp {
state.update_status(val); state.update_status(val);
state.write(*dst, val)?; state.write(*dst, val)?;
} }
BuiltinOp::StoreStatus { dst } => { BuiltinOp::StoreFlags { dst } => {
let packed = state.frame.status.store(); let packed = state.frame.status.store();
state.write(*dst, packed)?; state.write(*dst, packed)?;
} }
BuiltinOp::LoadStatus { src } => { BuiltinOp::LoadFlags { src } => {
let x = state.read(*src)?; let x = state.read(*src)?;
state.frame.status.load(x); state.frame.status.load(x);
} }
BuiltinOp::Sleep { micros } => { BuiltinOp::Sleep { count: micros, unit_us } => {
std::thread::sleep(Duration::from_micros(state.read(*micros)?)) std::thread::sleep(Duration::from_micros(state.read(*micros)? * unit_us.micros()))
} }
BuiltinOp::Delete(obj) => { BuiltinOp::Delete(obj) => {
let x = state.read(Rd::new(RdData::Register(obj.reg())))?; let x = state.read(Rd::new(RdData::Register(obj.reg())))?;

@ -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::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::parse::sexp_expect::{expect_any_string_atom};
use crate::asm::patches::ErrWithPos; use crate::asm::patches::ErrWithPos;
use crate::builtin::defs::{Barrier, BuiltinOp}; use crate::builtin::defs::{Barrier, BuiltinOp, SleepUnit};
use crate::module::ParseRes; use crate::module::ParseRes;
use crate::utils::A; use crate::utils::A;
@ -24,9 +24,24 @@ pub(crate) fn parse_op<'a>(op_pos: &SourcePosition, keyword: &str, mut args: Tok
BuiltinOp::Halt BuiltinOp::Halt
} }
"sleep" => { "uslp" => {
BuiltinOp::Sleep { 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)?) BuiltinOp::Routine(parse_routine_name(name.0, &name.1)?)
} }
"skip" => { "s" => {
BuiltinOp::Skip(args.next_rd()?) BuiltinOp::Skip(args.next_rd()?)
} }
@ -168,14 +183,14 @@ pub(crate) fn parse_op<'a>(op_pos: &SourcePosition, keyword: &str, mut args: Tok
} }
} }
"sst" => { "stf" => {
BuiltinOp::StoreStatus { BuiltinOp::StoreFlags {
dst: args.next_wr()?, dst: args.next_wr()?,
} }
} }
"sld" => { "ldf" => {
BuiltinOp::LoadStatus { BuiltinOp::LoadFlags {
src: args.next_rd()?, src: args.next_rd()?,
} }
} }
@ -224,7 +239,9 @@ pub(crate) fn to_sexp(op: &BuiltinOp) -> Sexp {
match op { match op {
BuiltinOp::Nop => sexp::list(&[A("nop")]), BuiltinOp::Nop => sexp::list(&[A("nop")]),
BuiltinOp::Halt => sexp::list(&[A("halt")]), 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::Label(label) => sexp::list(&[A(label)]),
BuiltinOp::Jump(label) => sexp::list(&[A("j"), A(label)]), BuiltinOp::Jump(label) => sexp::list(&[A("j"), A(label)]),
BuiltinOp::FarLabel(label) => sexp::list(&[A("far"), 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::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 } => { BuiltinOp::Barrier { kind, msg } => {
let mut inner = vec![]; let mut inner = vec![];
match kind { match kind {
@ -279,8 +296,8 @@ pub(crate) fn to_sexp(op: &BuiltinOp) -> Sexp {
} }
BuiltinOp::Delete(obj) => sexp::list(&[A("del"), A(obj)]), BuiltinOp::Delete(obj) => sexp::list(&[A("del"), A(obj)]),
BuiltinOp::Move { dst, src } => sexp::list(&[A("ld"), A(dst), A(src)]), BuiltinOp::Move { dst, src } => sexp::list(&[A("ld"), A(dst), A(src)]),
BuiltinOp::StoreStatus { dst } => sexp::list(&[A("sst"), A(dst)]), BuiltinOp::StoreFlags { dst } => sexp::list(&[A("stf"), A(dst)]),
BuiltinOp::LoadStatus { src } => sexp::list(&[A("sld"), A(src)]) BuiltinOp::LoadFlags { src } => sexp::list(&[A("ldf"), A(src)])
} }
} }
@ -302,26 +319,28 @@ mod test {
// jump is translated to a skip // jump is translated to a skip
("(nop)", "(nop)"), ("(nop)", "(nop)"),
("(halt)", "(halt)"), ("(halt)", "(halt)"),
("(sleep 1000)", "(sleep 1000)"), ("(uslp 1000)", "(uslp 1000)"),
("(sleep 1_0_0_0)", "(sleep 1000)"), ("(uslp 1_0_0_0)", "(uslp 1000)"),
("(sleep ' ')", "(sleep 32)"), ("(uslp ' ')", "(uslp 32)"),
("(sleep '\\n')", "(sleep 10)"), ("(uslp '\\n')", "(uslp 10)"),
("(sleep 0b111)", "(sleep 7)"), ("(uslp 0b111)", "(uslp 7)"),
("(sleep 0xab_cd)", "(sleep 43981)"), ("(uslp 0xab_cd)", "(uslp 43981)"),
("(sleep #ab_cd)", "(sleep 43981)"), ("(uslp #ab_cd)", "(uslp 43981)"),
("(mslp 1000)", "(mslp 1000)"),
("(sslp 1000)", "(sslp 1000)"),
("(:x)", "(:x)"), ("(:x)", "(:x)"),
("(j :x)", "(j :x)"), ("(j :x)", "(j :x)"),
("(:#7)", "(:#7)"), ("(:#7)", "(:#7)"),
("(j :#7)", "(j :#7)"), ("(j :#7)", "(j :#7)"),
("(fj :x)", "(fj :x)"), ("(fj :x)", "(fj :x)"),
("(skip 0)", "(skip 0)"), ("(s 0)", "(s 0)"),
("(skip r0)", "(skip r0)"), ("(s r0)", "(s r0)"),
("(sym banana r0)(unsym banana)(sym banana r1)(skip banana)", "(skip r1)"), ("(sym banana r0)(unsym banana)(sym banana r1)(s banana)", "(s r1)"),
("(def foo 123)(skip foo)", "(skip 123)"), ("(def foo 123)(s foo)", "(s 123)"),
("(def foo 123)(undef foo)(def foo 444)(skip foo)", "(skip 444)"), ("(def foo 123)(undef foo)(def foo 444)(s foo)", "(s 444)"),
("(def foo -777)(def bar foo)(skip bar)", "(skip -777)"), ("(def foo -777)(def bar foo)(s bar)", "(s -777)"),
("(skip -10)", "(skip -10)"), ("(s -10)", "(s -10)"),
("(skip -10000)", "(skip -10000)"), ("(s -10000)", "(s -10000)"),
("(call funcname)", "(call funcname)"), ("(call funcname)", "(call funcname)"),
("(call funcname 13)", "(call funcname 13)"), ("(call funcname 13)", "(call funcname 13)"),
("(sym haf r0)\ ("(sym haf r0)\
@ -348,8 +367,8 @@ mod test {
("(ld r0 r0)", "(ld r0 r0)"), ("(ld r0 r0)", "(ld r0 r0)"),
("(ld r0 156)", "(ld r0 156)"), ("(ld r0 156)", "(ld r0 156)"),
("(ld _ -32767)", "(ld _ -32767)"), ("(ld _ -32767)", "(ld _ -32767)"),
("(sst r0)", "(sst r0)"), ("(stf r0)", "(stf r0)"),
("(sld r0)", "(sld r0)"), ("(ldf r0)", "(ldf r0)"),
("(far :label)", "(far :label)"), ("(far :label)", "(far :label)"),
("(del @r5)", "(del @r5)"), ("(del @r5)", "(del @r5)"),
("(sym cat r0)(del @cat)", "(del @r0)"), ("(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 /// 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>; 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 /// pcx is available on the arg_tokens parser
fn parse_syntax<'a>(&self, pos: &SourcePosition, keyword: &str, tokens: TokenParser<'a>) fn parse_syntax<'a>(&self, pos: &SourcePosition, keyword: &str, tokens: TokenParser<'a>)

@ -1,5 +1,4 @@
use crsn::asm::data::{Rd, RdObj, Wr}; use crsn::asm::data::{Rd, RdObj, Wr};
use crsn::asm::data::literal::Value;
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub enum BufValue { pub enum BufValue {

@ -1,6 +1,5 @@
use std::collections::{HashMap, VecDeque}; use std::collections::{HashMap, VecDeque};
use crsn::asm::data::{Rd, RdObj, Wr};
use crsn::asm::data::literal::Value; use crsn::asm::data::literal::Value;
use crsn::asm::instr::Cond; use crsn::asm::instr::Cond;
use crsn::module::{EvalRes, OpTrait}; use crsn::module::{EvalRes, OpTrait};

@ -6,7 +6,6 @@ use crsn::sexp::{SourcePosition, Sexp, Atom};
use crate::defs::{BufOps, BufValue}; use crate::defs::{BufOps, BufValue};
use crsn::asm::data::Rd; use crsn::asm::data::Rd;
use crsn::sexp;
use crsn::asm::parse::parse_data::parse_rd; use crsn::asm::parse::parse_data::parse_rd;
pub(crate) fn parse<'a>(_pos: &SourcePosition, keyword: &str, mut args: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError> { pub(crate) fn parse<'a>(_pos: &SourcePosition, keyword: &str, mut args: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError> {

@ -16,7 +16,7 @@
(call draw_box x y) (call draw_box x y)
(:next) (:next)
(sleep 500) (uslp 500)
(j :loop) (j :loop)
(proc draw_box x y (proc draw_box x y

@ -0,0 +1,8 @@
(
(ld r0 65)
(sym buf r7)
(mkbfv buf (r0 66 67 68 '\n'))
(bfrpop @stdout @buf)
(s.nem -1)
)
Loading…
Cancel
Save