a
This commit is contained in:
parent
2c54025d00
commit
bc3fb597d5
7 changed files with 72 additions and 73 deletions
|
@ -1,4 +1,3 @@
|
|||
[workspace]
|
||||
members = ["talc-lang", "talc-bin", "talc-std", "talc-macros"]
|
||||
resolver = "2"
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ impl Div<Value> for Value {
|
|||
use Value as V;
|
||||
match promote(self, rhs) {
|
||||
(_, 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"),
|
||||
(V::Int(x), V::Int(y)) => Ok(V::Ratio(Rational64::new(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 {
|
||||
match v {
|
||||
Some(v) => v,
|
||||
None => Value::from(*SYM_END_ITERATION)
|
||||
}
|
||||
}
|
||||
pub fn iter_pack(v: Option<Self>) -> Self {
|
||||
match v {
|
||||
Some(v) => v,
|
||||
None => Value::from(*SYM_END_ITERATION)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_iter_function(self) -> Result<Self> {
|
||||
match self {
|
||||
|
@ -340,7 +340,7 @@ impl Value {
|
|||
let range_iter = RefCell::new(range.into_iter());
|
||||
let f = move |_: &mut Vm, _: Vec<Value>| -> Result<Value> {
|
||||
Ok(Value::iter_pack(range_iter.borrow_mut().next()
|
||||
.map(Value::from)))
|
||||
.map(Value::from)))
|
||||
};
|
||||
Ok(NativeFunc::new(Box::new(f), 0).into())
|
||||
},
|
||||
|
@ -375,7 +375,7 @@ impl Value {
|
|||
let keys = RefCell::new(keys.into_iter());
|
||||
let f = move |_: &mut Vm, _: Vec<Value>| -> Result<Value> {
|
||||
Ok(Value::iter_pack(keys.borrow_mut().next()
|
||||
.map(HashValue::into_inner)))
|
||||
.map(HashValue::into_inner)))
|
||||
};
|
||||
Ok(NativeFunc::new(Box::new(f), 0).into())
|
||||
},
|
||||
|
|
|
@ -17,9 +17,9 @@ impl CallFrame {
|
|||
Self {
|
||||
func,
|
||||
locals,
|
||||
try_frames: Vec::new(),
|
||||
ip: 0,
|
||||
root: false,
|
||||
try_frames: Vec::new(),
|
||||
ip: 0,
|
||||
root: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ fn get_call_outcome(mut args: Vec<Value>) -> Result<CallOutcome> {
|
|||
.expect("did not receive vararg") else {
|
||||
panic!("did not receive vararg")
|
||||
};
|
||||
let varargs = Rc::unwrap_or_clone(varargs).take();
|
||||
let varargs = Rc::unwrap_or_clone(varargs).take();
|
||||
args.extend(varargs);
|
||||
}
|
||||
vm.call_value(f.clone(), args)
|
||||
|
@ -407,8 +407,8 @@ impl Vm {
|
|||
|
||||
// safety: frame is restored immediately
|
||||
// after function call ends
|
||||
// ~25% performance improvement in
|
||||
// code heavy on native function calls
|
||||
// ~25% performance improvement in
|
||||
// code heavy on native function calls
|
||||
unsafe {
|
||||
let f = std::ptr::read(frame);
|
||||
self.call_stack.push(f);
|
||||
|
@ -416,16 +416,16 @@ impl Vm {
|
|||
|
||||
let res = (nf.func)(self, args);
|
||||
|
||||
// safety: frame was referencing invalid memory due to
|
||||
// previous unsafe block, write will fix that
|
||||
unsafe {
|
||||
let f = self.call_stack.pop().expect("no frame to pop");
|
||||
std::ptr::write(frame, f);
|
||||
}
|
||||
// safety: frame was referencing invalid memory due to
|
||||
// previous unsafe block, write will fix that
|
||||
unsafe {
|
||||
let f = self.call_stack.pop().expect("no frame to pop");
|
||||
std::ptr::write(frame, f);
|
||||
}
|
||||
|
||||
// make sure we restored the value of frame
|
||||
// before propagating exceptions
|
||||
let res = res?;
|
||||
// make sure we restored the value of frame
|
||||
// before propagating exceptions
|
||||
let res = res?;
|
||||
|
||||
self.stack.push(res);
|
||||
} else if let Value::Function(func) = &args[0] {
|
||||
|
|
|
@ -49,7 +49,7 @@ pub fn time_fn(vm: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
|||
vmcall!(vm; func)?;
|
||||
let tf = SystemTime::now();
|
||||
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) {
|
||||
|
|
|
@ -148,12 +148,12 @@ pub fn scan(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
|||
let result = RefCell::new(init);
|
||||
let f = move |vm: &mut Vm, _| {
|
||||
let Some(val) = vmcalliter!(vm; iter.clone())? else {
|
||||
result.take();
|
||||
return Ok(Value::iter_pack(None))
|
||||
};
|
||||
let r = vmcall!(vm; func.clone(), result.take(), val)?;
|
||||
*result.borrow_mut() = r.clone();
|
||||
Ok(r)
|
||||
result.take();
|
||||
return Ok(Value::iter_pack(None))
|
||||
};
|
||||
let r = vmcall!(vm; func.clone(), result.take(), val)?;
|
||||
*result.borrow_mut() = r.clone();
|
||||
Ok(r)
|
||||
};
|
||||
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))
|
||||
}
|
||||
let Some(next) = vmcalliter!(vm; iter.clone())? else {
|
||||
*taken.borrow_mut() = count;
|
||||
return Ok(Value::iter_pack(None))
|
||||
*taken.borrow_mut() = count;
|
||||
return Ok(Value::iter_pack(None))
|
||||
};
|
||||
*taken.borrow_mut() += 1;
|
||||
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() {
|
||||
Step::First => {
|
||||
let res = vmcalliter!(vm; iter.clone())?;
|
||||
if res.is_some() {
|
||||
*state.borrow_mut() = Step::Going;
|
||||
}
|
||||
Ok(Value::iter_pack(res))
|
||||
if res.is_some() {
|
||||
*state.borrow_mut() = Step::Going;
|
||||
}
|
||||
Ok(Value::iter_pack(res))
|
||||
},
|
||||
Step::Going => {
|
||||
for _ in 0..(by-1) {
|
||||
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 {
|
||||
|
@ -533,7 +533,7 @@ pub fn cartprod(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
|||
|
||||
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())
|
||||
|
@ -567,7 +567,7 @@ pub fn table(vm: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
|||
let Value::List(l) = value else {
|
||||
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 {
|
||||
throw!(*SYM_TYPE_ERROR, "table expected iterator to yield list of length 2")
|
||||
};
|
||||
|
|
|
@ -20,42 +20,42 @@ pub fn rand_in(vm: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
|||
let [_, col] = unpack_args!(args);
|
||||
match col {
|
||||
Value::List(l) => {
|
||||
let l = l.borrow();
|
||||
let l = l.borrow();
|
||||
let Some(v) = l.choose(&mut rand::thread_rng()) else {
|
||||
throw!(*SYM_TYPE_ERROR, "rand_in: empty list")
|
||||
};
|
||||
Ok(v.clone())
|
||||
throw!(*SYM_TYPE_ERROR, "rand_in: empty list")
|
||||
};
|
||||
Ok(v.clone())
|
||||
},
|
||||
Value::Table(t) => {
|
||||
let t = t.borrow();
|
||||
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 key = t.keys().nth(i).unwrap();
|
||||
Ok(key.clone().into_inner())
|
||||
},
|
||||
Value::Range(r) => {
|
||||
if r.is_empty() {
|
||||
throw!(*SYM_TYPE_ERROR, "rand_in: empty range")
|
||||
}
|
||||
match r.ty {
|
||||
RangeType::Open => Ok(Value::Int(
|
||||
rand::thread_rng().gen_range(r.start..r.stop))),
|
||||
RangeType::Closed => Ok(Value::Int(
|
||||
rand::thread_rng().gen_range(r.start..=r.stop))),
|
||||
RangeType::Endless => throw!(*SYM_TYPE_ERROR, "rand_in: endless range"),
|
||||
}
|
||||
}
|
||||
if r.is_empty() {
|
||||
throw!(*SYM_TYPE_ERROR, "rand_in: empty range")
|
||||
}
|
||||
match r.ty {
|
||||
RangeType::Open => Ok(Value::Int(
|
||||
rand::thread_rng().gen_range(r.start..r.stop))),
|
||||
RangeType::Closed => Ok(Value::Int(
|
||||
rand::thread_rng().gen_range(r.start..=r.stop))),
|
||||
RangeType::Endless => throw!(*SYM_TYPE_ERROR, "rand_in: endless range"),
|
||||
}
|
||||
}
|
||||
col => {
|
||||
let iter = col.to_iter_function()?;
|
||||
let mut values = Vec::new();
|
||||
while let Some(v) = vmcalliter!(vm; iter.clone())? {
|
||||
values.push(v);
|
||||
}
|
||||
if values.len() == 0 {
|
||||
throw!(*SYM_TYPE_ERROR, "rand_in: empty iterator")
|
||||
}
|
||||
if values.len() == 0 {
|
||||
throw!(*SYM_TYPE_ERROR, "rand_in: empty iterator")
|
||||
}
|
||||
let i = rand::thread_rng().gen_range(0..values.len());
|
||||
let v = values.swap_remove(i);
|
||||
Ok(v)
|
||||
|
@ -66,9 +66,9 @@ pub fn rand_in(vm: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
|||
#[native_func(1)]
|
||||
pub fn shuf(_: &mut Vm, args: Vec<Value>) -> Result<Value> {
|
||||
let [_, list] = unpack_args!(args);
|
||||
let Value::List(list) = list else {
|
||||
throw!(*SYM_TYPE_ERROR, "shuf expected list, got {list:#}")
|
||||
};
|
||||
list.borrow_mut().shuffle(&mut rand::thread_rng());
|
||||
Ok(Value::List(list))
|
||||
let Value::List(list) = list else {
|
||||
throw!(*SYM_TYPE_ERROR, "shuf expected list, got {list:#}")
|
||||
};
|
||||
list.borrow_mut().shuffle(&mut rand::thread_rng());
|
||||
Ok(Value::List(list))
|
||||
}
|
||||
|
|
|
@ -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::Float(x), "int") => Ok(Value::Int(x as i64)),
|
||||
(Value::Float(x), "ratio") => {
|
||||
let r = Rational64::approximate_float(x)
|
||||
.ok_or_else(|| exception!(*SYM_TYPE_ERROR, "float {x:?} could not be converted to ratio"))?;
|
||||
Ok(Value::Ratio(r))
|
||||
}
|
||||
let r = Rational64::approximate_float(x)
|
||||
.ok_or_else(|| exception!(*SYM_TYPE_ERROR, "float {x:?} could not be converted to ratio"))?;
|
||||
Ok(Value::Ratio(r))
|
||||
}
|
||||
(Value::Float(x), "complex") => Ok(Value::Complex(x.into())),
|
||||
|
||||
(Value::String(s), "int")
|
||||
|
@ -92,19 +92,19 @@ pub fn copy_inner(value: Value) -> Result<Value> {
|
|||
| Value::Complex(_) | Value::Range(_) | Value::String(_)
|
||||
=> Ok(value),
|
||||
Value::Cell(c) => {
|
||||
let c = Rc::unwrap_or_clone(c).take();
|
||||
let c = Rc::unwrap_or_clone(c).take();
|
||||
let c = copy_inner(c)?;
|
||||
Ok(RefCell::new(c).into())
|
||||
},
|
||||
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()
|
||||
.map(copy_inner)
|
||||
.collect();
|
||||
Ok(v?.into())
|
||||
},
|
||||
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()
|
||||
.map(|(k, v)| copy_inner(v).map(|v| (k, v)))
|
||||
.collect();
|
||||
|
|
Loading…
Reference in a new issue