This commit is contained in:
trimill 2024-02-28 11:47:15 -05:00
parent 2c54025d00
commit bc3fb597d5
Signed by: trimill
GPG Key ID: 4F77A16E17E10BCB
7 changed files with 72 additions and 73 deletions

View File

@ -1,4 +1,3 @@
[workspace] [workspace]
members = ["talc-lang", "talc-bin", "talc-std", "talc-macros"] members = ["talc-lang", "talc-bin", "talc-std", "talc-macros"]
resolver = "2" resolver = "2"

View File

@ -115,7 +115,7 @@ impl Div<Value> for Value {
use Value as V; use Value as V;
match promote(self, rhs) { match promote(self, rhs) {
(_, V::Int(0)) => throw!(*SYM_TYPE_ERROR, "integer division by 0"), (_, V::Int(0)) => throw!(*SYM_TYPE_ERROR, "integer division by 0"),
(_, V::Ratio(r)) if *r.numer() == 0 && *r.denom() != 0 (_, V::Ratio(r)) if *r.numer() == 0 && *r.denom() != 0
=> throw!(*SYM_TYPE_ERROR, "integer division by 0"), => throw!(*SYM_TYPE_ERROR, "integer division by 0"),
(V::Int(x), V::Int(y)) => Ok(V::Ratio(Rational64::new(x, y))), (V::Int(x), V::Int(y)) => Ok(V::Ratio(Rational64::new(x, y))),
(V::Ratio(x), V::Ratio(y)) => Ok(V::Ratio(x / y)), (V::Ratio(x), V::Ratio(y)) => Ok(V::Ratio(x / y)),
@ -326,12 +326,12 @@ impl Value {
} }
} }
pub fn iter_pack(v: Option<Self>) -> Self { pub fn iter_pack(v: Option<Self>) -> Self {
match v { match v {
Some(v) => v, Some(v) => v,
None => Value::from(*SYM_END_ITERATION) None => Value::from(*SYM_END_ITERATION)
} }
} }
pub fn to_iter_function(self) -> Result<Self> { pub fn to_iter_function(self) -> Result<Self> {
match self { match self {
@ -340,7 +340,7 @@ impl Value {
let range_iter = RefCell::new(range.into_iter()); let range_iter = RefCell::new(range.into_iter());
let f = move |_: &mut Vm, _: Vec<Value>| -> Result<Value> { let f = move |_: &mut Vm, _: Vec<Value>| -> Result<Value> {
Ok(Value::iter_pack(range_iter.borrow_mut().next() Ok(Value::iter_pack(range_iter.borrow_mut().next()
.map(Value::from))) .map(Value::from)))
}; };
Ok(NativeFunc::new(Box::new(f), 0).into()) Ok(NativeFunc::new(Box::new(f), 0).into())
}, },
@ -375,7 +375,7 @@ impl Value {
let keys = RefCell::new(keys.into_iter()); let keys = RefCell::new(keys.into_iter());
let f = move |_: &mut Vm, _: Vec<Value>| -> Result<Value> { let f = move |_: &mut Vm, _: Vec<Value>| -> Result<Value> {
Ok(Value::iter_pack(keys.borrow_mut().next() Ok(Value::iter_pack(keys.borrow_mut().next()
.map(HashValue::into_inner))) .map(HashValue::into_inner)))
}; };
Ok(NativeFunc::new(Box::new(f), 0).into()) Ok(NativeFunc::new(Box::new(f), 0).into())
}, },

View File

@ -17,9 +17,9 @@ impl CallFrame {
Self { Self {
func, func,
locals, locals,
try_frames: Vec::new(), try_frames: Vec::new(),
ip: 0, ip: 0,
root: false, root: false,
} }
} }
} }
@ -93,7 +93,7 @@ fn get_call_outcome(mut args: Vec<Value>) -> Result<CallOutcome> {
.expect("did not receive vararg") else { .expect("did not receive vararg") else {
panic!("did not receive vararg") panic!("did not receive vararg")
}; };
let varargs = Rc::unwrap_or_clone(varargs).take(); let varargs = Rc::unwrap_or_clone(varargs).take();
args.extend(varargs); args.extend(varargs);
} }
vm.call_value(f.clone(), args) vm.call_value(f.clone(), args)
@ -407,8 +407,8 @@ impl Vm {
// safety: frame is restored immediately // safety: frame is restored immediately
// after function call ends // after function call ends
// ~25% performance improvement in // ~25% performance improvement in
// code heavy on native function calls // code heavy on native function calls
unsafe { unsafe {
let f = std::ptr::read(frame); let f = std::ptr::read(frame);
self.call_stack.push(f); self.call_stack.push(f);
@ -416,16 +416,16 @@ impl Vm {
let res = (nf.func)(self, args); let res = (nf.func)(self, args);
// safety: frame was referencing invalid memory due to // safety: frame was referencing invalid memory due to
// previous unsafe block, write will fix that // previous unsafe block, write will fix that
unsafe { unsafe {
let f = self.call_stack.pop().expect("no frame to pop"); let f = self.call_stack.pop().expect("no frame to pop");
std::ptr::write(frame, f); std::ptr::write(frame, f);
} }
// make sure we restored the value of frame // make sure we restored the value of frame
// before propagating exceptions // before propagating exceptions
let res = res?; let res = res?;
self.stack.push(res); self.stack.push(res);
} else if let Value::Function(func) = &args[0] { } else if let Value::Function(func) = &args[0] {

View File

@ -49,7 +49,7 @@ pub fn time_fn(vm: &mut Vm, args: Vec<Value>) -> Result<Value> {
vmcall!(vm; func)?; vmcall!(vm; func)?;
let tf = SystemTime::now(); let tf = SystemTime::now();
let time = tf.duration_since(t0).expect("time went backwards"); let time = tf.duration_since(t0).expect("time went backwards");
Ok((time.as_secs_f64() as i64).into()) Ok(time.as_secs_f64().into())
} }
pub fn load(vm: &mut Vm) { pub fn load(vm: &mut Vm) {

View File

@ -148,12 +148,12 @@ pub fn scan(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
let result = RefCell::new(init); let result = RefCell::new(init);
let f = move |vm: &mut Vm, _| { let f = move |vm: &mut Vm, _| {
let Some(val) = vmcalliter!(vm; iter.clone())? else { let Some(val) = vmcalliter!(vm; iter.clone())? else {
result.take(); result.take();
return Ok(Value::iter_pack(None)) return Ok(Value::iter_pack(None))
}; };
let r = vmcall!(vm; func.clone(), result.take(), val)?; let r = vmcall!(vm; func.clone(), result.take(), val)?;
*result.borrow_mut() = r.clone(); *result.borrow_mut() = r.clone();
Ok(r) Ok(r)
}; };
Ok(NativeFunc::new(Box::new(f), 0).into()) Ok(NativeFunc::new(Box::new(f), 0).into())
} }
@ -194,8 +194,8 @@ pub fn take(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
return Ok(Value::iter_pack(None)) return Ok(Value::iter_pack(None))
} }
let Some(next) = vmcalliter!(vm; iter.clone())? else { let Some(next) = vmcalliter!(vm; iter.clone())? else {
*taken.borrow_mut() = count; *taken.borrow_mut() = count;
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.into())
@ -305,15 +305,15 @@ pub fn step(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
let f = move |vm: &mut Vm, _| match state.take() { let f = move |vm: &mut Vm, _| match state.take() {
Step::First => { Step::First => {
let res = vmcalliter!(vm; iter.clone())?; let res = vmcalliter!(vm; iter.clone())?;
if res.is_some() { if res.is_some() {
*state.borrow_mut() = Step::Going; *state.borrow_mut() = Step::Going;
} }
Ok(Value::iter_pack(res)) Ok(Value::iter_pack(res))
}, },
Step::Going => { Step::Going => {
for _ in 0..(by-1) { for _ in 0..(by-1) {
if vmcall!(vm; iter.clone())? == Value::Nil { if vmcall!(vm; iter.clone())? == Value::Nil {
return Ok(Value::iter_pack(None)) return Ok(Value::iter_pack(None))
} }
} }
let Some(x) = vmcalliter!(vm; iter.clone())? else { let Some(x) = vmcalliter!(vm; iter.clone())? else {
@ -533,7 +533,7 @@ pub fn cartprod(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
state.borrow_mut().b_idx += 1; state.borrow_mut().b_idx += 1;
Ok(Value::from(vec![a_res, b_res]).to_cell()) Ok(Value::from(vec![a_res, b_res]))
}; };
Ok(NativeFunc::new(Box::new(f), 0).into()) Ok(NativeFunc::new(Box::new(f), 0).into())
@ -567,7 +567,7 @@ pub fn table(vm: &mut Vm, args: Vec<Value>) -> Result<Value> {
let Value::List(l) = value else { let Value::List(l) = value else {
throw!(*SYM_TYPE_ERROR, "table expected iterator to yield list") throw!(*SYM_TYPE_ERROR, "table expected iterator to yield list")
}; };
let l = Rc::unwrap_or_clone(l).take(); let l = Rc::unwrap_or_clone(l).take();
let Ok([k, v]): std::result::Result<[Value; 2], Vec<Value>> = l.try_into() else { let Ok([k, v]): std::result::Result<[Value; 2], Vec<Value>> = l.try_into() else {
throw!(*SYM_TYPE_ERROR, "table expected iterator to yield list of length 2") throw!(*SYM_TYPE_ERROR, "table expected iterator to yield list of length 2")
}; };

View File

@ -20,42 +20,42 @@ pub fn rand_in(vm: &mut Vm, args: Vec<Value>) -> Result<Value> {
let [_, col] = unpack_args!(args); let [_, col] = unpack_args!(args);
match col { match col {
Value::List(l) => { Value::List(l) => {
let l = l.borrow(); let l = l.borrow();
let Some(v) = l.choose(&mut rand::thread_rng()) else { let Some(v) = l.choose(&mut rand::thread_rng()) else {
throw!(*SYM_TYPE_ERROR, "rand_in: empty list") throw!(*SYM_TYPE_ERROR, "rand_in: empty list")
}; };
Ok(v.clone()) Ok(v.clone())
}, },
Value::Table(t) => { Value::Table(t) => {
let t = t.borrow(); let t = t.borrow();
if t.is_empty() { if t.is_empty() {
throw!(*SYM_TYPE_ERROR, "rand_in: empty table") throw!(*SYM_TYPE_ERROR, "rand_in: empty table")
}; };
let i = rand::thread_rng().gen_range(0..t.len()); let i = rand::thread_rng().gen_range(0..t.len());
let key = t.keys().nth(i).unwrap(); let key = t.keys().nth(i).unwrap();
Ok(key.clone().into_inner()) Ok(key.clone().into_inner())
}, },
Value::Range(r) => { Value::Range(r) => {
if r.is_empty() { if r.is_empty() {
throw!(*SYM_TYPE_ERROR, "rand_in: empty range") throw!(*SYM_TYPE_ERROR, "rand_in: empty range")
} }
match r.ty { match r.ty {
RangeType::Open => Ok(Value::Int( RangeType::Open => Ok(Value::Int(
rand::thread_rng().gen_range(r.start..r.stop))), rand::thread_rng().gen_range(r.start..r.stop))),
RangeType::Closed => Ok(Value::Int( RangeType::Closed => Ok(Value::Int(
rand::thread_rng().gen_range(r.start..=r.stop))), rand::thread_rng().gen_range(r.start..=r.stop))),
RangeType::Endless => throw!(*SYM_TYPE_ERROR, "rand_in: endless range"), RangeType::Endless => throw!(*SYM_TYPE_ERROR, "rand_in: endless range"),
} }
} }
col => { col => {
let iter = col.to_iter_function()?; let iter = col.to_iter_function()?;
let mut values = Vec::new(); let mut values = Vec::new();
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.len() == 0 {
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());
let v = values.swap_remove(i); let v = values.swap_remove(i);
Ok(v) Ok(v)
@ -66,9 +66,9 @@ pub fn rand_in(vm: &mut Vm, args: Vec<Value>) -> Result<Value> {
#[native_func(1)] #[native_func(1)]
pub fn shuf(_: &mut Vm, args: Vec<Value>) -> Result<Value> { pub fn shuf(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
let [_, list] = unpack_args!(args); let [_, list] = unpack_args!(args);
let Value::List(list) = list else { let Value::List(list) = list else {
throw!(*SYM_TYPE_ERROR, "shuf expected list, got {list:#}") throw!(*SYM_TYPE_ERROR, "shuf expected list, got {list:#}")
}; };
list.borrow_mut().shuffle(&mut rand::thread_rng()); list.borrow_mut().shuffle(&mut rand::thread_rng());
Ok(Value::List(list)) Ok(Value::List(list))
} }

View File

@ -64,10 +64,10 @@ pub fn as_(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
(Value::Ratio(x), "complex") => Ok(Value::Complex((*x.numer() as f64 / *x.denom() as f64).into())), (Value::Ratio(x), "complex") => Ok(Value::Complex((*x.numer() as f64 / *x.denom() as 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)
.ok_or_else(|| exception!(*SYM_TYPE_ERROR, "float {x:?} could not be converted to ratio"))?; .ok_or_else(|| exception!(*SYM_TYPE_ERROR, "float {x:?} could not be converted to ratio"))?;
Ok(Value::Ratio(r)) Ok(Value::Ratio(r))
} }
(Value::Float(x), "complex") => Ok(Value::Complex(x.into())), (Value::Float(x), "complex") => Ok(Value::Complex(x.into())),
(Value::String(s), "int") (Value::String(s), "int")
@ -92,19 +92,19 @@ pub fn copy_inner(value: Value) -> Result<Value> {
| Value::Complex(_) | Value::Range(_) | Value::String(_) | Value::Complex(_) | Value::Range(_) | Value::String(_)
=> Ok(value), => Ok(value),
Value::Cell(c) => { Value::Cell(c) => {
let c = Rc::unwrap_or_clone(c).take(); let c = Rc::unwrap_or_clone(c).take();
let c = copy_inner(c)?; let c = copy_inner(c)?;
Ok(RefCell::new(c).into()) Ok(RefCell::new(c).into())
}, },
Value::List(l) => { Value::List(l) => {
let l = Rc::unwrap_or_clone(l).take(); let l = Rc::unwrap_or_clone(l).take();
let v: Result<Vec<Value>> = l.into_iter() let v: Result<Vec<Value>> = l.into_iter()
.map(copy_inner) .map(copy_inner)
.collect(); .collect();
Ok(v?.into()) Ok(v?.into())
}, },
Value::Table(t) => { Value::Table(t) => {
let t = Rc::unwrap_or_clone(t).take(); let t = Rc::unwrap_or_clone(t).take();
let v: Result<HashMap<HashValue, Value>> = t.into_iter() let v: Result<HashMap<HashValue, Value>> = t.into_iter()
.map(|(k, v)| copy_inner(v).map(|v| (k, v))) .map(|(k, v)| copy_inner(v).map(|v| (k, v)))
.collect(); .collect();