88 lines
2.8 KiB
Rust
88 lines
2.8 KiB
Rust
use gc_arena::{Gc, Mutation};
|
|
use hashbrown::HashMap;
|
|
|
|
use crate::env::VmEnv;
|
|
use crate::ty::internal::{AttrSet, CoW, PrimOp, Value};
|
|
use crate::vm::VM;
|
|
|
|
pub fn env<'gc>(vm: &VM, mc: &Mutation<'gc>) -> Gc<'gc, VmEnv<'gc>> {
|
|
let primops = [
|
|
PrimOp::new("add", 2, |args, _, mc| {
|
|
let Ok([mut first, second]): Result<[Value; 2], _> = args.try_into() else {
|
|
unreachable!()
|
|
};
|
|
first.add(second, mc);
|
|
first.ok()
|
|
}),
|
|
PrimOp::new("sub", 2, |args, _, mc| {
|
|
let Ok([mut first, mut second]): Result<[Value; 2], _> = args.try_into() else {
|
|
unreachable!()
|
|
};
|
|
second.neg();
|
|
first.add(second, mc);
|
|
first.ok()
|
|
}),
|
|
PrimOp::new("mul", 2, |args, _, _| {
|
|
let Ok([mut first, second]): Result<[Value; 2], _> = args.try_into() else {
|
|
unreachable!()
|
|
};
|
|
first.mul(second);
|
|
first.ok()
|
|
}),
|
|
PrimOp::new("div", 2, |args, _, _| {
|
|
let Ok([mut first, second]): Result<[Value; 2], _> = args.try_into() else {
|
|
unreachable!()
|
|
};
|
|
first.div(second)?;
|
|
first.ok()
|
|
}),
|
|
PrimOp::new("lessThan", 2, |args, _, _| {
|
|
let Ok([mut first, second]): Result<[Value; 2], _> = args.try_into() else {
|
|
unreachable!()
|
|
};
|
|
first.lt(second);
|
|
first.ok()
|
|
}),
|
|
/* PrimOp::new("seq", 2, |args, vm, mc| {
|
|
let Ok([mut first, second]): Result<[_; 2], _> = args.try_into() else {
|
|
unreachable!()
|
|
};
|
|
first.force(vm, mc).unwrap();
|
|
second.ok()
|
|
}),
|
|
PrimOp::new("deepSeq", 2, |args, vm, mc| {
|
|
let Ok([mut first, second]): Result<[_; 2], _> = args.try_into() else {
|
|
unreachable!()
|
|
};
|
|
first.force_deep(vm, mc).unwrap();
|
|
second.ok()
|
|
}), */
|
|
];
|
|
|
|
let mut env_map = HashMap::new();
|
|
env_map.insert(vm.new_sym("true"), Value::Bool(true));
|
|
env_map.insert(vm.new_sym("false"), Value::Bool(false));
|
|
|
|
let mut map = HashMap::new();
|
|
for primop in primops {
|
|
let primop = Gc::new(mc, primop);
|
|
env_map.insert(
|
|
vm.new_sym(format!("__{}", primop.name)),
|
|
Value::PrimOp(primop.clone()),
|
|
);
|
|
map.insert(vm.new_sym(primop.name), Value::PrimOp(primop));
|
|
}
|
|
let sym = vm.new_sym("builtins");
|
|
let attrs = CoW::new_cyclic(
|
|
|this| {
|
|
map.insert(sym, Value::AttrSet(this));
|
|
AttrSet::from_inner(map)
|
|
},
|
|
mc,
|
|
);
|
|
let builtins = Value::AttrSet(attrs);
|
|
|
|
env_map.insert(sym, builtins);
|
|
VmEnv::new(Gc::new(mc, env_map.into()), mc)
|
|
}
|