diff --git a/src/builtins/mod.rs b/src/builtins/mod.rs index 8b3c910..f415b94 100644 --- a/src/builtins/mod.rs +++ b/src/builtins/mod.rs @@ -12,24 +12,29 @@ pub fn env<'jit, 'vm>(vm: &'vm VM<'jit>) -> VmEnv<'jit, 'vm> { let primops = [ PrimOp::new("add", 2, |_, args| { - let [first, second]: [Value; 2] = args.try_into().unwrap(); - first.add(second).ok() + let [mut first, second]: [Value; 2] = args.try_into().unwrap(); + first.add(second); + first.ok() }), PrimOp::new("sub", 2, |_, args| { - let [first, second]: [Value; 2] = args.try_into().unwrap(); - first.add(second.neg()).ok() + let [mut first, second]: [Value; 2] = args.try_into().unwrap(); + first.add(second.neg()); + first.ok() }), PrimOp::new("mul", 2, |_, args| { - let [first, second]: [Value; 2] = args.try_into().unwrap(); - first.mul(second).ok() + let [mut first, second]: [Value; 2] = args.try_into().unwrap(); + first.mul(second); + first.ok() }), PrimOp::new("div", 2, |_, args| { - let [first, second]: [Value; 2] = args.try_into().unwrap(); - first.div(second) + let [mut first, second]: [Value; 2] = args.try_into().unwrap(); + first.div(second)?; + first.ok() }), PrimOp::new("lessThan", 2, |_, args| { - let [first, second]: [Value; 2] = args.try_into().unwrap(); - first.lt(second).ok() + let [mut first, second]: [Value; 2] = args.try_into().unwrap(); + first.lt(second); + first.ok() }), PrimOp::new("seq", 2, |vm, args| { let [mut first, second]: [Value; 2] = args.try_into().unwrap(); diff --git a/src/jit/mod.rs b/src/jit/mod.rs index 4f93d8a..5588daf 100644 --- a/src/jit/mod.rs +++ b/src/jit/mod.rs @@ -289,7 +289,7 @@ impl<'vm, 'ctx: 'vm> JITContext<'ctx> { .new_thunk(Rc::into_raw(Rc::new(Thunk::new(vm.get_thunk(idx))))), )?, OpCode::CaptureEnv => { - let thunk = *stack.tos()?; + let thunk = *stack.tos(); self.builder.build_direct_call( self.helpers.capture_env, &[thunk.into(), env.into()], diff --git a/src/stack.rs b/src/stack.rs index 2081006..e4ee773 100644 --- a/src/stack.rs +++ b/src/stack.rs @@ -51,20 +51,12 @@ impl Stack { unsafe { replace(item, MaybeUninit::uninit()).assume_init() } } - pub fn tos(&self) -> Result<&T> { - if self.top == 0 { - panic!("stack empty") - } else { - Ok(into!(&self.items[self.top - 1])) - } + pub fn tos(&self) -> &T { + into!(&self.items[self.top - 1]) } - pub fn tos_mut(&mut self) -> Result<&mut T> { - if self.top == 0 { - panic!("stack empty") - } else { - Ok(into!(&mut self.items[self.top - 1])) - } + pub fn tos_mut(&mut self) -> &mut T { + into!(&mut self.items[self.top - 1]) } } diff --git a/src/ty/internal/attrset.rs b/src/ty/internal/attrset.rs index 687f172..b1c6c8c 100644 --- a/src/ty/internal/attrset.rs +++ b/src/ty/internal/attrset.rs @@ -87,13 +87,13 @@ impl<'jit: 'vm, 'vm> AttrSet<'jit, 'vm> { Ok(()) } - pub fn eq_impl(&self, other: &AttrSet<'jit, 'vm>, vm: &'vm VM<'jit>) -> bool { + pub fn eq_impl(&self, other: &AttrSet<'jit, 'vm>) -> bool { self.data.iter().len() == other.data.iter().len() && std::iter::zip( self.data.iter().sorted_by_key(|(k, _)| **k), self.data.iter().sorted_by_key(|(k, _)| **k), ) - .all(|((_, v1), (_, v2))| v1.eq_impl(v2, vm)) + .all(|((_, v1), (_, v2))| v1.eq_impl(v2)) } pub fn to_public(&self, vm: &'vm VM, seen: &mut HashSet>) -> p::Value { diff --git a/src/ty/internal/mod.rs b/src/ty/internal/mod.rs index 6415834..aace4e5 100644 --- a/src/ty/internal/mod.rs +++ b/src/ty/internal/mod.rs @@ -56,14 +56,12 @@ impl Hash for Value<'_, '_> { } impl<'jit: 'vm, 'vm> Value<'jit, 'vm> { - fn eq_impl(&self, other: &Self, vm: &'vm VM<'jit>) -> bool { + fn eq_impl(&self, other: &Self) -> bool { use Value::*; match (self, other) { (Const(a), Const(b)) => a.eq(b), - (AttrSet(a), AttrSet(b)) => a.eq_impl(b, vm), + (AttrSet(a), AttrSet(b)) => a.eq_impl(b), (List(a), List(b)) => a.eq(b), - (Builtins(_), AttrSet(attrs)) => attrs.has_attr(vm.new_sym("builtins")), - (AttrSet(attrs), Builtins(_)) => attrs.has_attr(vm.new_sym("builtins")), _ => false, } } @@ -213,41 +211,48 @@ impl<'jit, 'vm> Value<'jit, 'vm> { } } - pub fn and(self, other: Self) -> Self { + pub fn and(&mut self, other: Self) { use Const::*; - match (self, other) { - (VmConst(Bool(a)), VmConst(Bool(b))) => VmConst(Bool(a && b)), - (x @ Value::Catchable(_), _) | (_, x @ Value::Catchable(_)) => x, + *self = match (&*self, other) { + (VmConst(Bool(a)), VmConst(Bool(b))) => VmConst(Bool(*a && b)), + (Value::Catchable(_), _) => return, + (_, x @ Value::Catchable(_)) => x, _ => todo!(), } } - pub fn or(self, other: Self) -> Self { + pub fn or(&mut self, other: Self) { use Const::*; - match (self, other) { - (VmConst(Bool(a)), VmConst(Bool(b))) => VmConst(Bool(a || b)), - (x @ Value::Catchable(_), _) | (_, x @ Value::Catchable(_)) => x, + *self = match (&*self, other) { + (VmConst(Bool(a)), VmConst(Bool(b))) => VmConst(Bool(*a || b)), + (Value::Catchable(_), _) => return, + (_, x @ Value::Catchable(_)) => x, _ => todo!(), } } - pub fn eq(self, other: Self, vm: &'vm VM<'jit>) -> Self { + pub fn eq(&mut self, other: Self) { use Const::Bool; - match (self, other) { - (x @ Value::Catchable(_), _) | (_, x @ Value::Catchable(_)) => x, - (s, other) => VmConst(Bool(s.eq_impl(&other, vm))), - } + *self = match (&*self, other) { + (Value::Catchable(_), _) => return, + (_, x @ Value::Catchable(_)) => x, + (s, other) => VmConst(Bool(s.eq_impl(&other))), + }; } - pub fn lt(self, other: Self) -> Self { + pub fn lt(&mut self, other: Self) { use Const::*; - VmConst(Bool(match (self, other) { - (VmConst(Int(a)), VmConst(Int(b))) => a < b, - (VmConst(Int(a)), VmConst(Float(b))) => (a as f64) < b, - (VmConst(Float(a)), VmConst(Int(b))) => a < b as f64, - (VmConst(Float(a)), VmConst(Float(b))) => a < b, - (VmConst(String(a)), VmConst(String(b))) => a < b, - (x @ Value::Catchable(_), _) | (_, x @ Value::Catchable(_)) => return x, + *self = VmConst(Bool(match (&*self, other) { + (VmConst(Int(a)), VmConst(Int(b))) => *a < b, + (VmConst(Int(a)), VmConst(Float(b))) => (*a as f64) < b, + (VmConst(Float(a)), VmConst(Int(b))) => *a < b as f64, + (VmConst(Float(a)), VmConst(Float(b))) => *a < b, + (VmConst(String(a)), VmConst(String(b))) => a < &b, + (Value::Catchable(_), _) => return, + (_, x @ Value::Catchable(_)) => { + *self = x; + return; + }, _ => todo!(), })) } @@ -262,11 +267,11 @@ impl<'jit, 'vm> Value<'jit, 'vm> { } } - pub fn add(self, other: Self) -> Self { + pub fn add(&mut self, other: Self) { use Const::*; - match (self, other) { + *self = match (&*self, other) { (VmConst(Int(a)), VmConst(Int(b))) => VmConst(Int(a + b)), - (VmConst(Int(a)), VmConst(Float(b))) => VmConst(Float(a as f64 + b)), + (VmConst(Int(a)), VmConst(Float(b))) => VmConst(Float(*a as f64 + b)), (VmConst(Float(a)), VmConst(Int(b))) => VmConst(Float(a + b as f64)), (VmConst(Float(a)), VmConst(Float(b))) => VmConst(Float(a + b)), (VmConst(String(a)), VmConst(String(b))) => { @@ -274,37 +279,41 @@ impl<'jit, 'vm> Value<'jit, 'vm> { string.push_str(b.as_str()); VmConst(String(string)) } - (x @ Value::Catchable(_), _) | (_, x @ Value::Catchable(_)) => x, + (Value::Catchable(_), _) => return, + (_, x @ Value::Catchable(_)) => x, _ => todo!(), } } - pub fn mul(self, other: Self) -> Self { + pub fn mul(&mut self, other: Self) { use Const::*; - match (self, other) { + *self = match (&*self, other) { (VmConst(Int(a)), VmConst(Int(b))) => VmConst(Int(a * b)), - (VmConst(Int(a)), VmConst(Float(b))) => VmConst(Float(a as f64 * b)), + (VmConst(Int(a)), VmConst(Float(b))) => VmConst(Float(*a as f64 * b)), (VmConst(Float(a)), VmConst(Int(b))) => VmConst(Float(a * b as f64)), (VmConst(Float(a)), VmConst(Float(b))) => VmConst(Float(a * b)), - (x @ Value::Catchable(_), _) | (_, x @ Value::Catchable(_)) => x, + (Value::Catchable(_), _) => return, + (_, x @ Value::Catchable(_)) => x, _ => todo!(), } } - pub fn div(self, other: Self) -> Result { + pub fn div(&mut self, other: Self) -> Result<()> { use Const::*; - Ok(match (self, other) { + *self = match (&*self, other) { (_, VmConst(Int(0))) => return Err(Error::EvalError("division by zero".to_string())), (_, VmConst(Float(0.))) => { return Err(Error::EvalError("division by zero".to_string())); } (VmConst(Int(a)), VmConst(Int(b))) => VmConst(Int(a / b)), - (VmConst(Int(a)), VmConst(Float(b))) => VmConst(Float(a as f64 / b)), + (VmConst(Int(a)), VmConst(Float(b))) => VmConst(Float(*a as f64 / b)), (VmConst(Float(a)), VmConst(Int(b))) => VmConst(Float(a / b as f64)), (VmConst(Float(a)), VmConst(Float(b))) => VmConst(Float(a / b)), - (x @ Value::Catchable(_), _) | (_, x @ Value::Catchable(_)) => x, + (Value::Catchable(_), _) => return Ok(()), + (_, x @ Value::Catchable(_)) => x, _ => todo!(), - }) + }; + Ok(()) } pub fn concat_string(&mut self, mut other: Self) -> &mut Self { @@ -329,13 +338,16 @@ impl<'jit, 'vm> Value<'jit, 'vm> { self } - pub fn concat(self, other: Self) -> Self { + pub fn concat(&mut self, other: Self) { + if let x @ Value::Catchable(_) = other { + *self = x; + return; + } match (self, other) { - (Value::List(mut a), Value::List(b)) => { - Rc::make_mut(&mut a).concat(b.as_ref()); - Value::List(a) + (Value::List(a), Value::List(b)) => { + Rc::make_mut(a).concat(b.as_ref()); } - (x @ Value::Catchable(_), _) | (_, x @ Value::Catchable(_)) => x, + (Value::Catchable(_), _) => (), _ => todo!(), } } @@ -352,13 +364,16 @@ impl<'jit, 'vm> Value<'jit, 'vm> { self } - pub fn update(self, other: Self) -> Self { + pub fn update(&mut self, other: Self) { + if let x @ Value::Catchable(_) = other { + *self = x; + return; + } match (self, other) { - (Value::AttrSet(mut a), Value::AttrSet(b)) => { - Rc::make_mut(&mut a).update(b.as_ref()); - Value::AttrSet(a) + (Value::AttrSet(a), Value::AttrSet(b)) => { + Rc::make_mut(a).update(b.as_ref()); } - (x @ Value::Catchable(_), _) | (_, x @ Value::Catchable(_)) => x, + (Value::Catchable(_), _) => (), _ => todo!(), } } diff --git a/src/vm/mod.rs b/src/vm/mod.rs index f45c1f2..ce5cbf5 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -112,14 +112,9 @@ impl<'vm, 'jit: 'vm> VM<'jit> { OpCode::LoadThunk { idx } => { stack.push(Value::Thunk(Thunk::new(self.get_thunk(idx)).into()))? } - OpCode::CaptureEnv => stack - .tos() - .unwrap() - .as_ref() - .unwrap_thunk() - .capture(env.clone()), + OpCode::CaptureEnv => stack.tos().as_ref().unwrap_thunk().capture(env.clone()), OpCode::ForceValue => { - stack.tos_mut()?.force(self)?; + stack.tos_mut().force(self)?; } OpCode::Jmp { step } => return Ok(step), OpCode::JmpIfFalse { step } => { @@ -154,26 +149,26 @@ impl<'vm, 'jit: 'vm> VM<'jit> { OpCode::BinOp { op } => { use BinOp::*; let mut rhs = stack.pop(); - let mut lhs = stack.pop(); + let lhs = stack.tos_mut(); lhs.force(self)?; rhs.force(self)?; - stack.push(match op { + match op { Add => lhs.add(rhs), Sub => lhs.add(rhs.neg()), Mul => lhs.mul(rhs), Div => lhs.div(rhs)?, And => lhs.and(rhs), Or => lhs.or(rhs), - Eq => lhs.eq(rhs, self), + Eq => Value::eq(lhs, rhs), Lt => lhs.lt(rhs), Con => lhs.concat(rhs), Upd => lhs.update(rhs), - })?; + } } OpCode::ConcatString => { let mut rhs = stack.pop(); rhs.force(self)?; - stack.tos_mut()?.concat_string(rhs); + stack.tos_mut().concat_string(rhs); } OpCode::Path => { todo!() @@ -183,33 +178,33 @@ impl<'vm, 'jit: 'vm> VM<'jit> { } OpCode::PushElem => { let elem = stack.pop(); - stack.tos_mut()?.push(elem); + stack.tos_mut().push(elem); } OpCode::AttrSet { cap } => { stack.push(Value::AttrSet(AttrSet::with_capacity(cap).into()))?; } OpCode::FinalizeRec => { - env.enter_let(stack.tos()?.clone().unwrap_attr_set().into_inner()); - stack.tos_mut()?.as_mut().unwrap_attr_set().capture(env); + env.enter_let(stack.tos().clone().unwrap_attr_set().into_inner()); + stack.tos_mut().as_mut().unwrap_attr_set().capture(env); } OpCode::PushStaticAttr { name } => { let val = stack.pop(); - stack.tos_mut()?.push_attr(name, val); + stack.tos_mut().push_attr(name, val); } OpCode::PushDynamicAttr => { let val = stack.pop(); let mut sym = stack.pop(); sym.force(self)?.coerce_to_string(); let sym = self.new_sym(sym.unwrap_const().unwrap_string()); - stack.tos_mut()?.push_attr(sym, val); + stack.tos_mut().push_attr(sym, val); } OpCode::Select { sym } => { - stack.tos_mut()?.force(self)?.select(sym, self)?; + stack.tos_mut().force(self)?.select(sym, self)?; } OpCode::SelectOrDefault { sym } => { let default = stack.pop(); stack - .tos_mut()? + .tos_mut() .force(self)? .select_with_default(sym, default)?; } @@ -218,7 +213,7 @@ impl<'vm, 'jit: 'vm> VM<'jit> { val.force(self)?; val.coerce_to_string(); let sym = self.new_sym(val.unwrap_const().unwrap_string()); - stack.tos_mut()?.force(self)?.select(sym, self)?; + stack.tos_mut().force(self)?.select(sym, self)?; } OpCode::SelectDynamicOrDefault => { let default = stack.pop(); @@ -227,18 +222,18 @@ impl<'vm, 'jit: 'vm> VM<'jit> { val.coerce_to_string(); let sym = self.new_sym(val.unwrap_const().unwrap_string()); stack - .tos_mut()? + .tos_mut() .force(self)? .select_with_default(sym, default)?; } OpCode::HasAttr { sym } => { - stack.tos_mut()?.force(self)?.has_attr(sym); + stack.tos_mut().force(self)?.has_attr(sym); } OpCode::HasDynamicAttr => { let mut val = stack.pop(); val.coerce_to_string(); let sym = self.new_sym(val.unwrap_const().unwrap_string()); - stack.tos_mut()?.force(self)?.has_attr(sym); + stack.tos_mut().force(self)?.has_attr(sym); } OpCode::LookUp { sym } => { stack.push( @@ -249,17 +244,9 @@ impl<'vm, 'jit: 'vm> VM<'jit> { .clone(), )?; } - OpCode::EnterLetEnv => match stack.pop() { - Value::AttrSet(attrs) => env.enter_let(attrs.into_inner()), - - _ => unreachable!(), - }, + OpCode::EnterLetEnv => env.enter_let(stack.pop().unwrap_attr_set().into_inner()), OpCode::LeaveLetEnv => env.leave_let(), - OpCode::EnterWithEnv => match stack.pop() { - Value::AttrSet(attrs) => env.enter_with(attrs.into_inner()), - - _ => unreachable!(), - }, + OpCode::EnterWithEnv => env.enter_with(stack.pop().unwrap_attr_set().into_inner()), OpCode::LeaveWithEnv => env.leave_with(), OpCode::Assert => { if !stack.pop().unwrap_const().unwrap_bool() {