diff --git a/crsn/crsn-sexp/src/error.rs b/crsn/crsn-sexp/src/error.rs index 8a3ada2..640903a 100644 --- a/crsn/crsn-sexp/src/error.rs +++ b/crsn/crsn-sexp/src/error.rs @@ -1,5 +1,6 @@ -use std::{cmp, fmt}; -use std::fmt::{Formatter, Debug}; +use std::{fmt}; +use super::SourcePosition; +use position::get_line_and_column; /// The representation of an s-expression parse error. pub struct Error { @@ -9,38 +10,6 @@ pub struct Error { pub pos: SourcePosition, } -/// Position in the input string -#[derive(PartialEq, Clone, Default)] -pub struct SourcePosition { - /// The line number on which the error occurred. - pub line: u32, - /// The column number on which the error occurred. - pub column: u32, - /// The index in the given string which caused the error. - pub index: u32, -} - -impl fmt::Display for SourcePosition { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, "{}:{}", self.line, self.column) - } -} - -impl Debug for SourcePosition { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - if f.alternate() { - f.debug_struct("SourcePosition") - .field("line", &self.line) - .field("column", &self.column) - .field("index", &self.index) - .finish() - } else { - // shorter version - write!(f, "Pos({}:{})", self.line, self.column) - } - } -} - /// Since errors are the uncommon case, they're boxed. This keeps the size of /// structs down, which helps performance in the common case. /// @@ -66,24 +35,6 @@ impl fmt::Debug for Error { impl std::error::Error for Error {} -pub(crate) fn get_line_and_column(s: &str, pos: usize) -> SourcePosition { - let mut line: usize = 1; - let mut col: isize = -1; - for c in s.chars().take(pos + 1) { - if c == '\n' { - line += 1; - col = -1; - } else { - col += 1; - } - } - SourcePosition { - line: line as u32, - column: cmp::max(col, 0) as u32, - index: pos as u32, - } -} - #[cold] fn err_impl(message: &'static str, s: &str, pos: usize) -> Err { Box::new(Error { @@ -96,12 +47,3 @@ fn err_impl(message: &'static str, s: &str, pos: usize) -> Err { pub(crate) fn err(message: &'static str, s: &str, pos: usize) -> ERes { Err(err_impl(message, s, pos)) } - -/// Build a span -pub(crate) fn spos(s: &str, pos: usize) -> SourcePosition { - if pos >= s.len() { - Default::default() - } else { - get_line_and_column(s, pos) - } -} diff --git a/crsn/crsn-sexp/src/lib.rs b/crsn/crsn-sexp/src/lib.rs index 50815ab..f5d6bc8 100644 --- a/crsn/crsn-sexp/src/lib.rs +++ b/crsn/crsn-sexp/src/lib.rs @@ -8,14 +8,16 @@ use std::borrow::Cow; use std::fmt; use std::str::{self, FromStr}; -use error::{ERes, err, spos}; +use error::{ERes, err}; pub use error::Error; -pub use error::SourcePosition; +pub use position::SourcePosition; +use position::spos; #[cfg(test)] mod test; mod error; +mod position; /// A single data element in an s-expression. Floats are excluded to ensure /// atoms may be used as keys in ordered and hashed data structures. diff --git a/crsn/crsn-sexp/src/position.rs b/crsn/crsn-sexp/src/position.rs new file mode 100644 index 0000000..f54859c --- /dev/null +++ b/crsn/crsn-sexp/src/position.rs @@ -0,0 +1,65 @@ +use std::{fmt, cmp}; +use std::fmt::{Formatter, Debug}; + +/// Position in the input string +#[derive(PartialEq, Clone, Default)] +pub struct SourcePosition { + /// The line number on which the error occurred. + pub line: u32, + /// The column number on which the error occurred. + pub column: u32, + /// The index in the given string which caused the error. + pub index: u32, + /// File index if there are multiple files + pub file: u32, +} + +impl fmt::Display for SourcePosition { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(f, "{}:{}", self.line, self.column) + } +} + +impl Debug for SourcePosition { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + if f.alternate() { + f.debug_struct("SourcePosition") + .field("line", &self.line) + .field("column", &self.column) + .field("index", &self.index) + .field("file", &self.file) + .finish() + } else { + // shorter version + write!(f, "Pos({}:{})", self.line, self.column) + } + } +} + +pub(crate) fn get_line_and_column(s: &str, pos: usize) -> SourcePosition { + let mut line: usize = 1; + let mut col: isize = -1; + for c in s.chars().take(pos + 1) { + if c == '\n' { + line += 1; + col = -1; + } else { + col += 1; + } + } + SourcePosition { + line: line as u32, + column: cmp::max(col, 0) as u32, + index: pos as u32, + file: 0 + } +} + +/// Build a span +pub(crate) fn spos(s: &str, pos: usize) -> SourcePosition { + if pos >= s.len() { + Default::default() + } else { + get_line_and_column(s, pos) + } +} diff --git a/crsn/crsn-sexp/src/test.rs b/crsn/crsn-sexp/src/test.rs index 3f71cb8..b7e8a86 100644 --- a/crsn/crsn-sexp/src/test.rs +++ b/crsn/crsn-sexp/src/test.rs @@ -1,5 +1,6 @@ use super::*; use super::error::get_line_and_column; +use super::position::get_line_and_column; #[test] fn test_hello_world() { @@ -67,16 +68,16 @@ fn show_an_error() { #[test] fn line_and_col_test() { let s = "0123456789\n0123456789\n\n6"; - assert_eq!(get_line_and_column(s, 4), SourcePosition { line: 1, column: 4, index: 4 }); + assert_eq!(get_line_and_column(s, 4), SourcePosition { line: 1, column: 4, index: 4, file: 0 }); - assert_eq!(get_line_and_column(s, 10), SourcePosition { line: 2, column: 0, index: 10 }); - assert_eq!(get_line_and_column(s, 11), SourcePosition { line: 2, column: 0, index: 11 }); - assert_eq!(get_line_and_column(s, 15), SourcePosition { line: 2, column: 4, index: 15 }); + assert_eq!(get_line_and_column(s, 10), SourcePosition { line: 2, column: 0, index: 10, file: 0 }); + assert_eq!(get_line_and_column(s, 11), SourcePosition { line: 2, column: 0, index: 11, file: 0 }); + assert_eq!(get_line_and_column(s, 15), SourcePosition { line: 2, column: 4, index: 15, file: 0 }); - assert_eq!(get_line_and_column(s, 21), SourcePosition { line: 3, column: 0, index: 21 }); - assert_eq!(get_line_and_column(s, 22), SourcePosition { line: 4, column: 0, index: 22 }); - assert_eq!(get_line_and_column(s, 23), SourcePosition { line: 4, column: 0, index: 23 }); - assert_eq!(get_line_and_column(s, 500), SourcePosition { line: 4, column: 0, index: 500 }); + assert_eq!(get_line_and_column(s, 21), SourcePosition { line: 3, column: 0, index: 21, file: 0 }); + assert_eq!(get_line_and_column(s, 22), SourcePosition { line: 4, column: 0, index: 22, file: 0 }); + assert_eq!(get_line_and_column(s, 23), SourcePosition { line: 4, column: 0, index: 23, file: 0 }); + assert_eq!(get_line_and_column(s, 500), SourcePosition { line: 4, column: 0, index: 500, file: 0 }); } #[test] diff --git a/crsn/src/runtime/program.rs b/crsn/src/runtime/program.rs index c2c1d05..e7f8599 100644 --- a/crsn/src/runtime/program.rs +++ b/crsn/src/runtime/program.rs @@ -100,6 +100,7 @@ impl Program { line: 0, column: 0, index: 0, + file: 0, }, cond: None, } diff --git a/crsn/src/runtime/run_thread.rs b/crsn/src/runtime/run_thread.rs index 89798d5..58a39a7 100644 --- a/crsn/src/runtime/run_thread.rs +++ b/crsn/src/runtime/run_thread.rs @@ -54,12 +54,12 @@ impl RunThread { let rs = RunState { thread_info: ti.clone(), - cr: CoroutineContext { + cr: Box::new(CoroutineContext { handle: 0, // this is the root frame: StackFrame::new(params.pc, params.args), call_stack: vec![], cr_state: Default::default(), - }, + }), parked: Default::default(), global_regs: [0; REG_COUNT], ext_data: Default::default(), diff --git a/crsn/src/runtime/run_thread/state.rs b/crsn/src/runtime/run_thread/state.rs index 81f8185..b0d86d8 100644 --- a/crsn/src/runtime/run_thread/state.rs +++ b/crsn/src/runtime/run_thread/state.rs @@ -17,9 +17,9 @@ use std::time::{Instant, Duration}; pub struct RunState { pub thread_info: Arc, /// The active coroutine - pub cr: CoroutineContext, + pub cr: Box, /// Parked coroutines - pub parked: VecDeque, + pub parked: VecDeque>, /// General purpose registers that stay valid for the entire run-time of the thread pub global_regs: [Value; REG_COUNT], /// Extension data @@ -87,12 +87,12 @@ impl RunState { trace!("Spawn cr {:#}", handle); // front - so it runs ASAP - self.parked.push_front(CoroutineContext { + self.parked.push_front(Box::new(CoroutineContext { handle, frame, call_stack: vec![], cr_state: Default::default() - }); + })); if self.cr_deadline.is_none() { // start context switching self.start_task_switching();