remove unnecessary cloning of SourcePosition, reduce SourcePosition size. clean, format

pull/21/head
Ondřej Hruška 4 years ago
parent 91573140a4
commit 33ec1461e4
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 2
      crsn/src/asm/data/rd.rs
  2. 13
      crsn/src/asm/data/reg.rs
  3. 2
      crsn/src/asm/data/wr.rs
  4. 6
      crsn/src/asm/error.rs
  5. 7
      crsn/src/asm/instr/cond.rs
  6. 11
      crsn/src/asm/instr/flatten.rs
  7. 2
      crsn/src/asm/instr/mod.rs
  8. 5
      crsn/src/asm/instr/op.rs
  9. 7
      crsn/src/asm/mod.rs
  10. 4
      crsn/src/asm/parse/arg_parser.rs
  11. 4
      crsn/src/asm/parse/mod.rs
  12. 4
      crsn/src/asm/parse/parse_cond.rs
  13. 31
      crsn/src/asm/parse/parse_data.rs
  14. 14
      crsn/src/asm/parse/parse_instr.rs
  15. 17
      crsn/src/asm/parse/parse_op.rs
  16. 14
      crsn/src/asm/parse/parse_routine.rs
  17. 20
      crsn/src/asm/patches/mod.rs
  18. 3
      crsn/src/builtin/defs.rs
  19. 7
      crsn/src/builtin/exec.rs
  20. 11
      crsn/src/builtin/mod.rs
  21. 48
      crsn/src/builtin/parse.rs
  22. 9
      crsn/src/module/mod.rs
  23. 9
      crsn/src/runtime/program.rs
  24. 5
      crsn/src/utils/mod.rs
  25. 10
      crsn_arith/src/exec.rs
  26. 2
      crsn_arith/src/lib.rs
  27. 34
      crsn_arith/src/parse.rs
  28. 16
      crsn_screen/src/exec.rs
  29. 2
      crsn_screen/src/lib.rs
  30. 10
      crsn_screen/src/parse.rs
  31. 12
      crsn_stacks/src/exec.rs
  32. 2
      crsn_stacks/src/lib.rs
  33. 4
      crsn_stacks/src/parse.rs
  34. 2
      launcher/src/main.rs
  35. 28
      lib/spanned_sexp/.travis.yml
  36. 6
      lib/spanned_sexp/Cargo.toml
  37. 14
      lib/spanned_sexp/src/error.rs
  38. 2
      lib/spanned_sexp/src/lib.rs
  39. 6
      lib/spanned_sexp/src/test.rs

@ -1,4 +1,4 @@
use std::fmt::{Debug, Formatter, Display}; use std::fmt::{Debug, Display, Formatter};
use std::fmt; use std::fmt;
use crate::asm::data::{DataDisp, Mask, RdData, Register}; use crate::asm::data::{DataDisp, Mask, RdData, Register};

@ -1,7 +1,8 @@
use std::fmt::{self, Display, Formatter}; use std::fmt::{self, Display, Formatter};
use crate::asm::error::CrsnError;
use sexp::SourcePosition; use sexp::SourcePosition;
use crate::asm::error::CrsnError;
use crate::asm::patches::ErrWithPos; use crate::asm::patches::ErrWithPos;
/// Register name /// Register name
@ -25,27 +26,27 @@ impl Display for Register {
} }
} }
pub fn parse_reg(name: &str, at: SourcePosition) -> Result<Register, CrsnError> { pub fn parse_reg(name: &str, at: &SourcePosition) -> Result<Register, CrsnError> {
// TODO deduplicate code // TODO deduplicate code
if let Some(rn) = name.strip_prefix("arg") { if let Some(rn) = name.strip_prefix("arg") {
if rn.chars().find(|c: &char| !c.is_ascii_digit()).is_some() { if rn.chars().find(|c: &char| !c.is_ascii_digit()).is_some() {
return Err(CrsnError::Parse(format!("Bad register: {}", name).into(), at))?; return Err(CrsnError::Parse(format!("Bad register: {}", name).into(), at.clone()))?;
} }
let val: u8 = rn.parse().err_pos(at)?; let val: u8 = rn.parse().err_pos(at)?;
Ok(Register::Arg(val)) Ok(Register::Arg(val))
} else if let Some(rn) = name.strip_prefix("res") { } else if let Some(rn) = name.strip_prefix("res") {
if rn.chars().find(|c: &char| !c.is_ascii_digit()).is_some() { if rn.chars().find(|c: &char| !c.is_ascii_digit()).is_some() {
return Err(CrsnError::Parse(format!("Bad register: {}", name).into(), at))?; return Err(CrsnError::Parse(format!("Bad register: {}", name).into(), at.clone()))?;
} }
let val: u8 = rn.parse().err_pos(at)?; let val: u8 = rn.parse().err_pos(at)?;
Ok(Register::Res(val)) Ok(Register::Res(val))
} else if let Some(rn) = name.strip_prefix("r") { } else if let Some(rn) = name.strip_prefix("r") {
if rn.chars().find(|c: &char| !c.is_ascii_digit()).is_some() { if rn.chars().find(|c: &char| !c.is_ascii_digit()).is_some() {
return Err(CrsnError::Parse(format!("Bad register: {}", name).into(), at))?; return Err(CrsnError::Parse(format!("Bad register: {}", name).into(), at.clone()))?;
} }
let val: u8 = rn.parse().err_pos(at)?; let val: u8 = rn.parse().err_pos(at)?;
Ok(Register::Gen(val)) Ok(Register::Gen(val))
} else { } else {
Err(CrsnError::Parse(format!("Bad reg name: {}", name).into(), at))? Err(CrsnError::Parse(format!("Bad reg name: {}", name).into(), at.clone()))?
} }
} }

@ -1,4 +1,4 @@
use std::fmt::{Debug, Formatter, Display}; use std::fmt::{Debug, Display, Formatter};
use std::fmt; use std::fmt;
use crate::asm::data::{DataDisp, Mask, Rd, WrData}; use crate::asm::data::{DataDisp, Mask, Rd, WrData};

@ -1,13 +1,13 @@
use std::borrow::Cow; use std::borrow::Cow;
use std::num::ParseIntError; use std::error::Error;
use thiserror::Error; use thiserror::Error;
use sexp::SourcePosition;
use crate::asm::data::{Mask, Register}; use crate::asm::data::{Mask, Register};
use crate::asm::data::literal::Label; use crate::asm::data::literal::Label;
use crate::asm::instr::Cond; use crate::asm::instr::Cond;
use sexp::SourcePosition;
use std::error::Error;
/// csn_asm unified error type /// csn_asm unified error type
#[derive(Error, Debug)] #[derive(Error, Debug)]

