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]
members = ["talc-lang", "talc-bin", "talc-std", "talc-macros"]
resolver = "2"

View file

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

View file

@ -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)
@ -408,7 +408,7 @@ impl Vm {
// safety: frame is restored immediately
// after function call ends
// ~25% performance improvement in
// code heavy on native function calls
// 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] {

View file

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

View file

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

View file

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

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::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();