cl-interpret: Make ConValues act like value types
(Aside from the fact that they're smothered in heap allocations)
This commit is contained in:
parent
01871bf455
commit
485afb7843
@ -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())
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user