add file index field to SourcePosition, some refactor, put coroutines in Box

master
Ondřej Hruška 4 years ago
parent daff23dd98
commit 9d4fef5222
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 64
      crsn/crsn-sexp/src/error.rs
  2. 6
      crsn/crsn-sexp/src/lib.rs
  3. 65
      crsn/crsn-sexp/src/position.rs
  4. 17
      crsn/crsn-sexp/src/test.rs
  5. 1
      crsn/src/runtime/program.rs
  6. 4
      crsn/src/runtime/run_thread.rs
  7. 8
      crsn/src/runtime/run_thread/state.rs

@ -1,5 +1,6 @@
use std::{cmp, fmt}; use std::{fmt};
use std::fmt::{Formatter, Debug}; use super::SourcePosition;
use position::get_line_and_column;
/// The representation of an s-expression parse error. /// The representation of an s-expression parse error.
pub struct Error { pub struct Error {
@ -9,38 +10,6 @@ pub struct Error {
pub pos: SourcePosition, 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 /// Since errors are the uncommon case, they're boxed. This keeps the size of
/// structs down, which helps performance in the common case. /// structs down, which helps performance in the common case.
/// ///
@ -66,24 +35,6 @@ impl fmt::Debug for Error {
impl std::error::Error 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] #[cold]
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 {
@ -96,12 +47,3 @@ fn err_impl(message: &'static str, s: &str, pos: usize) -> Err {
pub(crate) fn err<T>(message: &'static str, s: &str, pos: usize) -> ERes<T> { pub(crate) fn err<T>(message: &'static str, s: &str, pos: usize) -> ERes<T> {
Err(err_impl(message, s, pos)) 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)
}
}

@ -8,14 +8,16 @@ 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}; use error::{ERes, err};
pub use error::Error; pub use error::Error;
pub use error::SourcePosition; pub use position::SourcePosition;
use position::spos;
#[cfg(test)] #[cfg(test)]
mod test; mod test;
mod error; mod error;
mod position;
/// A single data element in an s-expression. Floats are excluded to ensure /// 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. /// atoms may be used as keys in ordered and hashed data structures.

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

@ -1,5 +1,6 @@
use super::*; use super::*;
use super::error::get_line_and_column; use super::error::get_line_and_column;
use super::position::get_line_and_column;
#[test] #[test]
fn test_hello_world() { fn test_hello_world() {
@ -67,16 +68,16 @@ fn show_an_error() {
#[test] #[test]
fn line_and_col_test() { fn line_and_col_test() {
let s = "0123456789\n0123456789\n\n6"; 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, 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 }); 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 }); 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, 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 }); 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 }); 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 }); assert_eq!(get_line_and_column(s, 500), SourcePosition { line: 4, column: 0, index: 500, file: 0 });
} }
#[test] #[test]

@ -100,6 +100,7 @@ impl Program {
line: 0, line: 0,
column: 0, column: 0,
index: 0, index: 0,
file: 0,
}, },
cond: None, cond: None,
} }

@ -54,12 +54,12 @@ impl RunThread {
let rs = RunState { let rs = RunState {
thread_info: ti.clone(), thread_info: ti.clone(),
cr: CoroutineContext { cr: Box::new(CoroutineContext {
handle: 0, // this is the root handle: 0, // this is the root
frame: StackFrame::new(params.pc, params.args), frame: StackFrame::new(params.pc, params.args),
call_stack: vec![], call_stack: vec![],
cr_state: Default::default(), cr_state: Default::default(),
}, }),
parked: Default::default(), parked: Default::default(),
global_regs: [0; REG_COUNT], global_regs: [0; REG_COUNT],
ext_data: Default::default(), ext_data: Default::default(),

@ -17,9 +17,9 @@ use std::time::{Instant, Duration};
pub struct RunState { pub struct RunState {
pub thread_info: Arc<ThreadInfo>, pub thread_info: Arc<ThreadInfo>,
/// The active coroutine /// The active coroutine
pub cr: CoroutineContext, pub cr: Box<CoroutineContext>,
/// Parked coroutines /// Parked coroutines
pub parked: VecDeque<CoroutineContext>, pub parked: VecDeque<Box<CoroutineContext>>,
/// General purpose registers that stay valid for the entire run-time of the thread /// General purpose registers that stay valid for the entire run-time of the thread
pub global_regs: [Value; REG_COUNT], pub global_regs: [Value; REG_COUNT],
/// Extension data /// Extension data
@ -87,12 +87,12 @@ impl RunState {
trace!("Spawn cr {:#}", handle); trace!("Spawn cr {:#}", handle);
// front - so it runs ASAP // front - so it runs ASAP
self.parked.push_front(CoroutineContext { self.parked.push_front(Box::new(CoroutineContext {
handle, handle,
frame, frame,
call_stack: vec![], call_stack: vec![],
cr_state: Default::default() cr_state: Default::default()
}); }));
if self.cr_deadline.is_none() { if self.cr_deadline.is_none() {
// start context switching // start context switching
self.start_task_switching(); self.start_task_switching();

Loading…
Cancel
Save