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 /// A reference
Ref(Rc<ConValue>), Ref(Rc<ConValue>),
/// An Array /// An Array
Array(Rc<[ConValue]>), Array(Box<[ConValue]>),
/// A tuple /// A tuple
Tuple(Rc<[ConValue]>), Tuple(Box<[ConValue]>),
/// An exclusive range /// An exclusive range
RangeExc(Integer, Integer), RangeExc(Integer, Integer),
/// An inclusive range /// An inclusive range
RangeInc(Integer, Integer), RangeInc(Integer, Integer),
/// A value of a product type /// 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 /// A callable thing
Function(Rc<Function>), Function(Rc<Function>),
/// A built-in function /// A built-in function
BuiltIn(&'static dyn BuiltIn), BuiltIn(&'static dyn BuiltIn),
} }
impl ConValue { impl ConValue {
/// Gets whether the current value is true or false /// Gets whether the current value is true or false
pub fn truthy(&self) -> IResult<bool> { pub fn truthy(&self) -> IResult<bool> {
@ -57,7 +60,7 @@ impl ConValue {
let (Self::Int(a), Self::Int(b)) = (self, other) else { let (Self::Int(a), Self::Int(b)) = (self, other) else {
Err(Error::TypeError)? 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> { pub fn range_inc(self, other: Self) -> IResult<Self> {
let (Self::Int(a), Self::Int(b)) = (self, other) else { let (Self::Int(a), Self::Int(b)) = (self, other) else {
@ -304,6 +307,18 @@ impl std::fmt::Display for ConValue {
} }
Ok(()) 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) => { ConValue::Function(func) => {
write!(f, "{}", func.decl()) write!(f, "{}", func.decl())
} }

View File

@ -67,11 +67,21 @@ impl Interpret for Static {
impl Interpret for Module { impl Interpret for Module {
fn interpret(&self, env: &mut Environment) -> IResult<ConValue> { fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
let Self { name, kind } = self; let Self { name, kind } = self;
// TODO: Enter this module's namespace env.push_frame(Interned::to_ref(name), Default::default());
match kind { let out = match kind {
ModuleKind::Inline(file) => file.interpret(env), 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 { impl Interpret for Function {