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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
use std::convert::TryFrom;
use std::ops::Deref;
use crate::{AST, ASTTy};
use crate::check::ast::NodeTy;
use crate::check::constrain::unify::finished::Finished;
use crate::check::name::{Empty, Name};
use crate::check::name::string_name::StringName;
use crate::parse::ast::Node;
impl From<(&Box<AST>, &Finished)> for NodeTy {
fn from((ast, finished): (&Box<AST>, &Finished)) -> Self {
NodeTy::from((ast.deref(), finished))
}
}
impl From<(&AST, &Finished)> for NodeTy {
fn from((ast, finished): (&AST, &Finished)) -> Self {
NodeTy::from((&ast.node, finished))
}
}
impl From<(&Box<Node>, &Finished)> for NodeTy {
fn from((node, finished): (&Box<Node>, &Finished)) -> Self {
NodeTy::from((node.deref(), finished))
}
}
impl From<(&Node, &Finished)> for NodeTy {
fn from((node, finished): (&Node, &Finished)) -> Self {
let pos_to_name = &finished.pos_to_name;
match node {
Node::Import { from, import, alias } => NodeTy::Import {
from: from.clone().map(|from| ASTTy::from((from, finished))).map(Box::from),
import: import.iter().map(|ast| ASTTy::from((ast, finished))).collect(),
alias: alias.iter().map(|ast| ASTTy::from((ast, finished))).collect(),
},
Node::Class { ty, args, parents, body } => NodeTy::Class {
ty: StringName::try_from(ty).unwrap_or_else(|_| StringName::empty()),
args: args.iter().map(|ast| ASTTy::from((ast, finished))).collect(),
parents: parents.iter().map(|ast| ASTTy::from((ast, finished))).collect(),
body: body.clone().map(|ast| ASTTy::from((ast, finished))).map(Box::from),
},
Node::Parent { ty, args } => NodeTy::Parent {
ty: StringName::try_from(ty).unwrap_or_else(|_| StringName::empty()),
args: args.iter().map(|ast| ASTTy::from((ast, finished))).collect(),
},
Node::Reassign { left, right, op } => NodeTy::Reassign {
left: Box::from(ASTTy::from((left, finished))),
right: Box::from(ASTTy::from((right, finished))),
op: op.clone(),
},
Node::VariableDef { mutable, var, expr, forward, ty, .. } => NodeTy::VariableDef {
mutable: *mutable,
var: Box::from(ASTTy::from((var, finished))),
ty: if let Some(ty) = ty {
Name::try_from(ty).ok()
} else {
pos_to_name.get(&var.pos).cloned()
},
expr: expr.clone().map(|ast| ASTTy::from((ast, finished))).map(Box::from),
forward: forward.iter().map(|ast| ASTTy::from((ast, finished))).collect(),
},
Node::FunDef { pure, id, args, ret, raises, body } => NodeTy::FunDef {
pure: *pure,
id: Box::from(ASTTy::from((id, finished))),
args: args.iter().map(|ast| ASTTy::from((ast, finished))).collect(),
ret: ret.as_ref().and_then(|ret_ty| Name::try_from(ret_ty).ok()),
raises: raises.iter().map(|ast| ASTTy::from((ast, finished))).collect(),
body: body.clone().map(|ast| ASTTy::from((ast, finished))).map(Box::from),
},
Node::AnonFun { args, body } => NodeTy::AnonFun {
args: args.iter().map(|ast| ASTTy::from((ast, finished))).collect(),
body: Box::from(ASTTy::from((body, finished))),
},
Node::Raise { error } => NodeTy::Raise {
error: Box::from(ASTTy::from((error, finished)))
},
Node::Handle { expr_or_stmt, cases } => NodeTy::Handle {
expr_or_stmt: Box::from(ASTTy::from((expr_or_stmt, finished))),
cases: cases.iter().map(|ast| ASTTy::from((ast, finished))).collect(),
},
Node::With { resource, alias, expr } => NodeTy::With {
resource: Box::from(ASTTy::from((resource, finished))),
alias: alias.clone().map(|(resource, alias, expr)| {
let resource = Box::from(ASTTy::from((resource, finished)));
let expr = expr.and_then(|expr| Name::try_from(&expr).ok());
(resource, alias, expr)
}),
expr: Box::from(ASTTy::from((expr, finished))),
},
Node::FunctionCall { name, args } => NodeTy::FunctionCall {
name: StringName::try_from(name).unwrap_or_else(|_| StringName::empty()),
args: args.iter().map(|ast| ASTTy::from((ast, finished))).collect(),
},
Node::PropertyCall { instance, property } => NodeTy::PropertyCall {
instance: Box::from(ASTTy::from((instance, finished))),
property: Box::from(ASTTy::from((property, finished))),
},
Node::ExpressionType { expr, mutable, ty } => NodeTy::ExpressionType {
expr: Box::from(ASTTy::from((expr, finished))),
mutable: *mutable,
ty: if let Some(ty) = ty {
Name::try_from(ty).ok()
} else {
pos_to_name.get(&expr.pos).cloned()
},
},
Node::TypeDef { ty, isa, body } => NodeTy::TypeDef {
ty: StringName::try_from(ty).ok().unwrap_or_else(StringName::empty),
isa: isa.as_ref().and_then(|isa| Name::try_from(isa).ok()),
body: body.clone().map(|ast| ASTTy::from((ast, finished))).map(Box::from),
},
Node::TypeAlias { ty, isa, conditions } => NodeTy::TypeAlias {
ty: StringName::try_from(ty).unwrap_or_else(|_| StringName::empty()),
isa: Name::try_from(isa).unwrap_or_else(|_| Name::empty()),
conditions: conditions.iter().map(|ast| ASTTy::from((ast, finished))).collect(),
},
Node::Condition { cond, el } => NodeTy::Condition {
cond: Box::from(ASTTy::from((cond, finished))),
el: el.clone().map(|ast| ASTTy::from((ast, finished))).map(Box::from),
},
Node::FunArg { vararg, mutable, var, default, ty } => NodeTy::FunArg {
vararg: *vararg,
mutable: *mutable,
var: Box::from(ASTTy::from((var, finished))),
ty: ty.as_ref().and_then(|ty| Name::try_from(ty).ok()),
default: default.clone().map(|ast| ASTTy::from((ast, finished))).map(Box::from),
},
Node::Dict { elements } => NodeTy::Dict {
elements: elements.iter().map(|(from, to)|
(ASTTy::from(from), ASTTy::from(to))
).collect()
},
Node::DictBuilder { from, to, conditions } => NodeTy::DictBuilder {
from: Box::from(ASTTy::from(from)),
to: Box::from(ASTTy::from(to)),
conditions: conditions.iter().map(ASTTy::from).collect(),
},
Node::Set { elements } => {
NodeTy::Set { elements: elements.iter().map(|ast| ASTTy::from((ast, finished))).collect() }
}
Node::SetBuilder { item, conditions } => NodeTy::SetBuilder {
item: Box::from(ASTTy::from((item, finished))),
conditions: conditions.iter().map(|ast| ASTTy::from((ast, finished))).collect(),
},
Node::List { elements } => {
NodeTy::List { elements: elements.iter().map(|ast| ASTTy::from((ast, finished))).collect() }
}
Node::ListBuilder { item, conditions } => NodeTy::ListBuilder {
item: Box::from(ASTTy::from((item, finished))),
conditions: conditions.iter().map(|ast| ASTTy::from((ast, finished))).collect(),
},
Node::Tuple { elements } => {
NodeTy::Tuple { elements: elements.iter().map(|ast| ASTTy::from((ast, finished))).collect() }
}
Node::Range { from, to, inclusive, step } => NodeTy::Range {
from: Box::from(ASTTy::from((from, finished))),
to: Box::from(ASTTy::from((to, finished))),
inclusive: *inclusive,
step: step.clone().map(|ast| ASTTy::from((ast, finished))).map(Box::from),
},
Node::Block { statements } => {
NodeTy::Block { statements: statements.iter().map(|ast| ASTTy::from((ast, finished))).collect() }
}
Node::Add { left, right } => NodeTy::Add {
left: Box::from(ASTTy::from((left, finished))),
right: Box::from(ASTTy::from((right, finished))),
},
Node::AddU { expr } => NodeTy::AddU {
expr: Box::from(ASTTy::from((expr, finished)))
},
Node::Sub { left, right } => NodeTy::Sub {
left: Box::from(ASTTy::from((left, finished))),
right: Box::from(ASTTy::from((right, finished))),
},
Node::SubU { expr } => NodeTy::SubU {
expr: Box::from(ASTTy::from((expr, finished)))
},
Node::Mul { left, right } => NodeTy::Mul {
left: Box::from(ASTTy::from((left, finished))),
right: Box::from(ASTTy::from((right, finished))),
},
Node::Div { left, right } => NodeTy::Div {
left: Box::from(ASTTy::from((left, finished))),
right: Box::from(ASTTy::from((right, finished))),
},
Node::FDiv { left, right } => NodeTy::FDiv {
left: Box::from(ASTTy::from((left, finished))),
right: Box::from(ASTTy::from((right, finished))),
},
Node::Mod { left, right } => NodeTy::Mod {
left: Box::from(ASTTy::from((left, finished))),
right: Box::from(ASTTy::from((right, finished))),
},
Node::Pow { left, right } => NodeTy::Pow {
left: Box::from(ASTTy::from((left, finished))),
right: Box::from(ASTTy::from((right, finished))),
},
Node::Sqrt { expr } => NodeTy::Sqrt {
expr: Box::from(ASTTy::from((expr, finished)))
},
Node::BAnd { left, right } => NodeTy::BAnd {
left: Box::from(ASTTy::from((left, finished))),
right: Box::from(ASTTy::from((right, finished))),
},
Node::BOr { left, right } => NodeTy::BOr {
left: Box::from(ASTTy::from((left, finished))),
right: Box::from(ASTTy::from((right, finished))),
},
Node::BXOr { left, right } => NodeTy::BXOr {
left: Box::from(ASTTy::from((left, finished))),
right: Box::from(ASTTy::from((right, finished))),
},
Node::BOneCmpl { expr } => NodeTy::BOneCmpl {
expr: Box::from(ASTTy::from((expr, finished)))
},
Node::BLShift { left, right } => NodeTy::BLShift {
left: Box::from(ASTTy::from((left, finished))),
right: Box::from(ASTTy::from((right, finished))),
},
Node::BRShift { left, right } => NodeTy::BRShift {
left: Box::from(ASTTy::from((left, finished))),
right: Box::from(ASTTy::from((right, finished))),
},
Node::Le { left, right } => NodeTy::Le {
left: Box::from(ASTTy::from((left, finished))),
right: Box::from(ASTTy::from((right, finished))),
},
Node::Ge { left, right } => NodeTy::Ge {
left: Box::from(ASTTy::from((left, finished))),
right: Box::from(ASTTy::from((right, finished))),
},
Node::Leq { left, right } => NodeTy::Leq {
left: Box::from(ASTTy::from((left, finished))),
right: Box::from(ASTTy::from((right, finished))),
},
Node::Geq { left, right } => NodeTy::Geq {
left: Box::from(ASTTy::from((left, finished))),
right: Box::from(ASTTy::from((right, finished))),
},
Node::Is { left, right } => NodeTy::Is {
left: Box::from(ASTTy::from((left, finished))),
right: Box::from(ASTTy::from((right, finished))),
},
Node::IsN { left, right } => NodeTy::IsN {
left: Box::from(ASTTy::from((left, finished))),
right: Box::from(ASTTy::from((right, finished))),
},
Node::Eq { left, right } => NodeTy::Eq {
left: Box::from(ASTTy::from((left, finished))),
right: Box::from(ASTTy::from((right, finished))),
},
Node::Neq { left, right } => NodeTy::Neq {
left: Box::from(ASTTy::from((left, finished))),
right: Box::from(ASTTy::from((right, finished))),
},
Node::IsA { left, right } => NodeTy::IsA {
left: Box::from(ASTTy::from((left, finished))),
right: Box::from(ASTTy::from((right, finished))),
},
Node::IsNA { left, right } => NodeTy::IsNA {
left: Box::from(ASTTy::from((left, finished))),
right: Box::from(ASTTy::from((right, finished))),
},
Node::Not { expr } => NodeTy::Not {
expr: Box::from(ASTTy::from((expr, finished)))
},
Node::And { left, right } => NodeTy::And {
left: Box::from(ASTTy::from((left, finished))),
right: Box::from(ASTTy::from((right, finished))),
},
Node::Or { left, right } => NodeTy::Or {
left: Box::from(ASTTy::from((left, finished))),
right: Box::from(ASTTy::from((right, finished))),
},
Node::IfElse { cond, then, el } => NodeTy::IfElse {
cond: Box::from(ASTTy::from((cond, finished))),
then: Box::from(ASTTy::from((then, finished))),
el: el.clone().map(|ast| ASTTy::from((ast, finished))).map(Box::from),
},
Node::Match { cond, cases } => NodeTy::Match {
cond: Box::from(ASTTy::from((cond, finished))),
cases: cases.iter().map(|ast| ASTTy::from((ast, finished))).collect(),
},
Node::Case { cond, body } => NodeTy::Case {
cond: Box::from(ASTTy::from((cond, finished))),
body: Box::from(ASTTy::from((body, finished))),
},
Node::For { expr, col, body } => NodeTy::For {
expr: Box::from(ASTTy::from((expr, finished))),
col: Box::from(ASTTy::from((col, finished))),
body: Box::from(ASTTy::from((body, finished))),
},
Node::In { left, right } => NodeTy::In {
left: Box::from(ASTTy::from((left, finished))),
right: Box::from(ASTTy::from((right, finished))),
},
Node::While { cond, body } => NodeTy::While {
cond: Box::from(ASTTy::from((cond, finished))),
body: Box::from(ASTTy::from((body, finished))),
},
Node::Return { expr } => NodeTy::Return {
expr: Box::from(ASTTy::from((expr, finished)))
},
Node::Question { left, right } => NodeTy::Question {
left: Box::from(ASTTy::from((left, finished))),
right: Box::from(ASTTy::from((right, finished))),
},
Node::QuestionOp { expr } => NodeTy::QuestionOp {
expr: Box::from(ASTTy::from((expr, finished)))
},
Node::Id { lit } => NodeTy::Id { lit: lit.clone() },
Node::Slice { from, to, inclusive, step } => NodeTy::Slice {
from: Box::from(ASTTy::from((from, finished))),
to: Box::from(ASTTy::from((to, finished))),
inclusive: *inclusive,
step: step.clone().map(|ast| ASTTy::from((ast, finished))).map(Box::from),
},
Node::Index { item, range } => NodeTy::Index {
item: Box::from(ASTTy::from((item, finished))),
range: Box::from(ASTTy::from((range, finished))),
},
Node::Real { lit } => NodeTy::Real { lit: lit.clone() },
Node::Int { lit } => NodeTy::Int { lit: lit.clone() },
Node::ENum { num, exp } => NodeTy::ENum { num: num.clone(), exp: exp.clone() },
Node::Str { lit, expressions } => NodeTy::Str {
lit: lit.clone(),
expressions: expressions.iter().map(|ast| ASTTy::from((ast, finished))).collect(),
},
Node::DocStr { lit } => NodeTy::DocStr { lit: lit.clone() },
Node::Bool { lit } => NodeTy::Bool { lit: *lit },
Node::Break => NodeTy::Break,
Node::Continue => NodeTy::Continue,
Node::ReturnEmpty => NodeTy::ReturnEmpty,
Node::Underscore => NodeTy::Underscore,
Node::Undefined => NodeTy::Undefined,
Node::Pass => NodeTy::Pass,
_ => NodeTy::Empty
}
}
}