Skip to content

Commit 1e87b2e

Browse files
committed
add type evaluation for dict set and tuples
1 parent 17f981b commit 1e87b2e

File tree

5 files changed

+91
-121
lines changed

5 files changed

+91
-121
lines changed

typechecker/src/semantic_analyzer.rs

Lines changed: 31 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -254,13 +254,9 @@ impl TraversalVisitor for SemanticAnalyzer {
254254
}
255255
}
256256

257-
fn visit_import(&mut self, _i: &parser::ast::Import) {
258-
todo!();
259-
}
257+
fn visit_import(&mut self, _i: &parser::ast::Import) {}
260258

261-
fn visit_import_from(&mut self, _i: &parser::ast::ImportFrom) {
262-
todo!();
263-
}
259+
fn visit_import_from(&mut self, _i: &parser::ast::ImportFrom) {}
264260

265261
fn visit_if(&mut self, i: &parser::ast::If) {
266262
for stmt in &i.body {
@@ -419,99 +415,55 @@ impl TraversalVisitor for SemanticAnalyzer {
419415

420416
fn visit_tuple(&mut self, _t: &parser::ast::Tuple) {}
421417

422-
fn visit_dict(&mut self, _d: &parser::ast::Dict) {
423-
todo!()
424-
}
418+
fn visit_dict(&mut self, _d: &parser::ast::Dict) {}
425419

426-
fn visit_set(&mut self, _s: &parser::ast::Set) {
427-
todo!()
428-
}
420+
fn visit_set(&mut self, _s: &parser::ast::Set) {}
429421

430422
fn visit_name(&mut self, _n: &parser::ast::Name) {}
431423

432-
fn visit_bool_op(&mut self, _b: &parser::ast::BoolOperation) {
433-
todo!()
434-
}
424+
fn visit_bool_op(&mut self, _b: &parser::ast::BoolOperation) {}
435425

436-
fn visit_unary_op(&mut self, _u: &parser::ast::UnaryOperation) {
437-
todo!()
438-
}
426+
fn visit_unary_op(&mut self, _u: &parser::ast::UnaryOperation) {}
439427

440428
fn visit_bin_op(&mut self, _b: &parser::ast::BinOp) {}
441429

442-
fn visit_named_expr(&mut self, _n: &parser::ast::NamedExpression) {
443-
todo!()
444-
}
430+
fn visit_named_expr(&mut self, _n: &parser::ast::NamedExpression) {}
445431

446-
fn visit_yield(&mut self, _y: &parser::ast::Yield) {
447-
todo!()
448-
}
432+
fn visit_yield(&mut self, _y: &parser::ast::Yield) {}
449433

450-
fn visit_yield_from(&mut self, _y: &parser::ast::YieldFrom) {
451-
todo!()
452-
}
434+
fn visit_yield_from(&mut self, _y: &parser::ast::YieldFrom) {}
453435

454-
fn visit_starred(&mut self, _s: &parser::ast::Starred) {
455-
todo!()
456-
}
436+
fn visit_starred(&mut self, _s: &parser::ast::Starred) {}
457437

458-
fn visit_generator(&mut self, _g: &parser::ast::Generator) {
459-
todo!()
460-
}
438+
fn visit_generator(&mut self, _g: &parser::ast::Generator) {}
461439

462-
fn visit_list_comp(&mut self, _l: &parser::ast::ListComp) {
463-
todo!()
464-
}
440+
fn visit_list_comp(&mut self, _l: &parser::ast::ListComp) {}
465441

466-
fn visit_set_comp(&mut self, _s: &parser::ast::SetComp) {
467-
todo!()
468-
}
442+
fn visit_set_comp(&mut self, _s: &parser::ast::SetComp) {}
469443

470-
fn visit_dict_comp(&mut self, _d: &parser::ast::DictComp) {
471-
todo!()
472-
}
444+
fn visit_dict_comp(&mut self, _d: &parser::ast::DictComp) {}
473445

474-
fn visit_attribute(&mut self, _a: &parser::ast::Attribute) {
475-
todo!()
476-
}
446+
fn visit_attribute(&mut self, _a: &parser::ast::Attribute) {}
477447

478-
fn visit_subscript(&mut self, _s: &parser::ast::Subscript) {
479-
todo!()
480-
}
448+
fn visit_subscript(&mut self, _s: &parser::ast::Subscript) {}
481449

482-
fn visit_slice(&mut self, _s: &parser::ast::Slice) {
483-
todo!()
484-
}
450+
fn visit_slice(&mut self, _s: &parser::ast::Slice) {}
485451

486452
fn visit_call(&mut self, _c: &parser::ast::Call) {}
487453

488-
fn visit_await(&mut self, _a: &parser::ast::Await) {
489-
todo!()
490-
}
454+
fn visit_await(&mut self, _a: &parser::ast::Await) {}
491455

492-
fn visit_compare(&mut self, _c: &parser::ast::Compare) {
493-
todo!()
494-
}
456+
fn visit_compare(&mut self, _c: &parser::ast::Compare) {}
495457

496-
fn visit_lambda(&mut self, _l: &parser::ast::Lambda) {
497-
todo!()
498-
}
458+
fn visit_lambda(&mut self, _l: &parser::ast::Lambda) {}
499459

500-
fn visit_if_exp(&mut self, _i: &parser::ast::IfExp) {
501-
todo!()
502-
}
460+
fn visit_if_exp(&mut self, _i: &parser::ast::IfExp) {}
503461

504-
fn visit_joined_str(&mut self, _j: &parser::ast::JoinedStr) {
505-
todo!()
506-
}
462+
fn visit_joined_str(&mut self, _j: &parser::ast::JoinedStr) {}
507463

508-
fn visit_formatted_value(&mut self, _f: &parser::ast::FormattedValue) {
509-
todo!()
510-
}
464+
fn visit_formatted_value(&mut self, _f: &parser::ast::FormattedValue) {}
511465

512-
fn visit_alias(&mut self, _a: &parser::ast::Alias) {
513-
todo!()
514-
}
466+
fn visit_alias(&mut self, _a: &parser::ast::Alias) {}
515467

516468
fn visit_assign(&mut self, assign: &parser::ast::Assign) {
517469
let value = &assign.value;
@@ -557,35 +509,21 @@ impl TraversalVisitor for SemanticAnalyzer {
557509
self.visit_expr(&a.value);
558510
}
559511

560-
fn visit_assert(&mut self, _a: &parser::ast::Assert) {
561-
todo!()
562-
}
512+
fn visit_assert(&mut self, _a: &parser::ast::Assert) {}
563513

564514
fn visit_pass(&mut self, _p: &parser::ast::Pass) {}
565515

566-
fn visit_delete(&mut self, _d: &parser::ast::Delete) {
567-
todo!()
568-
}
516+
fn visit_delete(&mut self, _d: &parser::ast::Delete) {}
569517

570518
fn visit_return(&mut self, _r: &parser::ast::Return) {}
571519

572-
fn visit_raise(&mut self, _r: &parser::ast::Raise) {
573-
todo!()
574-
}
520+
fn visit_raise(&mut self, _r: &parser::ast::Raise) {}
575521

576-
fn visit_break(&mut self, _b: &parser::ast::Break) {
577-
todo!()
578-
}
522+
fn visit_break(&mut self, _b: &parser::ast::Break) {}
579523

580-
fn visit_continue(&mut self, _c: &parser::ast::Continue) {
581-
todo!()
582-
}
524+
fn visit_continue(&mut self, _c: &parser::ast::Continue) {}
583525

584-
fn visit_global(&mut self, _g: &parser::ast::Global) {
585-
todo!()
586-
}
526+
fn visit_global(&mut self, _g: &parser::ast::Global) {}
587527

588-
fn visit_nonlocal(&mut self, _n: &parser::ast::Nonlocal) {
589-
todo!()
590-
}
528+
fn visit_nonlocal(&mut self, _n: &parser::ast::Nonlocal) {}
591529
}

typechecker/src/testdata/output/typechecker__type_check__type_evaluator__tests__type_eval_vars.snap

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
source: typechecker/src/type_check/type_evaluator.rs
3-
description: "# define variables with various types for testing\na = 1\nb = 2\nc = True\nd = False\ne = \"hello\"\nf = \"world\"\n# g = [1,2,3]\n# h = (1,2,3)\n# i = {1,2,3}\n# j = {\"a\":1,\"b\":2,\"c\":3}\n# k = None\n\na\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\n\n"
3+
description: "# define variables with various types for testing\na = 1\nb = 2\nc = True\nd = False\ne = \"hello\"\nf = \"world\"\njoined_str = f\"{e} {f}\"\n\ng = [1,2,3]\nh = (1,2,3)\ni = {1,2,3}\nj = {\"a\":1,\"b\":2,\"c\":3}\nk = None\n\na\nb\nc\nd\ne\nf\njoined_str\ng\nh\ni\nj\nk\n\n"
44
expression: result
55
---
66
[
@@ -30,22 +30,26 @@ expression: result
3030
),
3131
(
3232
"g",
33-
"Unknown",
33+
"builtins.list[Int]",
3434
),
3535
(
3636
"h",
37-
"Unknown",
37+
"builtins.tuple[Int]",
3838
),
3939
(
4040
"i",
41-
"Unknown",
41+
"builtins.set[Int]",
4242
),
4343
(
4444
"j",
45-
"Unknown",
45+
"builtins.dict[Str, Int]",
46+
),
47+
(
48+
"joined_str",
49+
"Str",
4650
),
4751
(
4852
"k",
49-
"Unknown",
53+
"None",
5054
),
5155
]
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
11
pub const LIST_TYPE: &str = "builtins.list";
2+
pub const TUPLE_TYPE: &str = "builtins.tuple";
3+
pub const DICT_TYPE: &str = "builtins.dict";
4+
pub const SET_TYPE: &str = "builtins.set";

typechecker/src/type_check/testdata/inputs/type_eval_vars.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,21 @@
55
d = False
66
e = "hello"
77
f = "world"
8-
# g = [1,2,3]
9-
# h = (1,2,3)
10-
# i = {1,2,3}
11-
# j = {"a":1,"b":2,"c":3}
12-
# k = None
8+
joined_str = f"{e} {f}"
9+
10+
g = [1,2,3]
11+
h = (1,2,3)
12+
i = {1,2,3}
13+
j = {"a":1,"b":2,"c":3}
14+
k = None
1315

1416
a
1517
b
1618
c
1719
d
1820
e
1921
f
22+
joined_str
2023
g
2124
h
2225
i

typechecker/src/type_check/type_evaluator.rs

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -59,25 +59,34 @@ impl TypeEvaluator {
5959
&b.op,
6060
),
6161
ast::Expression::List(l) => {
62-
let mut prev_elm_type = Type::Unknown;
63-
for elm in &l.elements {
64-
let elm_type = self.get_type(elm);
65-
if prev_elm_type == Type::Unknown {
66-
prev_elm_type = elm_type;
67-
} else if prev_elm_type != elm_type {
68-
prev_elm_type = Type::Unknown;
69-
break;
70-
}
71-
}
72-
let final_elm_type = prev_elm_type;
62+
let final_elm_type = self.get_sequence_type_from_elements(&l.elements);
7363
Type::Class(super::types::ClassType {
7464
name: builtins::LIST_TYPE.to_string(),
7565
args: vec![final_elm_type],
7666
})
7767
}
78-
ast::Expression::Tuple(_) => todo!(),
79-
ast::Expression::Dict(_) => todo!(),
80-
ast::Expression::Set(_) => todo!(),
68+
ast::Expression::Tuple(t) => {
69+
let elm_type = self.get_sequence_type_from_elements(&t.elements);
70+
Type::Class(super::types::ClassType {
71+
name: builtins::TUPLE_TYPE.to_string(),
72+
args: vec![elm_type],
73+
})
74+
}
75+
ast::Expression::Dict(d) => {
76+
let key_type = self.get_sequence_type_from_elements(&d.keys);
77+
let value_type = self.get_sequence_type_from_elements(&d.values);
78+
Type::Class(super::types::ClassType {
79+
name: builtins::DICT_TYPE.to_string(),
80+
args: vec![key_type, value_type],
81+
})
82+
}
83+
ast::Expression::Set(s) => {
84+
let elm_type = self.get_sequence_type_from_elements(&s.elements);
85+
Type::Class(super::types::ClassType {
86+
name: builtins::SET_TYPE.to_string(),
87+
args: vec![elm_type],
88+
})
89+
}
8190
ast::Expression::BoolOp(_) => todo!(),
8291
ast::Expression::UnaryOp(_) => todo!(),
8392
ast::Expression::NamedExpr(_) => todo!(),
@@ -110,8 +119,8 @@ impl TypeEvaluator {
110119
ast::Expression::Compare(_) => todo!(),
111120
ast::Expression::Lambda(_) => todo!(),
112121
ast::Expression::IfExp(_) => todo!(),
113-
ast::Expression::JoinedStr(_) => todo!(),
114-
ast::Expression::FormattedValue(_) => todo!(),
122+
ast::Expression::JoinedStr(_) => Type::Str,
123+
ast::Expression::FormattedValue(f) => self.get_type(&f.value),
115124
}
116125
}
117126

@@ -152,6 +161,20 @@ impl TypeEvaluator {
152161
None => Type::Unknown,
153162
}
154163
}
164+
165+
fn get_sequence_type_from_elements(&self, elements: &Vec<ast::Expression>) -> Type {
166+
let mut prev_elm_type = Type::Unknown;
167+
for elm in elements {
168+
let elm_type = self.get_type(elm);
169+
if prev_elm_type == Type::Unknown {
170+
prev_elm_type = elm_type;
171+
} else if prev_elm_type != elm_type {
172+
prev_elm_type = Type::Unknown;
173+
break;
174+
}
175+
}
176+
prev_elm_type
177+
}
155178
}
156179

157180
impl TraversalVisitorImmutGeneric<Type> for TypeEvaluator {
@@ -425,7 +448,6 @@ impl TraversalVisitorImmutGeneric<Type> for TypeEvaluator {
425448
#[cfg(test)]
426449
mod tests {
427450
use std::collections::HashMap;
428-
429451
use super::*;
430452
// TODO: refactor and move the test to type check mod
431453
fn snapshot_type_eval(source: &str) -> String {

0 commit comments

Comments
 (0)