From d403565c534991c78df8916ee760b8e46e205e4c Mon Sep 17 00:00:00 2001 From: Glyphack Date: Fri, 25 Aug 2023 07:41:19 +0200 Subject: [PATCH 1/4] Create type checker structs --- typechecker/src/ast_visitor_immut.rs | 295 +++++++++++++++ typechecker/src/lib.rs | 2 + typechecker/src/type_check/checker.rs | 360 +++++++++++++++++++ typechecker/src/type_check/mod.rs | 3 + typechecker/src/type_check/type_inference.rs | 19 + typechecker/src/type_check/types.rs | 9 + 6 files changed, 688 insertions(+) create mode 100644 typechecker/src/ast_visitor_immut.rs create mode 100644 typechecker/src/type_check/checker.rs create mode 100644 typechecker/src/type_check/mod.rs create mode 100644 typechecker/src/type_check/type_inference.rs create mode 100644 typechecker/src/type_check/types.rs diff --git a/typechecker/src/ast_visitor_immut.rs b/typechecker/src/ast_visitor_immut.rs new file mode 100644 index 00000000..1e480538 --- /dev/null +++ b/typechecker/src/ast_visitor_immut.rs @@ -0,0 +1,295 @@ +use ast::{Expression, Statement}; + +use parser::ast::{self, *}; + +pub trait TraversalVisitorImmut { + fn visit_stmt(&self, s: &Statement) { + // map all statements and call visit + match s { + Statement::ExpressionStatement(e) => self.visit_expr(e), + Statement::Import(i) => self.visit_import(i), + Statement::ImportFrom(i) => self.visit_import_from(i), + Statement::AssignStatement(a) => self.visit_assign(a), + Statement::AnnAssignStatement(a) => self.visit_ann_assign(a), + Statement::AugAssignStatement(a) => self.visit_aug_assign(a), + Statement::Assert(a) => self.visit_assert(a), + Statement::Pass(p) => self.visit_pass(p), + Statement::Delete(d) => self.visit_delete(d), + Statement::Return(r) => self.visit_return(r), + Statement::Raise(r) => self.visit_raise(r), + Statement::Break(b) => self.visit_break(b), + Statement::Continue(c) => self.visit_continue(c), + Statement::Global(g) => self.visit_global(g), + Statement::Nonlocal(n) => self.visit_nonlocal(n), + Statement::IfStatement(i) => self.visit_if(i), + Statement::WhileStatement(w) => self.visit_while(w), + Statement::ForStatement(f) => self.visit_for(f), + Statement::WithStatement(w) => self.visit_with(w), + Statement::TryStatement(t) => self.visit_try(t), + Statement::TryStarStatement(t) => self.visit_try_star(t), + Statement::FunctionDef(f) => self.visit_function_def(f), + Statement::ClassDef(c) => self.visit_class_def(c), + Statement::Match(m) => self.visit_match(m), + } + } + fn visit_expr(&self, e: &Expression) { + match e { + Expression::Constant(c) => self.visit_constant(c), + Expression::List(l) => self.visit_list(l), + Expression::Tuple(t) => self.visit_tuple(t), + Expression::Dict(d) => self.visit_dict(d), + Expression::Set(s) => self.visit_set(s), + Expression::Name(n) => self.visit_name(n), + Expression::BoolOp(b) => self.visit_bool_op(b), + Expression::UnaryOp(u) => self.visit_unary_op(u), + Expression::BinOp(b) => self.visit_bin_op(b), + Expression::NamedExpr(n) => self.visit_named_expr(n), + Expression::Yield(y) => self.visit_yield(y), + Expression::YieldFrom(y) => self.visit_yield_from(y), + Expression::Starred(s) => self.visit_starred(s), + Expression::Generator(g) => self.visit_generator(g), + Expression::ListComp(l) => self.visit_list_comp(l), + Expression::SetComp(s) => self.visit_set_comp(s), + Expression::DictComp(d) => self.visit_dict_comp(d), + Expression::Attribute(a) => self.visit_attribute(a), + Expression::Subscript(s) => self.visit_subscript(s), + Expression::Slice(s) => self.visit_slice(s), + Expression::Call(c) => self.visit_call(c), + Expression::Await(a) => self.visit_await(a), + Expression::Compare(c) => self.visit_compare(c), + Expression::Lambda(l) => self.visit_lambda(l), + Expression::IfExp(i) => self.visit_if_exp(i), + Expression::JoinedStr(j) => self.visit_joined_str(j), + Expression::FormattedValue(f) => self.visit_formatted_value(f), + } + } + fn visit_import(&self, i: &Import) { + todo!(); + } + + fn visit_import_from(&self, i: &ImportFrom) { + todo!(); + } + + fn visit_if(&self, i: &parser::ast::If) { + for stmt in &i.body { + self.visit_stmt(&stmt); + } + for stmt in &i.orelse { + self.visit_stmt(&stmt); + } + } + + fn visit_while(&self, w: &parser::ast::While) { + for stmt in &w.body { + self.visit_stmt(&stmt) + } + } + + fn visit_for(&self, f: &parser::ast::For) { + for stmt in &f.body { + self.visit_stmt(&stmt); + } + } + + fn visit_with(&self, w: &parser::ast::With) { + for stmt in &w.body { + self.visit_stmt(&stmt); + } + for with_items in &w.items { + self.visit_expr(&*&with_items.context_expr); + match &with_items.optional_vars { + Some(items) => self.visit_expr(&items), + None => (), + } + } + } + + fn visit_try(&self, t: &parser::ast::Try) { + for stmt in &t.body { + self.visit_stmt(&stmt); + } + for stmt in &t.orelse { + self.visit_stmt(&stmt); + } + for stmt in &t.finalbody { + self.visit_stmt(&stmt); + } + // TODO: need to visit exception handler name and type but let's keep it simple for now + for handler in &t.handlers { + for stmt in &handler.body { + self.visit_stmt(&stmt); + } + } + } + + fn visit_try_star(&self, t: &parser::ast::TryStar) { + for stmt in &t.body { + self.visit_stmt(&stmt); + } + for stmt in &t.orelse { + self.visit_stmt(&stmt); + } + for stmt in &t.finalbody { + self.visit_stmt(&stmt); + } + // TODO: need to visit exception handler name and type but let's keep it simple for now + for handler in &t.handlers { + for stmt in &handler.body { + self.visit_stmt(&stmt); + } + } + } + + fn visit_function_def(&self, f: &parser::ast::FunctionDef) { + for stmt in &f.body { + self.visit_stmt(&stmt); + } + } + + fn visit_class_def(&self, c: &parser::ast::ClassDef) { + for stmt in &c.body { + self.visit_stmt(&stmt); + } + } + + fn visit_match(&self, m: &parser::ast::Match) { + for case in &m.cases { + for stmt in &case.body { + self.visit_stmt(&stmt); + } + } + } + + fn visit_constant(&self, c: &Constant) { + todo!() + } + fn visit_list(&self, l: &List) { + todo!() + } + fn visit_tuple(&self, t: &Tuple) { + todo!() + } + fn visit_dict(&self, d: &Dict) { + todo!() + } + fn visit_set(&self, s: &Set) { + todo!() + } + fn visit_name(&self, n: &Name) {} + fn visit_bool_op(&self, b: &BoolOperation) { + todo!() + } + fn visit_unary_op(&self, u: &UnaryOperation) { + todo!() + } + fn visit_bin_op(&self, b: &BinOp) { + todo!() + } + fn visit_named_expr(&self, n: &NamedExpression) { + todo!() + } + fn visit_yield(&self, y: &Yield) { + todo!() + } + fn visit_yield_from(&self, y: &YieldFrom) { + todo!() + } + fn visit_starred(&self, s: &Starred) { + todo!() + } + fn visit_generator(&self, g: &Generator) { + todo!() + } + fn visit_list_comp(&self, l: &ListComp) { + todo!() + } + fn visit_set_comp(&self, s: &SetComp) { + todo!() + } + fn visit_dict_comp(&self, d: &DictComp) { + todo!() + } + fn visit_attribute(&self, a: &Attribute) { + todo!() + } + fn visit_subscript(&self, s: &Subscript) { + todo!() + } + fn visit_slice(&self, s: &Slice) { + todo!() + } + fn visit_call(&self, c: &Call) { + todo!() + } + fn visit_await(&self, a: &Await) { + todo!() + } + fn visit_compare(&self, c: &Compare) { + todo!() + } + fn visit_lambda(&self, l: &Lambda) { + todo!() + } + fn visit_if_exp(&self, i: &IfExp) { + todo!() + } + fn visit_joined_str(&self, j: &JoinedStr) { + todo!() + } + fn visit_formatted_value(&self, f: &FormattedValue) { + todo!() + } + + fn visit_alias(&self, a: &Alias) { + todo!() + } + + fn visit_assign(&self, a: &Assign) { + todo!() + } + + fn visit_ann_assign(&self, a: &AnnAssign) { + todo!() + } + + fn visit_aug_assign(&self, a: &AugAssign) { + todo!() + } + + fn visit_assert(&self, a: &Assert) { + todo!() + } + + fn visit_pass(&self, p: &Pass) { + todo!() + } + + fn visit_delete(&self, d: &Delete) { + todo!() + } + + fn visit_return(&self, r: &Return) { + todo!() + } + + fn visit_raise(&self, r: &Raise) { + todo!() + } + + fn visit_break(&self, b: &Break) { + todo!() + } + + fn visit_continue(&self, c: &Continue) { + todo!() + } + + fn visit_global(&self, g: &Global) { + todo!() + } + + fn visit_nonlocal(&self, n: &Nonlocal) { + todo!() + } +} diff --git a/typechecker/src/lib.rs b/typechecker/src/lib.rs index c5daa671..5c0a9e4b 100644 --- a/typechecker/src/lib.rs +++ b/typechecker/src/lib.rs @@ -1,8 +1,10 @@ mod ast_visitor; +mod ast_visitor_immut; mod nodes; mod semanal_utils; mod state; mod symbol_table; +mod type_check; pub mod build; pub mod build_error; diff --git a/typechecker/src/type_check/checker.rs b/typechecker/src/type_check/checker.rs new file mode 100644 index 00000000..3cb0ec8d --- /dev/null +++ b/typechecker/src/type_check/checker.rs @@ -0,0 +1,360 @@ +use ast::{Expression, Statement}; +use parser::ast::{self, *}; + +use crate::{ + ast_visitor::TraversalVisitor, ast_visitor_immut::TraversalVisitorImmut, settings::Settings, + state::State, +}; + +use super::types::Type; + +pub struct TypeChecker<'a> { + pub errors: Vec, + // TODO: currently only supporting a single file + pub module: &'a State, + pub options: Settings, +} + +impl<'a> TypeChecker<'a> { + fn new(module: &'a State, options: Settings) -> Self { + TypeChecker { + errors: vec![], + module, + options, + } + } + + fn infer_expr_type(&mut self, expr: &ast::Expression) -> Type { + match expr { + ast::Expression::Constant(c) => match c.value { + ast::ConstantValue::Int(_) => Type::Int, + ast::ConstantValue::Float(_) => Type::Float, + ast::ConstantValue::Str(_) => Type::Str, + ast::ConstantValue::Bool(_) => Type::Bool, + ast::ConstantValue::None => Type::None, + _ => Type::Unknown, + }, + _ => Type::Unknown, + } + } +} + +impl<'a> TraversalVisitorImmut for TypeChecker<'a> { + fn visit_stmt(&self, s: &Statement) { + // map all statements and call visit + match s { + Statement::ExpressionStatement(e) => self.visit_expr(e), + Statement::Import(i) => self.visit_import(i), + Statement::ImportFrom(i) => self.visit_import_from(i), + Statement::AssignStatement(a) => self.visit_assign(a), + Statement::AnnAssignStatement(a) => self.visit_ann_assign(a), + Statement::AugAssignStatement(a) => self.visit_aug_assign(a), + Statement::Assert(a) => self.visit_assert(a), + Statement::Pass(p) => self.visit_pass(p), + Statement::Delete(d) => self.visit_delete(d), + Statement::Return(r) => self.visit_return(r), + Statement::Raise(r) => self.visit_raise(r), + Statement::Break(b) => self.visit_break(b), + Statement::Continue(c) => self.visit_continue(c), + Statement::Global(g) => self.visit_global(g), + Statement::Nonlocal(n) => self.visit_nonlocal(n), + Statement::IfStatement(i) => self.visit_if(i), + Statement::WhileStatement(w) => self.visit_while(w), + Statement::ForStatement(f) => self.visit_for(f), + Statement::WithStatement(w) => self.visit_with(w), + Statement::TryStatement(t) => self.visit_try(t), + Statement::TryStarStatement(t) => self.visit_try_star(t), + Statement::FunctionDef(f) => self.visit_function_def(f), + Statement::ClassDef(c) => self.visit_class_def(c), + Statement::Match(m) => self.visit_match(m), + } + } + + fn visit_expr(&self, e: &Expression) { + match e { + Expression::Constant(c) => self.visit_constant(c), + Expression::List(l) => self.visit_list(l), + Expression::Tuple(t) => self.visit_tuple(t), + Expression::Dict(d) => self.visit_dict(d), + Expression::Set(s) => self.visit_set(s), + Expression::Name(n) => self.visit_name(n), + Expression::BoolOp(b) => self.visit_bool_op(b), + Expression::UnaryOp(u) => self.visit_unary_op(u), + Expression::BinOp(b) => self.visit_bin_op(b), + Expression::NamedExpr(n) => self.visit_named_expr(n), + Expression::Yield(y) => self.visit_yield(y), + Expression::YieldFrom(y) => self.visit_yield_from(y), + Expression::Starred(s) => self.visit_starred(s), + Expression::Generator(g) => self.visit_generator(g), + Expression::ListComp(l) => self.visit_list_comp(l), + Expression::SetComp(s) => self.visit_set_comp(s), + Expression::DictComp(d) => self.visit_dict_comp(d), + Expression::Attribute(a) => self.visit_attribute(a), + Expression::Subscript(s) => self.visit_subscript(s), + Expression::Slice(s) => self.visit_slice(s), + Expression::Call(c) => self.visit_call(c), + Expression::Await(a) => self.visit_await(a), + Expression::Compare(c) => self.visit_compare(c), + Expression::Lambda(l) => self.visit_lambda(l), + Expression::IfExp(i) => self.visit_if_exp(i), + Expression::JoinedStr(j) => self.visit_joined_str(j), + Expression::FormattedValue(f) => self.visit_formatted_value(f), + } + } + + fn visit_import(&self, i: &Import) { + todo!(); + } + + fn visit_import_from(&self, i: &ImportFrom) { + todo!(); + } + + fn visit_if(&self, i: &parser::ast::If) { + for stmt in &i.body { + self.visit_stmt(&stmt); + } + for stmt in &i.orelse { + self.visit_stmt(&stmt); + } + } + + fn visit_while(&self, w: &parser::ast::While) { + for stmt in &w.body { + self.visit_stmt(&stmt) + } + } + + fn visit_for(&self, f: &parser::ast::For) { + for stmt in &f.body { + self.visit_stmt(&stmt); + } + } + + fn visit_with(&self, w: &parser::ast::With) { + for stmt in &w.body { + self.visit_stmt(&stmt); + } + for with_items in &w.items { + self.visit_expr(&*&with_items.context_expr); + match &with_items.optional_vars { + Some(items) => self.visit_expr(&items), + None => (), + } + } + } + + fn visit_try(&self, t: &parser::ast::Try) { + for stmt in &t.body { + self.visit_stmt(&stmt); + } + for stmt in &t.orelse { + self.visit_stmt(&stmt); + } + for stmt in &t.finalbody { + self.visit_stmt(&stmt); + } + // TODO: need to visit exception handler name and type but let's keep it simple for now + for handler in &t.handlers { + for stmt in &handler.body { + self.visit_stmt(&stmt); + } + } + } + + fn visit_try_star(&self, t: &parser::ast::TryStar) { + for stmt in &t.body { + self.visit_stmt(&stmt); + } + for stmt in &t.orelse { + self.visit_stmt(&stmt); + } + for stmt in &t.finalbody { + self.visit_stmt(&stmt); + } + // TODO: need to visit exception handler name and type but let's keep it simple for now + for handler in &t.handlers { + for stmt in &handler.body { + self.visit_stmt(&stmt); + } + } + } + + fn visit_function_def(&self, f: &parser::ast::FunctionDef) { + for stmt in &f.body { + self.visit_stmt(&stmt); + } + } + + fn visit_class_def(&self, c: &parser::ast::ClassDef) { + for stmt in &c.body { + self.visit_stmt(&stmt); + } + } + + fn visit_match(&self, m: &parser::ast::Match) { + for case in &m.cases { + for stmt in &case.body { + self.visit_stmt(&stmt); + } + } + } + + fn visit_constant(&self, c: &Constant) { + todo!() + } + + fn visit_list(&self, l: &List) { + todo!() + } + + fn visit_tuple(&self, t: &Tuple) { + todo!() + } + + fn visit_dict(&self, d: &Dict) { + todo!() + } + + fn visit_set(&self, s: &Set) { + todo!() + } + + fn visit_name(&self, n: &Name) {} + + fn visit_bool_op(&self, b: &BoolOperation) { + todo!() + } + + fn visit_unary_op(&self, u: &UnaryOperation) { + todo!() + } + + fn visit_bin_op(&self, b: &BinOp) { + todo!() + } + + fn visit_named_expr(&self, n: &NamedExpression) { + todo!() + } + + fn visit_yield(&self, y: &Yield) { + todo!() + } + + fn visit_yield_from(&self, y: &YieldFrom) { + todo!() + } + + fn visit_starred(&self, s: &Starred) { + todo!() + } + + fn visit_generator(&self, g: &Generator) { + todo!() + } + + fn visit_list_comp(&self, l: &ListComp) { + todo!() + } + + fn visit_set_comp(&self, s: &SetComp) { + todo!() + } + + fn visit_dict_comp(&self, d: &DictComp) { + todo!() + } + + fn visit_attribute(&self, a: &Attribute) { + todo!() + } + + fn visit_subscript(&self, s: &Subscript) { + todo!() + } + + fn visit_slice(&self, s: &Slice) { + todo!() + } + + fn visit_call(&self, c: &Call) { + todo!() + } + + fn visit_await(&self, a: &Await) { + todo!() + } + + fn visit_compare(&self, c: &Compare) { + todo!() + } + + fn visit_lambda(&self, l: &Lambda) { + todo!() + } + + fn visit_if_exp(&self, i: &IfExp) { + todo!() + } + + fn visit_joined_str(&self, j: &JoinedStr) { + todo!() + } + + fn visit_formatted_value(&self, f: &FormattedValue) { + todo!() + } + + fn visit_alias(&self, a: &Alias) { + todo!() + } + + fn visit_assign(&self, a: &Assign) { + todo!() + } + + fn visit_ann_assign(&self, a: &AnnAssign) { + todo!() + } + + fn visit_aug_assign(&self, a: &AugAssign) { + todo!() + } + + fn visit_assert(&self, a: &Assert) { + todo!() + } + + fn visit_pass(&self, p: &Pass) { + todo!() + } + + fn visit_delete(&self, d: &Delete) { + todo!() + } + + fn visit_return(&self, r: &Return) { + todo!() + } + + fn visit_raise(&self, r: &Raise) { + todo!() + } + + fn visit_break(&self, b: &Break) { + todo!() + } + + fn visit_continue(&self, c: &Continue) { + todo!() + } + + fn visit_global(&self, g: &Global) { + todo!() + } + + fn visit_nonlocal(&self, n: &Nonlocal) { + todo!() + } +} diff --git a/typechecker/src/type_check/mod.rs b/typechecker/src/type_check/mod.rs new file mode 100644 index 00000000..909147ba --- /dev/null +++ b/typechecker/src/type_check/mod.rs @@ -0,0 +1,3 @@ +mod checker; +mod type_inference; +mod types; diff --git a/typechecker/src/type_check/type_inference.rs b/typechecker/src/type_check/type_inference.rs new file mode 100644 index 00000000..7ee2c98a --- /dev/null +++ b/typechecker/src/type_check/type_inference.rs @@ -0,0 +1,19 @@ +use parser::ast; + +use super::types::Type; + +pub fn get_type_from_annotation(type_annotation: ast::Expression) -> Type { + let expr_type = match type_annotation { + ast::Expression::Name(name) => match name.id.as_str() { + "int" => Type::Int, + "float" => Type::Float, + "str" => Type::Str, + "bool" => Type::Bool, + "None" => Type::None, + _ => Type::Unknown, + }, + _ => Type::Unknown, + }; + + expr_type +} diff --git a/typechecker/src/type_check/types.rs b/typechecker/src/type_check/types.rs new file mode 100644 index 00000000..609f08b6 --- /dev/null +++ b/typechecker/src/type_check/types.rs @@ -0,0 +1,9 @@ +pub enum Type { + Any, + None, + Bool, + Int, + Float, + Str, + Unknown, +} From 5379df8a6d90c4d7fbc6dc7ccc89f036e1d07fd6 Mon Sep 17 00:00:00 2001 From: Glyphack Date: Sat, 26 Aug 2023 23:43:59 +0200 Subject: [PATCH 2/4] (type-check) first diagnosis error --- parser/src/parser/ast.rs | 22 ++ typechecker/src/build.rs | 50 +++- typechecker/src/nodes.rs | 235 +++++++++++++++++- typechecker/src/symbol_table.rs | 4 + typechecker/src/type_check/checker.rs | 162 +++++++----- typechecker/src/type_check/mod.rs | 2 +- typechecker/src/type_check/type_inference.rs | 11 + typechecker/src/type_check/types.rs | 18 ++ typechecker/testdata/inputs/type_check_var.py | 3 + ...ker__build__tests__type_check_var.snap.new | 7 + 10 files changed, 434 insertions(+), 80 deletions(-) create mode 100644 typechecker/testdata/inputs/type_check_var.py create mode 100644 typechecker/testdata/output/typechecker__build__tests__type_check_var.snap.new diff --git a/parser/src/parser/ast.rs b/parser/src/parser/ast.rs index 158a2920..7f6a636b 100644 --- a/parser/src/parser/ast.rs +++ b/parser/src/parser/ast.rs @@ -395,6 +395,28 @@ pub enum BinaryOperator { FloorDiv, } +impl std::fmt::Display for BinaryOperator { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let op_str = match self { + BinaryOperator::Add => "+", + BinaryOperator::Sub => "-", + BinaryOperator::Mult => "*", + BinaryOperator::MatMult => "@", + BinaryOperator::Div => "/", + BinaryOperator::Mod => "%", + BinaryOperator::Pow => "**", + BinaryOperator::LShift => "<<", + BinaryOperator::RShift => ">>", + BinaryOperator::BitOr => "|", + BinaryOperator::BitXor => "^", + BinaryOperator::BitAnd => "&", + BinaryOperator::FloorDiv => "//", + }; + + write!(f, "{}", op_str) + } +} + // https://docs.python.org/3/library/ast.html#ast.NamedExpr #[derive(Debug, Clone)] pub struct NamedExpression { diff --git a/typechecker/src/build.rs b/typechecker/src/build.rs index 467bb750..185a4011 100644 --- a/typechecker/src/build.rs +++ b/typechecker/src/build.rs @@ -6,6 +6,7 @@ use crate::nodes::EnderpyFile; use crate::settings::Settings; use crate::state::State; use crate::symbol_table::SymbolTable; +use crate::type_check::checker::TypeChecker; pub struct BuildSource { pub path: PathBuf, @@ -75,15 +76,15 @@ impl BuildManager { } } + // TODO: separate this can build to be able to test pre analysis and type checking separately // Performs type checking passes over the code - fn type_check(&mut self) { - panic!("not implemented") - } - - // Performs type checking for a specific file - fn type_check_file(&mut self, file_path: &str) { - // Logic to perform type checking for a file - // Updates self.type_checked_files after successful type checking + pub fn type_check(&mut self) { + self.pre_analysis(); + for state in self.modules.iter_mut() { + let mut checker = TypeChecker::new(state.1, &self.options); + checker.type_check(); + self.errors.append(&mut checker.errors); + } } } @@ -104,6 +105,21 @@ fn snapshot_symbol_table(source: &str) -> String { format!("{}", module.symbol_table) } +fn snapshot_type_check(source: &str) -> String { + let mut manager = BuildManager::new( + vec![BuildSource { + path: PathBuf::from("test.py"), + module: String::from("test"), + source: source.to_string(), + followed: false, + }], + Settings::test_settings(), + ); + manager.type_check(); + + format!("{}", manager.errors.join("\n")) +} + #[cfg(test)] mod tests { use super::*; @@ -124,6 +140,22 @@ mod tests { }; } + macro_rules! snap_type { + ($name:tt, $path:tt) => { + #[test] + fn $name() { + let contents = include_str!($path); + let result = snapshot_type_check(contents); + let mut settings = insta::Settings::clone_current(); + settings.set_snapshot_path("../testdata/output/"); + settings.set_description(contents); + settings.bind(|| { + insta::assert_snapshot!(result); + }); + } + }; + } + snap!( test_simple_var_assignments, "../testdata/inputs/simple_var_assignment.py" @@ -135,4 +167,6 @@ mod tests { ); snap!(test_class_def, "../testdata/inputs/class_definition.py"); + + snap_type!(test_type_check_var, "../testdata/inputs/type_check_var.py"); } diff --git a/typechecker/src/nodes.rs b/typechecker/src/nodes.rs index 53bcc24d..505d9aa4 100755 --- a/typechecker/src/nodes.rs +++ b/typechecker/src/nodes.rs @@ -22,6 +22,9 @@ pub struct EnderpyFile { pub imports: Vec, // high level definitions inside the file pub defs: Vec, + + // All high level statements inside the file + pub body: Vec, } impl<'a> EnderpyFile { @@ -30,10 +33,12 @@ impl<'a> EnderpyFile { module_name, defs: vec![], imports: vec![], + body: vec![], }; for stmt in &ast.body { file.visit_stmt(stmt); + file.body.push(stmt.clone()); } file @@ -41,18 +46,68 @@ impl<'a> EnderpyFile { } impl<'a> TraversalVisitor for EnderpyFile { - fn visit_assign(&mut self, a: &parser::ast::Assign) { - let stmt = a.clone(); - self.defs.push(Statement::AssignStatement(stmt)); + fn visit_stmt(&mut self, s: &Statement) { + // map all statements and call visit + match s { + Statement::ExpressionStatement(e) => self.visit_expr(e), + Statement::Import(i) => self.visit_import(i), + Statement::ImportFrom(i) => self.visit_import_from(i), + Statement::AssignStatement(a) => self.visit_assign(a), + Statement::AnnAssignStatement(a) => self.visit_ann_assign(a), + Statement::AugAssignStatement(a) => self.visit_aug_assign(a), + Statement::Assert(a) => self.visit_assert(a), + Statement::Pass(p) => self.visit_pass(p), + Statement::Delete(d) => self.visit_delete(d), + Statement::Return(r) => self.visit_return(r), + Statement::Raise(r) => self.visit_raise(r), + Statement::Break(b) => self.visit_break(b), + Statement::Continue(c) => self.visit_continue(c), + Statement::Global(g) => self.visit_global(g), + Statement::Nonlocal(n) => self.visit_nonlocal(n), + Statement::IfStatement(i) => self.visit_if(i), + Statement::WhileStatement(w) => self.visit_while(w), + Statement::ForStatement(f) => self.visit_for(f), + Statement::WithStatement(w) => self.visit_with(w), + Statement::TryStatement(t) => self.visit_try(t), + Statement::TryStarStatement(t) => self.visit_try_star(t), + Statement::FunctionDef(f) => self.visit_function_def(f), + Statement::ClassDef(c) => self.visit_class_def(c), + Statement::Match(m) => self.visit_match(m), + } } - fn visit_ann_assign(&mut self, a: &parser::ast::AnnAssign) { - let stmt = a.clone(); - self.defs.push(Statement::AnnAssignStatement(stmt)); + fn visit_expr(&mut self, e: &parser::ast::Expression) { + match e { + parser::ast::Expression::Constant(c) => self.visit_constant(c), + parser::ast::Expression::List(l) => self.visit_list(l), + parser::ast::Expression::Tuple(t) => self.visit_tuple(t), + parser::ast::Expression::Dict(d) => self.visit_dict(d), + parser::ast::Expression::Set(s) => self.visit_set(s), + parser::ast::Expression::Name(n) => self.visit_name(n), + parser::ast::Expression::BoolOp(b) => self.visit_bool_op(b), + parser::ast::Expression::UnaryOp(u) => self.visit_unary_op(u), + parser::ast::Expression::BinOp(b) => self.visit_bin_op(b), + parser::ast::Expression::NamedExpr(n) => self.visit_named_expr(n), + parser::ast::Expression::Yield(y) => self.visit_yield(y), + parser::ast::Expression::YieldFrom(y) => self.visit_yield_from(y), + parser::ast::Expression::Starred(s) => self.visit_starred(s), + parser::ast::Expression::Generator(g) => self.visit_generator(g), + parser::ast::Expression::ListComp(l) => self.visit_list_comp(l), + parser::ast::Expression::SetComp(s) => self.visit_set_comp(s), + parser::ast::Expression::DictComp(d) => self.visit_dict_comp(d), + parser::ast::Expression::Attribute(a) => self.visit_attribute(a), + parser::ast::Expression::Subscript(s) => self.visit_subscript(s), + parser::ast::Expression::Slice(s) => self.visit_slice(s), + parser::ast::Expression::Call(c) => self.visit_call(c), + parser::ast::Expression::Await(a) => self.visit_await(a), + parser::ast::Expression::Compare(c) => self.visit_compare(c), + parser::ast::Expression::Lambda(l) => self.visit_lambda(l), + parser::ast::Expression::IfExp(i) => self.visit_if_exp(i), + parser::ast::Expression::JoinedStr(j) => self.visit_joined_str(j), + parser::ast::Expression::FormattedValue(f) => self.visit_formatted_value(f), + } } - fn visit_aug_assign(&mut self, a: &parser::ast::AugAssign) {} - fn visit_import(&mut self, i: &Import) { let import = i.clone(); self.imports.push(ImportKinds::Import(import)); @@ -63,6 +118,76 @@ impl<'a> TraversalVisitor for EnderpyFile { self.imports.push(ImportKinds::ImportFrom(import)); } + fn visit_if(&mut self, i: &parser::ast::If) { + for stmt in &i.body { + self.visit_stmt(&stmt); + } + for stmt in &i.orelse { + self.visit_stmt(&stmt); + } + } + + fn visit_while(&mut self, w: &parser::ast::While) { + for stmt in &w.body { + self.visit_stmt(&stmt) + } + } + + fn visit_for(&mut self, f: &parser::ast::For) { + for stmt in &f.body { + self.visit_stmt(&stmt); + } + } + + fn visit_with(&mut self, w: &parser::ast::With) { + for stmt in &w.body { + self.visit_stmt(&stmt); + } + for with_items in &w.items { + self.visit_expr(&*&with_items.context_expr); + match &with_items.optional_vars { + Some(items) => self.visit_expr(&items), + None => (), + } + } + } + + fn visit_try(&mut self, t: &parser::ast::Try) { + for stmt in &t.body { + self.visit_stmt(&stmt); + } + for stmt in &t.orelse { + self.visit_stmt(&stmt); + } + for stmt in &t.finalbody { + self.visit_stmt(&stmt); + } + // TODO: need to visit exception handler name and type but let's keep it simple for now + for handler in &t.handlers { + for stmt in &handler.body { + self.visit_stmt(&stmt); + } + } + } + + fn visit_try_star(&mut self, t: &parser::ast::TryStar) { + for stmt in &t.body { + self.visit_stmt(&stmt); + } + for stmt in &t.orelse { + self.visit_stmt(&stmt); + } + for stmt in &t.finalbody { + self.visit_stmt(&stmt); + } + // TODO: need to visit exception handler name and type but let's keep it simple for now + for handler in &t.handlers { + for stmt in &handler.body { + self.visit_stmt(&stmt); + } + } + } + fn visit_function_def(&mut self, f: &parser::ast::FunctionDef) { let func = f.clone(); self.defs.push(Statement::FunctionDef(func)); @@ -72,4 +197,98 @@ impl<'a> TraversalVisitor for EnderpyFile { let class = c.clone(); self.defs.push(Statement::ClassDef(class)); } + + fn visit_match(&mut self, m: &parser::ast::Match) { + for case in &m.cases { + for stmt in &case.body { + self.visit_stmt(&stmt); + } + } + } + + fn visit_constant(&mut self, c: &parser::ast::Constant) {} + + fn visit_list(&mut self, l: &parser::ast::List) {} + + fn visit_tuple(&mut self, t: &parser::ast::Tuple) {} + + fn visit_dict(&mut self, d: &parser::ast::Dict) {} + + 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) {} + + 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) {} + + fn visit_yield(&mut self, y: &parser::ast::Yield) {} + + fn visit_yield_from(&mut self, y: &parser::ast::YieldFrom) {} + + fn visit_starred(&mut self, s: &parser::ast::Starred) {} + + fn visit_generator(&mut self, g: &parser::ast::Generator) {} + + fn visit_list_comp(&mut self, l: &parser::ast::ListComp) {} + + fn visit_set_comp(&mut self, s: &parser::ast::SetComp) {} + + fn visit_dict_comp(&mut self, d: &parser::ast::DictComp) {} + + fn visit_attribute(&mut self, a: &parser::ast::Attribute) {} + + fn visit_subscript(&mut self, s: &parser::ast::Subscript) {} + + 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) {} + + fn visit_compare(&mut self, c: &parser::ast::Compare) {} + + fn visit_lambda(&mut self, l: &parser::ast::Lambda) {} + + fn visit_if_exp(&mut self, i: &parser::ast::IfExp) {} + + fn visit_joined_str(&mut self, j: &parser::ast::JoinedStr) {} + + fn visit_formatted_value(&mut self, f: &parser::ast::FormattedValue) {} + + fn visit_alias(&mut self, a: &parser::ast::Alias) {} + + fn visit_assign(&mut self, a: &parser::ast::Assign) { + let stmt = a.clone(); + self.defs.push(Statement::AssignStatement(stmt)); + } + + fn visit_ann_assign(&mut self, a: &parser::ast::AnnAssign) { + let stmt = a.clone(); + self.defs.push(Statement::AnnAssignStatement(stmt)); + } + + fn visit_aug_assign(&mut self, a: &parser::ast::AugAssign) {} + + 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) {} + + fn visit_return(&mut self, r: &parser::ast::Return) {} + + fn visit_raise(&mut self, r: &parser::ast::Raise) {} + + fn visit_break(&mut self, b: &parser::ast::Break) {} + + fn visit_continue(&mut self, c: &parser::ast::Continue) {} + + fn visit_global(&mut self, g: &parser::ast::Global) {} + + fn visit_nonlocal(&mut self, n: &parser::ast::Nonlocal) {} } diff --git a/typechecker/src/symbol_table.rs b/typechecker/src/symbol_table.rs index 2c4b9f79..12b31b95 100644 --- a/typechecker/src/symbol_table.rs +++ b/typechecker/src/symbol_table.rs @@ -167,6 +167,10 @@ impl SymbolTableNode { pub fn add_declaration(&mut self, decl: Declaration) { self.declarations.push(decl); } + + pub fn last_declaration(&self) -> Option<&Declaration> { + self.declarations.last() + } } // implement display for symbol table and sort the symbols by key diff --git a/typechecker/src/type_check/checker.rs b/typechecker/src/type_check/checker.rs index 3cb0ec8d..3d51238b 100644 --- a/typechecker/src/type_check/checker.rs +++ b/typechecker/src/type_check/checker.rs @@ -3,20 +3,23 @@ use parser::ast::{self, *}; use crate::{ ast_visitor::TraversalVisitor, ast_visitor_immut::TraversalVisitorImmut, settings::Settings, - state::State, + state::State, symbol_table::Declaration, }; -use super::types::Type; +use super::{ + type_inference::{self, type_equal}, + types::Type, +}; pub struct TypeChecker<'a> { pub errors: Vec, // TODO: currently only supporting a single file pub module: &'a State, - pub options: Settings, + pub options: &'a Settings, } impl<'a> TypeChecker<'a> { - fn new(module: &'a State, options: Settings) -> Self { + pub fn new(module: &'a State, options: &'a Settings) -> Self { TypeChecker { errors: vec![], module, @@ -24,6 +27,25 @@ impl<'a> TypeChecker<'a> { } } + pub fn type_check(&mut self) { + for stmt in &self.module.file.body { + self.visit_stmt(&stmt); + } + } + + fn infer_declaration_type(&mut self, declaration: &Declaration) -> Type { + match declaration { + Declaration::Variable(v) => { + if let Some(type_annotation) = &v.type_annotation { + type_inference::get_type_from_annotation(type_annotation.clone()) + } else { + Type::Unknown + } + } + _ => Type::Unknown, + } + } + fn infer_expr_type(&mut self, expr: &ast::Expression) -> Type { match expr { ast::Expression::Constant(c) => match c.value { @@ -34,13 +56,20 @@ impl<'a> TypeChecker<'a> { ast::ConstantValue::None => Type::None, _ => Type::Unknown, }, + ast::Expression::Name(n) => match self.module.symbol_table.lookup_in_scope(&n.id) { + Some(symbol) => match symbol.last_declaration() { + Some(declaration) => self.infer_declaration_type(declaration), + None => Type::Unknown, + }, + None => Type::Unknown, + }, _ => Type::Unknown, } } } -impl<'a> TraversalVisitorImmut for TypeChecker<'a> { - fn visit_stmt(&self, s: &Statement) { +impl<'a> TraversalVisitor for TypeChecker<'a> { + fn visit_stmt(&mut self, s: &Statement) { // map all statements and call visit match s { Statement::ExpressionStatement(e) => self.visit_expr(e), @@ -70,7 +99,7 @@ impl<'a> TraversalVisitorImmut for TypeChecker<'a> { } } - fn visit_expr(&self, e: &Expression) { + fn visit_expr(&mut self, e: &Expression) { match e { Expression::Constant(c) => self.visit_constant(c), Expression::List(l) => self.visit_list(l), @@ -102,15 +131,16 @@ impl<'a> TraversalVisitorImmut for TypeChecker<'a> { } } - fn visit_import(&self, i: &Import) { + fn visit_import(&mut self, i: &Import) { todo!(); } - fn visit_import_from(&self, i: &ImportFrom) { + fn visit_import_from(&mut self, i: &ImportFrom) { todo!(); } - fn visit_if(&self, i: &parser::ast::If) { + fn visit_if(&mut self, i: &parser::ast::If) { + // self.visit_stmt(i.test); for stmt in &i.body { self.visit_stmt(&stmt); } @@ -119,19 +149,19 @@ impl<'a> TraversalVisitorImmut for TypeChecker<'a> { } } - fn visit_while(&self, w: &parser::ast::While) { + fn visit_while(&mut self, w: &parser::ast::While) { for stmt in &w.body { self.visit_stmt(&stmt) } } - fn visit_for(&self, f: &parser::ast::For) { + fn visit_for(&mut self, f: &parser::ast::For) { for stmt in &f.body { self.visit_stmt(&stmt); } } - fn visit_with(&self, w: &parser::ast::With) { + fn visit_with(&mut self, w: &parser::ast::With) { for stmt in &w.body { self.visit_stmt(&stmt); } @@ -144,7 +174,7 @@ impl<'a> TraversalVisitorImmut for TypeChecker<'a> { } } - fn visit_try(&self, t: &parser::ast::Try) { + fn visit_try(&mut self, t: &parser::ast::Try) { for stmt in &t.body { self.visit_stmt(&stmt); } @@ -162,7 +192,7 @@ impl<'a> TraversalVisitorImmut for TypeChecker<'a> { } } - fn visit_try_star(&self, t: &parser::ast::TryStar) { + fn visit_try_star(&mut self, t: &parser::ast::TryStar) { for stmt in &t.body { self.visit_stmt(&stmt); } @@ -180,19 +210,19 @@ impl<'a> TraversalVisitorImmut for TypeChecker<'a> { } } - fn visit_function_def(&self, f: &parser::ast::FunctionDef) { + fn visit_function_def(&mut self, f: &parser::ast::FunctionDef) { for stmt in &f.body { self.visit_stmt(&stmt); } } - fn visit_class_def(&self, c: &parser::ast::ClassDef) { + fn visit_class_def(&mut self, c: &parser::ast::ClassDef) { for stmt in &c.body { self.visit_stmt(&stmt); } } - fn visit_match(&self, m: &parser::ast::Match) { + fn visit_match(&mut self, m: &parser::ast::Match) { for case in &m.cases { for stmt in &case.body { self.visit_stmt(&stmt); @@ -200,161 +230,167 @@ impl<'a> TraversalVisitorImmut for TypeChecker<'a> { } } - fn visit_constant(&self, c: &Constant) { + fn visit_constant(&mut self, c: &Constant) { todo!() } - fn visit_list(&self, l: &List) { + fn visit_list(&mut self, l: &List) { todo!() } - fn visit_tuple(&self, t: &Tuple) { + fn visit_tuple(&mut self, t: &Tuple) { todo!() } - fn visit_dict(&self, d: &Dict) { + fn visit_dict(&mut self, d: &Dict) { todo!() } - fn visit_set(&self, s: &Set) { + fn visit_set(&mut self, s: &Set) { todo!() } - fn visit_name(&self, n: &Name) {} + fn visit_name(&mut self, n: &Name) {} - fn visit_bool_op(&self, b: &BoolOperation) { + fn visit_bool_op(&mut self, b: &BoolOperation) { todo!() } - fn visit_unary_op(&self, u: &UnaryOperation) { + fn visit_unary_op(&mut self, u: &UnaryOperation) { todo!() } - fn visit_bin_op(&self, b: &BinOp) { - todo!() - } + fn visit_bin_op(&mut self, b: &BinOp) { + let l_type = self.infer_expr_type(&b.left); + let r_type = self.infer_expr_type(&b.right); - fn visit_named_expr(&self, n: &NamedExpression) { - todo!() + println!("left: {}", l_type); + println!("right: {}", r_type); + if !type_equal(&l_type, &r_type) { + self.errors.push(format!( + "Cannot do {} between types {} and {}", + b.op, l_type, r_type + )); + } } - fn visit_yield(&self, y: &Yield) { + fn visit_named_expr(&mut self, n: &NamedExpression) { todo!() } - fn visit_yield_from(&self, y: &YieldFrom) { + fn visit_yield(&mut self, y: &Yield) { todo!() } - fn visit_starred(&self, s: &Starred) { + fn visit_yield_from(&mut self, y: &YieldFrom) { todo!() } - fn visit_generator(&self, g: &Generator) { + fn visit_starred(&mut self, s: &Starred) { todo!() } - fn visit_list_comp(&self, l: &ListComp) { + fn visit_generator(&mut self, g: &Generator) { todo!() } - fn visit_set_comp(&self, s: &SetComp) { + fn visit_list_comp(&mut self, l: &ListComp) { todo!() } - fn visit_dict_comp(&self, d: &DictComp) { + fn visit_set_comp(&mut self, s: &SetComp) { todo!() } - fn visit_attribute(&self, a: &Attribute) { + fn visit_dict_comp(&mut self, d: &DictComp) { todo!() } - fn visit_subscript(&self, s: &Subscript) { + fn visit_attribute(&mut self, a: &Attribute) { todo!() } - fn visit_slice(&self, s: &Slice) { + fn visit_subscript(&mut self, s: &Subscript) { todo!() } - fn visit_call(&self, c: &Call) { + fn visit_slice(&mut self, s: &Slice) { todo!() } - fn visit_await(&self, a: &Await) { + fn visit_call(&mut self, c: &Call) { todo!() } - fn visit_compare(&self, c: &Compare) { + fn visit_await(&mut self, a: &Await) { todo!() } - fn visit_lambda(&self, l: &Lambda) { + fn visit_compare(&mut self, c: &Compare) { todo!() } - fn visit_if_exp(&self, i: &IfExp) { + fn visit_lambda(&mut self, l: &Lambda) { todo!() } - fn visit_joined_str(&self, j: &JoinedStr) { + fn visit_if_exp(&mut self, i: &IfExp) { todo!() } - fn visit_formatted_value(&self, f: &FormattedValue) { + fn visit_joined_str(&mut self, j: &JoinedStr) { todo!() } - fn visit_alias(&self, a: &Alias) { + fn visit_formatted_value(&mut self, f: &FormattedValue) { todo!() } - fn visit_assign(&self, a: &Assign) { + fn visit_alias(&mut self, a: &Alias) { todo!() } - fn visit_ann_assign(&self, a: &AnnAssign) { - todo!() - } + fn visit_assign(&mut self, a: &Assign) {} + + fn visit_ann_assign(&mut self, a: &AnnAssign) {} - fn visit_aug_assign(&self, a: &AugAssign) { + fn visit_aug_assign(&mut self, a: &AugAssign) { todo!() } - fn visit_assert(&self, a: &Assert) { + fn visit_assert(&mut self, a: &Assert) { todo!() } - fn visit_pass(&self, p: &Pass) { + fn visit_pass(&mut self, p: &Pass) { todo!() } - fn visit_delete(&self, d: &Delete) { + fn visit_delete(&mut self, d: &Delete) { todo!() } - fn visit_return(&self, r: &Return) { + fn visit_return(&mut self, r: &Return) { todo!() } - fn visit_raise(&self, r: &Raise) { + fn visit_raise(&mut self, r: &Raise) { todo!() } - fn visit_break(&self, b: &Break) { + fn visit_break(&mut self, b: &Break) { todo!() } - fn visit_continue(&self, c: &Continue) { + fn visit_continue(&mut self, c: &Continue) { todo!() } - fn visit_global(&self, g: &Global) { + fn visit_global(&mut self, g: &Global) { todo!() } - fn visit_nonlocal(&self, n: &Nonlocal) { + fn visit_nonlocal(&mut self, n: &Nonlocal) { todo!() } } diff --git a/typechecker/src/type_check/mod.rs b/typechecker/src/type_check/mod.rs index 909147ba..57e063b3 100644 --- a/typechecker/src/type_check/mod.rs +++ b/typechecker/src/type_check/mod.rs @@ -1,3 +1,3 @@ -mod checker; +pub mod checker; mod type_inference; mod types; diff --git a/typechecker/src/type_check/type_inference.rs b/typechecker/src/type_check/type_inference.rs index 7ee2c98a..4f06def1 100644 --- a/typechecker/src/type_check/type_inference.rs +++ b/typechecker/src/type_check/type_inference.rs @@ -17,3 +17,14 @@ pub fn get_type_from_annotation(type_annotation: ast::Expression) -> Type { expr_type } + +pub fn type_equal(t1: &Type, t2: &Type) -> bool { + match (t1, t2) { + (Type::Int, Type::Int) => true, + (Type::Float, Type::Float) => true, + (Type::Str, Type::Str) => true, + (Type::Bool, Type::Bool) => true, + (Type::None, Type::None) => true, + _ => false, + } +} diff --git a/typechecker/src/type_check/types.rs b/typechecker/src/type_check/types.rs index 609f08b6..32919140 100644 --- a/typechecker/src/type_check/types.rs +++ b/typechecker/src/type_check/types.rs @@ -1,3 +1,5 @@ +use std::fmt::Display; + pub enum Type { Any, None, @@ -7,3 +9,19 @@ pub enum Type { Str, Unknown, } + +impl Display for Type { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let type_str = match self { + Type::Any => "Any", + Type::None => "None", + Type::Bool => "Bool", + Type::Int => "Int", + Type::Float => "Float", + Type::Str => "Str", + Type::Unknown => "Unknown", + }; + + write!(f, "{}", type_str) + } +} diff --git a/typechecker/testdata/inputs/type_check_var.py b/typechecker/testdata/inputs/type_check_var.py new file mode 100644 index 00000000..8f826503 --- /dev/null +++ b/typechecker/testdata/inputs/type_check_var.py @@ -0,0 +1,3 @@ +a: int = 1 + +a + "str" diff --git a/typechecker/testdata/output/typechecker__build__tests__type_check_var.snap.new b/typechecker/testdata/output/typechecker__build__tests__type_check_var.snap.new new file mode 100644 index 00000000..376270a7 --- /dev/null +++ b/typechecker/testdata/output/typechecker__build__tests__type_check_var.snap.new @@ -0,0 +1,7 @@ +--- +source: typechecker/src/build.rs +assertion_line: 171 +description: "a: int = 1\n\na + \"str\"\n" +expression: result +--- +Cannot do + between types Int and Str From a81818e029b73add170bbbebaaa381549efd9f6e Mon Sep 17 00:00:00 2001 From: Glyphack Date: Sun, 27 Aug 2023 18:55:52 +0200 Subject: [PATCH 3/4] refactor type checking for bin operator --- test.py | 4 +++ typechecker/src/type_check/checker.rs | 14 ++++---- typechecker/src/type_check/type_inference.rs | 33 ++++++++++++++++++- ...hecker__build__tests__type_check_var.snap} | 3 +- 4 files changed, 43 insertions(+), 11 deletions(-) rename typechecker/testdata/output/{typechecker__build__tests__type_check_var.snap.new => typechecker__build__tests__type_check_var.snap} (63%) diff --git a/test.py b/test.py index 42e5ab35..2820babc 100644 --- a/test.py +++ b/test.py @@ -4,3 +4,7 @@ def func(a = 2 ,b = 2 , /, c = 2, *, d, e = 2): pass func(1,2,3, d= 1 ) +a = (1 + "s") + +a + 1 + diff --git a/typechecker/src/type_check/checker.rs b/typechecker/src/type_check/checker.rs index 3d51238b..38c6b27a 100644 --- a/typechecker/src/type_check/checker.rs +++ b/typechecker/src/type_check/checker.rs @@ -7,7 +7,7 @@ use crate::{ }; use super::{ - type_inference::{self, type_equal}, + type_inference::{self, type_check_bin_op, type_equal}, types::Type, }; @@ -230,9 +230,7 @@ impl<'a> TraversalVisitor for TypeChecker<'a> { } } - fn visit_constant(&mut self, c: &Constant) { - todo!() - } + fn visit_constant(&mut self, c: &Constant) {} fn visit_list(&mut self, l: &List) { todo!() @@ -261,14 +259,14 @@ impl<'a> TraversalVisitor for TypeChecker<'a> { } fn visit_bin_op(&mut self, b: &BinOp) { + self.visit_expr(&b.left); + self.visit_expr(&b.right); let l_type = self.infer_expr_type(&b.left); let r_type = self.infer_expr_type(&b.right); - println!("left: {}", l_type); - println!("right: {}", r_type); - if !type_equal(&l_type, &r_type) { + if !type_check_bin_op(&l_type, &r_type, &b.op) { self.errors.push(format!( - "Cannot do {} between types {} and {}", + "Operator '{}' not supported for types '{}' and '{}'", b.op, l_type, r_type )); } diff --git a/typechecker/src/type_check/type_inference.rs b/typechecker/src/type_check/type_inference.rs index 4f06def1..cc854ff2 100644 --- a/typechecker/src/type_check/type_inference.rs +++ b/typechecker/src/type_check/type_inference.rs @@ -1,4 +1,4 @@ -use parser::ast; +use parser::ast::{self, BinaryOperator}; use super::types::Type; @@ -28,3 +28,34 @@ pub fn type_equal(t1: &Type, t2: &Type) -> bool { _ => false, } } + +pub fn type_check_bin_op(t1: &Type, t2: &Type, op: &BinaryOperator) -> bool { + let check_table = match op { + BinaryOperator::Add => vec![(Type::Int, Type::Int), (Type::Float, Type::Float)], + BinaryOperator::Sub => vec![(Type::Int, Type::Int), (Type::Float, Type::Float)], + BinaryOperator::Mult => vec![ + (Type::Int, Type::Int), + (Type::Float, Type::Float), + (Type::Str, Type::Int), + (Type::Int, Type::Str), + ], + BinaryOperator::Div => vec![(Type::Int, Type::Int), (Type::Float, Type::Float)], + BinaryOperator::Mod => vec![(Type::Int, Type::Int), (Type::Float, Type::Float)], + BinaryOperator::Pow => vec![(Type::Int, Type::Int), (Type::Float, Type::Float)], + BinaryOperator::LShift => vec![(Type::Int, Type::Int)], + BinaryOperator::RShift => vec![(Type::Int, Type::Int)], + BinaryOperator::BitOr => vec![(Type::Int, Type::Int)], + BinaryOperator::BitAnd => vec![(Type::Int, Type::Int)], + BinaryOperator::BitXor => vec![(Type::Int, Type::Int)], + BinaryOperator::FloorDiv => vec![(Type::Int, Type::Int), (Type::Float, Type::Float)], + BinaryOperator::MatMult => vec![(Type::Int, Type::Int), (Type::Float, Type::Float)], + }; + + for (t1_, t2_) in check_table { + if type_equal(t1, &t1_) && type_equal(t2, &t2_) { + return true; + } + } + + false +} diff --git a/typechecker/testdata/output/typechecker__build__tests__type_check_var.snap.new b/typechecker/testdata/output/typechecker__build__tests__type_check_var.snap similarity index 63% rename from typechecker/testdata/output/typechecker__build__tests__type_check_var.snap.new rename to typechecker/testdata/output/typechecker__build__tests__type_check_var.snap index 376270a7..757ec01d 100644 --- a/typechecker/testdata/output/typechecker__build__tests__type_check_var.snap.new +++ b/typechecker/testdata/output/typechecker__build__tests__type_check_var.snap @@ -1,7 +1,6 @@ --- source: typechecker/src/build.rs -assertion_line: 171 description: "a: int = 1\n\na + \"str\"\n" expression: result --- -Cannot do + between types Int and Str +Operator '+' not supported for types 'Int' and 'Str' From 7f8ef878bbdc768e45b2e10406e0ff0a379a07f7 Mon Sep 17 00:00:00 2001 From: Glyphack Date: Sun, 27 Aug 2023 18:57:27 +0200 Subject: [PATCH 4/4] cargo clippy --- parser/src/lexer/lexer.rs | 6 +- parser/src/parser/ast.rs | 4 +- parser/src/parser/diagnostics.rs | 2 +- parser/src/parser/operator.rs | 2 +- parser/src/parser/parser.rs | 167 +++++++++++++------------- parser/src/parser/statement.rs | 6 +- parser/src/parser/string.rs | 14 +-- parser/src/token.rs | 2 +- typechecker/src/ast_visitor.rs | 120 +++++++++--------- typechecker/src/ast_visitor_immut.rs | 120 +++++++++--------- typechecker/src/build.rs | 2 +- typechecker/src/nodes.rs | 108 ++++++++--------- typechecker/src/semanal_utils.rs | 2 +- typechecker/src/semantic_analyzer.rs | 128 ++++++++++---------- typechecker/src/settings.rs | 2 +- typechecker/src/symbol_table.rs | 4 +- typechecker/src/type_check/checker.rs | 122 +++++++++---------- 17 files changed, 402 insertions(+), 409 deletions(-) diff --git a/parser/src/lexer/lexer.rs b/parser/src/lexer/lexer.rs index cac18573..e175b53a 100644 --- a/parser/src/lexer/lexer.rs +++ b/parser/src/lexer/lexer.rs @@ -112,7 +112,7 @@ impl Lexer { } } 3 => { - if curr == str_finisher.chars().nth(0).unwrap() + if curr == str_finisher.chars().next().unwrap() && self.peek() == Some(str_finisher.chars().nth(1).unwrap()) && self.double_peek() == Some(str_finisher.chars().nth(2).unwrap()) { @@ -140,7 +140,7 @@ impl Lexer { } } 3 => { - if peeked_char == str_finisher.chars().nth(0).unwrap() + if peeked_char == str_finisher.chars().next().unwrap() && self.double_peek() == Some(str_finisher.chars().nth(1).unwrap()) && self.triple_peek() == Some(str_finisher.chars().nth(2).unwrap()) { @@ -160,7 +160,7 @@ impl Lexer { return Ok(indent_kind); } } - if self.fstring_stack.len() > 0 { + if !self.fstring_stack.is_empty() { if let Some(kind) = self.next_fstring_token() { return Ok(kind); } diff --git a/parser/src/parser/ast.rs b/parser/src/parser/ast.rs index 7f6a636b..04e4fa74 100644 --- a/parser/src/parser/ast.rs +++ b/parser/src/parser/ast.rs @@ -26,8 +26,8 @@ trait GetNode { impl From for SourceSpan { fn from(val: Node) -> Self { Self::new( - SourceOffset::from(val.start as usize), - SourceOffset::from(val.len() as usize), + SourceOffset::from(val.start), + SourceOffset::from(val.len()), ) } } diff --git a/parser/src/parser/diagnostics.rs b/parser/src/parser/diagnostics.rs index 6af094ff..25c53bc5 100644 --- a/parser/src/parser/diagnostics.rs +++ b/parser/src/parser/diagnostics.rs @@ -1,4 +1,4 @@ -use crate::{parser::ast::Node, token::Kind}; +use crate::{parser::ast::Node}; use miette::{self, Diagnostic}; use thiserror::{self, Error}; diff --git a/parser/src/parser/operator.rs b/parser/src/parser/operator.rs index c5790d46..216f60f7 100644 --- a/parser/src/parser/operator.rs +++ b/parser/src/parser/operator.rs @@ -1,4 +1,4 @@ -use crate::parser::ast::{BinaryOperator, BooleanOperator, UnaryOperator}; +use crate::parser::ast::{BooleanOperator, UnaryOperator}; use crate::token::Kind; pub fn is_bool_op(kind: &Kind) -> bool { diff --git a/parser/src/parser/parser.rs b/parser/src/parser/parser.rs index 534e2550..d6f8c257 100644 --- a/parser/src/parser/parser.rs +++ b/parser/src/parser/parser.rs @@ -1,4 +1,4 @@ -use std::ops::Index; + use std::{panic, vec}; use crate::lexer::lexer::Lexer; @@ -48,7 +48,7 @@ impl Parser { let node = self.start_node(); let mut body = vec![]; while self.cur_kind() != Kind::Eof { - let stmt = if is_at_compound_statement(&self.cur_token()) { + let stmt = if is_at_compound_statement(self.cur_token()) { self.parse_compount_statement() } else { self.parse_simple_statement() @@ -675,7 +675,8 @@ impl Parser { } fn parse_closed_pattern(&mut self) -> Result { - let matching_pattern = match self.cur_kind() { + + match self.cur_kind() { Kind::LeftParen => self.parse_sequence_pattern(), Kind::LeftBrace => self.parse_sequence_pattern(), Kind::LeftBracket => self.parse_mapping_pattern(), @@ -689,13 +690,11 @@ impl Parser { } else { self.parse_value_pattern(value, node) } + } else if matches!(self.peek_kind(), Ok(Kind::LeftParen)) { + let value = self.parse_attr()?; + self.parse_class_pattern(value) } else { - if matches!(self.peek_kind(), Ok(Kind::LeftParen)) { - let value = self.parse_attr()?; - self.parse_class_pattern(value) - } else { - self.parse_capture_or_wildcard_pattern() - } + self.parse_capture_or_wildcard_pattern() } }, Kind::Integer @@ -720,13 +719,12 @@ impl Parser { let node = self.start_node(); let msg = format!("unexpected token {:?}", self.cur_token().value); self.bump_any(); - return Err(diagnostics::InvalidSyntax( + Err(diagnostics::InvalidSyntax( msg, self.finish_node(node), ).into()) }, - }; - matching_pattern + } } // https://docs.python.org/3/reference/compound_stmts.html#literal-patterns @@ -789,7 +787,7 @@ impl Parser { attr: attr_val, }))); } - return expr; + expr } // TODO: This has precedence over sequence pattern but I'm not sure @@ -948,7 +946,8 @@ impl Parser { fn parse_assignment_or_expression_statement(&mut self) -> Result { let node = self.start_node(); let lhs = self.parse_expression()?; - let stmt = if self.cur_kind() == Kind::Assign { + + if self.cur_kind() == Kind::Assign { self.parse_assignment_statement(node, lhs) } else if matches!( self.cur_kind(), @@ -970,8 +969,7 @@ impl Parser { self.parse_ann_assign_statement(node, lhs) } else { Ok(Statement::ExpressionStatement(lhs)) - }; - stmt + } } // https://docs.python.org/3/reference/compound_stmts.html#grammar-token-python-grammar-suite @@ -993,14 +991,14 @@ impl Parser { // https://docs.python.org/3/reference/compound_stmts.html#grammar-token-python-grammar-statement fn parse_statement(&mut self) -> Result> { - let stmt = if is_at_compound_statement(&self.cur_token()) { + + if is_at_compound_statement(self.cur_token()) { let comp_stmt = self.parse_compount_statement()?; Ok(vec![comp_stmt]) } else { - let stmt_list = self.parse_statement_list(); - stmt_list - }; - stmt + + self.parse_statement_list() + } } // https://docs.python.org/3/reference/simple_stmts.html#grammar-token-python-grammar-stmt-list @@ -1048,11 +1046,11 @@ impl Parser { break rhs; } }; - return Ok(Statement::AssignStatement(Assign { + Ok(Statement::AssignStatement(Assign { node: self.finish_node(start), targets, value, - })); + })) } fn parse_aug_assignment_statement( @@ -1063,12 +1061,12 @@ impl Parser { let op = self.parse_aug_assign_op()?; let value = self.parse_assignment_value()?; - return Ok(Statement::AugAssignStatement(AugAssign { + Ok(Statement::AugAssignStatement(AugAssign { node: self.finish_node(start), target: lhs, op, value, - })); + })) } fn parse_ann_assign_statement(&mut self, start: Node, lhs: Expression) -> Result { @@ -1079,21 +1077,21 @@ impl Parser { } else { None }; - return Ok(Statement::AnnAssignStatement(AnnAssign { + Ok(Statement::AnnAssignStatement(AnnAssign { node: self.finish_node(start), target: lhs, annotation, value, // TODO: implement simple simple: true, - })); + })) } // The value is either expression list or yield expression // https://docs.python.org/3/reference/simple_stmts.html#assignment-statements fn parse_assignment_value(&mut self) -> Result { if self.cur_kind() == Kind::Yield { - return Ok(self.parse_yield_expression()?); + return self.parse_yield_expression(); } self.parse_expression_list() } @@ -1135,19 +1133,19 @@ impl Parser { None }; - return Ok(Statement::Assert(Assert { + Ok(Statement::Assert(Assert { node: self.finish_node(node), test, msg, - })); + })) } fn parse_pass_statement(&mut self) -> Result { let node = self.start_node(); self.bump(Kind::Pass); - return Ok(Statement::Pass(Pass { + Ok(Statement::Pass(Pass { node: self.finish_node(node), - })); + })) } fn parse_return_statement(&mut self) -> Result { @@ -1158,10 +1156,10 @@ impl Parser { } else { Some(self.parse_expression_list()?) }; - return Ok(Statement::Return(Return { + Ok(Statement::Return(Return { node: self.finish_node(node), value, - })); + })) } // https://docs.python.org/3/reference/simple_stmts.html#the-raise-statement @@ -1178,29 +1176,29 @@ impl Parser { } else { None }; - return Ok(Statement::Raise(Raise { + Ok(Statement::Raise(Raise { node: self.finish_node(node), exc, cause, - })); + })) } // https://docs.python.org/3/reference/simple_stmts.html#the-break-statement fn parse_break_statement(&mut self) -> Result { let node = self.start_node(); self.bump(Kind::Break); - return Ok(Statement::Break(Break { + Ok(Statement::Break(Break { node: self.finish_node(node), - })); + })) } // https://docs.python.org/3/reference/simple_stmts.html#the-continue-statement fn parse_continue_statement(&mut self) -> Result { let node = self.start_node(); self.bump(Kind::Continue); - return Ok(Statement::Continue(Continue { + Ok(Statement::Continue(Continue { node: self.finish_node(node), - })); + })) } // https://docs.python.org/3/reference/simple_stmts.html#the-global-statement @@ -1216,10 +1214,10 @@ impl Parser { break; } } - return Ok(Statement::Global(Global { + Ok(Statement::Global(Global { node: self.finish_node(node), names, - })); + })) } // https://docs.python.org/3/reference/simple_stmts.html#the-nonlocal-statement @@ -1235,10 +1233,10 @@ impl Parser { break; } } - return Ok(Statement::Nonlocal(Nonlocal { + Ok(Statement::Nonlocal(Nonlocal { node: self.finish_node(node), names, - })); + })) } // https://docs.python.org/3/reference/simple_stmts.html#the-import-statement @@ -1256,10 +1254,10 @@ impl Parser { break; } } - return Ok(Statement::Import(Import { + Ok(Statement::Import(Import { node: self.finish_node(node), names: aliases, - })); + })) } // https://docs.python.org/3/reference/simple_stmts.html#the-from-import-statement @@ -1279,12 +1277,12 @@ impl Parser { break; } } - return Ok(Statement::ImportFrom(ImportFrom { + Ok(Statement::ImportFrom(ImportFrom { node: self.finish_node(import_node), module, names: aliases, level: 0, - })); + })) } fn parse_alias(&mut self, name: String, node: Node) -> Alias { @@ -1295,22 +1293,22 @@ impl Parser { } else { None }; - return Alias { + Alias { node: self.finish_node(node), name, asname, - }; + } } fn parse_module_name(&mut self) -> String { - let mut module = String::from(self.cur_token().value.to_string()); + let mut module = self.cur_token().value.to_string(); self.bump(Kind::Identifier); while self.eat(Kind::Dot) { module.push('.'); module.push_str(self.cur_token().value.to_string().as_str()); self.bump(Kind::Identifier); } - return module; + module } // https://docs.python.org/3/library/ast.html#ast.Expr @@ -1331,10 +1329,10 @@ impl Parser { return Ok(expr); } - return Ok(Expression::Tuple(Box::new(Tuple { + Ok(Expression::Tuple(Box::new(Tuple { node: self.finish_node(node), elements: exprs, - }))); + }))) } // https://docs.python.org/3/reference/expressions.html#conditional-expressions @@ -1446,7 +1444,7 @@ impl Parser { // https://docs.python.org/3/reference/expressions.html#displays-for-lists-sets-and-dictionaries fn parse_comp_for(&mut self) -> Result> { // if current token is async - let is_async = if self.eat(Kind::Async) { true } else { false }; + let is_async = self.eat(Kind::Async); let mut generators = vec![]; loop { @@ -1662,7 +1660,7 @@ impl Parser { fn parse_starred_item(&mut self) -> Result { let mut node = self.start_node(); if self.eat(Kind::Mul) { - let starred_value_kind = self.cur_kind().clone(); + let starred_value_kind = self.cur_kind(); let expr = self.parse_or_expr()?; node = self.finish_node(node); if !is_iterable(&expr) { @@ -1776,7 +1774,7 @@ impl Parser { right: Box::new(lhs), }))); } - return Ok(xor_expr); + Ok(xor_expr) } // https://docs.python.org/3/reference/expressions.html#binary-bitwise-operations @@ -1792,7 +1790,7 @@ impl Parser { right: Box::new(lhs), }))); } - return Ok(and_expr); + Ok(and_expr) } // https://docs.python.org/3/reference/expressions.html#binary-bitwise-operations @@ -1809,7 +1807,7 @@ impl Parser { right: Box::new(lhs), }))); } - return Ok(shift_expr); + Ok(shift_expr) } // https://docs.python.org/3/reference/expressions.html#shifting-operations @@ -1831,7 +1829,7 @@ impl Parser { right: Box::new(lhs), }))); } - return Ok(arith_expr); + Ok(arith_expr) } // https://docs.python.org/3/reference/expressions.html#binary-arithmetic-operations @@ -1848,7 +1846,7 @@ impl Parser { right: Box::new(rhs), }))); } - return Ok(lhs); + Ok(lhs) } // https://docs.python.org/3/reference/expressions.html#unary-arithmetic-and-bitwise-operations @@ -1890,7 +1888,7 @@ impl Parser { }))); } - return base; + base } // https://docs.python.org/3/reference/expressions.html#primaries @@ -1982,7 +1980,7 @@ impl Parser { Ok(atom_or_primary) }; - return primary; + primary } // https://docs.python.org/3/reference/expressions.html#grammar-token-python-grammar-argument_list @@ -2044,7 +2042,7 @@ impl Parser { break; } } - return Ok((positional_args, keyword_args)); + Ok((positional_args, keyword_args)) } fn parse_atribute_ref(&mut self, node: Node, value: Expression) -> Result { @@ -2058,7 +2056,7 @@ impl Parser { attr: attr_val, }))); } - return expr; + expr } fn parse_subscript(&mut self, node: Node, value: Expression) -> Result { @@ -2071,14 +2069,14 @@ impl Parser { slice: Box::new(slice), }))); } - return expr; + expr } // https://docs.python.org/3/reference/expressions.html#atoms fn parse_atom(&mut self) -> Result { let node = self.start_node(); if self.at(Kind::Yield) { - return self.parse_yield_expression(); + self.parse_yield_expression() } else if self.at(Kind::LeftBrace) { self.nested_expression_list += 1; let list_expr = self.parse_list(); @@ -2150,10 +2148,10 @@ impl Parser { let node = self.start_node(); let value = self.cur_token().value.to_string(); self.expect(Kind::Identifier)?; - return Ok(Expression::Name(Box::new(Name { + Ok(Expression::Name(Box::new(Name { node: self.finish_node(node), id: value, - }))); + }))) } // https://docs.python.org/3/reference/expressions.html#yield-expressions @@ -2178,10 +2176,10 @@ impl Parser { Ok(expr) => Some(Box::new(expr)), _ => None, }; - return Ok(Expression::Yield(Box::new(Yield { + Ok(Expression::Yield(Box::new(Yield { node: self.finish_node(yield_node), value, - }))); + }))) } // https://docs.python.org/3/reference/expressions.html#expression-lists @@ -2267,12 +2265,10 @@ impl Parser { let slice_lower = if lower.is_some() { Some(Box::new(lower.unwrap())) + } else if self.eat(Kind::Colon) { + None } else { - if self.eat(Kind::Colon) { - None - } else { - Some(Box::new(self.parse_expression_2()?)) - } + Some(Box::new(self.parse_expression_2()?)) }; let upper = if self.eat(Kind::Colon) { if self.at(Kind::RightBrace) { @@ -2333,7 +2329,7 @@ impl Parser { let bytes_val = extract_string_inside( value .to_string() - .strip_prefix("b") + .strip_prefix('b') .expect("bytes literal must start with b") .to_string(), ) @@ -2579,7 +2575,7 @@ impl Parser { } fn is_def_parameter(&mut self) -> bool { - return self.cur_kind() == Kind::Identifier; + self.cur_kind() == Kind::Identifier // && matches!(self.peek_kind(), Ok(Kind::Assign)) // || matches!(self.peek_kind(), Ok(Kind::Colon)) } @@ -2862,7 +2858,8 @@ mod tests { #[test] fn test_named_expression() { - for test_case in &["(a := b)"] { + { + let test_case = &"(a := b)"; let mut parser = Parser::new(test_case.to_string()); let program = parser.parse(); @@ -3000,7 +2997,8 @@ mod tests { #[test] fn test_starred() { - for test_case in &["(*a)"] { + { + let test_case = &"(*a)"; let mut parser = Parser::new(test_case.to_string()); let program = parser.parse(); @@ -3015,7 +3013,8 @@ mod tests { #[test] fn test_await_expression() { - for test_case in &["await a"] { + { + let test_case = &"await a"; let mut parser = Parser::new(test_case.to_string()); let program = parser.parse(); @@ -3139,10 +3138,8 @@ mod tests { #[test] fn test_conditional_expression() { - for test_case in &[ - // "a if b else c", - "a if b else c if d else e", - ] { + { + let test_case = &"a if b else c if d else e"; let mut parser = Parser::new(test_case.to_string()); let program = parser.parse(); diff --git a/parser/src/parser/statement.rs b/parser/src/parser/statement.rs index d30f3d51..88b1da50 100644 --- a/parser/src/parser/statement.rs +++ b/parser/src/parser/statement.rs @@ -18,10 +18,8 @@ pub fn is_at_compound_statement(token: &Token) -> bool { return true; } - if Kind::Identifier == token.kind { - if token.value.to_string() == "match" { - return true; - } + if Kind::Identifier == token.kind && token.value.to_string() == "match" { + return true; } false diff --git a/parser/src/parser/string.rs b/parser/src/parser/string.rs index cac50656..ae256561 100644 --- a/parser/src/parser/string.rs +++ b/parser/src/parser/string.rs @@ -10,22 +10,22 @@ pub fn extract_string_inside(val: String) -> String { val.strip_suffix("\"\"\"") .expect("String must be enclosed with \"\"\"") .to_string() - } else if let Some(val) = val.strip_prefix("\"") { - val.strip_suffix("\"") + } else if let Some(val) = val.strip_prefix('\"') { + val.strip_suffix('\"') .expect("String must be enclosed with \"") .to_string() } else if let Some(val) = val.strip_prefix("'''") { val.strip_suffix("'''") .expect("String must be enclosed with '''") .to_string() - } else if let Some(val) = val.strip_prefix("'") { - val.strip_suffix("'") + } else if let Some(val) = val.strip_prefix('\'') { + val.strip_suffix('\'') .expect("String must be enclosed with '") .to_string() } else { panic!( "String must be enclosed in \"\"\", \"', ''' or ' but got {} ", - val.starts_with("\'") + val.starts_with('\'') ); } } @@ -63,14 +63,14 @@ pub fn concat_string_exprs(lhs: Expression, rhs: Expression) -> Result { + (ConstantValue::Bytes(_lhs), _) => { return Err(diagnostics::InvalidSyntax( "Cannot concat bytes and string".to_string(), node, ) .into()) } - (_, ConstantValue::Bytes(rhs)) => { + (_, ConstantValue::Bytes(_rhs)) => { return Err(diagnostics::InvalidSyntax( "Cannot concat string and bytes".to_string(), node, diff --git a/parser/src/token.rs b/parser/src/token.rs index 9efbd109..b9b06980 100644 --- a/parser/src/token.rs +++ b/parser/src/token.rs @@ -281,7 +281,7 @@ impl TokenValue { TokenValue::None => "None".to_string(), TokenValue::Number(n) => n.to_string(), TokenValue::Str(s) => s.to_string(), - TokenValue::Indent(i) => panic!("not a string"), + TokenValue::Indent(_i) => panic!("not a string"), } } } diff --git a/typechecker/src/ast_visitor.rs b/typechecker/src/ast_visitor.rs index 7888b3c3..5ac901a0 100644 --- a/typechecker/src/ast_visitor.rs +++ b/typechecker/src/ast_visitor.rs @@ -135,43 +135,43 @@ pub trait TraversalVisitor { Expression::FormattedValue(f) => self.visit_formatted_value(f), } } - fn visit_import(&mut self, i: &Import) { + fn visit_import(&mut self, _i: &Import) { todo!(); } - fn visit_import_from(&mut self, i: &ImportFrom) { + fn visit_import_from(&mut self, _i: &ImportFrom) { todo!(); } fn visit_if(&mut self, i: &parser::ast::If) { for stmt in &i.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for stmt in &i.orelse { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } fn visit_while(&mut self, w: &parser::ast::While) { for stmt in &w.body { - self.visit_stmt(&stmt) + self.visit_stmt(stmt) } } fn visit_for(&mut self, f: &parser::ast::For) { for stmt in &f.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } fn visit_with(&mut self, w: &parser::ast::With) { for stmt in &w.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for with_items in &w.items { - self.visit_expr(&*&with_items.context_expr); + self.visit_expr(&with_items.context_expr); match &with_items.optional_vars { - Some(items) => self.visit_expr(&items), + Some(items) => self.visit_expr(items), None => (), } } @@ -179,189 +179,189 @@ pub trait TraversalVisitor { fn visit_try(&mut self, t: &parser::ast::Try) { for stmt in &t.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for stmt in &t.orelse { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for stmt in &t.finalbody { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } // TODO: need to visit exception handler name and type but let's keep it simple for now for handler in &t.handlers { for stmt in &handler.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } } fn visit_try_star(&mut self, t: &parser::ast::TryStar) { for stmt in &t.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for stmt in &t.orelse { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for stmt in &t.finalbody { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } // TODO: need to visit exception handler name and type but let's keep it simple for now for handler in &t.handlers { for stmt in &handler.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } } fn visit_function_def(&mut self, f: &parser::ast::FunctionDef) { for stmt in &f.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } fn visit_class_def(&mut self, c: &parser::ast::ClassDef) { for stmt in &c.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } fn visit_match(&mut self, m: &parser::ast::Match) { for case in &m.cases { for stmt in &case.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } } - fn visit_constant(&mut self, c: &Constant) { + fn visit_constant(&mut self, _c: &Constant) { todo!() } - fn visit_list(&mut self, l: &List) { + fn visit_list(&mut self, _l: &List) { todo!() } - fn visit_tuple(&mut self, t: &Tuple) { + fn visit_tuple(&mut self, _t: &Tuple) { todo!() } - fn visit_dict(&mut self, d: &Dict) { + fn visit_dict(&mut self, _d: &Dict) { todo!() } - fn visit_set(&mut self, s: &Set) { + fn visit_set(&mut self, _s: &Set) { todo!() } - fn visit_name(&mut self, n: &Name) {} - fn visit_bool_op(&mut self, b: &BoolOperation) { + fn visit_name(&mut self, _n: &Name) {} + fn visit_bool_op(&mut self, _b: &BoolOperation) { todo!() } - fn visit_unary_op(&mut self, u: &UnaryOperation) { + fn visit_unary_op(&mut self, _u: &UnaryOperation) { todo!() } - fn visit_bin_op(&mut self, b: &BinOp) { + fn visit_bin_op(&mut self, _b: &BinOp) { todo!() } - fn visit_named_expr(&mut self, n: &NamedExpression) { + fn visit_named_expr(&mut self, _n: &NamedExpression) { todo!() } - fn visit_yield(&mut self, y: &Yield) { + fn visit_yield(&mut self, _y: &Yield) { todo!() } - fn visit_yield_from(&mut self, y: &YieldFrom) { + fn visit_yield_from(&mut self, _y: &YieldFrom) { todo!() } - fn visit_starred(&mut self, s: &Starred) { + fn visit_starred(&mut self, _s: &Starred) { todo!() } - fn visit_generator(&mut self, g: &Generator) { + fn visit_generator(&mut self, _g: &Generator) { todo!() } - fn visit_list_comp(&mut self, l: &ListComp) { + fn visit_list_comp(&mut self, _l: &ListComp) { todo!() } - fn visit_set_comp(&mut self, s: &SetComp) { + fn visit_set_comp(&mut self, _s: &SetComp) { todo!() } - fn visit_dict_comp(&mut self, d: &DictComp) { + fn visit_dict_comp(&mut self, _d: &DictComp) { todo!() } - fn visit_attribute(&mut self, a: &Attribute) { + fn visit_attribute(&mut self, _a: &Attribute) { todo!() } - fn visit_subscript(&mut self, s: &Subscript) { + fn visit_subscript(&mut self, _s: &Subscript) { todo!() } - fn visit_slice(&mut self, s: &Slice) { + fn visit_slice(&mut self, _s: &Slice) { todo!() } - fn visit_call(&mut self, c: &Call) { + fn visit_call(&mut self, _c: &Call) { todo!() } - fn visit_await(&mut self, a: &Await) { + fn visit_await(&mut self, _a: &Await) { todo!() } - fn visit_compare(&mut self, c: &Compare) { + fn visit_compare(&mut self, _c: &Compare) { todo!() } - fn visit_lambda(&mut self, l: &Lambda) { + fn visit_lambda(&mut self, _l: &Lambda) { todo!() } - fn visit_if_exp(&mut self, i: &IfExp) { + fn visit_if_exp(&mut self, _i: &IfExp) { todo!() } - fn visit_joined_str(&mut self, j: &JoinedStr) { + fn visit_joined_str(&mut self, _j: &JoinedStr) { todo!() } - fn visit_formatted_value(&mut self, f: &FormattedValue) { + fn visit_formatted_value(&mut self, _f: &FormattedValue) { todo!() } - fn visit_alias(&mut self, a: &Alias) { + fn visit_alias(&mut self, _a: &Alias) { todo!() } - fn visit_assign(&mut self, a: &Assign) { + fn visit_assign(&mut self, _a: &Assign) { todo!() } - fn visit_ann_assign(&mut self, a: &AnnAssign) { + fn visit_ann_assign(&mut self, _a: &AnnAssign) { todo!() } - fn visit_aug_assign(&mut self, a: &AugAssign) { + fn visit_aug_assign(&mut self, _a: &AugAssign) { todo!() } - fn visit_assert(&mut self, a: &Assert) { + fn visit_assert(&mut self, _a: &Assert) { todo!() } - fn visit_pass(&mut self, p: &Pass) { + fn visit_pass(&mut self, _p: &Pass) { todo!() } - fn visit_delete(&mut self, d: &Delete) { + fn visit_delete(&mut self, _d: &Delete) { todo!() } - fn visit_return(&mut self, r: &Return) { + fn visit_return(&mut self, _r: &Return) { todo!() } - fn visit_raise(&mut self, r: &Raise) { + fn visit_raise(&mut self, _r: &Raise) { todo!() } - fn visit_break(&mut self, b: &Break) { + fn visit_break(&mut self, _b: &Break) { todo!() } - fn visit_continue(&mut self, c: &Continue) { + fn visit_continue(&mut self, _c: &Continue) { todo!() } - fn visit_global(&mut self, g: &Global) { + fn visit_global(&mut self, _g: &Global) { todo!() } - fn visit_nonlocal(&mut self, n: &Nonlocal) { + fn visit_nonlocal(&mut self, _n: &Nonlocal) { todo!() } } diff --git a/typechecker/src/ast_visitor_immut.rs b/typechecker/src/ast_visitor_immut.rs index 1e480538..fa5321cd 100644 --- a/typechecker/src/ast_visitor_immut.rs +++ b/typechecker/src/ast_visitor_immut.rs @@ -63,43 +63,43 @@ pub trait TraversalVisitorImmut { Expression::FormattedValue(f) => self.visit_formatted_value(f), } } - fn visit_import(&self, i: &Import) { + fn visit_import(&self, _i: &Import) { todo!(); } - fn visit_import_from(&self, i: &ImportFrom) { + fn visit_import_from(&self, _i: &ImportFrom) { todo!(); } fn visit_if(&self, i: &parser::ast::If) { for stmt in &i.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for stmt in &i.orelse { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } fn visit_while(&self, w: &parser::ast::While) { for stmt in &w.body { - self.visit_stmt(&stmt) + self.visit_stmt(stmt) } } fn visit_for(&self, f: &parser::ast::For) { for stmt in &f.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } fn visit_with(&self, w: &parser::ast::With) { for stmt in &w.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for with_items in &w.items { - self.visit_expr(&*&with_items.context_expr); + self.visit_expr(&with_items.context_expr); match &with_items.optional_vars { - Some(items) => self.visit_expr(&items), + Some(items) => self.visit_expr(items), None => (), } } @@ -107,189 +107,189 @@ pub trait TraversalVisitorImmut { fn visit_try(&self, t: &parser::ast::Try) { for stmt in &t.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for stmt in &t.orelse { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for stmt in &t.finalbody { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } // TODO: need to visit exception handler name and type but let's keep it simple for now for handler in &t.handlers { for stmt in &handler.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } } fn visit_try_star(&self, t: &parser::ast::TryStar) { for stmt in &t.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for stmt in &t.orelse { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for stmt in &t.finalbody { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } // TODO: need to visit exception handler name and type but let's keep it simple for now for handler in &t.handlers { for stmt in &handler.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } } fn visit_function_def(&self, f: &parser::ast::FunctionDef) { for stmt in &f.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } fn visit_class_def(&self, c: &parser::ast::ClassDef) { for stmt in &c.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } fn visit_match(&self, m: &parser::ast::Match) { for case in &m.cases { for stmt in &case.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } } - fn visit_constant(&self, c: &Constant) { + fn visit_constant(&self, _c: &Constant) { todo!() } - fn visit_list(&self, l: &List) { + fn visit_list(&self, _l: &List) { todo!() } - fn visit_tuple(&self, t: &Tuple) { + fn visit_tuple(&self, _t: &Tuple) { todo!() } - fn visit_dict(&self, d: &Dict) { + fn visit_dict(&self, _d: &Dict) { todo!() } - fn visit_set(&self, s: &Set) { + fn visit_set(&self, _s: &Set) { todo!() } - fn visit_name(&self, n: &Name) {} - fn visit_bool_op(&self, b: &BoolOperation) { + fn visit_name(&self, _n: &Name) {} + fn visit_bool_op(&self, _b: &BoolOperation) { todo!() } - fn visit_unary_op(&self, u: &UnaryOperation) { + fn visit_unary_op(&self, _u: &UnaryOperation) { todo!() } - fn visit_bin_op(&self, b: &BinOp) { + fn visit_bin_op(&self, _b: &BinOp) { todo!() } - fn visit_named_expr(&self, n: &NamedExpression) { + fn visit_named_expr(&self, _n: &NamedExpression) { todo!() } - fn visit_yield(&self, y: &Yield) { + fn visit_yield(&self, _y: &Yield) { todo!() } - fn visit_yield_from(&self, y: &YieldFrom) { + fn visit_yield_from(&self, _y: &YieldFrom) { todo!() } - fn visit_starred(&self, s: &Starred) { + fn visit_starred(&self, _s: &Starred) { todo!() } - fn visit_generator(&self, g: &Generator) { + fn visit_generator(&self, _g: &Generator) { todo!() } - fn visit_list_comp(&self, l: &ListComp) { + fn visit_list_comp(&self, _l: &ListComp) { todo!() } - fn visit_set_comp(&self, s: &SetComp) { + fn visit_set_comp(&self, _s: &SetComp) { todo!() } - fn visit_dict_comp(&self, d: &DictComp) { + fn visit_dict_comp(&self, _d: &DictComp) { todo!() } - fn visit_attribute(&self, a: &Attribute) { + fn visit_attribute(&self, _a: &Attribute) { todo!() } - fn visit_subscript(&self, s: &Subscript) { + fn visit_subscript(&self, _s: &Subscript) { todo!() } - fn visit_slice(&self, s: &Slice) { + fn visit_slice(&self, _s: &Slice) { todo!() } - fn visit_call(&self, c: &Call) { + fn visit_call(&self, _c: &Call) { todo!() } - fn visit_await(&self, a: &Await) { + fn visit_await(&self, _a: &Await) { todo!() } - fn visit_compare(&self, c: &Compare) { + fn visit_compare(&self, _c: &Compare) { todo!() } - fn visit_lambda(&self, l: &Lambda) { + fn visit_lambda(&self, _l: &Lambda) { todo!() } - fn visit_if_exp(&self, i: &IfExp) { + fn visit_if_exp(&self, _i: &IfExp) { todo!() } - fn visit_joined_str(&self, j: &JoinedStr) { + fn visit_joined_str(&self, _j: &JoinedStr) { todo!() } - fn visit_formatted_value(&self, f: &FormattedValue) { + fn visit_formatted_value(&self, _f: &FormattedValue) { todo!() } - fn visit_alias(&self, a: &Alias) { + fn visit_alias(&self, _a: &Alias) { todo!() } - fn visit_assign(&self, a: &Assign) { + fn visit_assign(&self, _a: &Assign) { todo!() } - fn visit_ann_assign(&self, a: &AnnAssign) { + fn visit_ann_assign(&self, _a: &AnnAssign) { todo!() } - fn visit_aug_assign(&self, a: &AugAssign) { + fn visit_aug_assign(&self, _a: &AugAssign) { todo!() } - fn visit_assert(&self, a: &Assert) { + fn visit_assert(&self, _a: &Assert) { todo!() } - fn visit_pass(&self, p: &Pass) { + fn visit_pass(&self, _p: &Pass) { todo!() } - fn visit_delete(&self, d: &Delete) { + fn visit_delete(&self, _d: &Delete) { todo!() } - fn visit_return(&self, r: &Return) { + fn visit_return(&self, _r: &Return) { todo!() } - fn visit_raise(&self, r: &Raise) { + fn visit_raise(&self, _r: &Raise) { todo!() } - fn visit_break(&self, b: &Break) { + fn visit_break(&self, _b: &Break) { todo!() } - fn visit_continue(&self, c: &Continue) { + fn visit_continue(&self, _c: &Continue) { todo!() } - fn visit_global(&self, g: &Global) { + fn visit_global(&self, _g: &Global) { todo!() } - fn visit_nonlocal(&self, n: &Nonlocal) { + fn visit_nonlocal(&self, _n: &Nonlocal) { todo!() } } diff --git a/typechecker/src/build.rs b/typechecker/src/build.rs index 185a4011..b01f74a2 100644 --- a/typechecker/src/build.rs +++ b/typechecker/src/build.rs @@ -117,7 +117,7 @@ fn snapshot_type_check(source: &str) -> String { ); manager.type_check(); - format!("{}", manager.errors.join("\n")) + manager.errors.join("\n").to_string() } #[cfg(test)] diff --git a/typechecker/src/nodes.rs b/typechecker/src/nodes.rs index 505d9aa4..e9ed5fa5 100755 --- a/typechecker/src/nodes.rs +++ b/typechecker/src/nodes.rs @@ -120,33 +120,33 @@ impl<'a> TraversalVisitor for EnderpyFile { fn visit_if(&mut self, i: &parser::ast::If) { for stmt in &i.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for stmt in &i.orelse { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } fn visit_while(&mut self, w: &parser::ast::While) { for stmt in &w.body { - self.visit_stmt(&stmt) + self.visit_stmt(stmt) } } fn visit_for(&mut self, f: &parser::ast::For) { for stmt in &f.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } fn visit_with(&mut self, w: &parser::ast::With) { for stmt in &w.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for with_items in &w.items { - self.visit_expr(&*&with_items.context_expr); + self.visit_expr(&with_items.context_expr); match &with_items.optional_vars { - Some(items) => self.visit_expr(&items), + Some(items) => self.visit_expr(items), None => (), } } @@ -154,36 +154,36 @@ impl<'a> TraversalVisitor for EnderpyFile { fn visit_try(&mut self, t: &parser::ast::Try) { for stmt in &t.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for stmt in &t.orelse { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for stmt in &t.finalbody { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } // TODO: need to visit exception handler name and type but let's keep it simple for now for handler in &t.handlers { for stmt in &handler.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } } fn visit_try_star(&mut self, t: &parser::ast::TryStar) { for stmt in &t.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for stmt in &t.orelse { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for stmt in &t.finalbody { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } // TODO: need to visit exception handler name and type but let's keep it simple for now for handler in &t.handlers { for stmt in &handler.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } } @@ -201,66 +201,66 @@ impl<'a> TraversalVisitor for EnderpyFile { fn visit_match(&mut self, m: &parser::ast::Match) { for case in &m.cases { for stmt in &case.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } } - fn visit_constant(&mut self, c: &parser::ast::Constant) {} + fn visit_constant(&mut self, _c: &parser::ast::Constant) {} - fn visit_list(&mut self, l: &parser::ast::List) {} + fn visit_list(&mut self, _l: &parser::ast::List) {} - fn visit_tuple(&mut self, t: &parser::ast::Tuple) {} + fn visit_tuple(&mut self, _t: &parser::ast::Tuple) {} - fn visit_dict(&mut self, d: &parser::ast::Dict) {} + fn visit_dict(&mut self, _d: &parser::ast::Dict) {} - fn visit_set(&mut self, s: &parser::ast::Set) {} + fn visit_set(&mut self, _s: &parser::ast::Set) {} - fn visit_name(&mut self, n: &parser::ast::Name) {} + fn visit_name(&mut self, _n: &parser::ast::Name) {} - fn visit_bool_op(&mut self, b: &parser::ast::BoolOperation) {} + fn visit_bool_op(&mut self, _b: &parser::ast::BoolOperation) {} - fn visit_unary_op(&mut self, u: &parser::ast::UnaryOperation) {} + fn visit_unary_op(&mut self, _u: &parser::ast::UnaryOperation) {} - fn visit_bin_op(&mut self, b: &parser::ast::BinOp) {} + fn visit_bin_op(&mut self, _b: &parser::ast::BinOp) {} - fn visit_named_expr(&mut self, n: &parser::ast::NamedExpression) {} + fn visit_named_expr(&mut self, _n: &parser::ast::NamedExpression) {} - fn visit_yield(&mut self, y: &parser::ast::Yield) {} + fn visit_yield(&mut self, _y: &parser::ast::Yield) {} - fn visit_yield_from(&mut self, y: &parser::ast::YieldFrom) {} + fn visit_yield_from(&mut self, _y: &parser::ast::YieldFrom) {} - fn visit_starred(&mut self, s: &parser::ast::Starred) {} + fn visit_starred(&mut self, _s: &parser::ast::Starred) {} - fn visit_generator(&mut self, g: &parser::ast::Generator) {} + fn visit_generator(&mut self, _g: &parser::ast::Generator) {} - fn visit_list_comp(&mut self, l: &parser::ast::ListComp) {} + fn visit_list_comp(&mut self, _l: &parser::ast::ListComp) {} - fn visit_set_comp(&mut self, s: &parser::ast::SetComp) {} + fn visit_set_comp(&mut self, _s: &parser::ast::SetComp) {} - fn visit_dict_comp(&mut self, d: &parser::ast::DictComp) {} + fn visit_dict_comp(&mut self, _d: &parser::ast::DictComp) {} - fn visit_attribute(&mut self, a: &parser::ast::Attribute) {} + fn visit_attribute(&mut self, _a: &parser::ast::Attribute) {} - fn visit_subscript(&mut self, s: &parser::ast::Subscript) {} + fn visit_subscript(&mut self, _s: &parser::ast::Subscript) {} - fn visit_slice(&mut self, s: &parser::ast::Slice) {} + fn visit_slice(&mut self, _s: &parser::ast::Slice) {} - fn visit_call(&mut self, c: &parser::ast::Call) {} + fn visit_call(&mut self, _c: &parser::ast::Call) {} - fn visit_await(&mut self, a: &parser::ast::Await) {} + fn visit_await(&mut self, _a: &parser::ast::Await) {} - fn visit_compare(&mut self, c: &parser::ast::Compare) {} + fn visit_compare(&mut self, _c: &parser::ast::Compare) {} - fn visit_lambda(&mut self, l: &parser::ast::Lambda) {} + fn visit_lambda(&mut self, _l: &parser::ast::Lambda) {} - fn visit_if_exp(&mut self, i: &parser::ast::IfExp) {} + fn visit_if_exp(&mut self, _i: &parser::ast::IfExp) {} - fn visit_joined_str(&mut self, j: &parser::ast::JoinedStr) {} + fn visit_joined_str(&mut self, _j: &parser::ast::JoinedStr) {} - fn visit_formatted_value(&mut self, f: &parser::ast::FormattedValue) {} + fn visit_formatted_value(&mut self, _f: &parser::ast::FormattedValue) {} - fn visit_alias(&mut self, a: &parser::ast::Alias) {} + fn visit_alias(&mut self, _a: &parser::ast::Alias) {} fn visit_assign(&mut self, a: &parser::ast::Assign) { let stmt = a.clone(); @@ -272,23 +272,23 @@ impl<'a> TraversalVisitor for EnderpyFile { self.defs.push(Statement::AnnAssignStatement(stmt)); } - fn visit_aug_assign(&mut self, a: &parser::ast::AugAssign) {} + fn visit_aug_assign(&mut self, _a: &parser::ast::AugAssign) {} - fn visit_assert(&mut self, a: &parser::ast::Assert) {} + fn visit_assert(&mut self, _a: &parser::ast::Assert) {} - fn visit_pass(&mut self, p: &parser::ast::Pass) {} + fn visit_pass(&mut self, _p: &parser::ast::Pass) {} - fn visit_delete(&mut self, d: &parser::ast::Delete) {} + fn visit_delete(&mut self, _d: &parser::ast::Delete) {} - fn visit_return(&mut self, r: &parser::ast::Return) {} + fn visit_return(&mut self, _r: &parser::ast::Return) {} - fn visit_raise(&mut self, r: &parser::ast::Raise) {} + fn visit_raise(&mut self, _r: &parser::ast::Raise) {} - fn visit_break(&mut self, b: &parser::ast::Break) {} + fn visit_break(&mut self, _b: &parser::ast::Break) {} - fn visit_continue(&mut self, c: &parser::ast::Continue) {} + fn visit_continue(&mut self, _c: &parser::ast::Continue) {} - fn visit_global(&mut self, g: &parser::ast::Global) {} + fn visit_global(&mut self, _g: &parser::ast::Global) {} - fn visit_nonlocal(&mut self, n: &parser::ast::Nonlocal) {} + fn visit_nonlocal(&mut self, _n: &parser::ast::Nonlocal) {} } diff --git a/typechecker/src/semanal_utils.rs b/typechecker/src/semanal_utils.rs index 1e16fa70..8b137891 100644 --- a/typechecker/src/semanal_utils.rs +++ b/typechecker/src/semanal_utils.rs @@ -1 +1 @@ -use parser::ast::Expression; + diff --git a/typechecker/src/semantic_analyzer.rs b/typechecker/src/semantic_analyzer.rs index dab4189f..f868d5ba 100644 --- a/typechecker/src/semantic_analyzer.rs +++ b/typechecker/src/semantic_analyzer.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; + use parser::ast::Expression; @@ -24,12 +24,12 @@ pub struct SemanticAnalyzer { impl SemanticAnalyzer { pub fn new(file: Box) -> Self { let globals = SymbolTable::new(crate::symbol_table::SymbolTableType::Module, 0); - return SemanticAnalyzer { + SemanticAnalyzer { globals, file, errors: vec![], scope: SymbolScope::Global, - }; + } } fn create_symbol(&mut self, name: String, decl: Declaration) { @@ -42,7 +42,7 @@ impl SemanticAnalyzer { fn report_unresolved_reference(&mut self) { self.errors - .push(String::from(format!("cannot resolve reference {}", ""))) + .push(format!("cannot resolve reference {}", "")) } fn current_scope(&self) -> &SymbolTableType { @@ -50,7 +50,7 @@ impl SemanticAnalyzer { } fn is_inside_class(&self) -> bool { - return matches!(self.current_scope(), SymbolTableType::Class); + matches!(self.current_scope(), SymbolTableType::Class) } fn create_variable_declaration_symbol( @@ -255,43 +255,43 @@ impl TraversalVisitor for SemanticAnalyzer { } } - fn visit_import(&mut self, i: &parser::ast::Import) { + fn visit_import(&mut self, _i: &parser::ast::Import) { todo!(); } - fn visit_import_from(&mut self, i: &parser::ast::ImportFrom) { + fn visit_import_from(&mut self, _i: &parser::ast::ImportFrom) { todo!(); } fn visit_if(&mut self, i: &parser::ast::If) { for stmt in &i.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for stmt in &i.orelse { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } fn visit_while(&mut self, w: &parser::ast::While) { for stmt in &w.body { - self.visit_stmt(&stmt) + self.visit_stmt(stmt) } } fn visit_for(&mut self, f: &parser::ast::For) { for stmt in &f.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } fn visit_with(&mut self, w: &parser::ast::With) { for stmt in &w.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for with_items in &w.items { - self.visit_expr(&*&with_items.context_expr); + self.visit_expr(&with_items.context_expr); match &with_items.optional_vars { - Some(items) => self.visit_expr(&items), + Some(items) => self.visit_expr(items), None => (), } } @@ -299,36 +299,36 @@ impl TraversalVisitor for SemanticAnalyzer { fn visit_try(&mut self, t: &parser::ast::Try) { for stmt in &t.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for stmt in &t.orelse { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for stmt in &t.finalbody { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } // TODO: need to visit exception handler name and type but let's keep it simple for now for handler in &t.handlers { for stmt in &handler.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } } fn visit_try_star(&mut self, t: &parser::ast::TryStar) { for stmt in &t.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for stmt in &t.orelse { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for stmt in &t.finalbody { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } // TODO: need to visit exception handler name and type but let's keep it simple for now for handler in &t.handlers { for stmt in &handler.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } } @@ -349,7 +349,7 @@ impl TraversalVisitor for SemanticAnalyzer { let mut yeild_statements = vec![]; let mut raise_statements = vec![]; for stmt in &f.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); match &stmt { parser::ast::Statement::Raise(r) => raise_statements.push(r.clone()), parser::ast::Statement::Return(r) => return_statements.push(r.clone()), @@ -391,7 +391,7 @@ impl TraversalVisitor for SemanticAnalyzer { } _ => (), } - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } self.globals.exit_scope(); @@ -405,116 +405,115 @@ impl TraversalVisitor for SemanticAnalyzer { fn visit_match(&mut self, m: &parser::ast::Match) { for case in &m.cases { for stmt in &case.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } } - fn visit_constant(&mut self, c: &parser::ast::Constant) {} + fn visit_constant(&mut self, _c: &parser::ast::Constant) {} - fn visit_list(&mut self, l: &parser::ast::List) { + fn visit_list(&mut self, _l: &parser::ast::List) { todo!() } - fn visit_tuple(&mut self, t: &parser::ast::Tuple) { - return; + fn visit_tuple(&mut self, _t: &parser::ast::Tuple) { } - fn visit_dict(&mut self, d: &parser::ast::Dict) { + fn visit_dict(&mut self, _d: &parser::ast::Dict) { todo!() } - fn visit_set(&mut self, s: &parser::ast::Set) { + fn visit_set(&mut self, _s: &parser::ast::Set) { todo!() } - fn visit_name(&mut self, n: &parser::ast::Name) { + fn visit_name(&mut self, _n: &parser::ast::Name) { todo!() } - fn visit_bool_op(&mut self, b: &parser::ast::BoolOperation) { + fn visit_bool_op(&mut self, _b: &parser::ast::BoolOperation) { todo!() } - fn visit_unary_op(&mut self, u: &parser::ast::UnaryOperation) { + fn visit_unary_op(&mut self, _u: &parser::ast::UnaryOperation) { todo!() } - fn visit_bin_op(&mut self, b: &parser::ast::BinOp) {} + fn visit_bin_op(&mut self, _b: &parser::ast::BinOp) {} - fn visit_named_expr(&mut self, n: &parser::ast::NamedExpression) { + fn visit_named_expr(&mut self, _n: &parser::ast::NamedExpression) { todo!() } - fn visit_yield(&mut self, y: &parser::ast::Yield) { + fn visit_yield(&mut self, _y: &parser::ast::Yield) { todo!() } - fn visit_yield_from(&mut self, y: &parser::ast::YieldFrom) { + fn visit_yield_from(&mut self, _y: &parser::ast::YieldFrom) { todo!() } - fn visit_starred(&mut self, s: &parser::ast::Starred) { + fn visit_starred(&mut self, _s: &parser::ast::Starred) { todo!() } - fn visit_generator(&mut self, g: &parser::ast::Generator) { + fn visit_generator(&mut self, _g: &parser::ast::Generator) { todo!() } - fn visit_list_comp(&mut self, l: &parser::ast::ListComp) { + fn visit_list_comp(&mut self, _l: &parser::ast::ListComp) { todo!() } - fn visit_set_comp(&mut self, s: &parser::ast::SetComp) { + fn visit_set_comp(&mut self, _s: &parser::ast::SetComp) { todo!() } - fn visit_dict_comp(&mut self, d: &parser::ast::DictComp) { + fn visit_dict_comp(&mut self, _d: &parser::ast::DictComp) { todo!() } - fn visit_attribute(&mut self, a: &parser::ast::Attribute) { + fn visit_attribute(&mut self, _a: &parser::ast::Attribute) { todo!() } - fn visit_subscript(&mut self, s: &parser::ast::Subscript) { + fn visit_subscript(&mut self, _s: &parser::ast::Subscript) { todo!() } - fn visit_slice(&mut self, s: &parser::ast::Slice) { + fn visit_slice(&mut self, _s: &parser::ast::Slice) { todo!() } - fn visit_call(&mut self, c: &parser::ast::Call) { + fn visit_call(&mut self, _c: &parser::ast::Call) { todo!() } - fn visit_await(&mut self, a: &parser::ast::Await) { + fn visit_await(&mut self, _a: &parser::ast::Await) { todo!() } - fn visit_compare(&mut self, c: &parser::ast::Compare) { + fn visit_compare(&mut self, _c: &parser::ast::Compare) { todo!() } - fn visit_lambda(&mut self, l: &parser::ast::Lambda) { + fn visit_lambda(&mut self, _l: &parser::ast::Lambda) { todo!() } - fn visit_if_exp(&mut self, i: &parser::ast::IfExp) { + fn visit_if_exp(&mut self, _i: &parser::ast::IfExp) { todo!() } - fn visit_joined_str(&mut self, j: &parser::ast::JoinedStr) { + fn visit_joined_str(&mut self, _j: &parser::ast::JoinedStr) { todo!() } - fn visit_formatted_value(&mut self, f: &parser::ast::FormattedValue) { + fn visit_formatted_value(&mut self, _f: &parser::ast::FormattedValue) { todo!() } - fn visit_alias(&mut self, a: &parser::ast::Alias) { + fn visit_alias(&mut self, _a: &parser::ast::Alias) { todo!() } @@ -553,7 +552,7 @@ impl TraversalVisitor for SemanticAnalyzer { ); if let Some(val) = &a.value { - self.visit_expr(&val); + self.visit_expr(val); } } @@ -562,37 +561,36 @@ impl TraversalVisitor for SemanticAnalyzer { self.visit_expr(&a.value); } - fn visit_assert(&mut self, a: &parser::ast::Assert) { + fn visit_assert(&mut self, _a: &parser::ast::Assert) { todo!() } - fn visit_pass(&mut self, p: &parser::ast::Pass) { - return; + fn visit_pass(&mut self, _p: &parser::ast::Pass) { } - fn visit_delete(&mut self, d: &parser::ast::Delete) { + fn visit_delete(&mut self, _d: &parser::ast::Delete) { todo!() } - fn visit_return(&mut self, r: &parser::ast::Return) {} + fn visit_return(&mut self, _r: &parser::ast::Return) {} - fn visit_raise(&mut self, r: &parser::ast::Raise) { + fn visit_raise(&mut self, _r: &parser::ast::Raise) { todo!() } - fn visit_break(&mut self, b: &parser::ast::Break) { + fn visit_break(&mut self, _b: &parser::ast::Break) { todo!() } - fn visit_continue(&mut self, c: &parser::ast::Continue) { + fn visit_continue(&mut self, _c: &parser::ast::Continue) { todo!() } - fn visit_global(&mut self, g: &parser::ast::Global) { + fn visit_global(&mut self, _g: &parser::ast::Global) { todo!() } - fn visit_nonlocal(&mut self, n: &parser::ast::Nonlocal) { + fn visit_nonlocal(&mut self, _n: &parser::ast::Nonlocal) { todo!() } } diff --git a/typechecker/src/settings.rs b/typechecker/src/settings.rs index 07818c80..2d9441a0 100644 --- a/typechecker/src/settings.rs +++ b/typechecker/src/settings.rs @@ -17,7 +17,7 @@ pub struct Settings { impl Settings { pub fn new() -> Result { - let run_mode = env::var("RUN_MODE").unwrap_or_else(|_| "development".into()); + let _run_mode = env::var("RUN_MODE").unwrap_or_else(|_| "development".into()); let s = Config::builder() // Start off by merging in the "default" configuration file .add_source(File::with_name("examples/hierarchical-env/config/default")) diff --git a/typechecker/src/symbol_table.rs b/typechecker/src/symbol_table.rs index 12b31b95..595b517d 100644 --- a/typechecker/src/symbol_table.rs +++ b/typechecker/src/symbol_table.rs @@ -112,7 +112,7 @@ pub enum SymbolScope { } impl SymbolTable { - pub fn new(symbol_table_type: SymbolTableType, start_line_number: u8) -> Self { + pub fn new(symbol_table_type: SymbolTableType, _start_line_number: u8) -> Self { let global_scope = SymbolTableScope { symbol_table_type, symbols: HashMap::new(), @@ -126,7 +126,7 @@ impl SymbolTable { fn current_scope(&self) -> &SymbolTableScope { if let Some(scope) = self.scopes.last() { - return &scope; + scope } else { panic!("no scopes") } diff --git a/typechecker/src/type_check/checker.rs b/typechecker/src/type_check/checker.rs index 38c6b27a..5e91d2ed 100644 --- a/typechecker/src/type_check/checker.rs +++ b/typechecker/src/type_check/checker.rs @@ -7,7 +7,7 @@ use crate::{ }; use super::{ - type_inference::{self, type_check_bin_op, type_equal}, + type_inference::{self, type_check_bin_op}, types::Type, }; @@ -29,7 +29,7 @@ impl<'a> TypeChecker<'a> { pub fn type_check(&mut self) { for stmt in &self.module.file.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } @@ -131,44 +131,44 @@ impl<'a> TraversalVisitor for TypeChecker<'a> { } } - fn visit_import(&mut self, i: &Import) { + fn visit_import(&mut self, _i: &Import) { todo!(); } - fn visit_import_from(&mut self, i: &ImportFrom) { + fn visit_import_from(&mut self, _i: &ImportFrom) { todo!(); } fn visit_if(&mut self, i: &parser::ast::If) { // self.visit_stmt(i.test); for stmt in &i.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for stmt in &i.orelse { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } fn visit_while(&mut self, w: &parser::ast::While) { for stmt in &w.body { - self.visit_stmt(&stmt) + self.visit_stmt(stmt) } } fn visit_for(&mut self, f: &parser::ast::For) { for stmt in &f.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } fn visit_with(&mut self, w: &parser::ast::With) { for stmt in &w.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for with_items in &w.items { - self.visit_expr(&*&with_items.context_expr); + self.visit_expr(&with_items.context_expr); match &with_items.optional_vars { - Some(items) => self.visit_expr(&items), + Some(items) => self.visit_expr(items), None => (), } } @@ -176,85 +176,85 @@ impl<'a> TraversalVisitor for TypeChecker<'a> { fn visit_try(&mut self, t: &parser::ast::Try) { for stmt in &t.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for stmt in &t.orelse { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for stmt in &t.finalbody { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } // TODO: need to visit exception handler name and type but let's keep it simple for now for handler in &t.handlers { for stmt in &handler.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } } fn visit_try_star(&mut self, t: &parser::ast::TryStar) { for stmt in &t.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for stmt in &t.orelse { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } for stmt in &t.finalbody { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } // TODO: need to visit exception handler name and type but let's keep it simple for now for handler in &t.handlers { for stmt in &handler.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } } fn visit_function_def(&mut self, f: &parser::ast::FunctionDef) { for stmt in &f.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } fn visit_class_def(&mut self, c: &parser::ast::ClassDef) { for stmt in &c.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } fn visit_match(&mut self, m: &parser::ast::Match) { for case in &m.cases { for stmt in &case.body { - self.visit_stmt(&stmt); + self.visit_stmt(stmt); } } } - fn visit_constant(&mut self, c: &Constant) {} + fn visit_constant(&mut self, _c: &Constant) {} - fn visit_list(&mut self, l: &List) { + fn visit_list(&mut self, _l: &List) { todo!() } - fn visit_tuple(&mut self, t: &Tuple) { + fn visit_tuple(&mut self, _t: &Tuple) { todo!() } - fn visit_dict(&mut self, d: &Dict) { + fn visit_dict(&mut self, _d: &Dict) { todo!() } - fn visit_set(&mut self, s: &Set) { + fn visit_set(&mut self, _s: &Set) { todo!() } - fn visit_name(&mut self, n: &Name) {} + fn visit_name(&mut self, _n: &Name) {} - fn visit_bool_op(&mut self, b: &BoolOperation) { + fn visit_bool_op(&mut self, _b: &BoolOperation) { todo!() } - fn visit_unary_op(&mut self, u: &UnaryOperation) { + fn visit_unary_op(&mut self, _u: &UnaryOperation) { todo!() } @@ -272,123 +272,123 @@ impl<'a> TraversalVisitor for TypeChecker<'a> { } } - fn visit_named_expr(&mut self, n: &NamedExpression) { + fn visit_named_expr(&mut self, _n: &NamedExpression) { todo!() } - fn visit_yield(&mut self, y: &Yield) { + fn visit_yield(&mut self, _y: &Yield) { todo!() } - fn visit_yield_from(&mut self, y: &YieldFrom) { + fn visit_yield_from(&mut self, _y: &YieldFrom) { todo!() } - fn visit_starred(&mut self, s: &Starred) { + fn visit_starred(&mut self, _s: &Starred) { todo!() } - fn visit_generator(&mut self, g: &Generator) { + fn visit_generator(&mut self, _g: &Generator) { todo!() } - fn visit_list_comp(&mut self, l: &ListComp) { + fn visit_list_comp(&mut self, _l: &ListComp) { todo!() } - fn visit_set_comp(&mut self, s: &SetComp) { + fn visit_set_comp(&mut self, _s: &SetComp) { todo!() } - fn visit_dict_comp(&mut self, d: &DictComp) { + fn visit_dict_comp(&mut self, _d: &DictComp) { todo!() } - fn visit_attribute(&mut self, a: &Attribute) { + fn visit_attribute(&mut self, _a: &Attribute) { todo!() } - fn visit_subscript(&mut self, s: &Subscript) { + fn visit_subscript(&mut self, _s: &Subscript) { todo!() } - fn visit_slice(&mut self, s: &Slice) { + fn visit_slice(&mut self, _s: &Slice) { todo!() } - fn visit_call(&mut self, c: &Call) { + fn visit_call(&mut self, _c: &Call) { todo!() } - fn visit_await(&mut self, a: &Await) { + fn visit_await(&mut self, _a: &Await) { todo!() } - fn visit_compare(&mut self, c: &Compare) { + fn visit_compare(&mut self, _c: &Compare) { todo!() } - fn visit_lambda(&mut self, l: &Lambda) { + fn visit_lambda(&mut self, _l: &Lambda) { todo!() } - fn visit_if_exp(&mut self, i: &IfExp) { + fn visit_if_exp(&mut self, _i: &IfExp) { todo!() } - fn visit_joined_str(&mut self, j: &JoinedStr) { + fn visit_joined_str(&mut self, _j: &JoinedStr) { todo!() } - fn visit_formatted_value(&mut self, f: &FormattedValue) { + fn visit_formatted_value(&mut self, _f: &FormattedValue) { todo!() } - fn visit_alias(&mut self, a: &Alias) { + fn visit_alias(&mut self, _a: &Alias) { todo!() } - fn visit_assign(&mut self, a: &Assign) {} + fn visit_assign(&mut self, _a: &Assign) {} - fn visit_ann_assign(&mut self, a: &AnnAssign) {} + fn visit_ann_assign(&mut self, _a: &AnnAssign) {} - fn visit_aug_assign(&mut self, a: &AugAssign) { + fn visit_aug_assign(&mut self, _a: &AugAssign) { todo!() } - fn visit_assert(&mut self, a: &Assert) { + fn visit_assert(&mut self, _a: &Assert) { todo!() } - fn visit_pass(&mut self, p: &Pass) { + fn visit_pass(&mut self, _p: &Pass) { todo!() } - fn visit_delete(&mut self, d: &Delete) { + fn visit_delete(&mut self, _d: &Delete) { todo!() } - fn visit_return(&mut self, r: &Return) { + fn visit_return(&mut self, _r: &Return) { todo!() } - fn visit_raise(&mut self, r: &Raise) { + fn visit_raise(&mut self, _r: &Raise) { todo!() } - fn visit_break(&mut self, b: &Break) { + fn visit_break(&mut self, _b: &Break) { todo!() } - fn visit_continue(&mut self, c: &Continue) { + fn visit_continue(&mut self, _c: &Continue) { todo!() } - fn visit_global(&mut self, g: &Global) { + fn visit_global(&mut self, _g: &Global) { todo!() } - fn visit_nonlocal(&mut self, n: &Nonlocal) { + fn visit_nonlocal(&mut self, _n: &Nonlocal) { todo!() } }