diff --git a/src/builtins/mod.rs b/src/builtins/mod.rs index 7743338..4fb6158 100644 --- a/src/builtins/mod.rs +++ b/src/builtins/mod.rs @@ -1,8 +1,6 @@ use derive_more::Constructor; -use super::vm::Env; -use super::vm::Symbol; -use super::vm::Value; +use crate::vm::{Env, Symbol, Value, AttrSet}; use crate::value::Const; pub fn env() -> Env { @@ -10,42 +8,39 @@ pub fn env() -> Env { env.insert(Symbol::from("true"), Value::Const(Const::Bool(true))); env.insert(Symbol::from("false"), Value::Const(Const::Bool(false))); - env.insert( - Symbol::from("__add"), - Value::PrimOp(PrimOp::new("add", 2, |args| { + let primops = [ + PrimOp::new("add", 2, |args| { let [first, second]: [Value; 2] = args.try_into().unwrap(); first.add(second) - })), - ); - env.insert( - Symbol::from("__sub"), - Value::PrimOp(PrimOp::new("sub", 2, |args| { + }), + PrimOp::new("sub", 2, |args| { let [first, second]: [Value; 2] = args.try_into().unwrap(); first.add(second.neg()) - })), - ); - env.insert( - Symbol::from("__mul"), - Value::PrimOp(PrimOp::new("mul", 2, |args| { + }), + PrimOp::new("mul", 2, |args| { let [first, second]: [Value; 2] = args.try_into().unwrap(); first.mul(second) - })), - ); - env.insert( - Symbol::from("__div"), - Value::PrimOp(PrimOp::new("div", 2, |args| { + }), + PrimOp::new("div", 2, |args| { let [first, second]: [Value; 2] = args.try_into().unwrap(); first.div(second) - })), - ); - env.insert( - Symbol::from("__lessThan"), - Value::PrimOp(PrimOp::new("lessThan", 2, |args| { + }), + PrimOp::new("lessThan", 2, |args| { let [first, second]: [Value; 2] = args.try_into().unwrap(); first.lt(second) - })), - ); + }) + ]; + let mut builtins = AttrSet::empty(); + for primop in primops { + env.insert( + Symbol::from(format!("__{}", primop.name)), + Value::PrimOp(primop.clone()), + ); + builtins.push_attr(Symbol::from(primop.name), Value::PrimOp(primop)); + } + + env.insert(Symbol::from("builtins"), Value::AttrSet(builtins)); env } diff --git a/src/vm/env.rs b/src/vm/env.rs index 0917df0..ec5422b 100644 --- a/src/vm/env.rs +++ b/src/vm/env.rs @@ -1,10 +1,10 @@ use rpds::HashTrieMapSync; -use super::value::{Symbol, VmValue}; +use super::value::{Symbol, Value}; pub struct Env { last: Option>, - map: HashTrieMapSync, + map: HashTrieMapSync, } impl Env { @@ -15,7 +15,7 @@ impl Env { } } - pub fn lookup(&self, symbol: Symbol) -> VmValue { + pub fn lookup(&self, symbol: Symbol) -> Value { if let Some(value) = self.map.get(&symbol) { value.clone() } else { @@ -24,11 +24,11 @@ impl Env { } } - pub fn insert(&mut self, symbol: Symbol, value: VmValue) { + pub fn insert(&mut self, symbol: Symbol, value: Value) { self.map.insert_mut(symbol, value); } - pub fn enter(&mut self, map: HashTrieMapSync) { + pub fn enter(&mut self, map: HashTrieMapSync) { let last = std::mem::replace(self, Env { last: None, map }); self.last = Some(Box::new(last)); } diff --git a/src/vm/mod.rs b/src/vm/mod.rs index 070abe0..5d273f3 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -9,4 +9,4 @@ mod test; pub use env::Env; pub use value::Symbol; -pub use value::VmValue as Value; +pub use value::*; diff --git a/src/vm/stack.rs b/src/vm/stack.rs index d7e302f..14ae85e 100644 --- a/src/vm/stack.rs +++ b/src/vm/stack.rs @@ -3,12 +3,12 @@ use std::ops::Deref; use anyhow::{Result, anyhow}; -use super::value::VmValue; +use super::value::Value; -pub const STACK_SIZE: usize = 8 * 1024 / size_of::(); +pub const STACK_SIZE: usize = 8 * 1024 / size_of::(); pub struct Stack { - items: Box<[MaybeUninit; CAP]>, + items: Box<[MaybeUninit; CAP]>, top: usize, } @@ -24,7 +24,7 @@ impl Stack { } } - pub fn push(&mut self, item: VmValue) -> Result<()> { + pub fn push(&mut self, item: Value) -> Result<()> { self.items .get_mut(self.top) .map_or(Err(anyhow!("stack overflow")), |ok| Ok(ok))? @@ -33,7 +33,7 @@ impl Stack { Ok(()) } - pub fn pop(&mut self) -> Result { + pub fn pop(&mut self) -> Result { self.top -= 1; let item = self .items @@ -42,7 +42,7 @@ impl Stack { unsafe { Ok(std::mem::replace(item, MaybeUninit::uninit()).assume_init()) } } - pub fn tos(&self) -> Result<&VmValue> { + pub fn tos(&self) -> Result<&Value> { if self.top == 0 { Err(anyhow!("")) } else { @@ -50,7 +50,7 @@ impl Stack { } } - pub fn tos_mut(&mut self) -> Result<&mut VmValue> { + pub fn tos_mut(&mut self) -> Result<&mut Value> { if self.top == 0 { Err(anyhow!("")) } else { @@ -58,7 +58,7 @@ impl Stack { } } - pub fn with_tos(&self, func: impl Fn(&VmValue)) -> Result<()> { + pub fn with_tos(&self, func: impl Fn(&Value)) -> Result<()> { if self.top != 0 { Err(anyhow!("")) } else { @@ -66,7 +66,7 @@ impl Stack { Ok(()) } } - pub fn with_tos_mut(&mut self, func: impl Fn(&mut VmValue)) -> Result<()> { + pub fn with_tos_mut(&mut self, func: impl Fn(&mut Value)) -> Result<()> { if self.top != 0 { Err(anyhow!("")) } else { @@ -77,7 +77,7 @@ impl Stack { } impl Deref for Stack { - type Target = [VmValue]; + type Target = [Value]; fn deref(&self) -> &Self::Target { unsafe { transmute(&self.items[0..self.top]) } } diff --git a/src/vm/value/attrset.rs b/src/vm/value/attrset.rs index 391ad82..3b9e858 100644 --- a/src/vm/value/attrset.rs +++ b/src/vm/value/attrset.rs @@ -1,29 +1,33 @@ use derive_more::Constructor; use rpds::HashTrieMapSync; -use crate::value::{self, Value}; +use crate::value::{self, Value as Value_}; use super::super::vm::VM; -use super::{Symbol, ToValue, VmValue}; +use super::{Symbol, ToValue, Value}; #[derive(Debug, Constructor, Clone, PartialEq)] pub struct AttrSet { - data: HashTrieMapSync, + data: HashTrieMapSync, } impl AttrSet { - pub fn push_attr_force(&mut self, sym: Symbol, val: VmValue) { + pub fn empty() -> AttrSet { + AttrSet { data: HashTrieMapSync::new_sync() } + } + + pub fn push_attr_force(&mut self, sym: Symbol, val: Value) { self.data.insert_mut(sym, val); } - pub fn push_attr(&mut self, sym: Symbol, val: VmValue) { + pub fn push_attr(&mut self, sym: Symbol, val: Value) { if self.data.get(&sym).is_some() { todo!() } self.data.insert_mut(sym, val); } - pub fn select(&self, sym: Symbol) -> Option { + pub fn select(&self, sym: Symbol) -> Option { self.data.get(&sym).cloned() } @@ -38,14 +42,14 @@ impl AttrSet { self } - pub fn to_data(self) -> HashTrieMapSync { + pub fn to_data(self) -> HashTrieMapSync { self.data } } impl ToValue for AttrSet { - fn to_value(self, vm: &VM) -> Value { - Value::AttrSet(value::AttrSet::new( + fn to_value(self, vm: &VM) -> Value_ { + Value_::AttrSet(value::AttrSet::new( self.data .iter() .map(|(sym, value)| { diff --git a/src/vm/value/list.rs b/src/vm/value/list.rs index 5ba9cae..cb0ab2d 100644 --- a/src/vm/value/list.rs +++ b/src/vm/value/list.rs @@ -1,18 +1,24 @@ use derive_more::Constructor; use rpds::VectorSync; -use crate::value::{self, Value}; +use crate::value::{self, Value as Value_}; use super::super::vm::VM; -use super::{ToValue, VmValue}; +use super::{ToValue, Value}; #[derive(Debug, Constructor, Clone, PartialEq)] pub struct List { - data: VectorSync, + data: VectorSync, } impl List { - pub fn push(&mut self, elem: VmValue) { + pub fn empty() -> List { + List { + data: VectorSync::new_sync() + } + } + + pub fn push(&mut self, elem: Value) { self.data.push_back_mut(elem); } @@ -25,8 +31,8 @@ impl List { } impl ToValue for List { - fn to_value(self, vm: &VM) -> Value { - Value::List(value::List::new( + fn to_value(self, vm: &VM) -> Value_ { + Value_::List(value::List::new( self.data .iter() .map(|value| value.clone().to_value(vm)) diff --git a/src/vm/value/mod.rs b/src/vm/value/mod.rs index 6d3b4ae..dd8eb2a 100644 --- a/src/vm/value/mod.rs +++ b/src/vm/value/mod.rs @@ -2,7 +2,7 @@ use anyhow::Result; use derive_more::{Constructor, IsVariant, Unwrap}; use ecow::EcoString; -use crate::value::*; +use crate::value::{Value as Value_, Const, Catchable}; use super::env::Env; use super::vm::VM; @@ -16,7 +16,7 @@ pub use list::List; pub use string::ContextfulString; pub trait ToValue { - fn to_value(self, vm: &VM) -> Value; + fn to_value(self, vm: &VM) -> Value_; } #[derive(Debug, PartialEq, Eq, Hash, Clone, Constructor)] @@ -32,7 +32,7 @@ impl> From for Symbol { pub struct Thunk(usize); #[derive(Debug, IsVariant, Unwrap, Clone, PartialEq)] -pub enum VmValue { +pub enum Value { Const(Const), Thunk(Thunk), AttrSet(AttrSet), @@ -42,17 +42,17 @@ pub enum VmValue { PartialPrimOp(crate::builtins::PartialPrimOp), } -use VmValue::Const as VmConst; -impl VmValue { - pub fn call(self, args: Vec) -> VmValue { +use Value::Const as VmConst; +impl Value { + pub fn call(self, args: Vec) -> Value { match self { - VmValue::PrimOp(func) => func.call(args), - VmValue::PartialPrimOp(func) => func.call(args), + Value::PrimOp(func) => func.call(args), + Value::PartialPrimOp(func) => func.call(args), _ => todo!(), } } - pub fn not(self) -> VmValue { + pub fn not(self) -> Value { use Const::*; match self { VmConst(Bool(bool)) => VmConst(Bool(!bool)), @@ -60,7 +60,7 @@ impl VmValue { } } - pub fn and(self, other: VmValue) -> VmValue { + pub fn and(self, other: Value) -> Value { use Const::*; match (self, other) { (VmConst(Bool(a)), VmConst(Bool(b))) => VmConst(Bool(a && b)), @@ -68,7 +68,7 @@ impl VmValue { } } - pub fn or(self, other: VmValue) -> VmValue { + pub fn or(self, other: Value) -> Value { use Const::*; match (self, other) { (VmConst(Bool(a)), VmConst(Bool(b))) => VmConst(Bool(a || b)), @@ -76,12 +76,12 @@ impl VmValue { } } - pub fn eq(self, other: VmValue) -> VmValue { + pub fn eq(self, other: Value) -> Value { use Const::Bool; VmConst(Bool(self == other)) } - pub fn lt(self, other: VmValue) -> VmValue { + pub fn lt(self, other: Value) -> Value { use Const::*; VmConst(Bool(match (self, other) { (VmConst(Int(a)), VmConst(Int(b))) => a < b, @@ -93,7 +93,7 @@ impl VmValue { })) } - pub fn neg(self) -> VmValue { + pub fn neg(self) -> Value { use Const::*; match self { VmConst(Int(int)) => VmConst(Int(-int)), @@ -102,7 +102,7 @@ impl VmValue { } } - pub fn add(self, other: VmValue) -> VmValue { + pub fn add(self, other: Value) -> Value { use Const::*; match (self, other) { (VmConst(Int(a)), VmConst(Int(b))) => VmConst(Int(a + b)), @@ -118,7 +118,7 @@ impl VmValue { } } - pub fn mul(self, other: VmValue) -> VmValue { + pub fn mul(self, other: Value) -> Value { use Const::*; match (self, other) { (VmConst(Int(a)), VmConst(Int(b))) => VmConst(Int(a * b)), @@ -129,7 +129,7 @@ impl VmValue { } } - pub fn div(self, other: VmValue) -> VmValue { + pub fn div(self, other: Value) -> Value { use Const::*; match (self, other) { (_, VmConst(Int(0))) => todo!(), @@ -142,7 +142,7 @@ impl VmValue { } } - pub fn concat_string(&mut self, mut other: VmValue) -> &mut Self { + pub fn concat_string(&mut self, mut other: Value) -> &mut Self { if let (VmConst(Const::String(a)), VmConst(Const::String(b))) = (self.coerce_to_string(), other.coerce_to_string()) { @@ -153,8 +153,8 @@ impl VmValue { self } - pub fn push(&mut self, elem: VmValue) -> &mut Self { - if let VmValue::List(list) = self { + pub fn push(&mut self, elem: Value) -> &mut Self { + if let Value::List(list) = self { list.push(elem); } else { todo!() @@ -162,16 +162,16 @@ impl VmValue { self } - pub fn concat(self, other: VmValue) -> VmValue { - if let (VmValue::List(a), VmValue::List(b)) = (self, other) { - VmValue::List(a.concat(b)) + pub fn concat(self, other: Value) -> Value { + if let (Value::List(a), Value::List(b)) = (self, other) { + Value::List(a.concat(b)) } else { todo!() } } - pub fn push_attr(&mut self, sym: Symbol, val: VmValue) -> &mut Self { - if let VmValue::AttrSet(attrs) = self { + pub fn push_attr(&mut self, sym: Symbol, val: Value) -> &mut Self { + if let Value::AttrSet(attrs) = self { attrs.push_attr(sym, val) } else { todo!() @@ -179,19 +179,19 @@ impl VmValue { self } - pub fn update(self, other: VmValue) -> VmValue { - if let (VmValue::AttrSet(a), VmValue::AttrSet(b)) = (self, other) { - VmValue::AttrSet(a.update(b)) + pub fn update(self, other: Value) -> Value { + if let (Value::AttrSet(a), Value::AttrSet(b)) = (self, other) { + Value::AttrSet(a.update(b)) } else { todo!() } } pub fn select(&mut self, sym: Symbol) -> &mut Self { - if let VmValue::AttrSet(attrs) = self { + if let Value::AttrSet(attrs) = self { let val = attrs .select(sym.clone()) - .unwrap_or(VmValue::Catchable(Catchable::new(Some(format!( + .unwrap_or(Value::Catchable(Catchable::new(Some(format!( "{sym:?} not found" ))))); *self = val; @@ -201,8 +201,8 @@ impl VmValue { self } - pub fn select_with_default(&mut self, sym: Symbol, default: VmValue) -> &mut Self { - if let VmValue::AttrSet(attrs) = self { + pub fn select_with_default(&mut self, sym: Symbol, default: Value) -> &mut Self { + if let Value::AttrSet(attrs) = self { let val = attrs.select(sym).unwrap_or(default); *self = val; } else { @@ -212,7 +212,7 @@ impl VmValue { } pub fn has_attr(&mut self, sym: Symbol) -> &mut Self { - if let VmValue::AttrSet(attrs) = self { + if let Value::AttrSet(attrs) = self { let val = VmConst(Const::Bool(attrs.has_attr(sym))); *self = val; } else { @@ -231,7 +231,7 @@ impl VmValue { } pub fn force(&mut self, vm: &VM, env: &mut Env) -> Result<&mut Self> { - if let VmValue::Thunk(thunk) = self { + if let Value::Thunk(thunk) = self { let value = vm.get_thunk_value(thunk.0, env)?; *self = value } @@ -239,16 +239,16 @@ impl VmValue { } } -impl ToValue for VmValue { - fn to_value(self, vm: &VM) -> Value { +impl ToValue for Value { + fn to_value(self, vm: &VM) -> Value_ { match self { - VmValue::AttrSet(attrs) => attrs.to_value(vm), - VmValue::List(list) => list.to_value(vm), - VmValue::Catchable(catchable) => Value::Catchable(catchable), - VmValue::Const(cnst) => Value::Const(cnst), - VmValue::Thunk(_) => Value::Thunk, - VmValue::PrimOp(_) => Value::PrimOp, - VmValue::PartialPrimOp(_) => Value::PartialPrimOp, + Value::AttrSet(attrs) => attrs.to_value(vm), + Value::List(list) => list.to_value(vm), + Value::Catchable(catchable) => Value_::Catchable(catchable), + Value::Const(cnst) => Value_::Const(cnst), + Value::Thunk(_) => Value_::Thunk, + Value::PrimOp(_) => Value_::PrimOp, + Value::PartialPrimOp(_) => Value_::PartialPrimOp, } } } diff --git a/src/vm/vm.rs b/src/vm/vm.rs index 57fb69b..5c9e6da 100644 --- a/src/vm/vm.rs +++ b/src/vm/vm.rs @@ -1,16 +1,15 @@ use anyhow::Result; -use rpds::{HashTrieMap, HashTrieMapSync, Vector}; use crate::builtins::env; use crate::bytecode::{self, *}; -use crate::value::{Const, Value}; +use crate::value::{Const, Value as Value_}; use super::env::Env; use super::stack::{STACK_SIZE, Stack}; use super::value::{self as vmValue, *}; use super::vmthunk::*; -pub fn run(prog: Program) -> Result { +pub fn run(prog: Program) -> Result { let vm = VM::new(prog.thunks); Ok(vm.eval(prog.top_level, &mut env())?.to_value(&vm)) } @@ -28,11 +27,11 @@ impl VM { VM { thunks } } - pub fn get_thunk_value(&self, idx: usize, env: &mut Env) -> Result { + pub fn get_thunk_value(&self, idx: usize, env: &mut Env) -> Result { self.thunks.get(idx).unwrap().force(self, env) } - pub fn eval(&self, opcodes: OpCodes, env: &mut Env) -> Result { + pub fn eval(&self, opcodes: OpCodes, env: &mut Env) -> Result { let mut stack = Stack::::new(); let mut iter = opcodes.into_iter(); while let Some(opcode) = iter.next() { @@ -54,8 +53,8 @@ impl VM { ) -> Result { match opcode { OpCode::NoOp => (), - OpCode::Const { value } => stack.push(VmValue::Const(value))?, - OpCode::LoadThunk { idx } => stack.push(VmValue::Thunk(vmValue::Thunk::new(idx)))?, + OpCode::Const { value } => stack.push(Value::Const(value))?, + OpCode::LoadThunk { idx } => stack.push(Value::Thunk(vmValue::Thunk::new(idx)))?, OpCode::LoadValue { idx } => { stack.push(self.get_thunk_value(idx, env)?)?; } @@ -64,12 +63,12 @@ impl VM { } OpCode::Jmp { step } => return Ok(step), OpCode::JmpIfTrue { step } => { - if let VmValue::Const(Const::Bool(true)) = stack.pop()? { + if let Value::Const(Const::Bool(true)) = stack.pop()? { return Ok(step); } } OpCode::JmpIfFalse { step } => { - if let VmValue::Const(Const::Bool(false)) = stack.pop()? { + if let Value::Const(Const::Bool(false)) = stack.pop()? { return Ok(step); } } @@ -106,14 +105,14 @@ impl VM { stack.tos_mut()?.concat_string(rhs); } OpCode::List => { - stack.push(VmValue::List(List::new(Vector::new_sync())))?; + stack.push(Value::List(List::empty()))?; } OpCode::PushElem => { let elem = stack.pop()?; stack.tos_mut()?.push(elem); } OpCode::AttrSet => { - stack.push(VmValue::AttrSet(AttrSet::new(HashTrieMap::new_sync())))?; + stack.push(Value::AttrSet(AttrSet::empty()))?; } OpCode::PushStaticAttr { name } => { let val = stack.pop()?; @@ -138,7 +137,7 @@ impl VM { OpCode::SelectOrEmpty { sym } => { stack.tos_mut()?.select_with_default( Symbol::new(sym), - VmValue::AttrSet(AttrSet::new(HashTrieMapSync::new_sync())), + Value::AttrSet(AttrSet::empty()), ); } OpCode::SelectDynamic => { @@ -160,7 +159,7 @@ impl VM { let sym = val.unwrap_const().unwrap_string().into(); stack.tos_mut()?.select_with_default( sym, - VmValue::AttrSet(AttrSet::new(HashTrieMapSync::new_sync())), + Value::AttrSet(AttrSet::empty()), ); } OpCode::HasAttr { sym } => { diff --git a/src/vm/vmthunk.rs b/src/vm/vmthunk.rs index 32c01d4..3c1e6af 100644 --- a/src/vm/vmthunk.rs +++ b/src/vm/vmthunk.rs @@ -7,7 +7,7 @@ use derive_more::{IsVariant, Unwrap}; use crate::bytecode::OpCodes; use super::env::Env; -use super::value::VmValue; +use super::value::Value; use super::vm::VM; pub struct VmThunk { @@ -19,7 +19,7 @@ pub struct VmThunk { enum _VmThunk { Code(OpCodes), SuspendedFrom(*const VmThunk), - Value(VmValue), + Value(Value), } impl VmThunk { @@ -30,7 +30,7 @@ impl VmThunk { } } - pub fn force(&self, vm: &VM, env: &mut Env) -> Result { + pub fn force(&self, vm: &VM, env: &mut Env) -> Result { { let _guard = self.lock.read().unwrap(); match &*self.thunk.borrow() { @@ -59,7 +59,7 @@ impl VmThunk { } } - pub fn value(&self) -> Option { + pub fn value(&self) -> Option { let _guard = self.lock.read(); match &*self.thunk.borrow() { _VmThunk::Value(value) => Some(value.clone()),