cl-interpret: Make ConValues act like value types

(Aside from the fact that they're smothered in heap allocations)
This commit is contained in:
John 2025-01-28 06:20:10 -06:00
parent 01871bf455
commit 485afb7843
2 changed files with 33 additions and 8 deletions

View File

@ -31,20 +31,23 @@ pub enum ConValue {
/// A reference
Ref(Rc<ConValue>),
/// An Array
Array(Rc<[ConValue]>),
Array(Box<[ConValue]>),
/// A tuple
Tuple(Rc<[ConValue]>),
Tuple(Box<[ConValue]>),
/// An exclusive range
RangeExc(Integer, Integer),
/// An inclusive range
RangeInc(Integer, Integer),
/// A value of a product type
Struct(Rc<(Sym, HashMap<Sym, ConValue>)>),
Struct(Box<(Sym, HashMap<Sym, ConValue>)>),
/// An entire namespace
Module(Box<HashMap<Sym, Option<ConValue>>>),
/// A callable thing
Function(Rc<Function>),
/// A built-in function
BuiltIn(&'static dyn BuiltIn),
}
impl ConValue {
/// Gets whether the current value is true or false
pub fn truthy(&self) -> IResult<bool> {
@ -57,7 +60,7 @@ impl ConValue {
let (Self::Int(a), Self::Int(b)) = (self, other) else {
Err(Error::TypeError)?
};
Ok(Self::RangeExc(a, b.saturating_sub(1)))
Ok(Self::RangeExc(a, b))
}
pub fn range_inc(self, other: Self) -> IResult<Self> {
let (Self::Int(a), Self::Int(b)) = (self, other) else {
@ -304,6 +307,18 @@ impl std::fmt::Display for ConValue {
}
Ok(())
}
ConValue::Module(module) => {
use std::fmt::Write;
let mut f = f.delimit_with("{", "\n}");
for (k, v) in module.iter() {
write!(f, "\n{k}: ")?;
match v {
Some(v) => write!(f, "{v},"),
None => write!(f, "_,"),
}?
}
Ok(())
}
ConValue::Function(func) => {
write!(f, "{}", func.decl())
}

View File

@ -67,11 +67,21 @@ impl Interpret for Static {
impl Interpret for Module {
fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
let Self { name, kind } = self;
// TODO: Enter this module's namespace
match kind {
env.push_frame(Interned::to_ref(name), Default::default());
let out = match kind {
ModuleKind::Inline(file) => file.interpret(env),
ModuleKind::Outline => Err(Error::Outlined(*name)),
}
ModuleKind::Outline => {
eprintln!("{}", Error::Outlined(*name));
Ok(ConValue::Empty)
}
};
let frame = env
.pop_frame()
.expect("Environment frames must be balanced");
env.insert(*name, Some(ConValue::Module(frame.into())));
out
}
}
impl Interpret for Function {