cl-interpret: process use items and imports in the interpreter
This commit is contained in:
parent
af9c293907
commit
edabbe1655
@ -81,7 +81,6 @@ pub struct Item {
|
||||
/// What kind of [Item] is this?
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum ItemKind {
|
||||
// TODO: Import declaration ("use") item
|
||||
// TODO: Trait declaration ("trait") item?
|
||||
/// A [module](Module)
|
||||
Module(Module),
|
||||
|
@ -97,8 +97,8 @@ impl Environment {
|
||||
self.frames.push((frame, name));
|
||||
}
|
||||
|
||||
pub fn pop_frame(&mut self) -> Option<StackFrame> {
|
||||
self.frames.pop().map(|f| f.0)
|
||||
pub fn pop_frame(&mut self) -> Option<(StackFrame, &'static str)> {
|
||||
self.frames.pop()
|
||||
}
|
||||
|
||||
pub fn eval(&mut self, node: &impl Interpret) -> IResult<ConValue> {
|
||||
|
@ -68,7 +68,7 @@ impl Callable for Function {
|
||||
}
|
||||
let res = body.interpret(&mut frame);
|
||||
drop(frame);
|
||||
if let Some(upvars) = env.pop_frame() {
|
||||
if let Some((upvars, _)) = env.pop_frame() {
|
||||
self.upvars.replace(upvars);
|
||||
}
|
||||
match res {
|
||||
|
@ -37,10 +37,7 @@ impl Interpret for Item {
|
||||
ItemKind::Struct(item) => item.interpret(env),
|
||||
ItemKind::Enum(item) => item.interpret(env),
|
||||
ItemKind::Impl(item) => item.interpret(env),
|
||||
ItemKind::Use(item) => {
|
||||
eprintln!("TODO: namespaces and imports in the interpreter!\n{item}\n");
|
||||
Ok(ConValue::Empty)
|
||||
}
|
||||
ItemKind::Use(item) => item.interpret(env),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -80,7 +77,7 @@ impl Interpret for Module {
|
||||
}
|
||||
};
|
||||
|
||||
let frame = env
|
||||
let (frame, _) = env
|
||||
.pop_frame()
|
||||
.expect("Environment frames must be balanced");
|
||||
env.insert(*name, Some(ConValue::Module(frame.into())));
|
||||
@ -114,6 +111,73 @@ impl Interpret for Impl {
|
||||
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 {
|
||||
fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
|
||||
let Self { extents: _, kind, semi } = self;
|
||||
|
@ -681,7 +681,11 @@ impl Parse<'_> for UseTree {
|
||||
let PathPart::Ident(name) = name else {
|
||||
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))?,
|
||||
|
@ -1,5 +1,6 @@
|
||||
//! Formats numbers in hexadecimal, octal, or binary
|
||||
mod math;
|
||||
use math::{min, count_leading_zeroes};
|
||||
|
||||
fn as_digit(n: u32) -> char {
|
||||
(if n > 9 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user