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
78
79
80
81
82
83
|
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<(Type, Option<Value>)>,
pub methods: HashMap<TypeFamily, HashMap<&'static str, Func>>,
}
impl Context {
pub fn execute(&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)]
pub struct Module<T>(pub HashMap<String, ModuleEntry<T>>);
impl<T> Module<T> {
pub fn lookup(&self, path: &[ast::Ident<'_>]) -> Option<&T> {
let (ident, rest) = path.split_first()?;
match self.0.get(ident.name)? {
ModuleEntry::Module(module) => module.lookup(rest),
ModuleEntry::Def(def) => {
if rest.is_empty() {
Some(def)
} else {
None
}
}
}
}
}
impl<T> Default for Module<T> {
fn default() -> Self {
Self(HashMap::new())
}
}
#[derive(Debug)]
pub enum ModuleEntry<T> {
Module(Module<T>),
Def(T),
}
|