forked from MightyPork/crsn
remove unnecessary cloning of SourcePosition, reduce SourcePosition size. clean, format
This commit is contained in:
@@ -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,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-3
@@ -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,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-10
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-24
@@ -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::builtin::defs::{Barrier, BuiltinOp};
|
|
||||||
use crate::module::{ParseRes};
|
|
||||||
use crate::utils::A;
|
|
||||||
use crate::asm::patches::ErrWithPos;
|
use crate::asm::patches::ErrWithPos;
|
||||||
|
use crate::builtin::defs::{Barrier, BuiltinOp};
|
||||||
|
use crate::module::ParseRes;
|
||||||
|
use crate::utils::A;
|
||||||
|
|
||||||
|
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 crsn::sexp;
|
||||||
|
use crsn::sexp::Sexp;
|
||||||
|
use crsn::utils::A;
|
||||||
|
|
||||||
use crate::defs::ArithOp;
|
use crate::defs::ArithOp;
|
||||||
use crsn::sexp::Sexp;
|
|
||||||
use crsn::sexp;
|
|
||||||
use crsn::utils::A;
|
|
||||||
use crsn::asm::data::{Rd, Wr};
|
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-18
@@ -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 crate::defs::ArithOp;
|
|
||||||
use crsn::sexp::SourcePosition;
|
use crsn::sexp::SourcePosition;
|
||||||
|
|
||||||
pub(crate) fn parse<'a>(pos: SourcePosition, keyword: &str, mut args: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError> {
|
use crate::defs::ArithOp;
|
||||||
|
|
||||||
|
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()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-11
@@ -1,18 +1,18 @@
|
|||||||
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 crsn::sexp;
|
||||||
|
use crsn::sexp::Sexp;
|
||||||
|
use crsn::utils::A;
|
||||||
|
|
||||||
use crate::defs::ScreenOp;
|
use crate::defs::ScreenOp;
|
||||||
use crsn::sexp::Sexp;
|
|
||||||
use crsn::sexp;
|
|
||||||
use crsn::utils::A;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Opts {
|
struct Opts {
|
||||||
@@ -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 crate::defs::ScreenOp;
|
|
||||||
use crsn::sexp::SourcePosition;
|
use crsn::sexp::SourcePosition;
|
||||||
|
|
||||||
pub(crate) fn parse<'a>(pos: SourcePosition, keyword: &str, mut args: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError> {
|
use crate::defs::ScreenOp;
|
||||||
|
|
||||||
|
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 crsn::sexp;
|
||||||
|
use crsn::sexp::Sexp;
|
||||||
|
use crsn::utils::A;
|
||||||
|
|
||||||
use crate::defs::StackOp;
|
use crate::defs::StackOp;
|
||||||
use crsn::sexp::Sexp;
|
|
||||||
use crsn::sexp;
|
|
||||||
use crsn::utils::A;
|
|
||||||
use crsn::asm::data::{RdObj, Rd, Wr};
|
|
||||||
|
|
||||||
#[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 crate::defs::StackOp;
|
|
||||||
use crsn::sexp::SourcePosition;
|
use crsn::sexp::SourcePosition;
|
||||||
|
|
||||||
pub(crate) fn parse<'a>(pos: SourcePosition, keyword: &str, mut args: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError> {
|
use crate::defs::StackOp;
|
||||||
|
|
||||||
|
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
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ 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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user