@ -1,9 +1,10 @@
use std::fmt::{self, Display, Formatter}; use std::fmt::{self, Display, Formatter};
use std::ops::Not; use std::ops::Not;
use crate::asm::error::CrsnError;
use sexp::SourcePosition; use sexp::SourcePosition;
use crate::asm::error::CrsnError;
/// Condition flag /// Condition flag
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum Cond { pub enum Cond {
@ -46,7 +47,7 @@ pub enum Cond {
NotCarry, NotCarry,
} }
pub fn parse_cond(text: &str, pos : SourcePosition) -> Result<Cond, CrsnError> { pub fn parse_cond(text: &str, pos: &SourcePosition) -> Result<Cond, CrsnError> {
Ok(match text.trim_end_matches('?') { Ok(match text.trim_end_matches('?') {
"eq" | "=" | "==" => Cond::Equal, "eq" | "=" | "==" => Cond::Equal,
"ne" | "<>" | "!=" | "≠" => Cond::NotEqual, "ne" | "<>" | "!=" | "≠" => Cond::NotEqual,
@ -67,7 +68,7 @@ pub fn parse_cond(text: &str, pos : SourcePosition) -> Result<Cond, CrsnError> {
"ov" | "^" => Cond::Overflow, "ov" | "^" => Cond::Overflow,
"nov" | "!ov" | "!^" => Cond::NotOverflow, "nov" | "!ov" | "!^" => Cond::NotOverflow,
_ => { _ => {
return Err(CrsnError::Parse(format!("Unknown cond: {}", text).into(), pos)); return Err(CrsnError::Parse(format!("Unknown cond: {}", text).into(), pos.clone()));
} }
}) })
} }

@ -1,5 +1,8 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::atomic::{AtomicU32}; use std::fmt::Debug;
use std::sync::atomic::AtomicU32;
use sexp::SourcePosition;
use crate::asm::data::{Rd, RdData}; use crate::asm::data::{Rd, RdData};
use crate::asm::data::literal::{Label, Value}; use crate::asm::data::literal::{Label, Value};
@ -8,11 +11,9 @@ use crate::asm::instr::{Cond, InstrWithBranches, Op, Routine};
use crate::asm::instr::op::OpKind; use crate::asm::instr::op::OpKind;
use crate::builtin::defs::Barrier; use crate::builtin::defs::Barrier;
use crate::builtin::defs::BuiltinOp; use crate::builtin::defs::BuiltinOp;
use std::fmt::Debug;
use sexp::SourcePosition;
/// A trait for something that can turn into multiple instructions /// A trait for something that can turn into multiple instructions
pub trait Flatten : Debug { pub trait Flatten: Debug {
fn flatten(self: Box<Self>, label_num: &AtomicU32) -> Result<Vec<Op>, CrsnError>; fn flatten(self: Box<Self>, label_num: &AtomicU32) -> Result<Vec<Op>, CrsnError>;
fn pos(&self) -> SourcePosition; fn pos(&self) -> SourcePosition;
@ -154,7 +155,7 @@ pub fn labels_to_skips(ops: Vec<Op>) -> Result<Vec<Op>, CrsnError> {
let skip = *dest as isize - n as isize + skipped; let skip = *dest as isize - n as isize + skipped;
cleaned.push(Op { cleaned.push(Op {
cond: op.cond, cond: op.cond,
pos : op.pos.clone(), pos: op.pos.clone(),
kind: OpKind::BuiltIn(BuiltinOp::Skip(Rd::new(RdData::Immediate(skip as Value)))), kind: OpKind::BuiltIn(BuiltinOp::Skip(Rd::new(RdData::Immediate(skip as Value)))),
}); });
} else { } else {

@ -1,9 +1,9 @@
pub use cond::Cond; pub use cond::Cond;
pub use flatten::Flatten; pub use flatten::Flatten;
pub use op::Op; pub use op::Op;
use sexp::SourcePosition;
use crate::asm::data::literal::RoutineName; use crate::asm::data::literal::RoutineName;
use sexp::SourcePosition;
pub mod op; pub mod op;
pub mod cond; pub mod cond;

@ -1,11 +1,12 @@
use std::fmt::Debug; use std::fmt::Debug;
use sexp::{Atom, Sexp, SourcePosition};
use crate::asm::instr::Cond; use crate::asm::instr::Cond;
use crate::builtin::defs::BuiltinOp; use crate::builtin::defs::BuiltinOp;
use crate::module::{EvalRes, OpTrait}; use crate::module::{EvalRes, OpTrait};
use crate::runtime::fault::Fault; use crate::runtime::fault::Fault;
use crate::runtime::run_thread::{info::ThreadInfo, state::RunState}; use crate::runtime::run_thread::{info::ThreadInfo, state::RunState};
use sexp::{Sexp, Atom, SourcePosition};
/// A higher level simple opration /// A higher level simple opration
#[derive(Debug)] #[derive(Debug)]
@ -18,7 +19,7 @@ pub enum OpKind {
#[derive(Debug)] #[derive(Debug)]
pub struct Op { pub struct Op {
pub cond: Option<Cond>, pub cond: Option<Cond>,
pub pos : SourcePosition, pub pos: SourcePosition,
pub kind: OpKind, pub kind: OpKind,
} }

@ -1,11 +1,12 @@
use std::cell::RefCell; use std::cell::RefCell;
use std::sync::Arc; use std::sync::Arc;
use sexp::SourcePosition;
use crate::asm::instr::flatten::labels_to_skips;
use crate::asm::parse::{ParserContext, ParserState}; use crate::asm::parse::{ParserContext, ParserState};
use crate::module::CrsnExtension; use crate::module::CrsnExtension;
use crate::runtime::program::Program; use crate::runtime::program::Program;
use crate::asm::instr::flatten::labels_to_skips;
use sexp::SourcePosition;
pub mod data; pub mod data;
pub mod error; pub mod error;
@ -24,7 +25,7 @@ pub fn assemble(source: &str, parsers: Arc<Vec<Box<dyn CrsnExtension>>>) -> Resu
}), }),
}; };
let ops = parse::parse(source, SourcePosition::default(), &pcx)?; let ops = parse::parse(source, &SourcePosition::default(), &pcx)?;
let ops = labels_to_skips(ops)?; let ops = labels_to_skips(ops)?;
Ok(Program::new(ops, parsers)?) Ok(Program::new(ops, parsers)?)

