fix and refactor

This commit is contained in:
trimill 2024-03-07 19:38:57 -05:00
parent bc3fb597d5
commit 296ff666cb
Signed by: trimill
GPG key ID: 4F77A16E17E10BCB
15 changed files with 138 additions and 114 deletions

1
Cargo.lock generated
View file

@ -772,6 +772,7 @@ dependencies = [
"lazy_static", "lazy_static",
"num-complex", "num-complex",
"num-rational", "num-rational",
"num-traits",
"thiserror", "thiserror",
] ]

View file

@ -1,3 +1,7 @@
[workspace] [workspace]
members = ["talc-lang", "talc-bin", "talc-std", "talc-macros"] members = ["talc-lang", "talc-bin", "talc-std", "talc-macros"]
resolver = "2" resolver = "2"
[profile.release-lto]
inherits = "release"
lto = "fat"

View file

@ -3,6 +3,10 @@ name = "talc-bin"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
[[bin]]
name = "talc"
path = "src/main.rs"
[dependencies] [dependencies]
talc-lang = { path = "../talc-lang" } talc-lang = { path = "../talc-lang" }
talc-std = { path = "../talc-std" } talc-std = { path = "../talc-std" }

View file

@ -106,7 +106,7 @@ impl Highlighter for TalcHelper {
} }
fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> { fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> {
Cow::Owned(format!("\x1b[37m{}\x1b[0m", hint)) Cow::Owned(format!("\x1b[37m{hint}\x1b[0m"))
} }
fn highlight_char(&self, line: &str, _: usize, forced: bool) -> bool { fn highlight_char(&self, line: &str, _: usize, forced: bool) -> bool {

View file

@ -19,6 +19,10 @@ struct Args {
#[arg(short, long)] #[arg(short, long)]
disasm: bool, disasm: bool,
/// show disassembled bytecode
#[arg(short='H', long)]
histfile: Option<PathBuf>,
/// enable or disable color /// enable or disable color
#[arg(short, long, default_value="auto")] #[arg(short, long, default_value="auto")]
color: ColorChoice, color: ColorChoice,

View file

@ -1,7 +1,7 @@
use std::{cell::RefCell, io::IsTerminal, process::ExitCode, rc::Rc}; use std::{cell::RefCell, io::IsTerminal, process::ExitCode, rc::Rc};
use clap::ColorChoice; use clap::ColorChoice;
use rustyline::{error::ReadlineError, history::MemHistory, ColorMode, Config, Editor}; use rustyline::{error::ReadlineError, history::{FileHistory, History}, ColorMode, Config, Editor};
use talc_lang::{compiler::compile_repl, symbol::Symbol, value::{function::disasm_recursive, Value}, Vm}; use talc_lang::{compiler::compile_repl, symbol::Symbol, value::{function::disasm_recursive, Value}, Vm};
use crate::{helper::TalcHelper, Args}; use crate::{helper::TalcHelper, Args};
@ -39,21 +39,30 @@ fn get_colmode(args: &Args) -> ColorMode {
} }
} }
pub fn init_rustyline(args: &Args) -> Result<Editor<TalcHelper, MemHistory>, ExitCode> { pub fn init_rustyline(args: &Args) -> Result<Editor<TalcHelper, FileHistory>, ExitCode> {
let config = Config::builder() let config = Config::builder()
.auto_add_history(true) .auto_add_history(true)
.color_mode(get_colmode(args)) .color_mode(get_colmode(args))
.check_cursor_position(true) .check_cursor_position(true)
.completion_type(rustyline::CompletionType::List) .completion_type(rustyline::CompletionType::List)
.max_history_size(4096).unwrap()
.build(); .build();
match rustyline::Editor::with_history(config, MemHistory::default()) { let mut hist = FileHistory::default();
if let Some(f) = &args.histfile {
if hist.load(f).is_err() {
eprintln!("Warn: failed to load history");
} else if hist.save(f).is_err() {
eprintln!("Warn: failed to save history");
}
}
match rustyline::Editor::with_history(config, hist) {
Ok(rl) => Ok(rl), Ok(rl) => Ok(rl),
Err(ReadlineError::Io(e)) => { Err(ReadlineError::Io(e)) => {
eprintln!("Error: {e}"); eprintln!("Error creating repl: {e}");
Err(ExitCode::FAILURE) Err(ExitCode::FAILURE)
}, },
Err(ReadlineError::Errno(e)) => { Err(ReadlineError::Errno(e)) => {
eprintln!("Error: {e}"); eprintln!("Error creating repl: {e}");
Err(ExitCode::FAILURE) Err(ExitCode::FAILURE)
}, },
Err(_) => Err(ExitCode::SUCCESS) Err(_) => Err(ExitCode::SUCCESS)
@ -75,7 +84,7 @@ pub fn repl(args: &Args) -> ExitCode {
interrupt.fetch_or(true, std::sync::atomic::Ordering::Relaxed); interrupt.fetch_or(true, std::sync::atomic::Ordering::Relaxed);
}); });
if let Err(e) = ctrlc_res { if let Err(e) = ctrlc_res {
eprintln!("Warn: couldn't set ctrl+c handler: {e}") eprintln!("Warn: couldn't set ctrl+c handler: {e}");
} }
let prev1_sym = Symbol::get("_"); let prev1_sym = Symbol::get("_");
@ -98,6 +107,9 @@ pub fn repl(args: &Args) -> ExitCode {
rl.set_helper(Some(TalcHelper::new(vm.clone()))); rl.set_helper(Some(TalcHelper::new(vm.clone())));
loop { loop {
if let Some(f) = &args.histfile {
let _ = rl.save_history(f);
}
let line = rl.readline(">> "); let line = rl.readline(">> ");
let line = match line { let line = match line {
Ok(line) => line, Ok(line) => line,

View file

@ -7,6 +7,7 @@ edition = "2021"
lalrpop-util = { version = "0.20", features = ["lexer", "unicode"] } lalrpop-util = { version = "0.20", features = ["lexer", "unicode"] }
num-complex = "0.4" num-complex = "0.4"
num-rational = { version = "0.4", default-features = false, features = [] } num-rational = { version = "0.4", default-features = false, features = [] }
num-traits = "*"
thiserror = "1.0" thiserror = "1.0"
lazy_static = "1.4" lazy_static = "1.4"

View file

@ -43,6 +43,7 @@ static TABLE: OnceLock<Mutex<SymbolTable>> = OnceLock::new();
const MAX_SYMBOL: usize = 0xff_ffff; const MAX_SYMBOL: usize = 0xff_ffff;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
#[repr(transparent)]
pub struct Symbol(u32); pub struct Symbol(u32);
fn get_table() -> &'static Mutex<SymbolTable> { fn get_table() -> &'static Mutex<SymbolTable> {

View file

@ -34,7 +34,7 @@ impl Value {
let col = col.clone(); let col = col.clone();
let func = move |vm: &mut Vm, _| { let func = move |vm: &mut Vm, _| {
match vmcalliter!(vm; ii.clone())? { match vmcalliter!(vm; ii.clone())? {
Some(i) => Ok(col.index(i)?.to_cell()), Some(i) => col.index(i),
None => Ok(Value::from(*SYM_END_ITERATION)), None => Ok(Value::from(*SYM_END_ITERATION)),
} }
}; };
@ -82,7 +82,7 @@ impl Value {
} }
let end = tm.split_off(r.stop as usize); let end = tm.split_off(r.stop as usize);
tm.truncate(r.start as usize); tm.truncate(r.start as usize);
tm.extend(vals.into_iter().chain(end)) tm.extend(vals.into_iter().chain(end));
}, },
RangeType::Closed => { RangeType::Closed => {
if r.start < 0 || r.start > tm.len() as i64 { if r.start < 0 || r.start > tm.len() as i64 {
@ -95,7 +95,7 @@ impl Value {
} }
let end = tm.split_off(r.stop as usize + 1); let end = tm.split_off(r.stop as usize + 1);
tm.truncate(r.start as usize); tm.truncate(r.start as usize);
tm.extend(vals.into_iter().chain(end)) tm.extend(vals.into_iter().chain(end));
}, },
RangeType::Endless => { RangeType::Endless => {
if r.start < 0 || r.start > tm.len() as i64 { if r.start < 0 || r.start > tm.len() as i64 {
@ -103,7 +103,7 @@ impl Value {
"index {} out of bounds for list of length {}", r.stop, tm.len()) "index {} out of bounds for list of length {}", r.stop, tm.len())
} }
tm.truncate(r.start as usize); tm.truncate(r.start as usize);
tm.extend(vals) tm.extend(vals);
}, },
} }
Ok(()) Ok(())

View file

@ -7,6 +7,16 @@ use crate::{exception::{throw, Result}, symbol::{SYM_END_ITERATION, SYM_TYPE_ERR
use super::{function::{FuncAttrs, NativeFunc}, range::Range, HashValue, Value}; use super::{function::{FuncAttrs, NativeFunc}, range::Range, HashValue, Value};
pub trait RatioExt {
fn to_f64(&self) -> f64;
}
impl RatioExt for Rational64 {
fn to_f64(&self) -> f64 {
num_traits::ToPrimitive::to_f64(self).unwrap_or(f64::NAN)
}
}
impl Value { impl Value {
pub fn truthy(&self) -> bool { pub fn truthy(&self) -> bool {
match self { match self {
@ -27,11 +37,6 @@ impl Value {
} }
} }
#[allow(clippy::cast_precision_loss)]
fn ratio_to_f64(r: Rational64) -> f64 {
*r.numer() as f64 / *r.denom() as f64
}
#[allow(clippy::cast_precision_loss)] #[allow(clippy::cast_precision_loss)]
pub fn promote(a: Value, b: Value) -> (Value, Value) { pub fn promote(a: Value, b: Value) -> (Value, Value) {
use Value as V; use Value as V;
@ -39,14 +44,14 @@ pub fn promote(a: Value, b: Value) -> (Value, Value) {
(V::Int(x), V::Ratio(..)) => (V::Ratio((*x).into()), b), (V::Int(x), V::Ratio(..)) => (V::Ratio((*x).into()), b),
(V::Int(x), V::Float(..)) => (V::Float(*x as f64), b), (V::Int(x), V::Float(..)) => (V::Float(*x as f64), b),
(V::Int(x), V::Complex(..)) => (V::Complex((*x as f64).into()), b), (V::Int(x), V::Complex(..)) => (V::Complex((*x as f64).into()), b),
(V::Ratio(x), V::Float(..)) => (V::Float(ratio_to_f64(*x)), b), (V::Ratio(x), V::Float(..)) => (V::Float(x.to_f64()), b),
(V::Ratio(x), V::Complex(..)) => (V::Complex(ratio_to_f64(*x).into()), b), (V::Ratio(x), V::Complex(..)) => (V::Complex(x.to_f64().into()), b),
(V::Float(x), V::Complex(..)) => (V::Complex((*x).into()), b), (V::Float(x), V::Complex(..)) => (V::Complex(x.into()), b),
(V::Ratio(..), V::Int(y)) => (a, V::Ratio((*y).into())), (V::Ratio(..), V::Int(y)) => (a, V::Ratio((*y).into())),
(V::Float(..), V::Int(y)) => (a, V::Float(*y as f64)), (V::Float(..), V::Int(y)) => (a, V::Float(*y as f64)),
(V::Complex(..), V::Int(y)) => (a, V::Complex((*y as f64).into())), (V::Complex(..), V::Int(y)) => (a, V::Complex((*y as f64).into())),
(V::Float(..), V::Ratio(y)) => (a, V::Float(ratio_to_f64(*y))), (V::Float(..), V::Ratio(y)) => (a, V::Float(y.to_f64())),
(V::Complex(..), V::Ratio(y)) => (a, V::Complex(ratio_to_f64(*y).into())), (V::Complex(..), V::Ratio(y)) => (a, V::Complex(y.to_f64().into())),
(V::Complex(..), V::Float(y)) => (a, V::Complex((*y).into())), (V::Complex(..), V::Float(y)) => (a, V::Complex((*y).into())),
_ => (a, b), _ => (a, b),
} }
@ -183,7 +188,7 @@ impl Value {
(V::Float(x), V::Float(y)) (V::Float(x), V::Float(y))
=> Ok(V::Float(x.powf(y))), => Ok(V::Float(x.powf(y))),
(V::Ratio(x), V::Ratio(y)) (V::Ratio(x), V::Ratio(y))
=> Ok(V::Float(ratio_to_f64(x).powf(ratio_to_f64(y)))), => Ok(V::Float(x.to_f64().powf(y.to_f64()))),
(V::Complex(x), V::Complex(y)) (V::Complex(x), V::Complex(y))
=> Ok(V::Complex(x.powc(y))), => Ok(V::Complex(x.powc(y))),
(l, r) => throw!(*SYM_TYPE_ERROR, "cannot exponentiate {l:#} and {r:#}") (l, r) => throw!(*SYM_TYPE_ERROR, "cannot exponentiate {l:#} and {r:#}")
@ -209,10 +214,10 @@ impl PartialEq for Value {
(V::Float(a), V::Int(b)) => *a == *b as f64, (V::Float(a), V::Int(b)) => *a == *b as f64,
(V::Int(a), V::Complex(b)) => Complex64::from(*a as f64) == *b, (V::Int(a), V::Complex(b)) => Complex64::from(*a as f64) == *b,
(V::Complex(a), V::Int(b)) => *a == Complex64::from(*b as f64), (V::Complex(a), V::Int(b)) => *a == Complex64::from(*b as f64),
(V::Ratio(a), V::Float(b)) => ratio_to_f64(*a) == *b, (V::Ratio(a), V::Float(b)) => a.to_f64() == *b,
(V::Float(a), V::Ratio(b)) => *a == ratio_to_f64(*b), (V::Float(a), V::Ratio(b)) => *a == b.to_f64(),
(V::Ratio(a), V::Complex(b)) => Complex64::from(ratio_to_f64(*a)) == *b, (V::Ratio(a), V::Complex(b)) => Complex64::from(a.to_f64()) == *b,
(V::Complex(a), V::Ratio(b)) => *a == Complex64::from(ratio_to_f64(*b)), (V::Complex(a), V::Ratio(b)) => *a == Complex64::from(b.to_f64()),
(V::Float(a), V::Complex(b)) => Complex64::from(*a) == *b, (V::Float(a), V::Complex(b)) => Complex64::from(*a) == *b,
(V::Complex(a), V::Float(b)) => *a == Complex64::from(*b), (V::Complex(a), V::Float(b)) => *a == Complex64::from(*b),
(V::String(a), V::String(b)) => *a == *b, (V::String(a), V::String(b)) => *a == *b,
@ -246,8 +251,8 @@ impl PartialOrd for Value {
(V::Ratio(a), V::Int(b)) => a.partial_cmp(&Rational64::from(*b)), (V::Ratio(a), V::Int(b)) => a.partial_cmp(&Rational64::from(*b)),
(V::Int(a), V::Float(b)) => (*a as f64).partial_cmp(b), (V::Int(a), V::Float(b)) => (*a as f64).partial_cmp(b),
(V::Float(a), V::Int(b)) => a.partial_cmp(&(*b as f64)), (V::Float(a), V::Int(b)) => a.partial_cmp(&(*b as f64)),
(V::Ratio(a), V::Float(b)) => ratio_to_f64(*a).partial_cmp(b), (V::Ratio(a), V::Float(b)) => a.to_f64().partial_cmp(b),
(V::Float(a), V::Ratio(b)) => a.partial_cmp(&ratio_to_f64(*b)), (V::Float(a), V::Ratio(b)) => a.partial_cmp(&b.to_f64()),
(V::String(a), V::String(b)) => a.partial_cmp(b), (V::String(a), V::String(b)) => a.partial_cmp(b),
(V::List(a), V::List(b)) => a.borrow().partial_cmp(&*b.borrow()), (V::List(a), V::List(b)) => a.borrow().partial_cmp(&*b.borrow()),
(V::Symbol(a), V::Symbol(b)) => a.partial_cmp(b), (V::Symbol(a), V::Symbol(b)) => a.partial_cmp(b),

View file

@ -296,7 +296,7 @@ impl Vm {
// [a0,a1...an] -.> [[a0,a1...an]] // [a0,a1...an] -.> [[a0,a1...an]]
I::NewList(n) => { I::NewList(n) => {
let list = self.pop_n(n as usize); let list = self.pop_n(n as usize);
self.push(list.into()) self.push(list.into());
}, },
// [l,a0,a1...an] -.> [l ++ [a0,a1...an]] // [l,a0,a1...an] -.> [l ++ [a0,a1...an]]
I::GrowList(n) => { I::GrowList(n) => {
@ -314,7 +314,7 @@ impl Vm {
let k = self.pop(); let k = self.pop();
table.insert(k.try_into()?, v); table.insert(k.try_into()?, v);
} }
self.push(table.into()) self.push(table.into());
}, },
// [t,k0,v0...kn,vn] -> [t ++ {k0=v0...kn=vn}] // [t,k0,v0...kn,vn] -> [t ++ {k0=v0...kn=vn}]
I::GrowTable(n) => { I::GrowTable(n) => {
@ -348,17 +348,17 @@ impl Vm {
// ip = n // ip = n
I::Jump(n) => { I::Jump(n) => {
self.check_interrupt()?; self.check_interrupt()?;
frame.ip = usize::from(n) frame.ip = usize::from(n);
}, },
// [v] ->, [], if v then ip = n // [v] ->, [], if v then ip = n
I::JumpTrue(n) => if self.pop().truthy() { I::JumpTrue(n) => if self.pop().truthy() {
self.check_interrupt()?; self.check_interrupt()?;
frame.ip = usize::from(n) frame.ip = usize::from(n);
}, },
// [v] ->, [], if not v then ip = n // [v] ->, [], if not v then ip = n
I::JumpFalse(n) => if !self.pop().truthy() { I::JumpFalse(n) => if !self.pop().truthy() {
self.check_interrupt()?; self.check_interrupt()?;
frame.ip = usize::from(n) frame.ip = usize::from(n);
}, },
// [v] -> [iter(v)] // [v] -> [iter(v)]
I::IterBegin => { I::IterBegin => {
@ -368,12 +368,11 @@ impl Vm {
// [i,cell(v)] -> [i,v] // [i,cell(v)] -> [i,v]
// [i,nil] -> [], ip = n // [i,nil] -> [], ip = n
I::IterTest(n) => { I::IterTest(n) => {
match self.pop().iter_unpack() { if let Some(v) = self.pop().iter_unpack() {
Some(v) => self.push(v), self.push(v);
None => { } else {
self.pop(); self.pop();
frame.ip = usize::from(n) frame.ip = usize::from(n);
},
} }
}, },
// try_frames.push(t, stack.len()) // try_frames.push(t, stack.len())

View file

@ -132,7 +132,7 @@ pub fn tee(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
match vmcalliter!(vm; iter.clone())? { match vmcalliter!(vm; iter.clone())? {
Some(val) => { Some(val) => {
vmcall!(vm; tee.clone(), val.clone())?; vmcall!(vm; tee.clone(), val.clone())?;
Ok(val.into()) Ok(val)
} }
None => Ok(Value::iter_pack(None)), None => Ok(Value::iter_pack(None)),
} }
@ -170,7 +170,7 @@ pub fn filter(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
}; };
let res = vmcall!(vm; filter.clone(), next.clone())?; let res = vmcall!(vm; filter.clone(), next.clone())?;
if res.truthy() { if res.truthy() {
return Ok(next.into()) return Ok(next)
} }
} }
}; };
@ -198,7 +198,7 @@ pub fn take(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
return Ok(Value::iter_pack(None)) return Ok(Value::iter_pack(None))
}; };
*taken.borrow_mut() += 1; *taken.borrow_mut() += 1;
Ok(next.into()) Ok(next)
}; };
Ok(NativeFunc::new(Box::new(f), 0).into()) Ok(NativeFunc::new(Box::new(f), 0).into())
} }
@ -262,22 +262,19 @@ pub fn cycle(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
} }
let val = r.0[r.2].clone(); let val = r.0[r.2].clone();
r.2 = (r.2 + 1) % r.0.len(); r.2 = (r.2 + 1) % r.0.len();
return Ok(val.into()) return Ok(val)
} }
match vmcalliter!(vm; iter.clone())? { if let Some(v) = vmcalliter!(vm; iter.clone())? {
Some(v) => { record.borrow_mut().0.push(v.clone());
record.borrow_mut().0.push(v.clone()); Ok(v)
Ok(v.into()) } else {
}, let mut r = record.borrow_mut();
None => { r.1 = true;
let mut r = record.borrow_mut(); if r.0.is_empty() {
r.1 = true; Ok(Value::iter_pack(None))
if r.0.is_empty() { } else {
Ok(Value::iter_pack(None)) r.2 = (r.2 + 1) % r.0.len();
} else { Ok(r.0[0].clone())
r.2 = (r.2 + 1) % r.0.len();
Ok(r.0[0].clone().into())
}
} }
} }
}; };
@ -337,7 +334,7 @@ pub fn rev(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
if lst.borrow().is_none() { if lst.borrow().is_none() {
let mut l = Vec::new(); let mut l = Vec::new();
while let Some(x) = vmcalliter!(vm; iter.clone())? { while let Some(x) = vmcalliter!(vm; iter.clone())? {
l.push(x) l.push(x);
} }
*lst.borrow_mut() = Some(l); *lst.borrow_mut() = Some(l);
} }
@ -392,12 +389,11 @@ pub fn alternate(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
let n = s.0; let n = s.0;
s.0 = (s.0 + 1) % iters.len(); s.0 = (s.0 + 1) % iters.len();
drop(s); drop(s);
match vmcalliter!(vm; iters[n].clone())? { if let Some(v) = vmcalliter!(vm; iters[n].clone())? {
Some(v) => Ok(v), Ok(v)
None => { } else {
state.borrow_mut().1 = true; state.borrow_mut().1 = true;
Ok(Value::iter_pack(None)) Ok(Value::iter_pack(None))
}
} }
}; };
@ -417,25 +413,23 @@ pub fn intersperse(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
let state = RefCell::new(Intersperse::Init); let state = RefCell::new(Intersperse::Init);
let f = move |vm: &mut Vm, _| { let f = move |vm: &mut Vm, _| {
match state.take() { match state.take() {
Intersperse::Init => match vmcalliter!(vm; iter.clone())? { Intersperse::Init => {
Some(v) => { if let Some(v) = vmcalliter!(vm; iter.clone())? {
*state.borrow_mut() = Intersperse::Waiting; *state.borrow_mut() = Intersperse::Waiting;
Ok(v) Ok(v)
}, } else {
None => {
*state.borrow_mut() = Intersperse::End; *state.borrow_mut() = Intersperse::End;
Ok(Value::iter_pack(None)) Ok(Value::iter_pack(None))
}, }
}, },
Intersperse::Waiting => match vmcalliter!(vm; iter.clone())? { Intersperse::Waiting => {
Some(v) => { if let Some(v) = vmcalliter!(vm; iter.clone())? {
*state.borrow_mut() = Intersperse::HasNext(v); *state.borrow_mut() = Intersperse::HasNext(v);
Ok(val.clone()) Ok(val.clone())
}, } else {
None => {
*state.borrow_mut() = Intersperse::End; *state.borrow_mut() = Intersperse::End;
Ok(Value::iter_pack(None)) Ok(Value::iter_pack(None))
}, }
}, },
Intersperse::HasNext(v) => { Intersperse::HasNext(v) => {
*state.borrow_mut() = Intersperse::Waiting; *state.borrow_mut() = Intersperse::Waiting;
@ -460,12 +454,11 @@ pub fn chain(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
if *done_first.borrow() { if *done_first.borrow() {
return vmcall!(vm; iter2.clone()) return vmcall!(vm; iter2.clone())
} }
match vmcalliter!(vm; iter1.clone())? { if let Some(v) = vmcalliter!(vm; iter1.clone())? {
Some(v) => Ok(v), Ok(v)
None => { } else {
*done_first.borrow_mut() = true; *done_first.borrow_mut() = true;
vmcall!(vm; iter2.clone()) vmcall!(vm; iter2.clone())
}
} }
}; };
@ -494,38 +487,36 @@ pub fn cartprod(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
} }
if state.borrow().b_idx >= state.borrow().b_data.len() { if state.borrow().b_idx >= state.borrow().b_data.len() {
if !state.borrow().b_done { if state.borrow().b_done {
let v = vmcalliter!(vm; b.clone())?;
let mut s = state.borrow_mut();
match v {
Some(x) => s.b_data.push(x),
None => {
s.b_done = true;
if s.b_idx == 0 {
s.done = true;
return Ok(Value::iter_pack(None))
}
s.b_idx = 0;
}
};
} else {
if state.borrow().b_idx == 0 { if state.borrow().b_idx == 0 {
state.borrow_mut().done = true; state.borrow_mut().done = true;
return Ok(Value::Nil) return Ok(Value::Nil)
} }
state.borrow_mut().b_idx = 0; state.borrow_mut().b_idx = 0;
} else {
let v = vmcalliter!(vm; b.clone())?;
let mut s = state.borrow_mut();
if let Some(x) = v {
s.b_data.push(x)
} else {
s.b_done = true;
if s.b_idx == 0 {
s.done = true;
return Ok(Value::iter_pack(None))
}
s.b_idx = 0;
}
} }
} }
let b_res = state.borrow().b_data[state.borrow().b_idx].clone(); let b_res = state.borrow().b_data[state.borrow().b_idx].clone();
if state.borrow().b_idx == 0 { if state.borrow().b_idx == 0 {
match vmcalliter!(vm; a.clone())? { if let Some(v) = vmcalliter!(vm; a.clone())? {
Some(v) => state.borrow_mut().a_val = v, state.borrow_mut().a_val = v
None => { } else {
state.borrow_mut().done = true; state.borrow_mut().done = true;
return Ok(Value::iter_pack(None)) return Ok(Value::iter_pack(None))
}
} }
} }
@ -629,7 +620,7 @@ pub fn sum(vm: &mut Vm, args: Vec<Value>) -> Result<Value> {
let mut result = Value::Int(0); let mut result = Value::Int(0);
while let Some(value) = vmcalliter!(vm; iter.clone())? { while let Some(value) = vmcalliter!(vm; iter.clone())? {
result = (result + value)? result = (result + value)?;
} }
Ok(result) Ok(result)
} }
@ -641,7 +632,7 @@ pub fn prod(vm: &mut Vm, args: Vec<Value>) -> Result<Value> {
let mut result = Value::Int(1); let mut result = Value::Int(1);
while let Some(value) = vmcalliter!(vm; iter.clone())? { while let Some(value) = vmcalliter!(vm; iter.clone())? {
result = (result * value)? result = (result * value)?;
} }
Ok(result) Ok(result)
} }

View file

@ -124,10 +124,10 @@ fn to_radix_inner(n: i64, radix: u32) -> String {
if n < 0 { if n < 0 {
result.push('-' as u32 as u8); result.push('-' as u32 as u8);
begin = 1; begin = 1;
x = (-n) as u64 x = (-n) as u64;
} else { } else {
x = n as u64 x = n as u64;
}; }
loop { loop {
let m = x % (radix as u64); let m = x % (radix as u64);
@ -360,9 +360,8 @@ pub fn factors(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
x /= 3; x /= 3;
factors.push(Value::Int(3)); factors.push(Value::Int(3));
} }
//let lim = isqrt_inner(x);
let mut i = 5; let mut i = 5;
while x > 1 { while x >= i*i {
while x % i == 0 { while x % i == 0 {
x /= i; x /= i;
factors.push(Value::Int(i)); factors.push(Value::Int(i));
@ -374,6 +373,9 @@ pub fn factors(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
} }
i += 4; i += 4;
} }
if x > 1 {
factors.push(Value::Int(x));
}
Ok(factors.into()) Ok(factors.into())
} }

View file

@ -53,7 +53,7 @@ pub fn rand_in(vm: &mut Vm, args: Vec<Value>) -> Result<Value> {
while let Some(v) = vmcalliter!(vm; iter.clone())? { while let Some(v) = vmcalliter!(vm; iter.clone())? {
values.push(v); values.push(v);
} }
if values.len() == 0 { if values.is_empty() {
throw!(*SYM_TYPE_ERROR, "rand_in: empty iterator") throw!(*SYM_TYPE_ERROR, "rand_in: empty iterator")
} }
let i = rand::thread_rng().gen_range(0..values.len()); let i = rand::thread_rng().gen_range(0..values.len());

View file

@ -1,6 +1,6 @@
use std::{cell::RefCell, collections::HashMap, rc::Rc}; use std::{cell::RefCell, collections::HashMap, rc::Rc};
use talc_lang::{exception, parse_float, parse_int, symbol::SYM_TYPE_ERROR, throw, value::{HashValue, Rational64, Value}, Vm, exception::Result}; use talc_lang::{exception::Result, parse_float, parse_int, symbol::SYM_TYPE_ERROR, throw, exception, value::{ops::RatioExt, HashValue, Rational64, Value}, Vm};
use talc_macros::native_func; use talc_macros::native_func;
use crate::unpack_args; use crate::unpack_args;
@ -49,7 +49,7 @@ pub fn as_(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
if val.get_type() == ty { if val.get_type() == ty {
return Ok(val) return Ok(val)
} }
match (val, ty.name().as_ref()) { match (val, ty.name()) {
(_, "nil") => Ok(Value::Nil), (_, "nil") => Ok(Value::Nil),
(v, "string") => Ok(Value::String(v.to_string().into())), (v, "string") => Ok(Value::String(v.to_string().into())),
(v, "bool") => Ok(Value::Bool(v.truthy())), (v, "bool") => Ok(Value::Bool(v.truthy())),
@ -59,9 +59,9 @@ pub fn as_(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
(Value::Int(x), "ratio") => Ok(Value::Ratio(x.into())), (Value::Int(x), "ratio") => Ok(Value::Ratio(x.into())),
(Value::Int(x), "float") => Ok(Value::Float(x as f64)), (Value::Int(x), "float") => Ok(Value::Float(x as f64)),
(Value::Int(x), "complex") => Ok(Value::Complex((x as f64).into())), (Value::Int(x), "complex") => Ok(Value::Complex((x as f64).into())),
(Value::Ratio(x), "int") => Ok(Value::Int(*x.numer() / *x.denom())), (Value::Ratio(x), "int") => Ok(Value::Int(x.to_integer())),
(Value::Ratio(x), "float") => Ok(Value::Float(*x.numer() as f64 / *x.denom() as f64)), (Value::Ratio(x), "float") => Ok(Value::Float(x.to_f64())),
(Value::Ratio(x), "complex") => Ok(Value::Complex((*x.numer() as f64 / *x.denom() as f64).into())), (Value::Ratio(x), "complex") => Ok(Value::Complex(x.to_f64().into())),
(Value::Float(x), "int") => Ok(Value::Int(x as i64)), (Value::Float(x), "int") => Ok(Value::Int(x as i64)),
(Value::Float(x), "ratio") => { (Value::Float(x), "ratio") => {
let r = Rational64::approximate_float(x) let r = Rational64::approximate_float(x)