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
use super::type_system::*;
use parser::ast;
use std::collections::HashMap;
use strtab::Symbol;
use utils::ref_eq::RefEq;
use std::rc::Rc;
#[derive(Default, Debug)]
pub struct TypeAnalysis<'src, 'ast> {
class_types: HashMap<RefEq<&'ast ast::ClassDeclaration<'src>>, ClassDefId<'src>>,
expr_info: HashMap<RefEq<&'ast ast::Expr<'src>>, ExprInfo<'src, 'ast>>,
local_val_defs: HashMap<RefEq<&'ast ast::Stmt<'src>>, Rc<LocalVarDef<'src>>>,
}
impl<'src, 'ast, 'ts> TypeAnalysis<'src, 'ast> {
pub fn new() -> TypeAnalysis<'src, 'ast> {
TypeAnalysis::default()
}
pub fn expr_info(&self, expr: &'ast ast::Expr<'src>) -> &ExprInfo<'src, 'ast> {
self.expr_info
.get(&RefEq(expr))
.expect("after typechecking every expression should have a type")
}
pub fn set_expr_info(&mut self, expr: &'ast ast::Expr<'src>, expr_info: ExprInfo<'src, 'ast>) {
self.expr_info.insert(RefEq(expr), expr_info);
}
pub fn set_local_var_def(
&mut self,
local_var_def_stmt: &'ast ast::Stmt<'src>,
var_def: Rc<LocalVarDef<'src>>,
) {
self.local_val_defs
.insert(RefEq(local_var_def_stmt), var_def);
}
pub fn local_var_def(
&self,
local_var_def_stmt: &'ast ast::Stmt<'src>,
) -> Option<Rc<LocalVarDef<'src>>> {
match self.local_val_defs.get(&RefEq(local_var_def_stmt)) {
Some(var_def) => Some(Rc::clone(var_def)),
None => None,
}
}
pub fn decl_set_class_id(
&mut self,
class_decl: &'ast ast::ClassDeclaration<'src>,
name: ClassDefId<'src>,
) {
self.class_types.insert(RefEq(class_decl), name);
}
pub fn decl_get_class_id(
&mut self,
class_decl: &'ast ast::ClassDeclaration<'src>,
) -> Option<ClassDefId<'src>> {
self.class_types.get(&RefEq(class_decl)).cloned()
}
}
#[derive(Debug, Clone)]
pub struct LocalVarDef<'src> {
pub name: Symbol<'src>,
pub ty: CheckedType<'src>,
}
#[derive(Debug, Clone)]
pub struct ExprInfo<'src, 'ast> {
pub ty: CheckedType<'src>,
pub ref_info: Option<RefInfo<'src, 'ast>>,
}
impl<'src, 'ast> ExprInfo<'src, 'ast> {
pub fn new(ty: CheckedType<'src>, ref_info: RefInfo<'src, 'ast>) -> Self {
ExprInfo {
ty,
ref_info: Some(ref_info),
}
}
}
impl<'src, 'ast, 'ts> From<CheckedType<'src>> for ExprInfo<'src, 'ast> {
fn from(item: CheckedType<'src>) -> ExprInfo<'src, 'ast> {
ExprInfo {
ty: item,
ref_info: None,
}
}
}
#[derive(Debug, Clone)]
pub enum RefInfo<'src, 'ast> {
GlobalVar(Symbol<'src>),
Var(Rc<LocalVarDef<'src>>),
Param(Rc<MethodParamDef<'src>>),
Field(Rc<ClassFieldDef<'src>>),
Method(Rc<ClassMethodDef<'src, 'ast>>),
This(Rc<ClassDef<'src, 'ast>>),
ArrayAccess,
}