@ -11,7 +11,7 @@ use crate::asm::patches::NextOrErr;
pub struct TokenParser<'a> { pub struct TokenParser<'a> {
orig_len: usize, orig_len: usize,
args: Vec<Sexp>, args: Vec<Sexp>,
start_pos: SourcePosition, start_pos: &'a SourcePosition,
pub pcx: &'a ParserContext<'a>, pub pcx: &'a ParserContext<'a>,
} }
@ -29,7 +29,7 @@ impl<'a> IntoIterator for TokenParser<'a> {
impl<'a> TokenParser<'a> { impl<'a> TokenParser<'a> {
/// Create a new argument parser /// Create a new argument parser
pub fn new(mut args: Vec<Sexp>, start_pos: SourcePosition, pcx: &'a ParserContext) -> Self { pub fn new(mut args: Vec<Sexp>, start_pos: &'a SourcePosition, pcx: &'a ParserContext) -> Self {
args.reverse(); args.reverse();
Self { Self {
orig_len: args.len(), orig_len: args.len(),

@ -3,6 +3,7 @@ use std::collections::HashMap;
use std::sync::atomic::AtomicU32; use std::sync::atomic::AtomicU32;
pub use parse_instr::parse_instructions; pub use parse_instr::parse_instructions;
use sexp::SourcePosition;
use crate::asm::data::literal::{ConstantName, RegisterAlias, Value}; use crate::asm::data::literal::{ConstantName, RegisterAlias, Value};
use crate::asm::data::Register; use crate::asm::data::Register;
@ -10,7 +11,6 @@ use crate::asm::error::CrsnError;
use crate::asm::instr::Op; use crate::asm::instr::Op;
use crate::asm::parse::sexp_expect::expect_list; use crate::asm::parse::sexp_expect::expect_list;
use crate::module::CrsnExtension; use crate::module::CrsnExtension;
use sexp::SourcePosition;
pub mod parse_cond; pub mod parse_cond;
pub mod parse_instr; pub mod parse_instr;
@ -39,7 +39,7 @@ pub struct ParserState {
pub constants: HashMap<ConstantName, Value>, pub constants: HashMap<ConstantName, Value>,
} }
pub fn parse(source: &str, pos: SourcePosition, parsers: &ParserContext) -> Result<Vec<Op>, CrsnError> { pub fn parse(source: &str, pos: &SourcePosition, parsers: &ParserContext) -> Result<Vec<Op>, CrsnError> {
let (items, _pos) = expect_list(sexp::parse(source)?, true)?; let (items, _pos) = expect_list(sexp::parse(source)?, true)?;
/* numbered labels start with a weird high number /* numbered labels start with a weird high number

@ -9,12 +9,12 @@ use crate::asm::patches::TryRemove;
pub fn parse_cond_branch(tok: Sexp, parsers: &ParserContext) -> Result<(Cond, Box<dyn Flatten>), CrsnError> { pub fn parse_cond_branch(tok: Sexp, parsers: &ParserContext) -> Result<(Cond, Box<dyn Flatten>), CrsnError> {
let (mut list, pos) = expect_list(tok, false)?; let (mut list, pos) = expect_list(tok, false)?;
let (kw, kw_pos) = expect_string_atom(list.remove_or_err(0, pos.clone(), "Missing \"cond?\" keyword in conditional branch")?)?; let (kw, kw_pos) = expect_string_atom(list.remove_or_err(0, &pos, "Missing \"cond?\" keyword in conditional branch")?)?;
if !kw.ends_with('?') { if !kw.ends_with('?') {
return Err(CrsnError::Parse(format!("Condition must end with '?': {}", kw).into(), kw_pos)); return Err(CrsnError::Parse(format!("Condition must end with '?': {}", kw).into(), kw_pos));
} }
Ok((cond::parse_cond(&kw, kw_pos)?, parse_instructions(list.into_iter(), pos, parsers)?)) Ok((cond::parse_cond(&kw, &kw_pos)?, parse_instructions(list.into_iter(), &pos, parsers)?))
} }

@ -8,7 +8,6 @@ use crate::asm::data::literal::{ConstantName, Label, RegisterAlias, Value};
use crate::asm::error::CrsnError; use crate::asm::error::CrsnError;
use crate::asm::parse::ParserContext; use crate::asm::parse::ParserContext;
use crate::asm::parse::sexp_expect::expect_string_atom; use crate::asm::parse::sexp_expect::expect_string_atom;
use std::num::TryFromIntError;
use crate::asm::patches::ErrWithPos; use crate::asm::patches::ErrWithPos;
fn is_valid_identifier(name: &str) -> bool { fn is_valid_identifier(name: &str) -> bool {
@ -46,14 +45,14 @@ pub fn parse_constant_name(name: Sexp) -> Result<(ConstantName, SourcePosition),
pub fn parse_label(name: Sexp) -> Result<Label, CrsnError> { pub fn parse_label(name: Sexp) -> Result<Label, CrsnError> {
// trace!("parse label: {:?}", name); // trace!("parse label: {:?}", name);
let (name, namepos) = expect_string_atom(name)?; let (name, namepos) = expect_string_atom(name)?;
Ok(parse_label_str(&name, namepos)?) Ok(parse_label_str(&name, &namepos)?)
} }
pub fn parse_label_str(name: &str, pos: SourcePosition) -> Result<Label, CrsnError> { pub fn parse_label_str(name: &str, pos: &SourcePosition) -> Result<Label, CrsnError> {
let label = name.trim_start_matches(':'); let label = name.trim_start_matches(':');
Ok(if label.starts_with('#') { Ok(if label.starts_with('#') {
let val = parse_u64(&label[1..], pos.clone())?; let val = parse_u64(&label[1..], pos)?;
Label::Numbered(u32::try_from(val).err_pos(pos)?) Label::Numbered(u32::try_from(val).err_pos(pos)?)
} else { } else {
Label::Named(label.to_string()) Label::Named(label.to_string())
@ -67,7 +66,7 @@ pub fn parse_data_disp(tok: Sexp, pcx: &ParserContext) -> Result<DataDisp, CrsnE
// TODO implement masks // TODO implement masks
match tok { match tok {
Sexp::Atom(Atom::I(val), pos) => { Sexp::Atom(Atom::I(val), _pos) => {
Ok(DataDisp::Immediate(unsafe { std::mem::transmute(val) })) Ok(DataDisp::Immediate(unsafe { std::mem::transmute(val) }))
} }
Sexp::Atom(Atom::S(s), pos) => { Sexp::Atom(Atom::S(s), pos) => {
@ -92,7 +91,7 @@ pub fn parse_data_disp(tok: Sexp, pcx: &ParserContext) -> Result<DataDisp, CrsnE
if let Some(val) = pstate.reg_aliases.get(reference) { if let Some(val) = pstate.reg_aliases.get(reference) {
Ok(DataDisp::ObjectPtr(*val)) Ok(DataDisp::ObjectPtr(*val))
} else { } else {
let reg = reg::parse_reg(reference, pos.clone())?; let reg = reg::parse_reg(reference, &pos)?;
if pstate.reg_aliases.values().find(|v| **v == reg).is_some() { if pstate.reg_aliases.values().find(|v| **v == reg).is_some() {
Err(CrsnError::Parse(format!("Sym exists for register {}, direct access denied. Unsym it if needed.", reg).into(), pos)) Err(CrsnError::Parse(format!("Sym exists for register {}, direct access denied. Unsym it if needed.", reg).into(), pos))
@ -101,9 +100,9 @@ pub fn parse_data_disp(tok: Sexp, pcx: &ParserContext) -> Result<DataDisp, CrsnE
} }
} }
} else if s.starts_with(|c: char| c.is_ascii_digit()) { } else if s.starts_with(|c: char| c.is_ascii_digit()) {
Ok(DataDisp::Immediate(unsafe { std::mem::transmute(parse_i64(&s, pos)?) })) Ok(DataDisp::Immediate(unsafe { std::mem::transmute(parse_i64(&s, &pos)?) }))
} else { } else {
let reg = reg::parse_reg(&s, pos.clone())?; let reg = reg::parse_reg(&s, &pos)?;
let pstate = pcx.state.borrow(); let pstate = pcx.state.borrow();
if pstate.reg_aliases.values().find(|v| **v == reg).is_some() { if pstate.reg_aliases.values().find(|v| **v == reg).is_some() {
@ -122,7 +121,7 @@ pub fn parse_data_disp(tok: Sexp, pcx: &ParserContext) -> Result<DataDisp, CrsnE
/// Parse immediate value /// Parse immediate value
pub fn parse_value(tok: Sexp, pcx: &ParserContext) -> Result<Value, CrsnError> { pub fn parse_value(tok: Sexp, pcx: &ParserContext) -> Result<Value, CrsnError> {
match tok { match tok {
Sexp::Atom(Atom::I(val), pos) => { Sexp::Atom(Atom::I(val), _pos) => {
Ok(unsafe { std::mem::transmute(val) }) Ok(unsafe { std::mem::transmute(val) })
} }
Sexp::Atom(Atom::S(s), pos) => { Sexp::Atom(Atom::S(s), pos) => {
@ -131,7 +130,7 @@ pub fn parse_value(tok: Sexp, pcx: &ParserContext) -> Result<Value, CrsnError> {
return Ok(*val); return Ok(*val);
} }
Ok(unsafe { std::mem::transmute(parse_i64(&s, pos)?) }) Ok(unsafe { std::mem::transmute(parse_i64(&s, &pos)?) })
} }
other => { other => {
Err(CrsnError::Parse(format!("bad value format: {:?}", other).into(), other.pos().clone())) Err(CrsnError::Parse(format!("bad value format: {:?}", other).into(), other.pos().clone()))
@ -140,7 +139,7 @@ pub fn parse_value(tok: Sexp, pcx: &ParserContext) -> Result<Value, CrsnError> {
} }
pub fn parse_u64(literal: &str, pos: SourcePosition) -> Result<u64, CrsnError> { pub fn parse_u64(literal: &str, pos: &SourcePosition) -> Result<u64, CrsnError> {
// trace!("parse u64 from {}", literal); // trace!("parse u64 from {}", literal);
let mut without_underscores = Cow::Borrowed(literal); let mut without_underscores = Cow::Borrowed(literal);
if without_underscores.contains('_') { if without_underscores.contains('_') {
@ -156,21 +155,21 @@ pub fn parse_u64(literal: &str, pos: SourcePosition) -> Result<u64, CrsnError> {
} }
} }
pub fn parse_i64(literal: &str, pos: SourcePosition) -> Result<i64, CrsnError> { pub fn parse_i64(literal: &str, pos: &SourcePosition) -> Result<i64, CrsnError> {
// trace!("parse i64 from {}", literal); // trace!("parse i64 from {}", literal);
if let Some(_value) = literal.strip_prefix("-") { if let Some(_value) = literal.strip_prefix("-") {
Ok(-1 * i64::try_from(parse_u64(literal, pos.clone())?).err_pos(pos)?) Ok(-1 * i64::try_from(parse_u64(literal, pos)?).err_pos(pos)?)
} else { } else {
Ok(i64::try_from(parse_u64(literal, pos.clone())?).err_pos(pos)?) Ok(i64::try_from(parse_u64(literal, pos)?).err_pos(pos)?)
} }
} }
pub fn parse_rd(tok: Sexp, pcx: &ParserContext) -> Result<Rd, CrsnError> { pub fn parse_rd(tok: Sexp, pcx: &ParserContext) -> Result<Rd, CrsnError> {
let pos = tok.pos().clone(); let pos = tok.pos().clone();
Ok(Rd::new(RdData::try_from(parse_data_disp(tok, pcx)?).err_pos(pos)?)) Ok(Rd::new(RdData::try_from(parse_data_disp(tok, pcx)?).err_pos(&pos)?))
} }
pub fn parse_wr(tok: Sexp, pcx: &ParserContext) -> Result<Wr, CrsnError> { pub fn parse_wr(tok: Sexp, pcx: &ParserContext) -> Result<Wr, CrsnError> {
let pos = tok.pos().clone(); let pos = tok.pos().clone();
Ok(Wr::new(WrData::try_from(parse_data_disp(tok, pcx)?).err_pos(pos)?)) Ok(Wr::new(WrData::try_from(parse_data_disp(tok, pcx)?).err_pos(&pos)?))
} }

@ -7,12 +7,12 @@ use crate::asm::parse::parse_cond::parse_cond_branch;
use crate::asm::parse::parse_routine::parse_routine; use crate::asm::parse::parse_routine::parse_routine;
use crate::asm::parse::ParserContext; use crate::asm::parse::ParserContext;
use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom}; use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom};
use crate::asm::patches::NextOrErr;
use crate::module::ParseRes; use crate::module::ParseRes;
use super::parse_op::parse_op; use super::parse_op::parse_op;
use crate::asm::patches::NextOrErr;
pub fn parse_instructions(items: impl Iterator<Item=Sexp>, pos: SourcePosition, pcx: &ParserContext) -> Result<Box<dyn Flatten>, CrsnError> { pub fn parse_instructions(items: impl Iterator<Item=Sexp>, pos: &SourcePosition, pcx: &ParserContext) -> Result<Box<dyn Flatten>, CrsnError> {
let mut parsed = vec![]; let mut parsed = vec![];
for expr in items { for expr in items {
let (tokens, listpos) = expect_list(expr, false)?; let (tokens, listpos) = expect_list(expr, false)?;
@ -21,13 +21,13 @@ pub fn parse_instructions(items: impl Iterator<Item=Sexp>, pos: SourcePosition,
let (name, namepos) = expect_string_atom(toki.next_or_err(listpos.clone(), "Expected instruction name token")?)?; let (name, namepos) = expect_string_atom(toki.next_or_err(listpos.clone(), "Expected instruction name token")?)?;
if name == "proc" { if name == "proc" {
parsed.push(parse_routine(toki, pos.clone(), pcx)?); parsed.push(parse_routine(toki, pos, pcx)?);
continue; continue;
} }
let mut token_parser = TokenParser::new(toki.collect(), listpos.clone(), 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.clone(), &name, token_parser) { token_parser = match p.parse_syntax(pos, &name, token_parser) {
Ok(ParseRes::Parsed(op)) => return Ok(op), Ok(ParseRes::Parsed(op)) => return Ok(op),
Ok(ParseRes::ParsedNone) => return Ok(Box::new(())), Ok(ParseRes::ParsedNone) => return Ok(Box::new(())),
Ok(ParseRes::Unknown(to_reuse)) => { Ok(ParseRes::Unknown(to_reuse)) => {
@ -45,7 +45,7 @@ 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 toki = token_parser.into_iter();
let arg_tokens = TokenParser::new(toki.clone().take_while(|e| e.is_atom()).collect(), listpos.clone(), pcx); let arg_tokens = TokenParser::new(toki.clone().take_while(|e| e.is_atom()).collect(), &listpos, pcx);
let branch_tokens = toki let branch_tokens = toki
.skip_while(|e| e.is_atom()) .skip_while(|e| e.is_atom())
.take_while(|e| e.is_list()); .take_while(|e| e.is_list());
@ -62,7 +62,7 @@ pub fn parse_instructions(items: impl Iterator<Item=Sexp>, pos: SourcePosition,
} }
}; };
if let Some(op) = parse_op(name.as_str(), arg_tokens, namepos.clone())? { if let Some(op) = parse_op(name.as_str(), arg_tokens, &namepos)? {
parsed.push(Box::new(InstrWithBranches { parsed.push(Box::new(InstrWithBranches {
op, op,
pos: namepos, pos: namepos,

@ -1,32 +1,33 @@
use sexp::SourcePosition;
use crate::asm::error::CrsnError; use crate::asm::error::CrsnError;
use crate::asm::instr::cond::parse_cond; use crate::asm::instr::cond::parse_cond;
use crate::asm::instr::Op; use crate::asm::instr::Op;
use crate::asm::parse::arg_parser::TokenParser; use crate::asm::parse::arg_parser::TokenParser;
use crate::module::ParseRes;
use crate::builtin::BuiltinOps; use crate::builtin::BuiltinOps;
use sexp::SourcePosition; use crate::module::ParseRes;
pub fn parse_op<'a>(mut keyword: &str, mut arg_tokens: TokenParser<'a>, spos: SourcePosition) -> Result<Option<Op>, CrsnError> { pub fn parse_op<'a>(mut keyword: &str, mut arg_tokens: TokenParser<'a>, spos: &SourcePosition) -> Result<Option<Op>, CrsnError> {
// Include built-in instructions // Include built-in instructions
let builtins = [BuiltinOps::new()]; let builtins = [BuiltinOps::new()];
let mut cond = None; let mut cond = None;
if let Some(pos) = keyword.find('.') { if let Some(pos) = keyword.find('.') {
cond = Some(parse_cond(&keyword[(pos + 1)..], spos.clone())?); cond = Some(parse_cond(&keyword[(pos + 1)..], spos)?);
keyword = &keyword[..pos]; keyword = &keyword[..pos];
} }
for p in builtins.iter().chain(arg_tokens.pcx.parsers) { for p in builtins.iter().chain(arg_tokens.pcx.parsers) {
arg_tokens = match p.parse_op(spos.clone(), keyword, arg_tokens) { arg_tokens = match p.parse_op(spos, keyword, arg_tokens) {
Ok(ParseRes::Parsed(kind)) => return Ok(Some(Op { Ok(ParseRes::Parsed(kind)) => return Ok(Some(Op {
cond, cond,
pos: spos, pos: spos.clone(),
kind, kind,
})), })),
Ok(ParseRes::ParsedNone) => return Ok(None), Ok(ParseRes::ParsedNone) => return Ok(None),
Ok(ParseRes::Unknown(to_reuse)) => { Ok(ParseRes::Unknown(to_reuse)) => {
if to_reuse.parsing_started() { if to_reuse.parsing_started() {
return Err(CrsnError::Parse(format!("Module \"{}\" started parsing {}, but returned Unknown!", p.name(), keyword).into(), spos)); return Err(CrsnError::Parse(format!("Module \"{}\" started parsing {}, but returned Unknown!", p.name(), keyword).into(), spos.clone()));
} }
to_reuse to_reuse
} }
@ -36,5 +37,5 @@ pub fn parse_op<'a>(mut keyword: &str, mut arg_tokens: TokenParser<'a>, spos: So
} }
} }
return Err(CrsnError::Parse(format!("Unknown instruction: {}", keyword).into(), spos)); return Err(CrsnError::Parse(format!("Unknown instruction: {}", keyword).into(), spos.clone()));
} }

@ -7,14 +7,14 @@ use crate::asm::parse::{parse_instructions, ParserContext};
use crate::asm::parse::arg_parser::TokenParser; use crate::asm::parse::arg_parser::TokenParser;
use crate::asm::parse::parse_data::parse_reg_alias; use crate::asm::parse::parse_data::parse_reg_alias;
use crate::asm::parse::sexp_expect::expect_string_atom; use crate::asm::parse::sexp_expect::expect_string_atom;
use crate::builtin::parse::parse_routine_name;
use crate::asm::patches::NextOrErr; use crate::asm::patches::NextOrErr;
use crate::builtin::parse::parse_routine_name;
pub fn parse_routine(mut toki: impl Iterator<Item=Sexp> + Clone, rt_pos: SourcePosition, pcx: &ParserContext) -> Result<Box<dyn Flatten>, CrsnError> { pub fn parse_routine(mut toki: impl Iterator<Item=Sexp> + Clone, rt_pos: &SourcePosition, pcx: &ParserContext) -> Result<Box<dyn Flatten>, CrsnError> {
let (name, namepos) = expect_string_atom(toki.next_or_err(rt_pos.clone(), "Expected routine name")?)?; let (name, namepos) = expect_string_atom(toki.next_or_err(rt_pos.clone(), "Expected routine name")?)?;
let mut name = parse_routine_name(name, namepos)?; let mut name = parse_routine_name(name, &namepos)?;
let arg_tokens = TokenParser::new(toki.clone().take_while(|e| e.is_atom()).collect(), rt_pos.clone(), pcx); let arg_tokens = TokenParser::new(toki.clone().take_while(|e| e.is_atom()).collect(), rt_pos, pcx);
// If arity is explicitly given, then either no named argument must be provided, // If arity is explicitly given, then either no named argument must be provided,
// or their count must match the arity. If no arity is given, then arity is determined // or their count must match the arity. If no arity is given, then arity is determined
@ -22,7 +22,7 @@ pub fn parse_routine(mut toki: impl Iterator<Item=Sexp> + Clone, rt_pos: SourceP
if name.arity == 0 && arg_tokens.len() != 0 { if name.arity == 0 && arg_tokens.len() != 0 {
name.arity = arg_tokens.len() as u8; name.arity = arg_tokens.len() as u8;
} else if arg_tokens.len() != 0 && name.arity as usize != arg_tokens.len() { } else if arg_tokens.len() != 0 && name.arity as usize != arg_tokens.len() {
return Err(CrsnError::Parse(format!("arity mismatch in routine {}", name.name).into(), rt_pos)); return Err(CrsnError::Parse(format!("arity mismatch in routine {}", name.name).into(), rt_pos.clone()));
} }
let toki = toki.skip_while(|e| e.is_atom()); let toki = toki.skip_while(|e| e.is_atom());
@ -44,7 +44,7 @@ pub fn parse_routine(mut toki: impl Iterator<Item=Sexp> + Clone, rt_pos: SourceP
} }
} }
let body = parse_instructions(toki, rt_pos.clone(), pcx)?; let body = parse_instructions(toki, rt_pos, pcx)?;
{ {
let mut pstate = pcx.state.borrow_mut(); let mut pstate = pcx.state.borrow_mut();
@ -54,7 +54,7 @@ pub fn parse_routine(mut toki: impl Iterator<Item=Sexp> + Clone, rt_pos: SourceP
return Ok(Box::new(Routine { return Ok(Box::new(Routine {
name, name,
pos: rt_pos, pos: rt_pos.clone(),
body, body,
})); }));
} }

@ -1,12 +1,12 @@
use sexp::SourcePosition; use sexp::SourcePosition;
use crate::asm::error::CrsnError; use crate::asm::error::CrsnError;
use std::borrow::Cow;
pub trait TryRemove { pub trait TryRemove {
type Item; type Item;
fn try_remove(&mut self, index: usize) -> Option<Self::Item>; fn try_remove(&mut self, index: usize) -> Option<Self::Item>;
fn remove_or_err(&mut self, index: usize, pos: SourcePosition, err : &'static str) -> Result<Self::Item, CrsnError>; fn remove_or_err(&mut self, index: usize, pos: &SourcePosition, err: &'static str) -> Result<Self::Item, CrsnError>;
} }
impl<T> TryRemove for Vec<T> { impl<T> TryRemove for Vec<T> {
@ -20,10 +20,10 @@ impl<T> TryRemove for Vec<T> {
} }
} }
fn remove_or_err(&mut self, index: usize, pos: SourcePosition, err : &'static str) -> Result<Self::Item, CrsnError> { fn remove_or_err(&mut self, index: usize, pos: &SourcePosition, err: &'static str) -> Result<Self::Item, CrsnError> {
match self.try_remove(index) { match self.try_remove(index) {
None => { None => {
Err(CrsnError::Parse(err.into(), pos)) Err(CrsnError::Parse(err.into(), pos.clone()))
} }
Some(removed) => Ok(removed) Some(removed) => Ok(removed)
} }
@ -31,10 +31,10 @@ impl<T> TryRemove for Vec<T> {
} }
pub trait NextOrErr<T> { pub trait NextOrErr<T> {
fn next_or_err(&mut self, pos: SourcePosition, err : &'static str) -> Result<T, CrsnError>; fn next_or_err(&mut self, pos: SourcePosition, err: &'static str) -> Result<T, CrsnError>;
} }
impl<T, K : Iterator<Item=T>> NextOrErr<T> for K { impl<T, K: Iterator<Item=T>> NextOrErr<T> for K {
fn next_or_err(&mut self, pos: SourcePosition, err: &'static str) -> Result<T, CrsnError> { fn next_or_err(&mut self, pos: SourcePosition, err: &'static str) -> Result<T, CrsnError> {
match self.next() { match self.next() {
None => { None => {
@ -46,14 +46,14 @@ impl<T, K : Iterator<Item=T>> NextOrErr<T> for K {
} }
pub trait ErrWithPos<T> { pub trait ErrWithPos<T> {
fn err_pos(self, pos : SourcePosition) -> Result<T, CrsnError>; fn err_pos(self, pos: &SourcePosition) -> Result<T, CrsnError>;
} }
impl<T, E : std::error::Error + Send + Sync + 'static> ErrWithPos<T> for Result<T, E> { impl<T, E: std::error::Error + Send + Sync + 'static> ErrWithPos<T> for Result<T, E> {
fn err_pos(self, pos : SourcePosition) -> Result<T, CrsnError> { fn err_pos(self, pos: &SourcePosition) -> Result<T, CrsnError> {
match self { match self {
Ok(v) => Ok(v), Ok(v) => Ok(v),
Err(e) => Err(CrsnError::ParseOther(Box::new(e), pos)) Err(e) => Err(CrsnError::ParseOther(Box::new(e), pos.clone()))
} }
} }
} }

@ -1,8 +1,9 @@
use sexp::SourcePosition;
use crate::asm::data::{Rd, RdObj, Wr}; use crate::asm::data::{Rd, RdObj, Wr};
use crate::asm::data::literal::{DebugMsg, Label, RoutineName}; use crate::asm::data::literal::{DebugMsg, Label, RoutineName};
use crate::asm::instr::Op; use crate::asm::instr::Op;
use crate::asm::instr::op::OpKind; use crate::asm::instr::op::OpKind;
use sexp::SourcePosition;
#[derive(Debug)] #[derive(Debug)]
pub enum Barrier { pub enum Barrier {

@ -1,5 +1,7 @@
use std::time::Duration; use std::time::Duration;
use sexp::Sexp;
use crate::asm::data::{Rd, RdData}; use crate::asm::data::{Rd, RdData};
use crate::asm::data::literal::Addr; use crate::asm::data::literal::Addr;
use crate::asm::instr::Cond; use crate::asm::instr::Cond;
@ -8,11 +10,6 @@ use crate::module::{EvalRes, OpTrait};
use crate::runtime::fault::Fault; use crate::runtime::fault::Fault;
use crate::runtime::frame::StackFrame; use crate::runtime::frame::StackFrame;
use crate::runtime::run_thread::{state::RunState, ThreadInfo}; use crate::runtime::run_thread::{state::RunState, ThreadInfo};
use sexp::Sexp;
impl OpTrait for BuiltinOp { impl OpTrait for BuiltinOp {
fn execute(&self, info: &ThreadInfo, state: &mut RunState) -> Result<EvalRes, Fault> { fn execute(&self, info: &ThreadInfo, state: &mut RunState) -> Result<EvalRes, Fault> {

@ -1,9 +1,10 @@
use crate::module::{CrsnExtension, ParseRes};
use crate::asm::parse::arg_parser::TokenParser;
use crate::asm::instr::op::OpKind;
use crate::asm::error::CrsnError;
use sexp::SourcePosition; use sexp::SourcePosition;
use crate::asm::error::CrsnError;
use crate::asm::instr::op::OpKind;
use crate::asm::parse::arg_parser::TokenParser;
use crate::module::{CrsnExtension, ParseRes};
pub mod defs; pub mod defs;
pub mod exec; pub mod exec;
pub mod parse; pub mod parse;
@ -22,7 +23,7 @@ impl CrsnExtension for BuiltinOps {
"builtin" "builtin"
} }
fn parse_op<'a>(&self, pos: SourcePosition, keyword: &str, args: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError> { fn parse_op<'a>(&self, pos: &SourcePosition, keyword: &str, args: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError> {
parse::parse_op(pos, keyword, args) parse::parse_op(pos, keyword, args)
} }
} }

@ -5,15 +5,14 @@ use crate::asm::data::reg::parse_reg;
use crate::asm::error::CrsnError; use crate::asm::error::CrsnError;
use crate::asm::instr::op::OpKind; use crate::asm::instr::op::OpKind;
use crate::asm::parse::arg_parser::TokenParser; use crate::asm::parse::arg_parser::TokenParser;
use crate::asm::parse::parse_data::{parse_constant_name, parse_label, parse_rd, parse_reg_alias, parse_value, parse_label_str}; 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_string_atom; use crate::asm::parse::sexp_expect::expect_string_atom;
use crate::asm::patches::ErrWithPos;
use crate::builtin::defs::{Barrier, BuiltinOp}; use crate::builtin::defs::{Barrier, BuiltinOp};
use crate::module::{ParseRes}; use crate::module::ParseRes;
use crate::utils::A; use crate::utils::A;
use crate::asm::patches::ErrWithPos;
pub(crate) fn parse_op<'a>(op_pos: &SourcePosition, keyword: &str, mut args: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError> {
pub(crate) fn parse_op<'a>(op_pos: SourcePosition, keyword: &str, mut args: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError> {
let pcx = args.pcx; let pcx = args.pcx;
Ok(ParseRes::Parsed(OpKind::BuiltIn(match keyword { Ok(ParseRes::Parsed(OpKind::BuiltIn(match keyword {
@ -35,7 +34,7 @@ pub(crate) fn parse_op<'a>(op_pos: SourcePosition, keyword: &str, mut args: Toke
let (alias, aliaspos) = parse_reg_alias(args.next_or_err()?)?; let (alias, aliaspos) = parse_reg_alias(args.next_or_err()?)?;
trace!("alias={:?}", alias); trace!("alias={:?}", alias);
let (rn, rpos) = args.next_string()?; let (rn, rpos) = args.next_string()?;
let register = parse_reg(&rn, rpos.clone())?; let register = parse_reg(&rn, &rpos)?;
trace!("register={:?}", alias); trace!("register={:?}", alias);
let mut pstate = pcx.state.borrow_mut(); let mut pstate = pcx.state.borrow_mut();
@ -124,7 +123,7 @@ pub(crate) fn parse_op<'a>(op_pos: SourcePosition, keyword: &str, mut args: Toke
"routine" => { "routine" => {
let name = args.next_string()?; let name = args.next_string()?;
BuiltinOp::Routine(parse_routine_name(name.0, name.1)?) BuiltinOp::Routine(parse_routine_name(name.0, &name.1)?)
} }
"skip" => { "skip" => {
@ -200,7 +199,7 @@ pub(crate) fn parse_op<'a>(op_pos: SourcePosition, keyword: &str, mut args: Toke
other => { other => {
if let Some(label) = other.strip_prefix(':') { if let Some(label) = other.strip_prefix(':') {
BuiltinOp::Label(parse_label_str(label, op_pos)?) BuiltinOp::Label(parse_label_str(label, &op_pos)?)
} else { } else {
return Ok(ParseRes::Unknown(args)); return Ok(ParseRes::Unknown(args));
} }
@ -208,7 +207,7 @@ pub(crate) fn parse_op<'a>(op_pos: SourcePosition, keyword: &str, mut args: Toke
}))) })))
} }
pub(crate) fn parse_routine_name(name: String, pos: SourcePosition) -> Result<RoutineName, CrsnError> { pub(crate) fn parse_routine_name(name: String, pos: &SourcePosition) -> Result<RoutineName, CrsnError> {
let (name, arity) = if let Some(n) = name.find('/') { let (name, arity) = if let Some(n) = name.find('/') {
( (
(&name[0..n]).to_string(), (&name[0..n]).to_string(),
@ -238,7 +237,7 @@ pub(crate) fn to_sexp(op: &BuiltinOp) -> Sexp {
inner.extend(args.iter().map(A)); inner.extend(args.iter().map(A));
sexp::list(&inner) sexp::list(&inner)
} }
}, }
BuiltinOp::Ret(values) => { BuiltinOp::Ret(values) => {
if values.is_empty() { if values.is_empty() {
sexp::list(&[A("ret")]) sexp::list(&[A("ret")])
@ -287,16 +286,15 @@ pub(crate) fn to_sexp(op: &BuiltinOp) -> Sexp {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use std::sync::atomic::AtomicU32; use std::sync::atomic::AtomicU32;
use crate::asm::instr::{Flatten}; use sexp::SourcePosition;
use crate::asm::instr::Flatten;
use crate::asm::parse::{parse_instructions, ParserContext}; use crate::asm::parse::{parse_instructions, ParserContext};
use crate::asm::parse::sexp_expect::expect_list; use crate::asm::parse::sexp_expect::expect_list;
use crate::module::OpTrait;
use crate::builtin::BuiltinOps; use crate::builtin::BuiltinOps;
use crate::module::OpTrait;
#[test] #[test]
fn roundtrip() { fn roundtrip() {
@ -306,10 +304,10 @@ mod test {
("(nop)", "(nop)"), ("(nop)", "(nop)"),
("(halt)", "(halt)"), ("(halt)", "(halt)"),
("(sleep 1000)", "(sleep 1000)"), ("(sleep 1000)", "(sleep 1000)"),
("(:x)\ ("(:x)", "(:x)"),
(j :x)", "(skip 0)"), ("(j :x)", "(j :x)"),
("(:#7)\ ("(:#7)", "(:#7)"),
(j :#7)", "(skip 0)"), ("(j :#7)", "(j :#7)"),
("(fj :x)", "(fj :x)"), ("(fj :x)", "(fj :x)"),
("(skip 0)", "(skip 0)"), ("(skip 0)", "(skip 0)"),
("(skip r0)", "(skip r0)"), ("(skip r0)", "(skip r0)"),
@ -367,9 +365,9 @@ mod test {
/* first cycle */ /* first cycle */
let s = sexp::parse(&format!("({})", sample)) let s = sexp::parse(&format!("({})", sample))
.expect("parse sexp"); .expect("parse sexp");
let list = expect_list(Some(s), false).unwrap(); let list = expect_list(s, false).unwrap();
let num = AtomicU32::new(0); let num = AtomicU32::new(0);
let parsed = parse_instructions(list.into_iter(), &pcx) let parsed = parse_instructions(list.0.into_iter(), &SourcePosition::default(), &pcx)
.expect("parse instr").flatten(&num) .expect("parse instr").flatten(&num)
.expect("flatten").remove(0); .expect("flatten").remove(0);
@ -379,13 +377,17 @@ mod test {
assert_eq!(expected, exported); assert_eq!(expected, exported);
println!(" - 2nd cycle"); println!(" - 2nd cycle");
let pcx = ParserContext {
parsers,
state: Default::default(),
};
/* second cycle, nothing should change */ /* second cycle, nothing should change */
let s = sexp::parse(&format!("({})", exported)) let s = sexp::parse(&format!("({})", exported))
.expect("parse sexp (2c)"); .expect("parse sexp (2c)");
let list = expect_list(Some(s), false).unwrap(); let list = expect_list(s, false).unwrap();
let num = AtomicU32::new(0); let num = AtomicU32::new(0);
let parsed = parse_instructions(list.into_iter(), &pcx) let parsed = parse_instructions(list.0.into_iter(), &SourcePosition::default(), &pcx)
.expect("parse instr (2c)").flatten(&num) .expect("parse instr (2c)").flatten(&num)
.expect("flatten (2c)").remove(0); .expect("flatten (2c)").remove(0);

@ -1,8 +1,9 @@
#![allow(unused_variables)] #![allow(unused_variables)]
use std::fmt::{Debug}; use std::fmt::Debug;
pub use eval_res::EvalRes; pub use eval_res::EvalRes;
use sexp::{Sexp, SourcePosition};
use crate::asm::data::literal::Value; use crate::asm::data::literal::Value;
use crate::asm::data::Mask; use crate::asm::data::Mask;
@ -13,8 +14,6 @@ use crate::asm::parse::arg_parser::TokenParser;
use crate::runtime::fault::Fault; use crate::runtime::fault::Fault;
use crate::runtime::run_thread::state::RunState; use crate::runtime::run_thread::state::RunState;
use crate::runtime::run_thread::ThreadInfo; use crate::runtime::run_thread::ThreadInfo;
use sexp::{Sexp, SourcePosition};
mod eval_res; mod eval_res;
@ -53,12 +52,12 @@ pub trait CrsnExtension: Debug + Send + Sync + 'static {
/// If the instruction keyword is not recognized, return Unknown with the unchanged argument list. /// If the instruction keyword is not recognized, return Unknown with the unchanged argument list.
/// ///
/// 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)
/// ///
/// 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>)
-> Result<ParseRes<'a, Box<dyn Flatten>>, CrsnError> -> Result<ParseRes<'a, Box<dyn Flatten>>, CrsnError>
{ {
Ok(ParseRes::Unknown(tokens)) Ok(ParseRes::Unknown(tokens))

@ -1,14 +1,15 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
use sexp::SourcePosition;
use crate::asm::data::literal::{Addr, Label, RoutineName}; use crate::asm::data::literal::{Addr, Label, RoutineName};
use crate::asm::error::CrsnError;
use crate::asm::instr::Op; use crate::asm::instr::Op;
use crate::asm::instr::op::OpKind; use crate::asm::instr::op::OpKind;
use crate::builtin::defs::{Barrier, BuiltinOp}; use crate::builtin::defs::{Barrier, BuiltinOp};
use crate::module::CrsnExtension; use crate::module::CrsnExtension;
use crate::runtime::fault::Fault; use crate::runtime::fault::Fault;
use sexp::SourcePosition;
use crate::asm::error::CrsnError;
#[derive(Debug)] #[derive(Debug)]
pub struct Program { pub struct Program {
@ -96,9 +97,9 @@ impl Program {
pos: SourcePosition { pos: SourcePosition {
line: 0, line: 0,
column: 0, column: 0,
index: 0 index: 0,
}, },
cond: None cond: None,
} }
} else { } else {
&self.ops[addr.0 as usize] &self.ops[addr.0 as usize]

@ -1,8 +1,9 @@
pub use option_ext::UncheckedOptionExt;
use std::fmt::Display; use std::fmt::Display;
use sexp::{Sexp, Atom};
use std::str::FromStr; use std::str::FromStr;
pub use option_ext::UncheckedOptionExt;
use sexp::{Atom, Sexp};
mod option_ext; mod option_ext;
/// Convert a string token to Sexp /// Convert a string token to Sexp

@ -2,16 +2,16 @@ use std::ops::Rem;
use num_traits::PrimInt; use num_traits::PrimInt;
use crsn::asm::data::{Rd, Wr};
use crsn::asm::instr::Cond; use crsn::asm::instr::Cond;
use crsn::module::{EvalRes, OpTrait}; use crsn::module::{EvalRes, OpTrait};
use crsn::runtime::fault::Fault; use crsn::runtime::fault::Fault;
use crsn::runtime::run_thread::{state::RunState, ThreadInfo}; use crsn::runtime::run_thread::{state::RunState, ThreadInfo};
use crate::defs::ArithOp;
use crsn::sexp::Sexp;
use crsn::sexp; use crsn::sexp;
use crsn::sexp::Sexp;
use crsn::utils::A; use crsn::utils::A;
use crsn::asm::data::{Rd, Wr};
use crate::defs::ArithOp;
impl OpTrait for ArithOp { impl OpTrait for ArithOp {
fn execute(&self, _ti: &ThreadInfo, state: &mut RunState) -> Result<EvalRes, Fault> { fn execute(&self, _ti: &ThreadInfo, state: &mut RunState) -> Result<EvalRes, Fault> {
@ -238,7 +238,7 @@ impl OpTrait for ArithOp {
} }
} }
fn to_sexp_2_or_3(name: &str, dst : &Wr, a: &Rd, b: &Rd) -> Sexp { fn to_sexp_2_or_3(name: &str, dst: &Wr, a: &Rd, b: &Rd) -> Sexp {
if &dst.as_rd() == a { if &dst.as_rd() == a {
sexp::list(&[A(name), A(dst), A(b)]) sexp::list(&[A(name), A(dst), A(b)])
} else { } else {

@ -22,7 +22,7 @@ impl CrsnExtension for ArithOps {
"arith" "arith"
} }
fn parse_op<'a>(&self, pos: SourcePosition, keyword: &str, args: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError> { fn parse_op<'a>(&self, pos: &SourcePosition, keyword: &str, args: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError> {
parse::parse(pos, keyword, args) parse::parse(pos, keyword, args)
} }
} }

@ -3,11 +3,11 @@ use crsn::asm::error::CrsnError;
use crsn::asm::instr::op::OpKind; use crsn::asm::instr::op::OpKind;
use crsn::asm::parse::arg_parser::TokenParser; use crsn::asm::parse::arg_parser::TokenParser;
use crsn::module::ParseRes; use crsn::module::ParseRes;
use crsn::sexp::SourcePosition;
use crate::defs::ArithOp; use crate::defs::ArithOp;
use crsn::sexp::SourcePosition;
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> {
Ok(ParseRes::ext(match keyword { Ok(ParseRes::ext(match keyword {
"cmp" => { "cmp" => {
ArithOp::Compare { ArithOp::Compare {
@ -57,7 +57,7 @@ pub(crate) fn parse<'a>(pos: SourcePosition, keyword: &str, mut args: TokenParse
} }
} }
_ => { _ => {
return Err(CrsnError::Parse("Add requires 2 or 3 arguments".into(), pos)); return Err(CrsnError::Parse("Add requires 2 or 3 arguments".into(), pos.clone()));
} }
} }
} }
@ -80,7 +80,7 @@ pub(crate) fn parse<'a>(pos: SourcePosition, keyword: &str, mut args: TokenParse
} }
} }
_ => { _ => {
return Err(CrsnError::Parse("Sub requires 2 or 3 arguments".into(), pos)); return Err(CrsnError::Parse("Sub requires 2 or 3 arguments".into(), pos.clone()));
} }
} }
} }
@ -103,7 +103,7 @@ pub(crate) fn parse<'a>(pos: SourcePosition, keyword: &str, mut args: TokenParse
} }
} }
_ => { _ => {
return Err(CrsnError::Parse("Mul requires 2 or 3 arguments".into(), pos)); return Err(CrsnError::Parse("Mul requires 2 or 3 arguments".into(), pos.clone()));
} }
} }
} }
@ -130,7 +130,7 @@ pub(crate) fn parse<'a>(pos: SourcePosition, keyword: &str, mut args: TokenParse
} }
} }
_ => { _ => {
return Err(CrsnError::Parse("DivR requires 3 or 4 arguments".into(), pos)); return Err(CrsnError::Parse("DivR requires 3 or 4 arguments".into(), pos.clone()));
} }
} }
} }
@ -156,7 +156,7 @@ pub(crate) fn parse<'a>(pos: SourcePosition, keyword: &str, mut args: TokenParse
} }
} }
_ => { _ => {
return Err(CrsnError::Parse("Div requires 2 or 3 arguments".into(), pos)); return Err(CrsnError::Parse("Div requires 2 or 3 arguments".into(), pos.clone()));
} }
} }
} }
@ -180,7 +180,7 @@ pub(crate) fn parse<'a>(pos: SourcePosition, keyword: &str, mut args: TokenParse
} }
} }
_ => { _ => {
return Err(CrsnError::Parse("Mod requires 2 or 3 arguments".into(), pos)); return Err(CrsnError::Parse("Mod requires 2 or 3 arguments".into(), pos.clone()));
} }
} }
} }
@ -203,7 +203,7 @@ pub(crate) fn parse<'a>(pos: SourcePosition, keyword: &str, mut args: TokenParse
} }
} }
_ => { _ => {
return Err(CrsnError::Parse("And requires 2 or 3 arguments".into(), pos)); return Err(CrsnError::Parse("And requires 2 or 3 arguments".into(), pos.clone()));
} }
} }
} }
@ -226,7 +226,7 @@ pub(crate) fn parse<'a>(pos: SourcePosition, keyword: &str, mut args: TokenParse
} }
} }
_ => { _ => {
return Err(CrsnError::Parse("Or requires 2 or 3 arguments".into(), pos)); return Err(CrsnError::Parse("Or requires 2 or 3 arguments".into(), pos.clone()));
} }
} }
} }
@ -249,7 +249,7 @@ pub(crate) fn parse<'a>(pos: SourcePosition, keyword: &str, mut args: TokenParse
} }
} }
_ => { _ => {
return Err(CrsnError::Parse("Xor requires 2 or 3 arguments".into(), pos)); return Err(CrsnError::Parse("Xor requires 2 or 3 arguments".into(), pos.clone()));
} }
} }
} }
@ -270,7 +270,7 @@ pub(crate) fn parse<'a>(pos: SourcePosition, keyword: &str, mut args: TokenParse
} }
} }
_ => { _ => {
return Err(CrsnError::Parse("Cpl requires 1 or 2 arguments".into(), pos)); return Err(CrsnError::Parse("Cpl requires 1 or 2 arguments".into(), pos.clone()));
} }
} }
} }
@ -301,7 +301,7 @@ pub(crate) fn parse<'a>(pos: SourcePosition, keyword: &str, mut args: TokenParse
} }
} }
_ => { _ => {
return Err(CrsnError::Parse("Rol requires 1, 2 or 3 arguments".into(), pos)); return Err(CrsnError::Parse("Rol requires 1, 2 or 3 arguments".into(), pos.clone()));
} }
} }
} }
@ -332,7 +332,7 @@ pub(crate) fn parse<'a>(pos: SourcePosition, keyword: &str, mut args: TokenParse
} }
} }
_ => { _ => {
return Err(CrsnError::Parse("Ror requires 1, 2 or 3 arguments".into(), pos)); return Err(CrsnError::Parse("Ror requires 1, 2 or 3 arguments".into(), pos.clone()));
} }
} }
} }
@ -363,7 +363,7 @@ pub(crate) fn parse<'a>(pos: SourcePosition, keyword: &str, mut args: TokenParse
} }
} }
_ => { _ => {
return Err(CrsnError::Parse("Lsl requires 1, 2 or 3 arguments".into(), pos)); return Err(CrsnError::Parse("Lsl requires 1, 2 or 3 arguments".into(), pos.clone()));
} }
} }
} }
@ -394,7 +394,7 @@ pub(crate) fn parse<'a>(pos: SourcePosition, keyword: &str, mut args: TokenParse
} }
} }
_ => { _ => {
return Err(CrsnError::Parse("Lsr requires 1, 2 or 3 arguments".into(), pos)); return Err(CrsnError::Parse("Lsr requires 1, 2 or 3 arguments".into(), pos.clone()));
} }
} }
} }
@ -425,7 +425,7 @@ pub(crate) fn parse<'a>(pos: SourcePosition, keyword: &str, mut args: TokenParse
} }
} }
_ => { _ => {
return Err(CrsnError::Parse("Asr requires 1, 2 or 3 arguments".into(), pos)); return Err(CrsnError::Parse("Asr requires 1, 2 or 3 arguments".into(), pos.clone()));
} }
} }
} }

