1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
use std::collections::HashMap;
use rebel_parse::ast;
use crate::{
func::Func,
typing::{Type, TypeFamily},
value::{self, EvalError, Value},
};
#[derive(Debug, Default)]
pub struct Context {
pub values: Module,
pub methods: HashMap<TypeFamily, HashMap<&'static str, Func>>,
}
impl Context {
pub fn run(&mut self, stmt: &ast::BodyStmt) -> value::Result<Value> {
match stmt {
ast::BodyStmt::Assign { dest, expr } => {
let value = Value::eval(self, expr)?;
let typ = value.typ().or(Err(EvalError))?;
// TODO: Handle specified type
let ast::TypedExpr {
expr: dest_expr,
typ: _,
} = dest;
// TODO: Handle other assignable expressions
let dest_path = match dest_expr {
ast::Expr::Path(path) => path,
_ => return Err(EvalError),
};
let [dest_ident] = dest_path.components[..] else {
return Err(EvalError);
};
// TODO: Lexical scoping
self.values.0.insert(
dest_ident.name.to_owned(),
ModuleEntry::Def((typ, (Some(value.clone())))),
);
Ok(value)
}
ast::BodyStmt::Expr { expr } => Value::eval(self, expr),
ast::BodyStmt::Empty => Ok(Value::Unit),
}
}
}
#[derive(Debug, Default)]
pub struct Module(pub HashMap<String, ModuleEntry>);
impl Module {
pub fn lookup(&self, path: &[ast::Ident<'_>]) -> Option<(&Type, Option<&Value>)> {
let (ident, rest) = path.split_first()?;
match self.0.get(ident.name)? {
ModuleEntry::Module(module) => module.lookup(rest),
ModuleEntry::Def((typ, val)) => {
if rest.is_empty() {
Some((&typ, val.as_ref()))
} else {
None
}
}
}
}
}
#[derive(Debug)]
pub enum ModuleEntry {
Module(Module),
Def((Type, Option<Value>)),
}
|