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::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())))?;

@ -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>)

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

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

@ -6,7 +6,6 @@ use crsn::sexp::{SourcePosition, Sexp, Atom};
use crate::defs::{BufOps, BufValue};
use crsn::asm::data::Rd;
use crsn::sexp;
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> {

@ -16,7 +16,7 @@
(call draw_box x y)
(:next)
(sleep 500)
(uslp 500)
(j :loop)
(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