@ -1,19 +1,19 @@
use std::ops::Sub; use std::ops::Sub;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use minifb::{ScaleMode, Window, WindowOptions, MouseMode, Key, MouseButton}; use minifb::{Key, MouseButton, MouseMode, ScaleMode, Window, WindowOptions};
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};
use crsn::runtime::fault::Fault; use crsn::runtime::fault::Fault;
use crsn::runtime::run_thread::{state::RunState, ThreadInfo}; use crsn::runtime::run_thread::{state::RunState, ThreadInfo};
use crate::defs::ScreenOp;
use crsn::sexp::Sexp;
use crsn::sexp; use crsn::sexp;
use crsn::sexp::Sexp;
use crsn::utils::A; use crsn::utils::A;
use crate::defs::ScreenOp;
#[derive(Debug)] #[derive(Debug)]
struct Opts { struct Opts {
auto_blit: bool, auto_blit: bool,
@ -299,7 +299,7 @@ fn blit(backend: &mut Backend) {
backend.last_render = Instant::now(); backend.last_render = Instant::now();
} }
fn num2key(num : Value) -> Option<Key> { fn num2key(num: Value) -> Option<Key> {
let remap = [ let remap = [
Key::Key0, Key::Key0,
Key::Key1, Key::Key1,
@ -311,7 +311,6 @@ fn num2key(num : Value) -> Option<Key> {
Key::Key7, Key::Key7,
Key::Key8, Key::Key8,
Key::Key9, Key::Key9,
Key::A, // 10 Key::A, // 10
Key::B, Key::B,
Key::C, Key::C,
@ -361,7 +360,6 @@ fn num2key(num : Value) -> Option<Key> {
Key::Up, Key::Up,
Key::Apostrophe, Key::Apostrophe,
Key::Backquote, Key::Backquote,
Key::Backslash, // 57 Key::Backslash, // 57
Key::Comma, Key::Comma,
Key::Equal, Key::Equal,
@ -370,20 +368,17 @@ fn num2key(num : Value) -> Option<Key> {
Key::Period, Key::Period,
Key::RightBracket, Key::RightBracket,
Key::Semicolon, Key::Semicolon,
Key::Slash, // 65 Key::Slash, // 65
Key::Backspace, Key::Backspace,
Key::Delete, Key::Delete,
Key::End, Key::End,
Key::Enter, Key::Enter,
Key::Escape, // 70 Key::Escape, // 70
Key::Home, Key::Home,
Key::Insert, Key::Insert,
Key::Menu, Key::Menu,
Key::PageDown, Key::PageDown,
Key::PageUp, Key::PageUp,
Key::Pause, // 76 Key::Pause, // 76
Key::Space, Key::Space,
Key::Tab, Key::Tab,
@ -394,7 +389,6 @@ fn num2key(num : Value) -> Option<Key> {
Key::RightShift, Key::RightShift,
Key::LeftCtrl, Key::LeftCtrl,
Key::RightCtrl, Key::RightCtrl,
Key::NumPad0, // 86 Key::NumPad0, // 86
Key::NumPad1, Key::NumPad1,
Key::NumPad2, Key::NumPad2,

@ -25,7 +25,7 @@ impl CrsnExtension for ScreenOps {
"screen" "screen"
} }
fn parse_op<'a>(&self, pos: SourcePosition, keyword: &str, args: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError> { fn parse_op<'a>(&self, pos: &SourcePosition, keyword: &str, args: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError> {
parse::parse(pos, keyword, args) parse::parse(pos, keyword, args)
} }
} }

@ -1,13 +1,13 @@
use crsn::asm::data::{Rd}; use crsn::asm::data::Rd;
use crsn::asm::error::CrsnError; use crsn::asm::error::CrsnError;
use crsn::asm::instr::op::OpKind; use crsn::asm::instr::op::OpKind;
use crsn::asm::parse::arg_parser::TokenParser; use crsn::asm::parse::arg_parser::TokenParser;
use crsn::module::ParseRes; use crsn::module::ParseRes;
use crsn::sexp::SourcePosition;
use crate::defs::ScreenOp; use crate::defs::ScreenOp;
use crsn::sexp::SourcePosition;
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> {
Ok(ParseRes::ext(match keyword { Ok(ParseRes::ext(match keyword {
"sc-init" => { "sc-init" => {
ScreenOp::ScreenInit { ScreenOp::ScreenInit {
@ -65,14 +65,14 @@ pub(crate) fn parse<'a>(pos: SourcePosition, keyword: &str, mut args: TokenParse
"sc-key" => { "sc-key" => {
ScreenOp::TestKey { ScreenOp::TestKey {
pressed: args.next_wr()?, pressed: args.next_wr()?,
code: args.next_rd()? code: args.next_rd()?,
} }
} }
"sc-mbtn" => { "sc-mbtn" => {
ScreenOp::TestMouse { ScreenOp::TestMouse {
pressed: args.next_wr()?, pressed: args.next_wr()?,
button: args.next_rd()? button: args.next_rd()?,
} }
} }

@ -1,16 +1,16 @@
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};
use crsn::runtime::fault::Fault; use crsn::runtime::fault::Fault;
use crsn::runtime::run_thread::{state::RunState, ThreadInfo}; use crsn::runtime::run_thread::{state::RunState, ThreadInfo};
use crate::defs::StackOp;
use crsn::sexp::Sexp;
use crsn::sexp; use crsn::sexp;
use crsn::sexp::Sexp;
use crsn::utils::A; use crsn::utils::A;
use crsn::asm::data::{RdObj, Rd, Wr};
use crate::defs::StackOp;
#[derive(Debug, Default)] #[derive(Debug, Default)]
struct Stacks { struct Stacks {
@ -66,7 +66,7 @@ pub(crate) fn drop_obj(state: &mut RunState, handle: Value) -> Result<Option<()>
Ok(stacks.store.remove(&handle).map(|_| ())) Ok(stacks.store.remove(&handle).map(|_| ()))
} }
fn prepare_push(state: &mut RunState, obj: &RdObj, src: &Rd, pushfn : impl FnOnce(&mut VecDeque<Value>, Value) -> ()) -> Result<(), Fault> { fn prepare_push(state: &mut RunState, obj: &RdObj, src: &Rd, pushfn: impl FnOnce(&mut VecDeque<Value>, Value) -> ()) -> Result<(), Fault> {
state.clear_status(); state.clear_status();
let handle = state.read_obj(*obj)?; let handle = state.read_obj(*obj)?;
let val = state.read(*src)?; let val = state.read(*src)?;
@ -79,7 +79,7 @@ fn prepare_push(state: &mut RunState, obj: &RdObj, src: &Rd, pushfn : impl FnOnc
Ok(()) Ok(())
} }
fn prepare_pop(state: &mut RunState, dst: &Wr, obj: &RdObj, popfn : impl FnOnce(&mut VecDeque<Value>) -> Option<Value>) -> Result<(), Fault> { fn prepare_pop(state: &mut RunState, dst: &Wr, obj: &RdObj, popfn: impl FnOnce(&mut VecDeque<Value>) -> Option<Value>) -> Result<(), Fault> {
state.clear_status(); state.clear_status();
let handle = state.read_obj(*obj)?; let handle = state.read_obj(*obj)?;

@ -25,7 +25,7 @@ impl CrsnExtension for StackOps {
"stacks" "stacks"
} }
fn parse_op<'a>(&self, pos: SourcePosition, keyword: &str, args: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError> { fn parse_op<'a>(&self, pos: &SourcePosition, keyword: &str, args: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError> {
parse::parse(pos, keyword, args) parse::parse(pos, keyword, args)
} }

@ -2,11 +2,11 @@ use crsn::asm::error::CrsnError;
use crsn::asm::instr::op::OpKind; use crsn::asm::instr::op::OpKind;
use crsn::asm::parse::arg_parser::TokenParser; use crsn::asm::parse::arg_parser::TokenParser;
use crsn::module::ParseRes; use crsn::module::ParseRes;
use crsn::sexp::SourcePosition;
use crate::defs::StackOp; use crate::defs::StackOp;
use crsn::sexp::SourcePosition;
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> {
Ok(ParseRes::ext(match keyword { Ok(ParseRes::ext(match keyword {
"stack" => { "stack" => {
StackOp::NewStack { StackOp::NewStack {

@ -10,11 +10,11 @@ use clappconfig::clap::ArgMatches;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crsn::asm::data::literal::Addr; use crsn::asm::data::literal::Addr;
use crsn::module::OpTrait;
use crsn::runtime::run_thread::{RunThread, ThreadToken}; use crsn::runtime::run_thread::{RunThread, ThreadToken};
use crsn_arith::ArithOps; use crsn_arith::ArithOps;
use crsn_screen::ScreenOps; use crsn_screen::ScreenOps;
use crsn_stacks::StackOps; use crsn_stacks::StackOps;
use crsn::module::OpTrait;
mod read_file; mod read_file;
mod serde_duration_millis; mod serde_duration_millis;

@ -8,9 +8,9 @@ addons:
- libelf-dev - libelf-dev
- libdw-dev - libdw-dev
rust: rust:
- nightly - nightly
os: os:
- linux - linux
env: env:
global: global:
@ -21,16 +21,16 @@ before_script:
- pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH
script: script:
- travis-cargo build - travis-cargo build
- travis-cargo test - travis-cargo test
- travis-cargo bench - travis-cargo bench
- travis-cargo doc - travis-cargo doc
after_success: after_success:
- | - |
[ $TRAVIS_BRANCH = master ] && [ $TRAVIS_BRANCH = master ] &&
[ $TRAVIS_PULL_REQUEST = false ] && [ $TRAVIS_PULL_REQUEST = false ] &&
echo '<meta http-equiv=refresh content=0;url=sexp/index.html>' > target/doc/index.html && echo '<meta http-equiv=refresh content=0;url=sexp/index.html>' > target/doc/index.html &&
git clone --depth 1 https://github.com/davisp/ghp-import && git clone --depth 1 https://github.com/davisp/ghp-import &&
./ghp-import/ghp-import -n target/doc && ./ghp-import/ghp-import -n target/doc &&
git push -fq https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages git push -fq https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages
- travis-cargo coveralls --no-sudo - travis-cargo coveralls --no-sudo

@ -4,12 +4,12 @@ version = "1.1.4"
authors = ["Clark Gaebel <cg.wowus.cg@gmail.com>"] authors = ["Clark Gaebel <cg.wowus.cg@gmail.com>"]
documentation = "https://cgaebel.github.io/sexp" documentation = "https://cgaebel.github.io/sexp"
homepage = "https://github.com/cgaebel/sexp" homepage = "https://github.com/cgaebel/sexp"
repository = "https://github.com/cgaebel/sexp" repository = "https://github.com/cgaebel/sexp"
readme = "README.md" readme = "README.md"
keywords = [ "sexp", "parsing", "s-expression", "file-format" ] keywords = ["sexp", "parsing", "s-expression", "file-format"]
description = "A small, simple, self-contained, s-expression parser and pretty-printer." description = "A small, simple, self-contained, s-expression parser and pretty-printer."

@ -12,11 +12,11 @@ pub struct Error {
#[derive(Debug, PartialEq, Clone, Default)] #[derive(Debug, PartialEq, Clone, Default)]
pub struct SourcePosition { pub struct SourcePosition {
/// The line number on which the error occurred. /// The line number on which the error occurred.
pub line: usize, pub line: u32,
/// The column number on which the error occurred. /// The column number on which the error occurred.
pub column: usize, pub column: u32,
/// The index in the given string which caused the error. /// The index in the given string which caused the error.
pub index: usize, pub index: u32,
} }
/// Since errors are the uncommon case, they're boxed. This keeps the size of /// Since errors are the uncommon case, they're boxed. This keeps the size of
@ -56,9 +56,9 @@ pub(crate) fn get_line_and_column(s: &str, pos: usize) -> SourcePosition {
} }
} }
SourcePosition { SourcePosition {
line, line: line as u32,
column: cmp::max(col, 0) as usize, column: cmp::max(col, 0) as u32,
index: pos, index: pos as u32,
} }
} }
@ -66,7 +66,7 @@ pub(crate) fn get_line_and_column(s: &str, pos: usize) -> SourcePosition {
fn err_impl(message: &'static str, s: &str, pos: &usize) -> Err { fn err_impl(message: &'static str, s: &str, pos: &usize) -> Err {
Box::new(Error { Box::new(Error {
message, message,
pos: get_line_and_column(s, *pos) pos: get_line_and_column(s, *pos),
}) })
} }

@ -11,9 +11,9 @@ use std::borrow::Cow;
use std::fmt; use std::fmt;
use std::str::{self, FromStr}; use std::str::{self, FromStr};
use error::{ERes, err, spos};
pub use error::Error; pub use error::Error;
pub use error::SourcePosition; pub use error::SourcePosition;
use error::{ERes, err, spos};
#[cfg(test)] #[cfg(test)]
mod test; mod test;

@ -27,8 +27,8 @@ fn test_pp() {
fn test_tight_parens() { fn test_tight_parens() {
let s = "(hello(world))"; let s = "(hello(world))";
let sexp = parse(s).unwrap(); let sexp = parse(s).unwrap();
assert_eq!(sexp, Sexp::List(vec![Sexp::Atom(Atom::S("hello".into()), None), assert_eq!(sexp, Sexp::List(vec![Sexp::Atom(Atom::S("hello".into()), Default::default()),
Sexp::List(vec![Sexp::Atom(Atom::S("world".into()), None)], None)], None)); Sexp::List(vec![Sexp::Atom(Atom::S("world".into()), Default::default())], Default::default())], Default::default()));
let s = "(this (has)tight(parens))"; let s = "(this (has)tight(parens))";
let s2 = "( this ( has ) tight ( parens ) )"; let s2 = "( this ( has ) tight ( parens ) )";
assert_eq!(parse(s).unwrap(), parse(s2).unwrap()); assert_eq!(parse(s).unwrap(), parse(s2).unwrap());
@ -66,5 +66,5 @@ fn line_and_col_test() {
fn sexp_size() { fn sexp_size() {
// I just want to see when this changes, in the diff. // I just want to see when this changes, in the diff.
use std::mem; use std::mem;
assert_eq!(mem::size_of::<Sexp>(), mem::size_of::<isize>() * 5); assert_eq!(mem::size_of::<Sexp>(), mem::size_of::<isize>() * 6);
} }

Loading…
Cancel
Save