cl-interpret: process use items and imports in the interpreter

This commit is contained in:
John 2025-02-18 21:44:52 -06:00
parent af9c293907
commit edabbe1655
6 changed files with 78 additions and 10 deletions

View File

@ -81,7 +81,6 @@ pub struct Item {
/// What kind of [Item] is this? /// What kind of [Item] is this?
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum ItemKind { pub enum ItemKind {
// TODO: Import declaration ("use") item
// TODO: Trait declaration ("trait") item? // TODO: Trait declaration ("trait") item?
/// A [module](Module) /// A [module](Module)
Module(Module), Module(Module),

View File

@ -97,8 +97,8 @@ impl Environment {
self.frames.push((frame, name)); self.frames.push((frame, name));
} }
pub fn pop_frame(&mut self) -> Option<StackFrame> { pub fn pop_frame(&mut self) -> Option<(StackFrame, &'static str)> {
self.frames.pop().map(|f| f.0) self.frames.pop()
} }
pub fn eval(&mut self, node: &impl Interpret) -> IResult<ConValue> { pub fn eval(&mut self, node: &impl Interpret) -> IResult<ConValue> {

View File

@ -68,7 +68,7 @@ impl Callable for Function {
} }
let res = body.interpret(&mut frame); let res = body.interpret(&mut frame);
drop(frame); drop(frame);
if let Some(upvars) = env.pop_frame() { if let Some((upvars, _)) = env.pop_frame() {
self.upvars.replace(upvars); self.upvars.replace(upvars);
} }
match res { match res {

View File

@ -37,10 +37,7 @@ impl Interpret for Item {
ItemKind::Struct(item) => item.interpret(env), ItemKind::Struct(item) => item.interpret(env),
ItemKind::Enum(item) => item.interpret(env), ItemKind::Enum(item) => item.interpret(env),
ItemKind::Impl(item) => item.interpret(env), ItemKind::Impl(item) => item.interpret(env),
ItemKind::Use(item) => { ItemKind::Use(item) => item.interpret(env),
eprintln!("TODO: namespaces and imports in the interpreter!\n{item}\n");
Ok(ConValue::Empty)
}
} }
} }
} }
@ -80,7 +77,7 @@ impl Interpret for Module {
} }
}; };
let frame = env let (frame, _) = env
.pop_frame() .pop_frame()
.expect("Environment frames must be balanced"); .expect("Environment frames must be balanced");
env.insert(*name, Some(ConValue::Module(frame.into()))); env.insert(*name, Some(ConValue::Module(frame.into())));
@ -114,6 +111,73 @@ impl Interpret for Impl {
body.interpret(env) body.interpret(env)
} }
} }
impl Interpret for Use {
fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
let Self { absolute: _, tree } = self;
tree.interpret(env)
}
}
impl Interpret for UseTree {
fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
type Bindings = HashMap<Sym, ConValue>;
use std::collections::HashMap;
fn get_bindings(
tree: &UseTree,
env: &mut Environment,
bindings: &mut Bindings,
) -> IResult<()> {
match tree {
UseTree::Tree(use_trees) => {
for tree in use_trees {
get_bindings(tree, env, bindings)?;
}
}
UseTree::Path(PathPart::Ident(name), tree) => {
let Ok(ConValue::Module(m)) = env.get(*name) else {
Err(Error::TypeError)?
};
env.push_frame(Interned::to_ref(name), *m);
let out = get_bindings(tree, env, bindings);
env.pop_frame();
return out;
}
UseTree::Alias(name, alias) => {
bindings.insert(*alias, env.get(*name)?);
}
UseTree::Name(name) => {
bindings.insert(*name, env.get(*name)?);
}
UseTree::Glob => {
if let Some((frame, name)) = env.pop_frame() {
for (k, v) in &frame {
if let Some(v) = v {
bindings.insert(*k, v.clone());
}
}
env.push_frame(name, frame);
}
}
other => {
eprintln!("ERROR: Cannot use {other}");
}
}
Ok(())
}
let mut bindings = Bindings::new();
get_bindings(self, env, &mut bindings)?;
for (name, value) in bindings {
env.insert(name, Some(value));
}
Ok(ConValue::Empty)
}
}
impl Interpret for Stmt { impl Interpret for Stmt {
fn interpret(&self, env: &mut Environment) -> IResult<ConValue> { fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
let Self { extents: _, kind, semi } = self; let Self { extents: _, kind, semi } = self;

View File

@ -681,7 +681,11 @@ impl Parse<'_> for UseTree {
let PathPart::Ident(name) = name else { let PathPart::Ident(name) = name else {
Err(p.error(ErrorKind::ExpectedParsing { want: Parsing::Identifier }, P))? Err(p.error(ErrorKind::ExpectedParsing { want: Parsing::Identifier }, P))?
}; };
UseTree::Name(name) if p.match_type(TokenKind::As, P).is_ok() {
UseTree::Alias(name, p.parse()?)
} else {
UseTree::Name(name)
}
} }
} }
t => Err(p.error(Unexpected(t), Parsing::UseTree))?, t => Err(p.error(Unexpected(t), Parsing::UseTree))?,

View File

@ -1,5 +1,6 @@
//! Formats numbers in hexadecimal, octal, or binary //! Formats numbers in hexadecimal, octal, or binary
mod math; mod math;
use math::{min, count_leading_zeroes};
fn as_digit(n: u32) -> char { fn as_digit(n: u32) -> char {
(if n > 9 { (if n > 9 {