forked from MightyPork/crsn
rewrite the stdio module to be less broken. also add sehbang support
This commit is contained in:
@@ -144,7 +144,7 @@ fn atom_of_string(s: String) -> Atom {
|
||||
|
||||
// returns the char it found, and the new pos if you wish to consume that char
|
||||
fn peek(s: &str, pos: usize) -> ERes<(char, usize)> {
|
||||
trace!("peek {}", pos);
|
||||
//trace!("peek {}", pos);
|
||||
if pos == s.len() { return err("unexpected eof", s, pos); }
|
||||
if s.is_char_boundary(pos) {
|
||||
let ch = s[pos..].chars().next().unwrap();
|
||||
@@ -158,7 +158,7 @@ fn peek(s: &str, pos: usize) -> ERes<(char, usize)> {
|
||||
|
||||
// returns the char it found, and the new pos if you wish to consume that char
|
||||
fn peekn(s: &str, nth: usize, pos: usize) -> Option<(char, usize)> {
|
||||
trace!("peekn {}", pos);
|
||||
//trace!("peekn {}", pos);
|
||||
if nth == 0 {
|
||||
panic!("peekn with nth=0");
|
||||
}
|
||||
@@ -183,7 +183,7 @@ fn peekn(s: &str, nth: usize, pos: usize) -> Option<(char, usize)> {
|
||||
}
|
||||
|
||||
fn expect(s: &str, pos: &mut usize, c: char) -> ERes<()> {
|
||||
trace!("expect {}", pos);
|
||||
//trace!("expect {}", pos);
|
||||
let (ch, next) = peek(s, *pos)?;
|
||||
*pos = next;
|
||||
if ch == c {
|
||||
@@ -208,7 +208,7 @@ fn consume_until_newline(s: &str, pos: &mut usize) -> ERes<()> {
|
||||
|
||||
// zero or more spaces
|
||||
fn zspace(s: &str, pos: &mut usize) -> ERes<()> {
|
||||
trace!("zspace {}", pos);
|
||||
//trace!("zspace {}", pos);
|
||||
loop {
|
||||
if *pos == s.len() {
|
||||
return Ok(());
|
||||
@@ -226,7 +226,7 @@ fn zspace(s: &str, pos: &mut usize) -> ERes<()> {
|
||||
}
|
||||
|
||||
fn parse_quoted_atom(s: &str, quote: char, pos: &mut usize) -> ERes<Atom> {
|
||||
trace!("parse_quoted_atom {}", pos);
|
||||
//trace!("parse_quoted_atom {}", pos);
|
||||
let pos0 = *pos;
|
||||
let mut cs: String = String::new();
|
||||
|
||||
@@ -266,7 +266,7 @@ fn parse_quoted_atom(s: &str, quote: char, pos: &mut usize) -> ERes<Atom> {
|
||||
}
|
||||
|
||||
fn parse_unquoted_atom(s: &str, pos: &mut usize) -> ERes<Atom> {
|
||||
trace!("parse_unquoted_atom {}", pos);
|
||||
//trace!("parse_unquoted_atom {}", pos);
|
||||
let mut cs: String = String::new();
|
||||
|
||||
loop {
|
||||
@@ -288,7 +288,7 @@ fn parse_unquoted_atom(s: &str, pos: &mut usize) -> ERes<Atom> {
|
||||
}
|
||||
|
||||
fn parse_atom(s: &str, pos: &mut usize) -> ERes<Atom> {
|
||||
trace!("parse_atom {}", pos);
|
||||
//trace!("parse_atom {}", pos);
|
||||
let (ch, _) = peek(s, *pos)?;
|
||||
|
||||
if ch == '"' {
|
||||
@@ -309,7 +309,7 @@ fn parse_atom(s: &str, pos: &mut usize) -> ERes<Atom> {
|
||||
}
|
||||
|
||||
fn parse_list(s: &str, pos: &mut usize) -> ERes<Vec<Sexp>> {
|
||||
trace!("parse_list {}", pos);
|
||||
//trace!("parse_list {}", pos);
|
||||
zspace(s, pos)?;
|
||||
expect(s, pos, '(')?;
|
||||
|
||||
@@ -331,7 +331,7 @@ fn parse_list(s: &str, pos: &mut usize) -> ERes<Vec<Sexp>> {
|
||||
}
|
||||
|
||||
fn parse_sexp(s: &str, pos: &mut usize) -> ERes<Sexp> {
|
||||
trace!("parse_sexp {}", pos);
|
||||
//trace!("parse_sexp {}", pos);
|
||||
zspace(s, pos)?;
|
||||
let (c, _) = peek(s, *pos)?;
|
||||
let r = if c == '(' {
|
||||
|
||||
@@ -5,6 +5,55 @@ use sexp::SourcePosition;
|
||||
|
||||
use crate::asm::error::CrsnError;
|
||||
|
||||
/// Condition flag
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
||||
pub enum Flag {
|
||||
/// Equality
|
||||
Equal,
|
||||
/// Equal to zero
|
||||
Zero,
|
||||
/// A < B
|
||||
Lower,
|
||||
/// A > B
|
||||
Greater,
|
||||
/// A > 0
|
||||
Positive,
|
||||
/// A < 0
|
||||
Negative,
|
||||
/// Arithmetic operation caused an integer operand to overflow
|
||||
Overflow,
|
||||
/// Arithmetic (or other) operation was invalid.
|
||||
/// Example: division by zero
|
||||
Invalid,
|
||||
/// Arithmetic carry
|
||||
Carry,
|
||||
// Full
|
||||
Full,
|
||||
// Empty
|
||||
Empty,
|
||||
// Empty
|
||||
Eof,
|
||||
}
|
||||
|
||||
impl From<Flag> for Cond {
|
||||
fn from(flag: Flag) -> Self {
|
||||
match flag {
|
||||
Flag::Equal => Cond::Equal,
|
||||
Flag::Zero => Cond::Zero,
|
||||
Flag::Lower => Cond::Lower,
|
||||
Flag::Greater => Cond::Greater,
|
||||
Flag::Positive => Cond::Positive,
|
||||
Flag::Negative => Cond::Negative,
|
||||
Flag::Overflow => Cond::Overflow,
|
||||
Flag::Invalid => Cond::Invalid,
|
||||
Flag::Carry => Cond::Carry,
|
||||
Flag::Full => Cond::Full,
|
||||
Flag::Empty => Cond::Empty,
|
||||
Flag::Eof => Cond::Eof,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Condition flag
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
||||
pub enum Cond {
|
||||
@@ -53,6 +102,10 @@ pub enum Cond {
|
||||
Empty,
|
||||
/// Not empty
|
||||
NotEmpty,
|
||||
// Empty
|
||||
Eof,
|
||||
/// Not empty
|
||||
NotEof,
|
||||
}
|
||||
|
||||
pub fn parse_cond(text: &str, pos: &SourcePosition) -> Result<Cond, CrsnError> {
|
||||
@@ -77,6 +130,8 @@ pub fn parse_cond(text: &str, pos: &SourcePosition) -> Result<Cond, CrsnError> {
|
||||
"nf" | "nfull" => Cond::NotFull,
|
||||
"ok" | "val" | "valid" => Cond::Valid,
|
||||
"inval" | "invalid" | "nval" | "nok" => Cond::Invalid,
|
||||
"eof" => Cond::Eof,
|
||||
"neof" => Cond::NotEof,
|
||||
"ov" => Cond::Overflow,
|
||||
"nov" => Cond::NotOverflow,
|
||||
_ => {
|
||||
@@ -85,6 +140,13 @@ pub fn parse_cond(text: &str, pos: &SourcePosition) -> Result<Cond, CrsnError> {
|
||||
})
|
||||
}
|
||||
|
||||
impl Display for Flag {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
let cond : Cond = (*self).into();
|
||||
write!(f, "{}", cond)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Cond {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(match self {
|
||||
@@ -110,6 +172,8 @@ impl Display for Cond {
|
||||
Cond::NotCarry => "nc",
|
||||
Cond::Invalid => "inval",
|
||||
Cond::Valid => "valid",
|
||||
Cond::Eof => "eof",
|
||||
Cond::NotEof => "neof",
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -147,6 +211,9 @@ impl Not for Cond {
|
||||
|
||||
Cond::Invalid => Cond::Valid,
|
||||
Cond::Valid => Cond::Invalid,
|
||||
|
||||
Cond::NotEof => Cond::Eof,
|
||||
Cond::Eof => Cond::NotEof,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ impl Flatten for InstrWithBranches {
|
||||
let parent_pos = self.pos;
|
||||
|
||||
if let Some(branches) = self.branches {
|
||||
// trace!("Branches {:?}", branches);
|
||||
|
||||
let labels = HashMap::<Cond, u32>::new();
|
||||
let branch_count = branches.len();
|
||||
let end_lbl = Label::unique(label_num);
|
||||
|
||||
@@ -23,6 +23,17 @@ pub fn assemble(source: &str, uniq : &CrsnUniq, mut parsers: Vec<Box<dyn CrsnExt
|
||||
p.init(uniq);
|
||||
}
|
||||
|
||||
// remove first line if it looks like a shebang
|
||||
let source = if source.starts_with("#!") {
|
||||
if let Some(nl) = source.find('\n') {
|
||||
&source[nl + 1..]
|
||||
} else {
|
||||
source
|
||||
}
|
||||
} else {
|
||||
source
|
||||
};
|
||||
|
||||
let pcx = ParserContext {
|
||||
parsers: &parsers,
|
||||
state: RefCell::new(ParserState {
|
||||
|
||||
@@ -7,6 +7,7 @@ use crate::asm::parse::ParserContext;
|
||||
use crate::asm::parse::sexp_expect::expect_string_atom;
|
||||
|
||||
/// Utility for argument parsing
|
||||
#[derive(Debug)]
|
||||
pub struct TokenParser<'a> {
|
||||
orig_len: usize,
|
||||
args: Vec<Sexp>,
|
||||
|
||||
@@ -20,6 +20,7 @@ pub mod parse_op;
|
||||
pub mod arg_parser;
|
||||
pub mod parse_routine;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ParserContext<'a> {
|
||||
/// Extension modules
|
||||
pub parsers: &'a [Box<dyn CrsnExtension>],
|
||||
@@ -27,7 +28,7 @@ pub struct ParserContext<'a> {
|
||||
pub state: RefCell<ParserState>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Default, Debug)]
|
||||
pub struct ParserState {
|
||||
/// Register aliases within the routine
|
||||
pub reg_aliases: HashMap<RegisterAlias, Register>,
|
||||
|
||||
@@ -63,10 +63,11 @@ pub fn parse_instructions(items: impl Iterator<Item=Sexp>, pos: &SourcePosition,
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let arg_tokens = TokenParser::new(toki.take(token_count - branch_tokens.len()).collect(), &listpos, pcx);
|
||||
// debug!("branch_tokens: {:#?}", branch_tokens);
|
||||
|
||||
let branches = {
|
||||
let mut branches = vec![];
|
||||
for t in branch_tokens {
|
||||
for t in branch_tokens.into_iter().rev() {
|
||||
branches.push(parse_cond_branch(t, pcx)?);
|
||||
}
|
||||
if branches.is_empty() {
|
||||
|
||||
@@ -4,12 +4,12 @@ use sexp::Sexp;
|
||||
|
||||
use crate::asm::data::{Rd, RdData};
|
||||
use crate::asm::data::literal::Addr;
|
||||
use crate::asm::instr::Cond;
|
||||
use crate::builtin::defs::{Barrier, BuiltinOp};
|
||||
use crate::module::{EvalRes, OpTrait};
|
||||
use crate::runtime::fault::Fault;
|
||||
use crate::runtime::frame::StackFrame;
|
||||
use crate::runtime::run_thread::{state::RunState, ThreadInfo};
|
||||
use crate::asm::instr::cond::Flag;
|
||||
|
||||
impl OpTrait for BuiltinOp {
|
||||
fn execute(&self, info: &ThreadInfo, state: &mut RunState) -> Result<EvalRes, Fault> {
|
||||
@@ -138,7 +138,7 @@ impl OpTrait for BuiltinOp {
|
||||
}
|
||||
if !dropped {
|
||||
warn!("Object {:#x} to del does not exist!", x);
|
||||
state.set_flag(Cond::Invalid, true);
|
||||
state.set_flag(Flag::Invalid, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::fmt;
|
||||
|
||||
use crate::asm::data::literal::{is_negative, is_positive, Value};
|
||||
use crate::asm::instr::Cond;
|
||||
use crate::asm::instr::cond::Flag;
|
||||
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct StatusFlags {
|
||||
@@ -28,6 +29,8 @@ pub struct StatusFlags {
|
||||
pub full: bool,
|
||||
/// Buffer empty
|
||||
pub empty: bool,
|
||||
/// Stream ended
|
||||
pub eof: bool,
|
||||
}
|
||||
|
||||
impl StatusFlags {
|
||||
@@ -49,6 +52,7 @@ impl StatusFlags {
|
||||
if self.carry { val |= 0x100; }
|
||||
if self.full { val |= 0x200; }
|
||||
if self.empty { val |= 0x400; }
|
||||
if self.eof { val |= 0x800; }
|
||||
val
|
||||
}
|
||||
|
||||
@@ -64,6 +68,7 @@ impl StatusFlags {
|
||||
if val & 0x100 != 0 { self.carry = true; }
|
||||
if val & 0x200 != 0 { self.full = true; }
|
||||
if val & 0x400 != 0 { self.empty = true; }
|
||||
if val & 0x800 != 0 { self.eof = true; }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -98,50 +103,49 @@ impl StatusFlags {
|
||||
Cond::NotFull => !self.full,
|
||||
Cond::Empty => self.empty,
|
||||
Cond::NotEmpty => !self.empty,
|
||||
Cond::Eof => self.eof,
|
||||
Cond::NotEof => !self.eof,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn set(&mut self, cond: Cond) {
|
||||
pub fn set(&mut self, cond: Flag, val : bool) {
|
||||
match cond {
|
||||
Cond::Equal => {
|
||||
self.equal = true;
|
||||
Flag::Equal => {
|
||||
self.equal = val;
|
||||
}
|
||||
Cond::Zero => {
|
||||
self.zero = true;
|
||||
Flag::Zero => {
|
||||
self.zero = val;
|
||||
}
|
||||
Cond::Lower => {
|
||||
self.lower = true;
|
||||
Flag::Lower => {
|
||||
self.lower = val;
|
||||
}
|
||||
Cond::Greater => {
|
||||
self.lower = false;
|
||||
self.equal = false;
|
||||
self.greater = true;
|
||||
Flag::Greater => {
|
||||
self.greater = val;
|
||||
}
|
||||
Cond::Positive => {
|
||||
self.positive = true;
|
||||
Flag::Positive => {
|
||||
self.positive = val;
|
||||
}
|
||||
Cond::Negative => {
|
||||
self.negative = true;
|
||||
Flag::Negative => {
|
||||
self.negative = val;
|
||||
}
|
||||
Cond::Overflow => {
|
||||
self.overflow = true;
|
||||
Flag::Overflow => {
|
||||
self.overflow = val;
|
||||
}
|
||||
Cond::Invalid => {
|
||||
self.invalid = true;
|
||||
Flag::Invalid => {
|
||||
self.invalid = val;
|
||||
}
|
||||
Cond::Carry => {
|
||||
self.carry = true;
|
||||
Flag::Carry => {
|
||||
self.carry = val;
|
||||
}
|
||||
Cond::Empty => {
|
||||
self.empty = true;
|
||||
Flag::Empty => {
|
||||
self.empty = val;
|
||||
}
|
||||
Cond::Full => {
|
||||
self.full = true;
|
||||
Flag::Full => {
|
||||
self.full = val;
|
||||
}
|
||||
other => {
|
||||
error!("Cannot set cond by {:?}", other);
|
||||
// ...and do nothing. Don't panic, we don't want to crash the runtime!
|
||||
Flag::Eof => {
|
||||
self.eof = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -183,6 +187,9 @@ impl Display for StatusFlags {
|
||||
if self.empty {
|
||||
f.write_str(" Emp")?;
|
||||
}
|
||||
if self.eof {
|
||||
f.write_str(" Eof")?;
|
||||
}
|
||||
f.write_str(" ]")?;
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -9,6 +9,7 @@ use crate::runtime::frame::{CallStack, REG_COUNT, StackFrame};
|
||||
use std::sync::Arc;
|
||||
use crate::runtime::run_thread::ThreadInfo;
|
||||
use nudge::{likely};
|
||||
use crate::asm::instr::cond::Flag;
|
||||
|
||||
pub struct RunState {
|
||||
pub thread_info: Arc<ThreadInfo>,
|
||||
@@ -51,10 +52,9 @@ impl RunState {
|
||||
|
||||
/// Set a status flag. Only supports simple, positive conds (i.e. not GreaterOrEqual)
|
||||
#[inline(always)]
|
||||
pub fn set_flag(&mut self, cond: Cond, set: bool) {
|
||||
if set {
|
||||
self.frame.status.set(cond);
|
||||
}
|
||||
pub fn set_flag(&mut self, flag: Flag, set: bool) {
|
||||
trace!("Flag {} = {:?}", flag, set);
|
||||
self.frame.status.set(flag, set);
|
||||
}
|
||||
|
||||
/// Check status flags for a condition
|
||||
|
||||
Reference in New Issue
Block a user