parent
b1fccce8e3
commit
c75dafac8e
15 changed files with 203 additions and 56 deletions
|
@ -101,11 +101,12 @@ fn read_init_file(args: &Args) -> Result<Option<String>, std::io::Error> {
|
||||||
fn exec_line(
|
fn exec_line(
|
||||||
vm: &mut Vm,
|
vm: &mut Vm,
|
||||||
line: &str,
|
line: &str,
|
||||||
|
line_no: u32,
|
||||||
args: &Args,
|
args: &Args,
|
||||||
c: &ReplColors,
|
c: &ReplColors,
|
||||||
globals: &mut Vec<Symbol>,
|
globals: &mut Vec<Symbol>,
|
||||||
) {
|
) {
|
||||||
let mut ex = match parser::parse(line) {
|
let mut ex = match parser::parse_from(line, line_no) {
|
||||||
Ok(ex) => ex,
|
Ok(ex) => ex,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("{}Error:{} {e}", c.error, c.reset);
|
eprintln!("{}Error:{} {e}", c.error, c.reset);
|
||||||
|
@ -192,11 +193,13 @@ pub fn repl(args: &Args) -> ExitCode {
|
||||||
};
|
};
|
||||||
|
|
||||||
let vm = Rc::new(RefCell::new(vm));
|
let vm = Rc::new(RefCell::new(vm));
|
||||||
|
let mut line_no = 1;
|
||||||
|
|
||||||
rl.set_helper(Some(TalcHelper::new(vm.clone())));
|
rl.set_helper(Some(TalcHelper::new(vm.clone())));
|
||||||
|
|
||||||
if let Some(src) = init_src {
|
if let Some(src) = init_src {
|
||||||
exec_line(&mut vm.borrow_mut(), &src, args, &c, &mut globals);
|
exec_line(&mut vm.borrow_mut(), &src, line_no, args, &c, &mut globals);
|
||||||
|
line_no += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
@ -214,6 +217,7 @@ pub fn repl(args: &Args) -> ExitCode {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exec_line(&mut vm.borrow_mut(), &line, args, &c, &mut globals);
|
exec_line(&mut vm.borrow_mut(), &line, line_no, args, &c, &mut globals);
|
||||||
|
line_no += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -240,6 +240,7 @@ pub struct TryTable {
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct Chunk {
|
pub struct Chunk {
|
||||||
|
pub lines: Vec<(u32, u32)>,
|
||||||
pub consts: Vec<Value>,
|
pub consts: Vec<Value>,
|
||||||
pub instrs: Vec<Instruction>,
|
pub instrs: Vec<Instruction>,
|
||||||
pub try_tables: Vec<TryTable>,
|
pub try_tables: Vec<TryTable>,
|
||||||
|
@ -250,6 +251,26 @@ impl Chunk {
|
||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_line(&mut self, line: u32) {
|
||||||
|
let instr = self.instrs.len() as u32;
|
||||||
|
if let Some((i, l)) = self.lines.last_mut() {
|
||||||
|
if *i == instr {
|
||||||
|
*l = line;
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.lines.push((instr, line));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_line(&self, instr: u32) -> Option<u32> {
|
||||||
|
let res = self.lines.binary_search_by(|(i, _)| i.cmp(&instr));
|
||||||
|
let n = match res {
|
||||||
|
Ok(n) => n,
|
||||||
|
Err(n) => n.saturating_sub(1),
|
||||||
|
};
|
||||||
|
self.lines.get(n).map(|(_, l)| *l)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_const(&mut self, v: Value) -> usize {
|
pub fn add_const(&mut self, v: Value) -> usize {
|
||||||
assert!(
|
assert!(
|
||||||
self.consts.len() < 0xff_ffff,
|
self.consts.len() < 0xff_ffff,
|
||||||
|
|
|
@ -81,13 +81,18 @@ struct Compiler<'a> {
|
||||||
|
|
||||||
pub fn compile(expr: &Expr, name: Option<Symbol>) -> Result<Function> {
|
pub fn compile(expr: &Expr, name: Option<Symbol>) -> Result<Function> {
|
||||||
let mut comp = Compiler::new_module(name, None);
|
let mut comp = Compiler::new_module(name, None);
|
||||||
|
comp.chunk.set_line(0);
|
||||||
comp.expr(expr)?;
|
comp.expr(expr)?;
|
||||||
Ok(comp.finish())
|
Ok(comp.finish())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile_repl(expr: &Expr, globals: &mut Vec<Symbol>) -> Result<Function> {
|
pub fn compile_repl(expr: &Expr, globals: &mut Vec<Symbol>) -> Result<Function> {
|
||||||
let mut comp = Compiler::new_repl(globals);
|
let mut comp = Compiler::new_repl(globals);
|
||||||
|
comp.chunk.set_line(0);
|
||||||
match &expr.kind {
|
match &expr.kind {
|
||||||
|
ExprKind::Block(xs) if xs.is_empty() => {
|
||||||
|
comp.emit(I::Nil);
|
||||||
|
}
|
||||||
ExprKind::Block(xs) => {
|
ExprKind::Block(xs) => {
|
||||||
for x in &xs[0..xs.len() - 1] {
|
for x in &xs[0..xs.len() - 1] {
|
||||||
comp.expr(x)?;
|
comp.expr(x)?;
|
||||||
|
@ -439,6 +444,7 @@ impl<'a> Compiler<'a> {
|
||||||
|
|
||||||
fn expr(&mut self, e: &Expr) -> Result<()> {
|
fn expr(&mut self, e: &Expr) -> Result<()> {
|
||||||
let Expr { kind, span } = e;
|
let Expr { kind, span } = e;
|
||||||
|
self.chunk.set_line(span.start.line);
|
||||||
match kind {
|
match kind {
|
||||||
ExprKind::Block(xs) if xs.is_empty() => {
|
ExprKind::Block(xs) if xs.is_empty() => {
|
||||||
self.emit(I::Nil);
|
self.emit(I::Nil);
|
||||||
|
@ -845,6 +851,7 @@ impl<'a> Compiler<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lvalue(&mut self, lv: &LValue) -> Result<()> {
|
fn lvalue(&mut self, lv: &LValue) -> Result<()> {
|
||||||
|
self.chunk.set_line(lv.span.start.line);
|
||||||
match &lv.kind {
|
match &lv.kind {
|
||||||
LValueKind::Ident(i) => {
|
LValueKind::Ident(i) => {
|
||||||
self.emit(I::Dup);
|
self.emit(I::Dup);
|
||||||
|
|
|
@ -1,21 +1,59 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
lstring::LStr,
|
lstring::LStr,
|
||||||
symbol::{Symbol, SYM_MSG, SYM_TYPE},
|
symbol::{Symbol, SYM_MSG, SYM_TRACE, SYM_TYPE},
|
||||||
value::Value,
|
value::Value,
|
||||||
};
|
};
|
||||||
use std::{fmt::Display, rc::Rc};
|
use std::{fmt::Display, rc::Rc};
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, Exception>;
|
pub type Result<T> = std::result::Result<T, Exception>;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Trace {
|
||||||
|
line: Option<u32>,
|
||||||
|
scope: Option<Symbol>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Trace {
|
||||||
|
pub fn from_value(value: &Value) -> Option<Self> {
|
||||||
|
let Value::List(lst) = value else { return None };
|
||||||
|
let lst = lst.borrow();
|
||||||
|
if lst.len() < 2 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let line = match &lst[0] {
|
||||||
|
Value::Int(s) => Some(s.to_u32()?),
|
||||||
|
Value::Nil => None,
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
|
let scope = match &lst[1] {
|
||||||
|
Value::Symbol(s) => Some(*s),
|
||||||
|
Value::Nil => None,
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
|
Some(Self { line, scope })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_value(&self) -> Value {
|
||||||
|
let line = self.line.map_or(Value::Nil, Value::from);
|
||||||
|
let scope = self.scope.map_or(Value::Nil, Value::from);
|
||||||
|
vec![line, scope].into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Exception {
|
pub struct Exception {
|
||||||
pub ty: Symbol,
|
pub ty: Symbol,
|
||||||
pub msg: Rc<LStr>,
|
pub msg: Rc<LStr>,
|
||||||
|
pub trace: Vec<Trace>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Exception {
|
impl Exception {
|
||||||
pub fn new(ty: Symbol, msg: Rc<LStr>) -> Self {
|
pub fn new(ty: Symbol, msg: Rc<LStr>) -> Self {
|
||||||
Self { ty, msg }
|
Self {
|
||||||
|
ty,
|
||||||
|
msg,
|
||||||
|
trace: Vec::new(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_value(value: &Value) -> Option<Self> {
|
pub fn from_value(value: &Value) -> Option<Self> {
|
||||||
|
@ -25,27 +63,54 @@ impl Exception {
|
||||||
let table = table.borrow();
|
let table = table.borrow();
|
||||||
let ty = table.get(&(*SYM_TYPE).into())?;
|
let ty = table.get(&(*SYM_TYPE).into())?;
|
||||||
let msg = table.get(&(*SYM_MSG).into())?;
|
let msg = table.get(&(*SYM_MSG).into())?;
|
||||||
if let (Value::Symbol(ty), Value::String(msg)) = (ty, msg) {
|
let (Value::Symbol(ty), Value::String(msg)) = (ty, msg) else {
|
||||||
Some(Self {
|
return None
|
||||||
ty: *ty,
|
};
|
||||||
msg: msg.clone(),
|
let trace_lst = table.get(&(*SYM_TRACE).into())?;
|
||||||
})
|
let Value::List(trace_lst) = trace_lst else {
|
||||||
} else {
|
return None
|
||||||
None
|
};
|
||||||
}
|
let trace = trace_lst
|
||||||
|
.borrow()
|
||||||
|
.iter()
|
||||||
|
.map(Trace::from_value)
|
||||||
|
.collect::<Option<_>>()?;
|
||||||
|
Some(Self {
|
||||||
|
ty: *ty,
|
||||||
|
msg: msg.clone(),
|
||||||
|
trace,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_value(self) -> Value {
|
pub fn to_value(self) -> Value {
|
||||||
|
let trace: Vec<Value> = self.trace.iter().map(Trace::to_value).collect();
|
||||||
Value::new_table(|table| {
|
Value::new_table(|table| {
|
||||||
table.insert((*SYM_TYPE).into(), self.ty.into());
|
table.insert((*SYM_TYPE).into(), self.ty.into());
|
||||||
table.insert((*SYM_MSG).into(), Value::String(self.msg));
|
table.insert((*SYM_MSG).into(), Value::String(self.msg));
|
||||||
|
table.insert((*SYM_TRACE).into(), trace.into());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_trace(&mut self, line: Option<u32>, scope: Option<Symbol>) {
|
||||||
|
self.trace.push(Trace { line, scope });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Exception {
|
impl Display for Exception {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "{}: {}", self.ty.name(), self.msg)
|
write!(f, "{}: {}", self.ty.name(), self.msg)?;
|
||||||
|
for trace in &self.trace {
|
||||||
|
write!(f, "\n ")?;
|
||||||
|
if let Some(scope) = trace.scope {
|
||||||
|
write!(f, "in {}", scope.name())?;
|
||||||
|
} else {
|
||||||
|
write!(f, "in <anonymous>")?;
|
||||||
|
}
|
||||||
|
if let Some(line) = trace.line {
|
||||||
|
write!(f, " at {line}")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,4 +138,5 @@ macro_rules! throw {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use num::ToPrimitive;
|
||||||
pub use throw;
|
pub use throw;
|
||||||
|
|
|
@ -393,6 +393,13 @@ impl<'a> From<&'a str> for &'a LStr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a String> for &'a LStr {
|
||||||
|
#[inline]
|
||||||
|
fn from(value: &'a String) -> Self {
|
||||||
|
Self::from(value.as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a OsStr> for &'a LStr {
|
impl<'a> From<&'a OsStr> for &'a LStr {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(value: &'a OsStr) -> Self {
|
fn from(value: &'a OsStr) -> Self {
|
||||||
|
|
|
@ -212,11 +212,20 @@ pub struct Lexer<'s> {
|
||||||
|
|
||||||
impl<'s> Lexer<'s> {
|
impl<'s> Lexer<'s> {
|
||||||
pub fn new(src: &'s str) -> Self {
|
pub fn new(src: &'s str) -> Self {
|
||||||
|
Self::new_at(src, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_at(src: &'s str, line: u32) -> Self {
|
||||||
|
let pos = Pos {
|
||||||
|
line,
|
||||||
|
col: 0,
|
||||||
|
idx: 0,
|
||||||
|
};
|
||||||
Self {
|
Self {
|
||||||
src,
|
src,
|
||||||
chars: src.chars().peekable(),
|
chars: src.chars().peekable(),
|
||||||
start_pos: Pos::new(),
|
start_pos: pos,
|
||||||
pos: Pos::new(),
|
pos,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -229,6 +229,12 @@ impl<'s> Parser<'s> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn new_at(src: &'s str, line: u32) -> Self {
|
||||||
|
Self {
|
||||||
|
lexer: Lexer::new_at(src, line).peekable(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn next(&mut self) -> Result<Token<'s>> {
|
fn next(&mut self) -> Result<Token<'s>> {
|
||||||
self.lexer.next().unwrap()
|
self.lexer.next().unwrap()
|
||||||
}
|
}
|
||||||
|
@ -739,3 +745,7 @@ impl<'s> Parser<'s> {
|
||||||
pub fn parse(src: &str) -> Result<Expr> {
|
pub fn parse(src: &str) -> Result<Expr> {
|
||||||
Parser::new(src).parse()
|
Parser::new(src).parse()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_from(src: &str, line: u32) -> Result<Expr> {
|
||||||
|
Parser::new_at(src, line).parse()
|
||||||
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ lazy_static! {
|
||||||
pub static ref SYM_END_ITERATION: Symbol = symbol!(end_iteration);
|
pub static ref SYM_END_ITERATION: Symbol = symbol!(end_iteration);
|
||||||
pub static ref SYM_TYPE: Symbol = symbol!(type);
|
pub static ref SYM_TYPE: Symbol = symbol!(type);
|
||||||
pub static ref SYM_MSG: Symbol = symbol!(msg);
|
pub static ref SYM_MSG: Symbol = symbol!(msg);
|
||||||
|
pub static ref SYM_TRACE: Symbol = symbol!(trace);
|
||||||
pub static ref SYM_TYPE_ERROR: Symbol = symbol!(type_error);
|
pub static ref SYM_TYPE_ERROR: Symbol = symbol!(type_error);
|
||||||
pub static ref SYM_VALUE_ERROR: Symbol = symbol!(value_error);
|
pub static ref SYM_VALUE_ERROR: Symbol = symbol!(value_error);
|
||||||
pub static ref SYM_NAME_ERROR: Symbol = symbol!(name_error);
|
pub static ref SYM_NAME_ERROR: Symbol = symbol!(name_error);
|
||||||
|
|
|
@ -75,7 +75,7 @@ impl Value {
|
||||||
Some(i) => col.index(i),
|
Some(i) => col.index(i),
|
||||||
None => Ok(Value::from(*SYM_END_ITERATION)),
|
None => Ok(Value::from(*SYM_END_ITERATION)),
|
||||||
};
|
};
|
||||||
Ok(NativeFunc::new(Box::new(func), 0, symbol!("index...")).into())
|
Ok(NativeFunc::new(Box::new(func), 0, symbol!("<index...>")).into())
|
||||||
} else {
|
} else {
|
||||||
throw!(*SYM_TYPE_ERROR, "cannot index {col:#} with {idx:#}")
|
throw!(*SYM_TYPE_ERROR, "cannot index {col:#} with {idx:#}")
|
||||||
}
|
}
|
||||||
|
|
|
@ -448,9 +448,21 @@ macro_rules! impl_from {
|
||||||
impl_from!(bool, Bool, hash);
|
impl_from!(bool, Bool, hash);
|
||||||
impl_from!(Symbol, Symbol, hash);
|
impl_from!(Symbol, Symbol, hash);
|
||||||
impl_from!(Range, Range, rc);
|
impl_from!(Range, Range, rc);
|
||||||
|
|
||||||
impl_from!(Int, Int, hash);
|
impl_from!(Int, Int, hash);
|
||||||
impl_from!(i64, Int, into);
|
|
||||||
impl_from!(BigInt, Int, into);
|
impl_from!(BigInt, Int, into);
|
||||||
|
impl_from!(i8, Int, into);
|
||||||
|
impl_from!(i16, Int, into);
|
||||||
|
impl_from!(i32, Int, into);
|
||||||
|
impl_from!(i64, Int, into);
|
||||||
|
impl_from!(isize, Int, into);
|
||||||
|
impl_from!(u8, Int, into);
|
||||||
|
impl_from!(u16, Int, into);
|
||||||
|
impl_from!(u32, Int, into);
|
||||||
|
impl_from!(u64, Int, into);
|
||||||
|
impl_from!(usize, Int, into);
|
||||||
|
|
||||||
|
impl_from!(f32, Float, into);
|
||||||
impl_from!(f64, Float);
|
impl_from!(f64, Float);
|
||||||
impl_from!(Ratio, Ratio, rchash);
|
impl_from!(Ratio, Ratio, rchash);
|
||||||
impl_from!(Complex64, Complex);
|
impl_from!(Complex64, Complex);
|
||||||
|
|
|
@ -546,7 +546,7 @@ impl Value {
|
||||||
range_iter.borrow_mut().next().map(Value::from),
|
range_iter.borrow_mut().next().map(Value::from),
|
||||||
))
|
))
|
||||||
};
|
};
|
||||||
Ok(NativeFunc::new(Box::new(f), 0, symbol!("iter[range]")).into())
|
Ok(NativeFunc::new(Box::new(f), 0, symbol!("<range iter>")).into())
|
||||||
}
|
}
|
||||||
Self::String(s) => {
|
Self::String(s) => {
|
||||||
let byte_pos = RefCell::new(0);
|
let byte_pos = RefCell::new(0);
|
||||||
|
@ -559,7 +559,7 @@ impl Value {
|
||||||
Ok(Value::from(*SYM_END_ITERATION))
|
Ok(Value::from(*SYM_END_ITERATION))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(NativeFunc::new(Box::new(f), 0, symbol!("iter[string]")).into())
|
Ok(NativeFunc::new(Box::new(f), 0, symbol!("<string iter>")).into())
|
||||||
}
|
}
|
||||||
Self::List(list) => {
|
Self::List(list) => {
|
||||||
let idx = RefCell::new(0);
|
let idx = RefCell::new(0);
|
||||||
|
@ -572,7 +572,7 @@ impl Value {
|
||||||
Ok(Value::from(*SYM_END_ITERATION))
|
Ok(Value::from(*SYM_END_ITERATION))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(NativeFunc::new(Box::new(f), 0, symbol!("iter[list]")).into())
|
Ok(NativeFunc::new(Box::new(f), 0, symbol!("<list iter>")).into())
|
||||||
}
|
}
|
||||||
Self::Table(table) => {
|
Self::Table(table) => {
|
||||||
let keys: Vec<HashValue> = table.borrow().keys().cloned().collect();
|
let keys: Vec<HashValue> = table.borrow().keys().cloned().collect();
|
||||||
|
@ -582,7 +582,7 @@ impl Value {
|
||||||
keys.borrow_mut().next().map(HashValue::into_inner),
|
keys.borrow_mut().next().map(HashValue::into_inner),
|
||||||
))
|
))
|
||||||
};
|
};
|
||||||
Ok(NativeFunc::new(Box::new(f), 0, symbol!("iter[table]")).into())
|
Ok(NativeFunc::new(Box::new(f), 0, symbol!("<table iter>")).into())
|
||||||
}
|
}
|
||||||
_ => throw!(*SYM_TYPE_ERROR, "cannot iterate {self:#}"),
|
_ => throw!(*SYM_TYPE_ERROR, "cannot iterate {self:#}"),
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ use crate::{
|
||||||
SYM_VALUE_ERROR,
|
SYM_VALUE_ERROR,
|
||||||
},
|
},
|
||||||
value::{
|
value::{
|
||||||
function::{FuncAttrs, Function, NativeFunc},
|
function::{Function, NativeFunc},
|
||||||
HashValue, Value,
|
HashValue, Value,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -112,19 +112,20 @@ fn get_call_outcome(args: Vec<Value>) -> Result<CallOutcome> {
|
||||||
Ordering::Less => {
|
Ordering::Less => {
|
||||||
let remaining = attrs.arity - argc;
|
let remaining = attrs.arity - argc;
|
||||||
let f = f.clone();
|
let f = f.clone();
|
||||||
|
|
||||||
|
let name = match attrs.name {
|
||||||
|
None => Symbol::get("<partial>"),
|
||||||
|
Some(s) => Symbol::get(&format!("<partial {}>", s.name())),
|
||||||
|
};
|
||||||
|
|
||||||
let nf = move |vm: &mut Vm, inner_args: Vec<Value>| {
|
let nf = move |vm: &mut Vm, inner_args: Vec<Value>| {
|
||||||
let mut ia = inner_args.into_iter();
|
let mut ia = inner_args.into_iter();
|
||||||
ia.next();
|
ia.next();
|
||||||
let args: Vec<Value> = args.clone().into_iter().chain(ia).collect();
|
let args: Vec<Value> = args.clone().into_iter().chain(ia).collect();
|
||||||
vm.call_value(f.clone(), args)
|
vm.call_value(f.clone(), args)
|
||||||
};
|
};
|
||||||
let nf = NativeFunc {
|
|
||||||
attrs: FuncAttrs {
|
let nf = NativeFunc::new(Box::new(nf), remaining, name);
|
||||||
arity: remaining,
|
|
||||||
name: None,
|
|
||||||
},
|
|
||||||
func: Box::new(nf),
|
|
||||||
};
|
|
||||||
Ok(CallOutcome::Partial(nf.into()))
|
Ok(CallOutcome::Partial(nf.into()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -175,7 +176,10 @@ impl Vm {
|
||||||
CallOutcome::Partial(v) => Ok(v),
|
CallOutcome::Partial(v) => Ok(v),
|
||||||
CallOutcome::Call(args) => match value {
|
CallOutcome::Call(args) => match value {
|
||||||
Value::Function(f) => self.run_function(f, args),
|
Value::Function(f) => self.run_function(f, args),
|
||||||
Value::NativeFunc(f) => (f.func)(self, args),
|
Value::NativeFunc(f) => (f.func)(self, args).map_err(|mut e| {
|
||||||
|
e.add_trace(None, f.attrs.name);
|
||||||
|
e
|
||||||
|
}),
|
||||||
_ => unreachable!("already verified by calling get_call_type"),
|
_ => unreachable!("already verified by calling get_call_type"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -198,8 +202,8 @@ impl Vm {
|
||||||
self.stack.truncate(init_stack_len);
|
self.stack.truncate(init_stack_len);
|
||||||
return Ok(v)
|
return Ok(v)
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(exc) => {
|
||||||
if let Err(e) = self.handle_exception(&mut frame, e) {
|
if let Err(e) = self.handle_exception(&mut frame, exc) {
|
||||||
self.stack.truncate(init_stack_len);
|
self.stack.truncate(init_stack_len);
|
||||||
return Err(e)
|
return Err(e)
|
||||||
}
|
}
|
||||||
|
@ -208,8 +212,14 @@ impl Vm {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_exception(&mut self, frame: &mut CallFrame, exc: Exception) -> Result<()> {
|
fn handle_exception(
|
||||||
|
&mut self,
|
||||||
|
frame: &mut CallFrame,
|
||||||
|
mut exc: Exception,
|
||||||
|
) -> Result<()> {
|
||||||
loop {
|
loop {
|
||||||
|
let line = frame.func.chunk.get_line(frame.ip as u32);
|
||||||
|
exc.add_trace(line, frame.func.attrs.name);
|
||||||
while let Some(try_frame) = frame.try_frames.pop() {
|
while let Some(try_frame) = frame.try_frames.pop() {
|
||||||
let table = &frame.func.chunk.try_tables[try_frame.idx];
|
let table = &frame.func.chunk.try_tables[try_frame.idx];
|
||||||
for catch in &table.catches {
|
for catch in &table.catches {
|
||||||
|
|
|
@ -223,7 +223,7 @@ pub fn sort_key(vm: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let nf = NativeFunc::new(Box::new(f), 2, symbol!("inner[sort_key]")).into();
|
let nf = NativeFunc::new(Box::new(f), 2, symbol!("<sort_key inner>")).into();
|
||||||
sort_inner(&mut list.borrow_mut(), Some(&nf), vm)?;
|
sort_inner(&mut list.borrow_mut(), Some(&nf), vm)?;
|
||||||
Ok(list.into())
|
Ok(list.into())
|
||||||
}
|
}
|
||||||
|
|
|
@ -509,7 +509,7 @@ fn tcp_listen_inner(listener: TcpListener) -> Value {
|
||||||
},
|
},
|
||||||
Err(e) => throw!(*SYM_IO_ERROR, "{e}"),
|
Err(e) => throw!(*SYM_IO_ERROR, "{e}"),
|
||||||
};
|
};
|
||||||
NativeFunc::new(Box::new(func), 0, symbol!("inner[tcp_listen]")).into()
|
NativeFunc::new(Box::new(func), 0, symbol!("<tcp_listen inner>")).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[native_func(1)]
|
#[native_func(1)]
|
||||||
|
|
|
@ -95,7 +95,7 @@ pub fn pairs(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
||||||
Ok(Value::iter_pack(None))
|
Ok(Value::iter_pack(None))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(NativeFunc::new(Box::new(f), 0, symbol!("iter[pairs]")).into())
|
Ok(NativeFunc::new(Box::new(f), 0, symbol!("<pairs iterator>")).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[native_func(1)]
|
#[native_func(1)]
|
||||||
|
@ -104,7 +104,7 @@ pub fn once(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
||||||
|
|
||||||
let v = RefCell::new(Some(val));
|
let v = RefCell::new(Some(val));
|
||||||
let f = move |_: &mut Vm, _| Ok(Value::iter_pack(v.borrow_mut().take()));
|
let f = move |_: &mut Vm, _| Ok(Value::iter_pack(v.borrow_mut().take()));
|
||||||
Ok(NativeFunc::new(Box::new(f), 0, symbol!("iter[once]")).into())
|
Ok(NativeFunc::new(Box::new(f), 0, symbol!("<once iterator>")).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[native_func(1)]
|
#[native_func(1)]
|
||||||
|
@ -112,7 +112,7 @@ pub fn forever(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
||||||
let [_, val] = unpack_args!(args);
|
let [_, val] = unpack_args!(args);
|
||||||
|
|
||||||
let f = move |_: &mut Vm, _| Ok(val.clone());
|
let f = move |_: &mut Vm, _| Ok(val.clone());
|
||||||
Ok(NativeFunc::new(Box::new(f), 0, symbol!("iter[forever]")).into())
|
Ok(NativeFunc::new(Box::new(f), 0, symbol!("<forever iterator>")).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -128,7 +128,7 @@ pub fn map(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
||||||
Some(val) => Ok(vmcall!(vm; map.clone(), val)?),
|
Some(val) => Ok(vmcall!(vm; map.clone(), val)?),
|
||||||
None => Ok(Value::iter_pack(None)),
|
None => Ok(Value::iter_pack(None)),
|
||||||
};
|
};
|
||||||
Ok(NativeFunc::new(Box::new(f), 0, symbol!("iter[map]")).into())
|
Ok(NativeFunc::new(Box::new(f), 0, symbol!("<map iterator>")).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[native_func(2)]
|
#[native_func(2)]
|
||||||
|
@ -143,7 +143,7 @@ pub fn tee(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
||||||
}
|
}
|
||||||
None => Ok(Value::iter_pack(None)),
|
None => Ok(Value::iter_pack(None)),
|
||||||
};
|
};
|
||||||
Ok(NativeFunc::new(Box::new(f), 0, symbol!("iter[tee]")).into())
|
Ok(NativeFunc::new(Box::new(f), 0, symbol!("<tee iterator>")).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[native_func(3)]
|
#[native_func(3)]
|
||||||
|
@ -161,7 +161,7 @@ pub fn scan(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
||||||
*result.borrow_mut() = r.clone();
|
*result.borrow_mut() = r.clone();
|
||||||
Ok(r)
|
Ok(r)
|
||||||
};
|
};
|
||||||
Ok(NativeFunc::new(Box::new(f), 0, symbol!("iter[scan]")).into())
|
Ok(NativeFunc::new(Box::new(f), 0, symbol!("<scan iterator>")).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[native_func(2)]
|
#[native_func(2)]
|
||||||
|
@ -178,7 +178,7 @@ pub fn filter(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
||||||
return Ok(next)
|
return Ok(next)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(NativeFunc::new(Box::new(f), 0, symbol!("iter[filter]")).into())
|
Ok(NativeFunc::new(Box::new(f), 0, symbol!("<filter iterator>")).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[native_func(2)]
|
#[native_func(2)]
|
||||||
|
@ -207,7 +207,7 @@ pub fn take(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
||||||
*taken.borrow_mut() += 1;
|
*taken.borrow_mut() += 1;
|
||||||
Ok(next)
|
Ok(next)
|
||||||
};
|
};
|
||||||
Ok(NativeFunc::new(Box::new(f), 0, symbol!("iter[take]")).into())
|
Ok(NativeFunc::new(Box::new(f), 0, symbol!("<take iterator>")).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[native_func(2)]
|
#[native_func(2)]
|
||||||
|
@ -235,7 +235,7 @@ pub fn skip(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
||||||
}
|
}
|
||||||
vmcall!(vm; iter.clone())
|
vmcall!(vm; iter.clone())
|
||||||
};
|
};
|
||||||
Ok(NativeFunc::new(Box::new(f), 0, symbol!("iter[skip]")).into())
|
Ok(NativeFunc::new(Box::new(f), 0, symbol!("<skip iterator>")).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[native_func(1)]
|
#[native_func(1)]
|
||||||
|
@ -254,7 +254,7 @@ pub fn enumerate(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
||||||
Ok(Value::from(vec![n.into(), next]))
|
Ok(Value::from(vec![n.into(), next]))
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(NativeFunc::new(Box::new(f), 0, symbol!("iter[enumerate]")).into())
|
Ok(NativeFunc::new(Box::new(f), 0, symbol!("<enumerate iterator>")).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[native_func(1)]
|
#[native_func(1)]
|
||||||
|
@ -288,7 +288,7 @@ pub fn cycle(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(NativeFunc::new(Box::new(f), 0, symbol!("iter[cycle]")).into())
|
Ok(NativeFunc::new(Box::new(f), 0, symbol!("<cycle iterator>")).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Default)]
|
#[derive(Clone, Copy, Default)]
|
||||||
|
@ -336,7 +336,7 @@ pub fn step(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
||||||
}
|
}
|
||||||
Step::End => Ok(Value::Nil),
|
Step::End => Ok(Value::Nil),
|
||||||
};
|
};
|
||||||
Ok(NativeFunc::new(Box::new(f), 0, symbol!("iter[step]")).into())
|
Ok(NativeFunc::new(Box::new(f), 0, symbol!("<step iterator>")).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[native_func(1)]
|
#[native_func(1)]
|
||||||
|
@ -355,7 +355,7 @@ pub fn rev(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
||||||
}
|
}
|
||||||
Ok(Value::iter_pack(lst.borrow_mut().as_mut().unwrap().pop()))
|
Ok(Value::iter_pack(lst.borrow_mut().as_mut().unwrap().pop()))
|
||||||
};
|
};
|
||||||
Ok(NativeFunc::new(Box::new(f), 0, symbol!("iter[rev]")).into())
|
Ok(NativeFunc::new(Box::new(f), 0, symbol!("<rev iterator>")).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -381,7 +381,7 @@ pub fn zip(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
||||||
Ok(Value::from(res))
|
Ok(Value::from(res))
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(NativeFunc::new(Box::new(f), 0, symbol!("iter[zip]")).into())
|
Ok(NativeFunc::new(Box::new(f), 0, symbol!("<zip iterator>")).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[native_func(1)]
|
#[native_func(1)]
|
||||||
|
@ -407,7 +407,7 @@ pub fn zipn(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
||||||
Ok(Value::from(res))
|
Ok(Value::from(res))
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(NativeFunc::new(Box::new(f), 0, symbol!("iter[zipn]")).into())
|
Ok(NativeFunc::new(Box::new(f), 0, symbol!("<zipn iterator>")).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[native_func(2)]
|
#[native_func(2)]
|
||||||
|
@ -434,7 +434,7 @@ pub fn alternate(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(NativeFunc::new(Box::new(f), 0, symbol!("iter[alternate]")).into())
|
Ok(NativeFunc::new(Box::new(f), 0, symbol!("<alternate iterator>")).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[native_func(1)]
|
#[native_func(1)]
|
||||||
|
@ -466,7 +466,7 @@ pub fn alternaten(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(NativeFunc::new(Box::new(f), 0, symbol!("iter[alternaten]")).into())
|
Ok(NativeFunc::new(Box::new(f), 0, symbol!("<alternaten iterator>")).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -510,7 +510,7 @@ pub fn intersperse(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
||||||
Intersperse::End => Ok(Value::iter_pack(None)),
|
Intersperse::End => Ok(Value::iter_pack(None)),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(NativeFunc::new(Box::new(f), 0, symbol!("iter[intersperse]")).into())
|
Ok(NativeFunc::new(Box::new(f), 0, symbol!("<intersperse iterator>")).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[native_func(2)]
|
#[native_func(2)]
|
||||||
|
@ -532,7 +532,7 @@ pub fn chain(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(NativeFunc::new(Box::new(f), 0, symbol!("iter[chain]")).into())
|
Ok(NativeFunc::new(Box::new(f), 0, symbol!("<chain iterator>")).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
|
@ -597,7 +597,7 @@ pub fn cartprod(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
||||||
Ok(Value::from(vec![a_res, b_res]))
|
Ok(Value::from(vec![a_res, b_res]))
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(NativeFunc::new(Box::new(f), 0, symbol!("iter[cart_prod]")).into())
|
Ok(NativeFunc::new(Box::new(f), 0, symbol!("<cart_prod iterator>")).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
Loading…
Add table
Reference in a new issue