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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
use std::{collections::HashMap, ops::Deref};
use rebel_parse::ast::{self, pat};
use crate::{
func::Func,
typing::{self, Type, TypeError, TypeFamily},
value::{self, EvalError, Value},
};
#[derive(Debug, Clone)]
pub struct Var {
pub explicit_type: Type,
pub inferred_type: Type,
pub value: Option<Value>,
}
#[derive(Debug, Clone, Default)]
pub struct Context {
pub vars: Module<Var>,
pub methods: HashMap<TypeFamily, HashMap<&'static str, Func>>,
}
impl Context {
pub fn record_type(&mut self, stmt: &ast::BodyStmt) -> typing::Result<Type> {
match stmt {
ast::BodyStmt::Assign { dest, expr } => {
let typ = Type::ast_expr_type(self, expr)?;
// TODO: Handle explicit type
let ast::TypedPat { pat, typ: _ } = dest.deref();
// TODO: Handle other assignable expressions
let pat::Pat::Path(dest_path) = pat;
let [dest_ident] = dest_path.components[..] else {
return Err(TypeError);
};
// TODO: Lexical scoping
self.vars.0.insert(
dest_ident.name.to_owned(),
ModuleEntry::Def(Var {
explicit_type: Type::Free,
inferred_type: typ.clone(),
value: None,
}),
);
Ok(typ)
}
ast::BodyStmt::Expr { expr } => Type::ast_expr_type(self, expr),
ast::BodyStmt::Empty => Ok(Type::Unit),
}
}
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 explicit type
let ast::TypedPat { pat, typ: _ } = dest.deref();
// TODO: Handle other assignable expressions
let pat::Pat::Path(dest_path) = pat;
let [dest_ident] = dest_path.components[..] else {
return Err(EvalError);
};
// TODO: Lexical scoping
self.vars.0.insert(
dest_ident.name.to_owned(),
ModuleEntry::Def(Var {
explicit_type: Type::Free,
inferred_type: typ,
value: Some(value.clone()),
}),
);
Ok(value)
}
ast::BodyStmt::Expr { expr } => Value::eval(self, expr),
ast::BodyStmt::Empty => Ok(Value::Unit),
}
}
}
#[derive(Debug, Clone)]
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, Clone)]
pub enum ModuleEntry<T> {
Module(Module<T>),
Def(T),
}
|