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