diff --git a/typechecker/src/semantic_analyzer.rs b/typechecker/src/semantic_analyzer.rs index 8e43e465..42481821 100644 --- a/typechecker/src/semantic_analyzer.rs +++ b/typechecker/src/semantic_analyzer.rs @@ -254,13 +254,9 @@ impl TraversalVisitor for SemanticAnalyzer { } } - fn visit_import(&mut self, _i: &parser::ast::Import) { - todo!(); - } + fn visit_import(&mut self, _i: &parser::ast::Import) {} - fn visit_import_from(&mut self, _i: &parser::ast::ImportFrom) { - todo!(); - } + fn visit_import_from(&mut self, _i: &parser::ast::ImportFrom) {} fn visit_if(&mut self, i: &parser::ast::If) { for stmt in &i.body { @@ -419,99 +415,55 @@ impl TraversalVisitor for SemanticAnalyzer { fn visit_tuple(&mut self, _t: &parser::ast::Tuple) {} - fn visit_dict(&mut self, _d: &parser::ast::Dict) { - todo!() - } + fn visit_dict(&mut self, _d: &parser::ast::Dict) {} - fn visit_set(&mut self, _s: &parser::ast::Set) { - todo!() - } + fn visit_set(&mut self, _s: &parser::ast::Set) {} fn visit_name(&mut self, _n: &parser::ast::Name) {} - fn visit_bool_op(&mut self, _b: &parser::ast::BoolOperation) { - todo!() - } + fn visit_bool_op(&mut self, _b: &parser::ast::BoolOperation) {} - fn visit_unary_op(&mut self, _u: &parser::ast::UnaryOperation) { - todo!() - } + fn visit_unary_op(&mut self, _u: &parser::ast::UnaryOperation) {} fn visit_bin_op(&mut self, _b: &parser::ast::BinOp) {} - fn visit_named_expr(&mut self, _n: &parser::ast::NamedExpression) { - todo!() - } + fn visit_named_expr(&mut self, _n: &parser::ast::NamedExpression) {} - fn visit_yield(&mut self, _y: &parser::ast::Yield) { - todo!() - } + fn visit_yield(&mut self, _y: &parser::ast::Yield) {} - fn visit_yield_from(&mut self, _y: &parser::ast::YieldFrom) { - todo!() - } + fn visit_yield_from(&mut self, _y: &parser::ast::YieldFrom) {} - fn visit_starred(&mut self, _s: &parser::ast::Starred) { - todo!() - } + fn visit_starred(&mut self, _s: &parser::ast::Starred) {} - fn visit_generator(&mut self, _g: &parser::ast::Generator) { - todo!() - } + fn visit_generator(&mut self, _g: &parser::ast::Generator) {} - fn visit_list_comp(&mut self, _l: &parser::ast::ListComp) { - todo!() - } + fn visit_list_comp(&mut self, _l: &parser::ast::ListComp) {} - fn visit_set_comp(&mut self, _s: &parser::ast::SetComp) { - todo!() - } + fn visit_set_comp(&mut self, _s: &parser::ast::SetComp) {} - fn visit_dict_comp(&mut self, _d: &parser::ast::DictComp) { - todo!() - } + fn visit_dict_comp(&mut self, _d: &parser::ast::DictComp) {} - fn visit_attribute(&mut self, _a: &parser::ast::Attribute) { - todo!() - } + fn visit_attribute(&mut self, _a: &parser::ast::Attribute) {} - fn visit_subscript(&mut self, _s: &parser::ast::Subscript) { - todo!() - } + fn visit_subscript(&mut self, _s: &parser::ast::Subscript) {} - fn visit_slice(&mut self, _s: &parser::ast::Slice) { - todo!() - } + fn visit_slice(&mut self, _s: &parser::ast::Slice) {} fn visit_call(&mut self, _c: &parser::ast::Call) {} - fn visit_await(&mut self, _a: &parser::ast::Await) { - todo!() - } + fn visit_await(&mut self, _a: &parser::ast::Await) {} - fn visit_compare(&mut self, _c: &parser::ast::Compare) { - todo!() - } + fn visit_compare(&mut self, _c: &parser::ast::Compare) {} - fn visit_lambda(&mut self, _l: &parser::ast::Lambda) { - todo!() - } + fn visit_lambda(&mut self, _l: &parser::ast::Lambda) {} - fn visit_if_exp(&mut self, _i: &parser::ast::IfExp) { - todo!() - } + fn visit_if_exp(&mut self, _i: &parser::ast::IfExp) {} - fn visit_joined_str(&mut self, _j: &parser::ast::JoinedStr) { - todo!() - } + fn visit_joined_str(&mut self, _j: &parser::ast::JoinedStr) {} - fn visit_formatted_value(&mut self, _f: &parser::ast::FormattedValue) { - todo!() - } + fn visit_formatted_value(&mut self, _f: &parser::ast::FormattedValue) {} - fn visit_alias(&mut self, _a: &parser::ast::Alias) { - todo!() - } + fn visit_alias(&mut self, _a: &parser::ast::Alias) {} fn visit_assign(&mut self, assign: &parser::ast::Assign) { let value = &assign.value; @@ -557,35 +509,21 @@ impl TraversalVisitor for SemanticAnalyzer { self.visit_expr(&a.value); } - fn visit_assert(&mut self, _a: &parser::ast::Assert) { - todo!() - } + fn visit_assert(&mut self, _a: &parser::ast::Assert) {} fn visit_pass(&mut self, _p: &parser::ast::Pass) {} - fn visit_delete(&mut self, _d: &parser::ast::Delete) { - todo!() - } + fn visit_delete(&mut self, _d: &parser::ast::Delete) {} fn visit_return(&mut self, _r: &parser::ast::Return) {} - fn visit_raise(&mut self, _r: &parser::ast::Raise) { - todo!() - } + fn visit_raise(&mut self, _r: &parser::ast::Raise) {} - fn visit_break(&mut self, _b: &parser::ast::Break) { - todo!() - } + fn visit_break(&mut self, _b: &parser::ast::Break) {} - fn visit_continue(&mut self, _c: &parser::ast::Continue) { - todo!() - } + fn visit_continue(&mut self, _c: &parser::ast::Continue) {} - fn visit_global(&mut self, _g: &parser::ast::Global) { - todo!() - } + fn visit_global(&mut self, _g: &parser::ast::Global) {} - fn visit_nonlocal(&mut self, _n: &parser::ast::Nonlocal) { - todo!() - } + fn visit_nonlocal(&mut self, _n: &parser::ast::Nonlocal) {} } diff --git a/typechecker/src/testdata/output/typechecker__type_check__type_evaluator__tests__type_eval_vars.snap b/typechecker/src/testdata/output/typechecker__type_check__type_evaluator__tests__type_eval_vars.snap index 4dc4cef1..670ef791 100644 --- a/typechecker/src/testdata/output/typechecker__type_check__type_evaluator__tests__type_eval_vars.snap +++ b/typechecker/src/testdata/output/typechecker__type_check__type_evaluator__tests__type_eval_vars.snap @@ -1,6 +1,6 @@ --- source: typechecker/src/type_check/type_evaluator.rs -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" +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" expression: result --- [ @@ -30,22 +30,26 @@ expression: result ), ( "g", - "Unknown", + "builtins.list[Int]", ), ( "h", - "Unknown", + "builtins.tuple[Int]", ), ( "i", - "Unknown", + "builtins.set[Int]", ), ( "j", - "Unknown", + "builtins.dict[Str, Int]", + ), + ( + "joined_str", + "Str", ), ( "k", - "Unknown", + "None", ), ] diff --git a/typechecker/src/type_check/builtins.rs b/typechecker/src/type_check/builtins.rs index e8eac083..e9fc3bf5 100644 --- a/typechecker/src/type_check/builtins.rs +++ b/typechecker/src/type_check/builtins.rs @@ -1 +1,4 @@ pub const LIST_TYPE: &str = "builtins.list"; +pub const TUPLE_TYPE: &str = "builtins.tuple"; +pub const DICT_TYPE: &str = "builtins.dict"; +pub const SET_TYPE: &str = "builtins.set"; diff --git a/typechecker/src/type_check/testdata/inputs/type_eval_vars.py b/typechecker/src/type_check/testdata/inputs/type_eval_vars.py index 87aff117..42406478 100644 --- a/typechecker/src/type_check/testdata/inputs/type_eval_vars.py +++ b/typechecker/src/type_check/testdata/inputs/type_eval_vars.py @@ -5,11 +5,13 @@ d = False e = "hello" f = "world" -# g = [1,2,3] -# h = (1,2,3) -# i = {1,2,3} -# j = {"a":1,"b":2,"c":3} -# k = None +joined_str = f"{e} {f}" + +g = [1,2,3] +h = (1,2,3) +i = {1,2,3} +j = {"a":1,"b":2,"c":3} +k = None a b @@ -17,6 +19,7 @@ d e f +joined_str g h i diff --git a/typechecker/src/type_check/type_evaluator.rs b/typechecker/src/type_check/type_evaluator.rs index cc30de6d..bbd7610f 100755 --- a/typechecker/src/type_check/type_evaluator.rs +++ b/typechecker/src/type_check/type_evaluator.rs @@ -59,25 +59,34 @@ impl TypeEvaluator { &b.op, ), ast::Expression::List(l) => { - let mut prev_elm_type = Type::Unknown; - for elm in &l.elements { - let elm_type = self.get_type(elm); - if prev_elm_type == Type::Unknown { - prev_elm_type = elm_type; - } else if prev_elm_type != elm_type { - prev_elm_type = Type::Unknown; - break; - } - } - let final_elm_type = prev_elm_type; + let final_elm_type = self.get_sequence_type_from_elements(&l.elements); Type::Class(super::types::ClassType { name: builtins::LIST_TYPE.to_string(), args: vec![final_elm_type], }) } - ast::Expression::Tuple(_) => todo!(), - ast::Expression::Dict(_) => todo!(), - ast::Expression::Set(_) => todo!(), + ast::Expression::Tuple(t) => { + let elm_type = self.get_sequence_type_from_elements(&t.elements); + Type::Class(super::types::ClassType { + name: builtins::TUPLE_TYPE.to_string(), + args: vec![elm_type], + }) + } + ast::Expression::Dict(d) => { + let key_type = self.get_sequence_type_from_elements(&d.keys); + let value_type = self.get_sequence_type_from_elements(&d.values); + Type::Class(super::types::ClassType { + name: builtins::DICT_TYPE.to_string(), + args: vec![key_type, value_type], + }) + } + ast::Expression::Set(s) => { + let elm_type = self.get_sequence_type_from_elements(&s.elements); + Type::Class(super::types::ClassType { + name: builtins::SET_TYPE.to_string(), + args: vec![elm_type], + }) + } ast::Expression::BoolOp(_) => todo!(), ast::Expression::UnaryOp(_) => todo!(), ast::Expression::NamedExpr(_) => todo!(), @@ -110,8 +119,8 @@ impl TypeEvaluator { ast::Expression::Compare(_) => todo!(), ast::Expression::Lambda(_) => todo!(), ast::Expression::IfExp(_) => todo!(), - ast::Expression::JoinedStr(_) => todo!(), - ast::Expression::FormattedValue(_) => todo!(), + ast::Expression::JoinedStr(_) => Type::Str, + ast::Expression::FormattedValue(f) => self.get_type(&f.value), } } @@ -152,6 +161,20 @@ impl TypeEvaluator { None => Type::Unknown, } } + + fn get_sequence_type_from_elements(&self, elements: &Vec) -> Type { + let mut prev_elm_type = Type::Unknown; + for elm in elements { + let elm_type = self.get_type(elm); + if prev_elm_type == Type::Unknown { + prev_elm_type = elm_type; + } else if prev_elm_type != elm_type { + prev_elm_type = Type::Unknown; + break; + } + } + prev_elm_type + } } impl TraversalVisitorImmutGeneric for TypeEvaluator { @@ -425,7 +448,6 @@ impl TraversalVisitorImmutGeneric for TypeEvaluator { #[cfg(test)] mod tests { use std::collections::HashMap; - use super::*; // TODO: refactor and move the test to type check mod fn snapshot_type_eval(source: &str) -> String {