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
120
121
use erg_common::config::ErgConfig;
use erg_common::dict::Dict;
use erg_common::log;
use erg_common::traits::{Locational, Stream};
use erg_common::Str;
use erg_parser::ast::{ClassDef, Expr, Methods, Module, PreDeclTypeSpec, TypeSpec, AST};
use crate::error::{TyCheckError, TyCheckErrors};
#[derive(Debug, Default)]
pub struct Reorderer {
cfg: ErgConfig,
pub def_root_pos_map: Dict<Str, usize>,
pub deps: Dict<Str, Vec<Str>>,
pub errs: TyCheckErrors,
}
impl Reorderer {
pub fn new(cfg: ErgConfig) -> Self {
Self {
cfg,
def_root_pos_map: Dict::new(),
deps: Dict::new(),
errs: TyCheckErrors::empty(),
}
}
pub fn reorder(mut self, mut ast: AST) -> Result<AST, TyCheckErrors> {
log!(info "the reordering process has started.");
let mut new = vec![];
while let Some(chunk) = ast.module.lpop() {
match chunk {
Expr::Def(def) => {
match def.body.block.first().unwrap() {
Expr::Call(call) => {
match call.obj.get_name().map(|s| &s[..]) {
Some("Class" | "Inherit" | "Inheritable") => {
self.def_root_pos_map.insert(
def.sig.ident().unwrap().inspect().clone(),
new.len(),
);
let type_def = ClassDef::new(def, vec![]);
new.push(Expr::ClassDef(type_def));
}
_ => {
new.push(Expr::Def(def));
}
}
}
_ => {
new.push(Expr::Def(def));
}
}
}
Expr::Methods(methods) => match &methods.class {
TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(simple)) => {
self.link_methods(simple.ident.inspect().clone(), &mut new, methods)
}
TypeSpec::TypeApp { spec, .. } => {
if let TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(simple)) = spec.as_ref()
{
self.link_methods(simple.ident.inspect().clone(), &mut new, methods)
} else {
let similar_name = self
.def_root_pos_map
.keys()
.fold("".to_string(), |acc, key| acc + &key[..] + ",");
self.errs.push(TyCheckError::no_var_error(
self.cfg.input.clone(),
line!() as usize,
methods.class.loc(),
"".into(),
&methods.class.to_string(),
Some(&Str::from(similar_name)),
));
}
}
other => todo!("{other}"),
},
other => {
new.push(other);
}
}
}
let ast = AST::new(ast.name, Module::new(new));
log!(info "the reordering process has completed:\n{}", ast);
if self.errs.is_empty() {
Ok(ast)
} else {
Err(self.errs)
}
}
fn link_methods(&mut self, name: Str, new: &mut Vec<Expr>, methods: Methods) {
if let Some(pos) = self.def_root_pos_map.get(&name) {
let mut class_def = match new.remove(*pos) {
Expr::ClassDef(class_def) => class_def,
_ => unreachable!(),
};
class_def.methods_list.push(methods);
new.insert(*pos, Expr::ClassDef(class_def));
} else {
let similar_name = self
.def_root_pos_map
.keys()
.fold("".to_string(), |acc, key| acc + &key[..] + ",");
self.errs.push(TyCheckError::no_var_error(
self.cfg.input.clone(),
line!() as usize,
methods.class.loc(),
"".into(),
&name,
Some(&Str::from(similar_name)),
));
}
}
}