trace
All checks were successful
docs / test (push) Successful in 9s

This commit is contained in:
trimill 2025-01-01 16:27:14 -05:00
parent b1fccce8e3
commit c75dafac8e
15 changed files with 203 additions and 56 deletions

View file

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

View file

@ -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,

View file

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

View file

@ -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;

View file

@ -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 {

View file

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

View file

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

View file

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

View file

@ -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:#}")
} }

View file

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

View file

@ -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:#}"),
} }

View file

@ -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 {

View file

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

View file

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

View file

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