From b36dfc64945cf4ce9a2312e284af37ee5da82afa Mon Sep 17 00:00:00 2001 From: Glyphack Date: Sat, 17 Feb 2024 18:27:33 +0100 Subject: [PATCH 1/3] Support getting type for object attributes --- typechecker/src/build.rs | 9 +- typechecker/src/nodes.rs | 1 + typechecker/src/semantic_analyzer.rs | 257 +++++++++--------- typechecker/src/symbol_table.rs | 208 ++++++++------ typechecker/src/type_check/checker.rs | 2 +- typechecker/src/type_check/type_evaluator.rs | 177 ++++++------ typechecker/test_data/inputs/base.py | 7 +- ...sts__symbol_table@class_definition.py.snap | 42 ++- ...symbol_table@simple_var_assignment.py.snap | 4 - ...ild__tests__symbol_table@variables.py.snap | 1 - ...luator__tests__type_evaluator@base.py.snap | 89 +++--- 11 files changed, 444 insertions(+), 353 deletions(-) diff --git a/typechecker/src/build.rs b/typechecker/src/build.rs index 992bbabe..feac7cd2 100755 --- a/typechecker/src/build.rs +++ b/typechecker/src/build.rs @@ -37,7 +37,10 @@ impl BuildManager { let mut builder = Builder::new(); if options.debug { - builder.filter(None, log::LevelFilter::Debug).init(); + builder + .filter(None, log::LevelFilter::Debug) + .format_timestamp(None) + .init(); } else { builder.filter(None, log::LevelFilter::Warn); } @@ -120,6 +123,10 @@ impl BuildManager { } for state in self.modules.iter_mut() { + // do not type check builtins + if state.1.path().ends_with("builtins.pyi") { + continue; + } if !state.1.errors.is_empty() { for err in state.1.errors.iter() { match err { diff --git a/typechecker/src/nodes.rs b/typechecker/src/nodes.rs index 4cdf2c2d..c4e46cd0 100755 --- a/typechecker/src/nodes.rs +++ b/typechecker/src/nodes.rs @@ -116,6 +116,7 @@ impl EnderpyFile { sem_anal.visit_stmt(stmt) } self.symbol_table = sem_anal.symbol_table; + self.symbol_table.current_scope_id = 0; } pub fn get_symbol_table(&self) -> SymbolTable { diff --git a/typechecker/src/semantic_analyzer.rs b/typechecker/src/semantic_analyzer.rs index 8502322a..4735fc86 100644 --- a/typechecker/src/semantic_analyzer.rs +++ b/typechecker/src/semantic_analyzer.rs @@ -11,8 +11,8 @@ use crate::{ import_result::ImportResult, module_descriptor::ImportModuleDescriptor, }, symbol_table::{ - Alias, Class, Declaration, DeclarationPath, Function, Parameter, SymbolFlags, SymbolScope, - SymbolTable, SymbolTableNode, SymbolTableScope, SymbolTableType, TypeAlias, Variable, + Alias, Class, Declaration, DeclarationPath, Function, Parameter, SymbolFlags, SymbolTable, + SymbolTableNode, SymbolTableScope, SymbolTableType, TypeAlias, Variable, }, }; @@ -31,7 +31,6 @@ pub struct SemanticAnalyzer { // TODO: Replace errors with another type errors: Vec, - scope: SymbolScope, is_pyi: bool, } @@ -46,7 +45,6 @@ impl SemanticAnalyzer { file, imports, errors: vec![], - scope: SymbolScope::Global, is_pyi, } } @@ -60,12 +58,11 @@ impl SemanticAnalyzer { self.symbol_table.add_symbol(symbol_node) } - fn current_scope(&self) -> &SymbolTableType { - return self.symbol_table.current_scope_type(); - } - fn is_inside_class(&self) -> bool { - matches!(self.current_scope(), SymbolTableType::Class(_)) + matches!( + self.symbol_table.current_scope().kind, + SymbolTableType::Class(_) + ) } fn create_variable_declaration_symbol( @@ -79,7 +76,6 @@ impl SemanticAnalyzer { Expression::Name(n) => { let decl = Declaration::Variable(Variable { declaration_path, - scope: SymbolScope::Global, type_annotation, inferred_type_source: value, is_constant: false, @@ -102,8 +98,35 @@ impl SemanticAnalyzer { ) } } - // TODO: Fix attribute - Expression::Attribute(_) => {} + Expression::Attribute(a) => { + let member_access_info = get_member_access_info(&self.symbol_table, &a.value); + let symbol_flags = if member_access_info.is_some_and(|x| x) { + SymbolFlags::INSTANCE_MEMBER + } else { + SymbolFlags::CLASS_MEMBER + }; + + if self.function_assigns_attribute(&self.symbol_table) { + let declaration_path = DeclarationPath { + module_name: self.file.path(), + node: a.node, + }; + + let declaration = Declaration::Variable(Variable { + declaration_path, + type_annotation, + inferred_type_source: value, + is_constant: false, + }); + + let symbol_node = SymbolTableNode { + name: a.attr.clone(), + declarations: vec![declaration], + flags: symbol_flags, + }; + self.symbol_table.add_symbol(symbol_node) + } + } // TODO: Add other expressions that can be assigned _ => {} } @@ -216,19 +239,10 @@ impl SemanticAnalyzer { } } - // determines whether a member access expression is referring to a - // member of a class (either a class or instance member). this will - // typically take the form "self.x" or "cls.x". - // returns None if the expression is not a member access expression or - // or true if the member is an instance member and false if it is a class member - fn get_member_access_info(&self, value: &parser::ast::Expression) -> Option { - // TODO: Figure out how to get rid of double dereference - let name = value.as_name()?; - - let value_name = &name.id; - - let current_scope = self.symbol_table.current_scope(); - let Some(FunctionDef { + /// Returns true if the current function assigns an attribute to an object + /// Functions like __init__ and __new__ are considered to assign attributes + fn function_assigns_attribute(&self, symbol_table: &SymbolTable) -> bool { + if let Some(FunctionDef { node, name: fname, args, @@ -237,46 +251,13 @@ impl SemanticAnalyzer { returns, type_comment, type_params, - }) = current_scope.kind.as_function() - else { - return None; - }; - - let Some(parent_scope) = self.symbol_table.parent_scope() else { - return None; - }; - - let Some(enclosing_class) = parent_scope.kind.as_class() else { - return None; - }; - - let first_arg = args.args.first()?; - - let is_value_equal_to_first_arg = value_name == first_arg.arg.as_str(); - - if !is_value_equal_to_first_arg { - return None; - } - - // Check if one of the decorators is a classmethod or staticmethod - let mut is_class_member = false; - for decorator in decorator_list { - if let parser::ast::Expression::Call(call) = decorator { - if let Some(name) = call.func.as_name() { - if name.id == "classmethod" { - is_class_member = true; - } - } + }) = symbol_table.current_scope().kind.as_function() + { + if fname == "__init__" || fname == "__new__" { + return true; } } - - // e.g. "MyClass.x" - - if value_name == enclosing_class.name.as_str() || is_class_member { - Some(false) - } else { - Some(true) - } + return false; } } @@ -491,6 +472,26 @@ impl TraversalVisitor for SemanticAnalyzer { module_name: self.file.path(), node: f.node, }; + if f.type_params.len() > 0 { + // TODO + // Push a PEP 695 scope + // https://www.python.org/dev/peps/pep-0695/ + // for type_parameter in &f.type_params { + // let declaration_path = DeclarationPath { + // module_name: self.file.path(), + // node: type_parameter.get_node(), + // }; + // let flags = SymbolFlags::empty(); + // self.create_symbol( + // type_parameter.get_name(), + // Declaration::TypeParameter(crate::symbol_table::TypeParameter { + // declaration_path, + // type_parameter_node: type_parameter.clone(), + // }), + // flags, + // ); + // } + } self.symbol_table.push_scope(SymbolTableScope::new( crate::symbol_table::SymbolTableType::Function(f.clone()), f.name.clone(), @@ -569,13 +570,10 @@ impl TraversalVisitor for SemanticAnalyzer { _f.node.start, self.symbol_table.current_scope_id, )); + self.symbol_table.exit_scope(); } fn visit_class_def(&mut self, c: &parser::ast::ClassDef) { - let declaration_path = DeclarationPath { - module_name: self.file.path(), - node: c.node, - }; self.symbol_table.push_scope(SymbolTableScope::new( SymbolTableType::Class(c.clone()), c.name.clone(), @@ -599,27 +597,10 @@ impl TraversalVisitor for SemanticAnalyzer { ); } let mut methods = vec![]; - let mut attributes = HashMap::new(); - // TODO: Move off to function visitor for stmt in &c.body { if let parser::ast::Statement::FunctionDef(f) = stmt { - if f.name == "__init__" { - for stmt in &f.body { - if let parser::ast::Statement::AssignStatement(assign) = stmt { - for target in &assign.targets { - if let parser::ast::Expression::Attribute(attr) = target { - if let parser::ast::Expression::Name(ref n) = *attr.value { - if n.id == "self" { - attributes - .insert(attr.attr.clone(), assign.value.clone()); - } - } - } - } - } - } - } + // TODO: Maybe define these methods in the symbol table at this point? methods.push(f.name.clone()); } self.visit_stmt(stmt); @@ -627,13 +608,7 @@ impl TraversalVisitor for SemanticAnalyzer { self.symbol_table.exit_scope(); - let class_declaration = Declaration::Class(Class { - name: c.name.clone(), - declaration_path, - attributes, - methods, - special: false, - }); + let class_declaration = Declaration::Class(Class::new(c.clone(), methods)); let flags = SymbolFlags::empty(); self.create_symbol(c.name.clone(), class_declaration, flags); } @@ -685,42 +660,7 @@ impl TraversalVisitor for SemanticAnalyzer { fn visit_dict_comp(&mut self, _d: &parser::ast::DictComp) {} // Imagine it's always store - fn visit_attribute(&mut self, a: &parser::ast::Attribute) { - let member_access_info = self.get_member_access_info(&a.value); - let symbol_flags = if member_access_info.is_some_and(|x| x) { - SymbolFlags::INSTANCE_MEMBER - } else { - SymbolFlags::CLASS_MEMBER - }; - - // TODO: Only create symbols in class body or init method - let declaration_path = DeclarationPath { - module_name: self.file.path(), - node: a.node, - }; - - let declaration = Declaration::Variable(Variable { - declaration_path, - scope: SymbolScope::Global, - type_annotation: None, - inferred_type_source: None, - is_constant: false, - }); - - let attribute_name_node = a.value.as_name(); - - let name = match attribute_name_node { - Some(name) => name.id.clone(), - None => return, - }; - - let symbol_node = SymbolTableNode { - name, - declarations: vec![declaration], - flags: symbol_flags, - }; - self.symbol_table.add_symbol(symbol_node) - } + fn visit_attribute(&mut self, a: &parser::ast::Attribute) {} fn visit_subscript(&mut self, _s: &parser::ast::Subscript) {} @@ -809,3 +749,64 @@ impl TraversalVisitor for SemanticAnalyzer { fn visit_nonlocal(&mut self, _n: &parser::ast::Nonlocal) {} } + +pub struct MemberAccessInfo {} + +// determines whether a member access expression is referring to a +// member of a class (either a class or instance member). this will +// typically take the form "self.x" or "cls.x". +// returns None if the expression is not a member access expression or +// or true if the member is an instance member and false if it is a class member +pub fn get_member_access_info( + symbol_table: &SymbolTable, + value: &parser::ast::Expression, +) -> Option { + let name = value.as_name()?; + + let value_name = &name.id; + + let current_scope = symbol_table.current_scope(); + let Some(FunctionDef { + args, + decorator_list, + .. + }) = current_scope.kind.as_function() + else { + return None; + }; + + let Some(parent_scope) = symbol_table.parent_scope(symbol_table.current_scope()) else { + return None; + }; + + let Some(enclosing_class) = parent_scope.kind.as_class() else { + return None; + }; + + let first_arg = args.args.first()?; + + let is_value_equal_to_first_arg = value_name == first_arg.arg.as_str(); + + if !is_value_equal_to_first_arg { + return None; + } + + // Check if one of the decorators is a classmethod or staticmethod + let mut is_class_member = false; + for decorator in decorator_list { + if let parser::ast::Expression::Call(call) = decorator { + if let Some(name) = call.func.as_name() { + if name.id == "classmethod" { + is_class_member = true; + } + } + } + } + + // e.g. "MyClass.x = 1" + if value_name == enclosing_class.name.as_str() || is_class_member { + Some(false) + } else { + Some(true) + } +} diff --git a/typechecker/src/symbol_table.rs b/typechecker/src/symbol_table.rs index 6a5d019a..193c702c 100644 --- a/typechecker/src/symbol_table.rs +++ b/typechecker/src/symbol_table.rs @@ -12,7 +12,7 @@ pub struct SymbolTable { // after building symbol table is finished this only contains the most outer scope scopes: Vec, - prev_scope: Option, + prev_scope_id: Option, pub current_scope_id: usize, /// Name of the module that this symbol table is for @@ -94,6 +94,12 @@ pub struct SymbolTableNode { pub flags: SymbolFlags, } +impl Display for SymbolTableNode { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:#?}", self.name) + } +} + #[derive(Debug, Clone)] pub struct DeclarationPath { pub module_name: PathBuf, @@ -149,7 +155,6 @@ impl Display for DeclarationPath { #[derive(Debug, Clone)] pub struct Variable { pub declaration_path: DeclarationPath, - pub scope: SymbolScope, pub type_annotation: Option, pub inferred_type_source: Option, pub is_constant: bool, @@ -192,16 +197,39 @@ pub struct Class { // Method names, can be used to look up the function in the symbol table // of the class pub methods: Vec, - // instance attributes that are defined in the __init__ method - // if the attribute is referencing another symbol we need to look up that symbol in the - // __init__ method - pub attributes: HashMap, - // Special classes are classes that are _SpecialForm in typeshed. // These classes have their behavior defined in PEPs so we need to handle them differently pub special: bool, } +impl Class { + pub fn new(class_node: ast::ClassDef, methods: Vec) -> Self { + Class { + name: class_node.name.clone(), + declaration_path: DeclarationPath { + module_name: PathBuf::new(), + node: Node { + start: class_node.node.start, + end: class_node.node.end, + }, + }, + methods, + special: false, + } + } + + /// Class node refers to SpecialForm in typeshed + /// TODO: needs improvements mostly set the correct values + pub fn new_special(name: String, special_class: Class) -> Self { + Class { + name, + declaration_path: special_class.declaration_path, + methods: special_class.methods, + special: true, + } + } +} + #[derive(Debug, Clone)] pub struct Parameter { pub declaration_path: DeclarationPath, @@ -241,20 +269,12 @@ pub struct LookupSymbolRequest { pub position: Option, } -#[derive(Debug, Clone, Copy)] -pub enum SymbolScope { - Global, - Nonlocal, - Local, - Unknown, -} - impl SymbolTable { pub fn new(module_name: String, file_path: PathBuf) -> Self { SymbolTable { scopes: vec![SymbolTableScope::global_scope()], current_scope_id: 0, - prev_scope: None, + prev_scope_id: None, module_name, file_path, } @@ -284,17 +304,27 @@ impl SymbolTable { } } - pub fn parent_scope(&self) -> Option<&SymbolTableScope> { - if let Some(scope) = self - .scopes - .iter() - .filter(|scope| scope.id == self.current_scope().parent.unwrap_or(0)) - .last() - { - Some(scope) - } else { - None - } + /// Returns the parent scope of the current scope + pub fn parent_scope(&self, scope: &SymbolTableScope) -> Option<&SymbolTableScope> { + let parent_id = scope.parent?; + return Some( + self.scopes + .iter() + .filter(|scope| scope.id == parent_id) + .last() + .expect("parent scope id not found in scopes"), + ); + } + + pub fn parent_scope_mut(&mut self, scope: &SymbolTableScope) -> Option<&mut SymbolTableScope> { + let parent_id = scope.parent?; + return Some( + self.scopes + .iter_mut() + .filter(|scope| scope.id == parent_id) + .last() + .expect("parent scope id not found in scopes"), + ); } pub fn current_scope_mut(&mut self) -> &mut SymbolTableScope { @@ -305,45 +335,49 @@ impl SymbolTable { .expect("no current scope") } - pub fn current_scope_type(&self) -> &SymbolTableType { - return &self.current_scope().kind; + pub fn get_scope_by_id(&self, id: usize) -> Option<&SymbolTableScope> { + self.scopes.iter().filter(|scope| scope.id == id).last() } - /// Returns scopes until the given position - /// the scopes are sorted by start position descending - pub fn innermost_scope(&self, pos: usize) -> &SymbolTableScope { - log::debug!("looking for innermost scope"); - let scope = self.current_scope(); - if pos == 90 { - log::debug!("scopes: {:#?}", scope); + pub fn get_scope_mut_by_id(&mut self, id: usize) -> Option<&mut SymbolTableScope> { + self.scopes.iter_mut().filter(|scope| scope.id == id).last() + } + + pub fn get_enclosing_class_scope(&self) -> Option<&SymbolTableScope> { + let mut scope = self.current_scope(); + loop { + if let SymbolTableType::Class(_) = scope.kind { + return Some(scope); + } + scope = if let Some(parent) = self.parent_scope(scope) { + parent + } else { + break; + } } + None + } - scope + pub fn current_scope_type(&self) -> &SymbolTableType { + return &self.current_scope().kind; } - /// get innermost scope that contains that line /// search for symbol in that scope /// if not found search in parent scope /// continue until found or no parent scope /// TODO: This function does not work on the literal test pub fn lookup_in_scope(&self, lookup_request: LookupSymbolRequest) -> Option<&SymbolTableNode> { - let mut innermost_scope = Some(self.innermost_scope(0)); - while let Some(scope) = innermost_scope { - log::debug!("looking in scope: {:?}", scope.name); + let mut scope = self.current_scope(); + log::debug!("All symbols in scope: {:?}", scope.symbols.keys()); + loop { + // log::debug!("looking in scope: {:?}", scope.name); if let Some(symbol) = scope.symbols.get(&lookup_request.name) { return Some(symbol); } - // We reach the global scope - if scope.parent.is_none() { - break; - } - innermost_scope = if let Some(parent_id) = scope.parent { - self.scopes - .iter() - .filter(|scope| scope.id == parent_id) - .last() + scope = if let Some(parent) = self.parent_scope(scope) { + parent } else { - Some(self.global_scope()) + break; } } None @@ -357,17 +391,25 @@ impl SymbolTable { /// Sets the current scope to the scope that starts at the given position pub fn set_scope(&mut self, pos: usize) { - self.prev_scope = Some(self.current_scope_id); + self.prev_scope_id = Some(self.current_scope_id); let scope = self.scopes.iter().find(|scope| scope.start_pos == pos); if let Some(scope) = scope { self.current_scope_id = scope.id; } else { panic!("no scope found for position: {}", pos); } + log::debug!("Set scope to: {}", self.current_scope_id); + } + + pub fn get_scope(&self, node: &Node) -> Option<&SymbolTableScope> { + self.scopes + .iter() + .find(|scope| scope.start_pos == node.start) } pub fn revert_scope(&mut self) { - self.current_scope_id = self.prev_scope.expect("no previous scope"); + self.current_scope_id = self.prev_scope_id.expect("no previous scope"); + log::debug!("Reverted scope to: {}", self.current_scope_id); } pub fn global_scope(&self) -> &SymbolTableScope { @@ -386,7 +428,24 @@ impl SymbolTable { } pub fn add_symbol(&mut self, mut symbol_node: SymbolTableNode) { - let scope = self.current_scope_mut(); + log::debug!("Adding symbol: {:?}", symbol_node.name); + let scope = if symbol_node.flags.contains(SymbolFlags::CLASS_MEMBER) + || symbol_node.flags.contains(SymbolFlags::INSTANCE_MEMBER) + { + log::debug!("Finding the class scope that symbol belongs to"); + let mut scope = self.current_scope(); + while !matches!(scope.kind, SymbolTableType::Class(_)) { + match self.parent_scope(scope) { + Some(parent) => scope = parent, + None => panic!("tried to assign to self outside of a class scope"), + } + } + self.get_scope_mut_by_id(scope.id).expect("no scope found") + } else { + self.current_scope_mut() + }; + + log::debug!("Adding symbol {} to scope: {:?}", symbol_node, scope.name); if let Some(existing_symbol) = scope.symbols.get(&symbol_node.name) { symbol_node .declarations @@ -403,30 +462,25 @@ impl SymbolTable { /// Looks up an attribute in the current scope and its parents /// Attributes must have symbol flags CLASS_MEMBER or INSTANCE_MEMBER - pub(crate) fn lookup_attribute(&self, attr: String) -> Option<&SymbolTableNode> { - let mut innermost_scope = Some(self.innermost_scope(0)); - while let Some(scope) = innermost_scope { - log::debug!("looking for attribute in scope: {:?}", scope.name); - if let Some(symbol) = scope.symbols.get(&attr) { - if symbol.flags.contains(SymbolFlags::CLASS_MEMBER) - || symbol.flags.contains(SymbolFlags::INSTANCE_MEMBER) - { - return Some(symbol); - } - } - // We reach the global scope - if scope.parent.is_none() { - break; - } - innermost_scope = if let Some(parent_id) = scope.parent { - self.scopes - .iter() - .filter(|scope| scope.id == parent_id) - .last() - } else { - Some(self.global_scope()) - } + pub(crate) fn lookup_attribute<'a>( + &'a self, + attr: &str, + scope: &'a SymbolTableScope, + ) -> Option<&SymbolTableNode> { + log::debug!( + "looking for attribute {:#?} in scope: {}", + attr, + &scope.name + ); + if let Some(symbol) = scope.symbols.get(attr) { + // if symbol.flags.contains(SymbolFlags::CLASS_MEMBER) + // || symbol.flags.contains(SymbolFlags::INSTANCE_MEMBER) + // { + // return Some(symbol); + // } + return Some(symbol); } + log::debug!("attribute not found"); None } } diff --git a/typechecker/src/type_check/checker.rs b/typechecker/src/type_check/checker.rs index 709a69d7..ebdb6e12 100644 --- a/typechecker/src/type_check/checker.rs +++ b/typechecker/src/type_check/checker.rs @@ -27,8 +27,8 @@ impl<'a> TypeChecker<'a> { options: &'a Settings, symbol_tables: Vec, ) -> Self { + log::debug!("Type checking module: {}", module.module_name()); let mut symbol_table = module.get_symbol_table(); - symbol_table.current_scope_id = 0; TypeChecker { errors: vec![], options, diff --git a/typechecker/src/type_check/type_evaluator.rs b/typechecker/src/type_check/type_evaluator.rs index a2be398f..8c1c84de 100755 --- a/typechecker/src/type_check/type_evaluator.rs +++ b/typechecker/src/type_check/type_evaluator.rs @@ -19,6 +19,7 @@ use crate::{ ast_visitor_generic::TraversalVisitorImmutGeneric, diagnostic::Position, nodes::EnderpyFile, + semantic_analyzer::get_member_access_info, symbol_table::{self, Class, Declaration, LookupSymbolRequest, SymbolTable, SymbolTableNode}, type_check::types::ClassType, }; @@ -48,7 +49,7 @@ impl TypeEvaluator { /// the declaration to this function. To get the type of an annotation /// expression use get_type_from_annotation pub fn get_type(&self, expr: &ast::Expression) -> Result { - log::debug!("get_type: {:?}", expr); + log::debug!("get_type: {:#?}", expr); let r = match expr { ast::Expression::Constant(c) => { let typ = match &c.value { @@ -66,55 +67,16 @@ impl TypeEvaluator { Ok(typ) } ast::Expression::Name(n) => { + if let Some(t) = self.get_builtin_type(&n.id) { + return Ok(t); + } self.infer_type_from_symbol_table(&n.id, Some(n.node.start)) } ast::Expression::Call(call) => { let called_name = *call.func.clone(); - match called_name { - ast::Expression::Name(n) => { - // check if name is one of the builtins - if let Some(t) = self.get_builtin_type(&n.id) { - return Ok(t); - } - let lookup_request = LookupSymbolRequest { - name: n.id, - position: None, - }; - let f_type = - self.symbol_table - .lookup_in_scope(lookup_request) - .map(|symbol| { - let decl = symbol.last_declaration(); - - if let Some(class) = decl.as_class() { - PythonType::Class(ClassType { - details: class.clone(), - type_parameters: vec![], - }) - } else if let Some(func) = decl.as_function() { - return PythonType::Callable(Box::new(CallableType { - name: func.function_node.name.clone(), - arguments: func.function_node.args.clone(), - return_type: PythonType::Unknown, - })); - } else { - // TODO: Error type is not callable - return PythonType::Unknown; - } - }); - - log::debug!("f_type: {:?}", f_type); - match f_type { - Some(t) => Ok(t), - None => Ok(PythonType::Unknown), - } - } - ast::Expression::Attribute(_a) => Ok(PythonType::Unknown), - _ => { - debug!("infer type from call not implemented"); - Ok(PythonType::Unknown) - } - } + let f_type = self.get_type(&called_name)?; + log::debug!("f_type: {:?}", f_type); + Ok(f_type) } ast::Expression::List(l) => { let final_elm_type = self.get_sequence_type_from_elements(&l.elements); @@ -221,21 +183,85 @@ impl TypeEvaluator { ast::Expression::ListComp(_) => Ok(PythonType::Unknown), ast::Expression::SetComp(_) => Ok(PythonType::Unknown), ast::Expression::DictComp(_) => Ok(PythonType::Unknown), + /* + When attribute is accessed there are multilple cases: + + 1. Accessing an attribute of a class inside the class through self + ``` + class A: + def __init__(self): + self.a = 1 + def get_a(self): + return self.a + + # or a class method + @class_method + def class_method(cls): + return cls.a + ``` + + 2. Accessing an attribute of a class outside the class + ``` + class A: + def __init__(self): + self.a = 1 + a = A() + print(a.a) + ``` + */ ast::Expression::Attribute(a) => { - let Some(name) = a.value.as_name() else { - return Ok(PythonType::Unknown); + // Case 1 + log::debug!("Attribute access {:#?}", a); + if get_member_access_info(&self.symbol_table, &a.value).is_some() { + let enclosing_parent_class = self.symbol_table.get_enclosing_class_scope(); + if let Some(enclosing_parent_class) = enclosing_parent_class { + let symbol_table_node = self + .symbol_table + .lookup_attribute(&a.attr, &enclosing_parent_class); + let res = match symbol_table_node { + Some(node) => self.get_symbol_node_type(&node, None), + None => panic!("cannot find symbol table node for attribute access"), + }; + + log::debug!("attribute access result: {:?}", res); + + return res; + } + } + + // Case 2 + // First find the type of the attribute and then find the value in the scope of the attribute + + let value_type = match self.get_type(&a.value) { + Ok(t) => t, + Err(e) => { + log::debug!("error getting type of attribute value: {:?}", e); + return Ok(PythonType::Unknown); + } }; + log::debug!("checking type for expression: {:#?}", a); + log::debug!("looking up attribute in type: {:?}", value_type); + match value_type { + PythonType::Class(c) => { + let class_scope = self + .symbol_table + .get_scope(&c.details.declaration_path.node) + .expect("cannot find class scope for attribute access"); + + log::debug!("class scope for the attribute: {:#?}", class_scope); + let symbol_table_node = + self.symbol_table.lookup_attribute(&a.attr, class_scope); + log::debug!("found symbol table node: {:#?}", symbol_table_node); + let result = match symbol_table_node { + Some(node) => self.get_symbol_node_type(&node, None), + None => Ok(PythonType::Unknown), + }; - // TODO: support other attributes - if name.id == "self" { - // Lookup the attribute in the class in symbol table - let attr = self.symbol_table.lookup_attribute(a.attr.clone()); - return match attr { - Some(attr) => self.get_symbol_node_type(attr, None), - None => Ok(PythonType::Unknown), - }; + log::debug!("attribute access result: {:?}", result); + result + } + _ => Ok(PythonType::Unknown), } - Ok(PythonType::Unknown) } ast::Expression::BinOp(b) => Ok(self.bin_op_result_type( &self.get_type(&b.left)?, @@ -256,7 +282,7 @@ impl TypeEvaluator { ast::Expression::FormattedValue(f) => self.get_type(&f.value), }; - log::debug!("get_type result: {:?}", r); + log::debug!("get_type for expression: {:#?} => {:?}", expr, r); r } @@ -358,8 +384,8 @@ impl TypeEvaluator { None => Some(symbol.last_declaration()), }; - log::debug!("fetch symbol declaration: {:?}", decl); - match decl { + log::debug!("found {} declaration: {:#?}", symbol, decl); + let result = match decl { Some(decl) => match decl { Declaration::Variable(v) => { if let Some(type_annotation) = &v.type_annotation { @@ -406,7 +432,14 @@ impl TypeEvaluator { Declaration::Class(c) => Ok(PythonType::Class(ClassType::new(c.clone(), vec![]))), }, None => Ok(PythonType::Any), - } + }; + + log::debug!( + "evaluated type based on declaration: {} => {:?}", + symbol, + result + ); + result } fn get_sequence_type_from_elements(&self, elements: &Vec) -> PythonType { @@ -781,18 +814,12 @@ impl TypeEvaluator { let pointing_class = match &v.type_annotation { Some(annotation) => { - if let ast::Expression::Name(name) = annotation { - if name.id == SPECIAL_FORM { - return Some(Class { - name: n.id.clone(), - declaration_path: v.declaration_path.clone(), - methods: vec![], - attributes: HashMap::new(), - special: true, - }); - } + let class = self + .get_class_declaration(annotation, found_in_symbol_table)?; + if class.name == SPECIAL_FORM { + return Some(Class::new_special(n.id.clone(), class)); } - self.get_class_declaration(annotation, found_in_symbol_table) + Some(class) } None => { todo!("Variable declaration without type annotation") @@ -1157,7 +1184,7 @@ impl DumpTypes { /// This function is called on every expression in the ast pub fn save_type(&mut self, expr: &ast::Expression) { let typ = self.type_eval.get_type(expr).unwrap_or(PythonType::Unknown); - log::debug!("save_type: {:?} => {:?}", expr, typ); + log::debug!("save_type: {:#?} => {:#?}", expr, typ); let symbol_text = self.enderpy_file().source()[expr.get_node().start..expr.get_node().end].to_string(); let position = self.enderpy_file().get_position(expr.get_node().start); @@ -1289,7 +1316,7 @@ impl TraversalVisitor for DumpTypes { ast::Expression::ListComp(l) => (), ast::Expression::SetComp(s) => (), ast::Expression::DictComp(d) => (), - ast::Expression::Attribute(a) => (), + ast::Expression::Attribute(a) => {} ast::Expression::Subscript(s) => (), ast::Expression::Slice(s) => (), ast::Expression::Call(c) => { @@ -1341,8 +1368,6 @@ mod tests { let module = manager.get_state("test-file".into()).unwrap(); let mut symbol_table = module.get_symbol_table(); - // this is duplicated - symbol_table.current_scope_id = 0; let type_eval = TypeEvaluator { symbol_table, diff --git a/typechecker/test_data/inputs/base.py b/typechecker/test_data/inputs/base.py index 6e117957..a7b2bb33 100644 --- a/typechecker/test_data/inputs/base.py +++ b/typechecker/test_data/inputs/base.py @@ -4,6 +4,7 @@ d = False a + int(b) + a + c def func(param1: int) -> int: @@ -14,7 +15,7 @@ class C: def __init__(self, x: int): print(self.cls_attribute) - self.x = x + self.x = float(x) print(self.x) def add(self, value: int): @@ -23,7 +24,7 @@ def add(self, value: int): def get_attr(self) -> int: return self.cls_attribute - def get_x(self) -> int: + def get_x(self) -> float: return self.x t = C(0) @@ -37,4 +38,4 @@ def get_x(self) -> int: d = {"a": 1, "b": 2} s = {1,2,3} -l.append(1) +# l.append(1) diff --git a/typechecker/test_data/output/enderpy_python_type_checker__build__tests__symbol_table@class_definition.py.snap b/typechecker/test_data/output/enderpy_python_type_checker__build__tests__symbol_table@class_definition.py.snap index 4dcb596d..f900668b 100644 --- a/typechecker/test_data/output/enderpy_python_type_checker__build__tests__symbol_table@class_definition.py.snap +++ b/typechecker/test_data/output/enderpy_python_type_checker__build__tests__symbol_table@class_definition.py.snap @@ -18,7 +18,6 @@ SymbolFlags( end: 46, }, }, - scope: Global, type_annotation: None, inferred_type_source: Some( Constant( @@ -46,7 +45,6 @@ SymbolFlags( end: 60, }, }, - scope: Global, type_annotation: None, inferred_type_source: Some( Name( @@ -234,27 +232,22 @@ SymbolFlags( yield_statements: [], raise_statements: [], } - -Symbols in global (id: [REDACTED]) c SymbolFlags( - 0x0, + INSTANCE_MEMBER, ) - Declarations: ---: Class { - name: "c", +--: Variable { declaration_path: DeclarationPath { module_name: "[TYPECHECKER]/test_data/inputs/symbol_table/class_definition.py", node: Node { - start: 0, - end: 80, + start: 69, + end: 75, }, }, - methods: [ - "__init__", - ], - attributes: { - "c": Name( + type_annotation: None, + inferred_type_source: Some( + Name( Name { node: Node { start: 78, @@ -263,7 +256,28 @@ SymbolFlags( id: "b", }, ), + ), + is_constant: false, +} + +Symbols in global (id: [REDACTED]) +c +SymbolFlags( + 0x0, +) +- Declarations: +--: Class { + name: "c", + declaration_path: DeclarationPath { + module_name: "", + node: Node { + start: 0, + end: 80, + }, }, + methods: [ + "__init__", + ], special: false, } diff --git a/typechecker/test_data/output/enderpy_python_type_checker__build__tests__symbol_table@simple_var_assignment.py.snap b/typechecker/test_data/output/enderpy_python_type_checker__build__tests__symbol_table@simple_var_assignment.py.snap index 8a203fe8..56b7c137 100644 --- a/typechecker/test_data/output/enderpy_python_type_checker__build__tests__symbol_table@simple_var_assignment.py.snap +++ b/typechecker/test_data/output/enderpy_python_type_checker__build__tests__symbol_table@simple_var_assignment.py.snap @@ -18,7 +18,6 @@ SymbolFlags( end: 17, }, }, - scope: Global, type_annotation: None, inferred_type_source: Some( Constant( @@ -46,7 +45,6 @@ SymbolFlags( end: 29, }, }, - scope: Global, type_annotation: None, inferred_type_source: Some( BinOp( @@ -92,7 +90,6 @@ SymbolFlags( end: 41, }, }, - scope: Global, type_annotation: Some( Name( Name { @@ -130,7 +127,6 @@ SymbolFlags( end: 59, }, }, - scope: Global, type_annotation: Some( Name( Name { diff --git a/typechecker/test_data/output/enderpy_python_type_checker__build__tests__symbol_table@variables.py.snap b/typechecker/test_data/output/enderpy_python_type_checker__build__tests__symbol_table@variables.py.snap index 530fc779..e952955d 100644 --- a/typechecker/test_data/output/enderpy_python_type_checker__build__tests__symbol_table@variables.py.snap +++ b/typechecker/test_data/output/enderpy_python_type_checker__build__tests__symbol_table@variables.py.snap @@ -18,7 +18,6 @@ SymbolFlags( end: 5, }, }, - scope: Global, type_annotation: None, inferred_type_source: Some( Constant( diff --git a/typechecker/test_data/output/enderpy_python_type_checker__type_check__type_evaluator__tests__type_evaluator@base.py.snap b/typechecker/test_data/output/enderpy_python_type_checker__type_check__type_evaluator__tests__type_evaluator@base.py.snap index a61568ca..d8f16077 100644 --- a/typechecker/test_data/output/enderpy_python_type_checker__type_check__type_evaluator__tests__type_evaluator@base.py.snap +++ b/typechecker/test_data/output/enderpy_python_type_checker__type_check__type_evaluator__tests__type_evaluator@base.py.snap @@ -1,141 +1,134 @@ --- source: typechecker/src/type_check/type_evaluator.rs -description: "1: a = 1\n2: b = \"1\"\n3: c = True\n4: d = False\n5: a + int(b)\n6: \n7: a + c\n8: \n9: def func(param1: int) -> int:\n10: \treturn param1 + a\n11: \n12: class C:\n13: \tcls_attribute = 1\n14: \n15: \tdef __init__(self, x: int):\n16: \t\tprint(self.cls_attribute)\n17: \t\tself.x = x\n18: \t\tprint(self.x)\n19: \n20: \tdef add(self, value: int):\n21: \t\tself.cls_attribute += value\n22: \n23: \tdef get_attr(self) -> int:\n24: \t\treturn self.cls_attribute\n25: \n26: \tdef\tget_x(self) -> int:\n27: \t\treturn self.x\n28: \n29: t = C(0)\n30: t.add(2)\n31: t.cls_attribute\n32: t.x\n33: t.get_x()\n34: t.get_attr()\n35: \n36: l = [1,2,3]\n37: d = {\"a\": 1, \"b\": 2}\n38: s = {1,2,3}\n39: \n40: l.append(1)\n" +description: "1: a = 1\n2: b = \"1\"\n3: c = True\n4: d = False\n5: a + int(b)\n6: \n7: \n8: a + c\n9: \n10: def func(param1: int) -> int:\n11: \treturn param1 + a\n12: \n13: class C:\n14: \tcls_attribute = 1\n15: \n16: \tdef __init__(self, x: int):\n17: \t\tprint(self.cls_attribute)\n18: \t\tself.x = float(x)\n19: \t\tprint(self.x)\n20: \n21: \tdef add(self, value: int):\n22: \t\tself.cls_attribute += value\n23: \n24: \tdef get_attr(self) -> int:\n25: \t\treturn self.cls_attribute\n26: \n27: \tdef\tget_x(self) -> float:\n28: \t\treturn self.x\n29: \n30: t = C(0)\n31: t.add(2)\n32: t.cls_attribute\n33: t.x\n34: t.get_x()\n35: t.get_attr()\n36: \n37: l = [1,2,3]\n38: d = {\"a\": 1, \"b\": 2}\n39: s = {1,2,3}\n40: \n41: # l.append(1)\n" expression: result input_file: typechecker/test_data/inputs/base.py --- Line 1: a = 1 Expr types in the line --->: - "1" => Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: [TYPESHED].stdlib/builtins.pyi", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], attributes: {}, special: false }, type_parameters: [] }) + "1" => Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: "", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], special: false }, type_parameters: [] }) --- Line 2: b = "1" Expr types in the line --->: - "\"1\"" => Class(ClassType { details: Class { name: "str", declaration_path: DeclarationPath { module_name: [TYPESHED].stdlib/builtins.pyi", node: Node { start: 17176, end: 25985 } }, methods: ["__new__", "__new__", "capitalize", "capitalize", "casefold", "casefold", "center", "center", "count", "encode", "endswith", "find", "format", "format", "format_map", "index", "isalnum", "isalpha", "isascii", "isdecimal", "isdigit", "isidentifier", "islower", "isnumeric", "isprintable", "isspace", "istitle", "isupper", "join", "join", "ljust", "ljust", "lower", "lower", "lstrip", "lstrip", "partition", "partition", "replace", "replace", "rfind", "rindex", "rjust", "rjust", "rpartition", "rpartition", "rsplit", "rsplit", "rstrip", "rstrip", "split", "split", "splitlines", "splitlines", "startswith", "strip", "strip", "swapcase", "swapcase", "title", "title", "translate", "upper", "upper", "zfill", "zfill", "maketrans", "maketrans", "maketrans", "__add__", "__add__", "__contains__", "__eq__", "__ge__", "__getitem__", "__gt__", "__hash__", "__iter__", "__iter__", "__le__", "__len__", "__lt__", "__mod__", "__mod__", "__mul__", "__mul__", "__ne__", "__rmul__", "__rmul__", "__getnewargs__"], attributes: {}, special: false }, type_parameters: [] }) + "\"1\"" => Class(ClassType { details: Class { name: "str", declaration_path: DeclarationPath { module_name: "", node: Node { start: 17176, end: 25985 } }, methods: ["__new__", "__new__", "capitalize", "capitalize", "casefold", "casefold", "center", "center", "count", "encode", "endswith", "find", "format", "format", "format_map", "index", "isalnum", "isalpha", "isascii", "isdecimal", "isdigit", "isidentifier", "islower", "isnumeric", "isprintable", "isspace", "istitle", "isupper", "join", "join", "ljust", "ljust", "lower", "lower", "lstrip", "lstrip", "partition", "partition", "replace", "replace", "rfind", "rindex", "rjust", "rjust", "rpartition", "rpartition", "rsplit", "rsplit", "rstrip", "rstrip", "split", "split", "splitlines", "splitlines", "startswith", "strip", "strip", "swapcase", "swapcase", "title", "title", "translate", "upper", "upper", "zfill", "zfill", "maketrans", "maketrans", "maketrans", "__add__", "__add__", "__contains__", "__eq__", "__ge__", "__getitem__", "__gt__", "__hash__", "__iter__", "__iter__", "__le__", "__len__", "__lt__", "__mod__", "__mod__", "__mul__", "__mul__", "__ne__", "__rmul__", "__rmul__", "__getnewargs__"], special: false }, type_parameters: [] }) --- Line 3: c = True Expr types in the line --->: - "True" => Class(ClassType { details: Class { name: "bool", declaration_path: DeclarationPath { module_name: [TYPESHED].stdlib/builtins.pyi", node: Node { start: 39629, end: 40711 } }, methods: ["__new__", "__and__", "__and__", "__or__", "__or__", "__xor__", "__xor__", "__rand__", "__rand__", "__ror__", "__ror__", "__rxor__", "__rxor__", "__getnewargs__"], attributes: {}, special: false }, type_parameters: [] }) + "True" => Class(ClassType { details: Class { name: "bool", declaration_path: DeclarationPath { module_name: "", node: Node { start: 39629, end: 40711 } }, methods: ["__new__", "__and__", "__and__", "__or__", "__or__", "__xor__", "__xor__", "__rand__", "__rand__", "__ror__", "__ror__", "__rxor__", "__rxor__", "__getnewargs__"], special: false }, type_parameters: [] }) --- Line 4: d = False Expr types in the line --->: - "False" => Class(ClassType { details: Class { name: "bool", declaration_path: DeclarationPath { module_name: [TYPESHED].stdlib/builtins.pyi", node: Node { start: 39629, end: 40711 } }, methods: ["__new__", "__and__", "__and__", "__or__", "__or__", "__xor__", "__xor__", "__rand__", "__rand__", "__ror__", "__ror__", "__rxor__", "__rxor__", "__getnewargs__"], attributes: {}, special: false }, type_parameters: [] }) + "False" => Class(ClassType { details: Class { name: "bool", declaration_path: DeclarationPath { module_name: "", node: Node { start: 39629, end: 40711 } }, methods: ["__new__", "__and__", "__and__", "__or__", "__or__", "__xor__", "__xor__", "__rand__", "__rand__", "__ror__", "__ror__", "__rxor__", "__rxor__", "__getnewargs__"], special: false }, type_parameters: [] }) --- Line 5: a + int(b) Expr types in the line --->: - "a" => Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: [TYPESHED].stdlib/builtins.pyi", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], attributes: {}, special: false }, type_parameters: [] }) - "int(b)" => Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: [TYPESHED].stdlib/builtins.pyi", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], attributes: {}, special: false }, type_parameters: [] }) + "a" => Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: "", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], special: false }, type_parameters: [] }) + "int(b)" => Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: "", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], special: false }, type_parameters: [] }) --- -Line 7: a + c +Line 8: a + c Expr types in the line --->: - "a" => Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: [TYPESHED].stdlib/builtins.pyi", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], attributes: {}, special: false }, type_parameters: [] }) - "c" => Class(ClassType { details: Class { name: "bool", declaration_path: DeclarationPath { module_name: [TYPESHED].stdlib/builtins.pyi", node: Node { start: 39629, end: 40711 } }, methods: ["__new__", "__and__", "__and__", "__or__", "__or__", "__xor__", "__xor__", "__rand__", "__rand__", "__ror__", "__ror__", "__rxor__", "__rxor__", "__getnewargs__"], attributes: {}, special: false }, type_parameters: [] }) + "a" => Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: "", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], special: false }, type_parameters: [] }) + "c" => Class(ClassType { details: Class { name: "bool", declaration_path: DeclarationPath { module_name: "", node: Node { start: 39629, end: 40711 } }, methods: ["__new__", "__and__", "__and__", "__or__", "__or__", "__xor__", "__xor__", "__rand__", "__rand__", "__ror__", "__ror__", "__rxor__", "__rxor__", "__getnewargs__"], special: false }, type_parameters: [] }) --- -Line 10: return param1 + a +Line 11: return param1 + a Expr types in the line --->: - "param1" => Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: [TYPESHED].stdlib/builtins.pyi", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], attributes: {}, special: false }, type_parameters: [] }) - "a" => Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: [TYPESHED].stdlib/builtins.pyi", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], attributes: {}, special: false }, type_parameters: [] }) - "param1 + a" => Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: [TYPESHED].stdlib/builtins.pyi", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], attributes: {}, special: false }, type_parameters: [] }) + "param1" => Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: "", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], special: false }, type_parameters: [] }) + "a" => Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: "", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], special: false }, type_parameters: [] }) + "param1 + a" => Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: "", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], special: false }, type_parameters: [] }) --- -Line 13: cls_attribute = 1 +Line 14: cls_attribute = 1 Expr types in the line --->: - "1" => Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: [TYPESHED].stdlib/builtins.pyi", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], attributes: {}, special: false }, type_parameters: [] }) + "1" => Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: "", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], special: false }, type_parameters: [] }) --- -Line 16: print(self.cls_attribute) +Line 17: print(self.cls_attribute) Expr types in the line --->: "print(self.cls_attribute)" => Callable(CallableType { name: "print", arguments: Arguments { node: Node { start: 69542, end: 69692 }, posonlyargs: [], args: [], vararg: Some(Arg { node: Node { start: 69543, end: 69557 }, arg: "values", annotation: Some(Name(Name { node: Node { start: 69551, end: 69557 }, id: "object" })) }), kwonlyargs: [Arg { node: Node { start: 69563, end: 69584 }, arg: "sep", annotation: Some(BinOp(BinOp { node: Node { start: 69568, end: 69578 }, op: BitOr, left: Name(Name { node: Node { start: 69568, end: 69571 }, id: "str" }), right: Constant(Constant { node: Node { start: 69574, end: 69578 }, value: None }) })) }, Arg { node: Node { start: 69590, end: 69612 }, arg: "end", annotation: Some(BinOp(BinOp { node: Node { start: 69595, end: 69605 }, op: BitOr, left: Name(Name { node: Node { start: 69595, end: 69598 }, id: "str" }), right: Constant(Constant { node: Node { start: 69601, end: 69605 }, value: None }) })) }, Arg { node: Node { start: 69618, end: 69656 }, arg: "file", annotation: Some(BinOp(BinOp { node: Node { start: 69624, end: 69649 }, op: BitOr, left: Subscript(Subscript { node: Node { start: 69624, end: 69642 }, value: Name(Name { node: Node { start: 69624, end: 69637 }, id: "SupportsWrite" }), slice: Name(Name { node: Node { start: 69638, end: 69641 }, id: "str" }) }), right: Constant(Constant { node: Node { start: 69645, end: 69649 }, value: None }) })) }, Arg { node: Node { start: 69662, end: 69691 }, arg: "flush", annotation: Some(Subscript(Subscript { node: Node { start: 69669, end: 69683 }, value: Name(Name { node: Node { start: 69669, end: 69676 }, id: "Literal" }), slice: Constant(Constant { node: Node { start: 69677, end: 69682 }, value: false }) })) }], kw_defaults: [Some(Constant(Constant { node: Node { start: 69581, end: 69584 }, value: " " })), Some(Constant(Constant { node: Node { start: 69608, end: 69612 }, value: "\n" })), Some(Constant(Constant { node: Node { start: 69652, end: 69656 }, value: None })), Some(Constant(Constant { node: Node { start: 69686, end: 69691 }, value: false }))], kwarg: None, defaults: [] }, return_type: None }) - "self.cls_attribute" => Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: [TYPESHED].stdlib/builtins.pyi", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], attributes: {}, special: false }, type_parameters: [] }) + "self.cls_attribute" => Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: "", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], special: false }, type_parameters: [] }) --- -Line 17: self.x = x +Line 18: self.x = float(x) Expr types in the line --->: - "x" => Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: [TYPESHED].stdlib/builtins.pyi", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], attributes: {}, special: false }, type_parameters: [] }) + "float(x)" => Class(ClassType { details: Class { name: "float", declaration_path: DeclarationPath { module_name: "", node: Node { start: 12343, end: 15122 } }, methods: ["__new__", "as_integer_ratio", "hex", "is_integer", "fromhex", "real", "imag", "conjugate", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__pow__", "__pow__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__rpow__", "__rpow__", "__rpow__", "__getnewargs__", "__trunc__", "__round__", "__round__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__neg__", "__pos__", "__int__", "__float__", "__abs__", "__hash__", "__bool__"], special: false }, type_parameters: [] }) --- -Line 18: print(self.x) +Line 19: print(self.x) Expr types in the line --->: "print(self.x)" => Callable(CallableType { name: "print", arguments: Arguments { node: Node { start: 69542, end: 69692 }, posonlyargs: [], args: [], vararg: Some(Arg { node: Node { start: 69543, end: 69557 }, arg: "values", annotation: Some(Name(Name { node: Node { start: 69551, end: 69557 }, id: "object" })) }), kwonlyargs: [Arg { node: Node { start: 69563, end: 69584 }, arg: "sep", annotation: Some(BinOp(BinOp { node: Node { start: 69568, end: 69578 }, op: BitOr, left: Name(Name { node: Node { start: 69568, end: 69571 }, id: "str" }), right: Constant(Constant { node: Node { start: 69574, end: 69578 }, value: None }) })) }, Arg { node: Node { start: 69590, end: 69612 }, arg: "end", annotation: Some(BinOp(BinOp { node: Node { start: 69595, end: 69605 }, op: BitOr, left: Name(Name { node: Node { start: 69595, end: 69598 }, id: "str" }), right: Constant(Constant { node: Node { start: 69601, end: 69605 }, value: None }) })) }, Arg { node: Node { start: 69618, end: 69656 }, arg: "file", annotation: Some(BinOp(BinOp { node: Node { start: 69624, end: 69649 }, op: BitOr, left: Subscript(Subscript { node: Node { start: 69624, end: 69642 }, value: Name(Name { node: Node { start: 69624, end: 69637 }, id: "SupportsWrite" }), slice: Name(Name { node: Node { start: 69638, end: 69641 }, id: "str" }) }), right: Constant(Constant { node: Node { start: 69645, end: 69649 }, value: None }) })) }, Arg { node: Node { start: 69662, end: 69691 }, arg: "flush", annotation: Some(Subscript(Subscript { node: Node { start: 69669, end: 69683 }, value: Name(Name { node: Node { start: 69669, end: 69676 }, id: "Literal" }), slice: Constant(Constant { node: Node { start: 69677, end: 69682 }, value: false }) })) }], kw_defaults: [Some(Constant(Constant { node: Node { start: 69581, end: 69584 }, value: " " })), Some(Constant(Constant { node: Node { start: 69608, end: 69612 }, value: "\n" })), Some(Constant(Constant { node: Node { start: 69652, end: 69656 }, value: None })), Some(Constant(Constant { node: Node { start: 69686, end: 69691 }, value: false }))], kwarg: None, defaults: [] }, return_type: None }) - "self.x" => Unknown + "self.x" => Class(ClassType { details: Class { name: "float", declaration_path: DeclarationPath { module_name: "", node: Node { start: 12343, end: 15122 } }, methods: ["__new__", "as_integer_ratio", "hex", "is_integer", "fromhex", "real", "imag", "conjugate", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__pow__", "__pow__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__rpow__", "__rpow__", "__rpow__", "__getnewargs__", "__trunc__", "__round__", "__round__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__neg__", "__pos__", "__int__", "__float__", "__abs__", "__hash__", "__bool__"], special: false }, type_parameters: [] }) --- -Line 24: return self.cls_attribute +Line 25: return self.cls_attribute Expr types in the line --->: - "self.cls_attribute" => Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: [TYPESHED].stdlib/builtins.pyi", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], attributes: {}, special: false }, type_parameters: [] }) + "self.cls_attribute" => Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: "", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], special: false }, type_parameters: [] }) --- -Line 27: return self.x +Line 28: return self.x Expr types in the line --->: - "self.x" => Unknown + "self.x" => Class(ClassType { details: Class { name: "float", declaration_path: DeclarationPath { module_name: "", node: Node { start: 12343, end: 15122 } }, methods: ["__new__", "as_integer_ratio", "hex", "is_integer", "fromhex", "real", "imag", "conjugate", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__pow__", "__pow__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__rpow__", "__rpow__", "__rpow__", "__getnewargs__", "__trunc__", "__round__", "__round__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__neg__", "__pos__", "__int__", "__float__", "__abs__", "__hash__", "__bool__"], special: false }, type_parameters: [] }) --- -Line 29: t = C(0) +Line 30: t = C(0) Expr types in the line --->: - "C(0)" => Class(ClassType { details: Class { name: "C", declaration_path: DeclarationPath { module_name: "test-file", node: Node { start: 102, end: 376 } }, methods: ["__init__", "add", "get_attr", "get_x"], attributes: {"x": Name(Name { node: Node { start: 199, end: 200 }, id: "x" })}, special: false }, type_parameters: [] }) + "C(0)" => Class(ClassType { details: Class { name: "C", declaration_path: DeclarationPath { module_name: "", node: Node { start: 103, end: 386 } }, methods: ["__init__", "add", "get_attr", "get_x"], special: false }, type_parameters: [] }) --- -Line 30: t.add(2) +Line 31: t.add(2) Expr types in the line --->: - "(2)" => Unknown - "2" => Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: [TYPESHED].stdlib/builtins.pyi", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], attributes: {}, special: false }, type_parameters: [] }) + "(2)" => Callable(CallableType { name: "add", arguments: Arguments { node: Node { start: 235, end: 251 }, posonlyargs: [], args: [Arg { node: Node { start: 235, end: 239 }, arg: "self", annotation: None }, Arg { node: Node { start: 241, end: 251 }, arg: "value", annotation: Some(Name(Name { node: Node { start: 248, end: 251 }, id: "int" })) }], vararg: None, kwonlyargs: [], kw_defaults: [], kwarg: None, defaults: [] }, return_type: None }) + "2" => Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: "", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], special: false }, type_parameters: [] }) --- -Line 33: t.get_x() +Line 34: t.get_x() Expr types in the line --->: - "()" => Unknown + "()" => Callable(CallableType { name: "get_x", arguments: Arguments { node: Node { start: 353, end: 357 }, posonlyargs: [], args: [Arg { node: Node { start: 353, end: 357 }, arg: "self", annotation: None }], vararg: None, kwonlyargs: [], kw_defaults: [], kwarg: None, defaults: [] }, return_type: Class(ClassType { details: Class { name: "float", declaration_path: DeclarationPath { module_name: "", node: Node { start: 12343, end: 15122 } }, methods: ["__new__", "as_integer_ratio", "hex", "is_integer", "fromhex", "real", "imag", "conjugate", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__pow__", "__pow__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__rpow__", "__rpow__", "__rpow__", "__getnewargs__", "__trunc__", "__round__", "__round__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__neg__", "__pos__", "__int__", "__float__", "__abs__", "__hash__", "__bool__"], special: false }, type_parameters: [] }) }) --- -Line 34: t.get_attr() +Line 35: t.get_attr() Expr types in the line --->: - "()" => Unknown + "()" => Callable(CallableType { name: "get_attr", arguments: Arguments { node: Node { start: 299, end: 303 }, posonlyargs: [], args: [Arg { node: Node { start: 299, end: 303 }, arg: "self", annotation: None }], vararg: None, kwonlyargs: [], kw_defaults: [], kwarg: None, defaults: [] }, return_type: Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: "", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], special: false }, type_parameters: [] }) }) --- -Line 36: l = [1,2,3] +Line 37: l = [1,2,3] Expr types in the line --->: - "[1,2,3]" => Class(ClassType { details: Class { name: "list", declaration_path: DeclarationPath { module_name: [TYPESHED].stdlib/builtins.pyi", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], attributes: {}, special: false }, type_parameters: [] })] }) + "[1,2,3]" => Class(ClassType { details: Class { name: "list", declaration_path: DeclarationPath { module_name: "", node: Node { start: 43505, end: 46298 } }, methods: ["__init__", "__init__", "copy", "append", "extend", "pop", "index", "count", "insert", "remove", "sort", "sort", "__len__", "__iter__", "__getitem__", "__getitem__", "__setitem__", "__setitem__", "__delitem__", "__add__", "__add__", "__iadd__", "__mul__", "__rmul__", "__imul__", "__contains__", "__reversed__", "__gt__", "__ge__", "__lt__", "__le__", "__eq__"], special: false }, type_parameters: [Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: "", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], special: false }, type_parameters: [] })] }) --- -Line 37: d = {"a": 1, "b": 2} +Line 38: d = {"a": 1, "b": 2} Expr types in the line --->: - "{\"a\": 1, \"b\": 2}" => Class(ClassType { details: Class { name: "dict", declaration_path: DeclarationPath { module_name: [TYPESHED].stdlib/builtins.pyi", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], attributes: {}, special: false }, type_parameters: [] })] }) + "{\"a\": 1, \"b\": 2}" => Class(ClassType { details: Class { name: "dict", declaration_path: DeclarationPath { module_name: "", node: Node { start: 46298, end: 49982 } }, methods: ["__init__", "__init__", "__init__", "__init__", "__init__", "__init__", "__init__", "__init__", "__new__", "copy", "keys", "values", "items", "fromkeys", "fromkeys", "get", "get", "get", "pop", "pop", "pop", "__len__", "__getitem__", "__setitem__", "__delitem__", "__iter__", "__eq__"], special: false }, type_parameters: [Class(ClassType { details: Class { name: "str", declaration_path: DeclarationPath { module_name: "", node: Node { start: 17176, end: 25985 } }, methods: ["__new__", "__new__", "capitalize", "capitalize", "casefold", "casefold", "center", "center", "count", "encode", "endswith", "find", "format", "format", "format_map", "index", "isalnum", "isalpha", "isascii", "isdecimal", "isdigit", "isidentifier", "islower", "isnumeric", "isprintable", "isspace", "istitle", "isupper", "join", "join", "ljust", "ljust", "lower", "lower", "lstrip", "lstrip", "partition", "partition", "replace", "replace", "rfind", "rindex", "rjust", "rjust", "rpartition", "rpartition", "rsplit", "rsplit", "rstrip", "rstrip", "split", "split", "splitlines", "splitlines", "startswith", "strip", "strip", "swapcase", "swapcase", "title", "title", "translate", "upper", "upper", "zfill", "zfill", "maketrans", "maketrans", "maketrans", "__add__", "__add__", "__contains__", "__eq__", "__ge__", "__getitem__", "__gt__", "__hash__", "__iter__", "__iter__", "__le__", "__len__", "__lt__", "__mod__", "__mod__", "__mul__", "__mul__", "__ne__", "__rmul__", "__rmul__", "__getnewargs__"], special: false }, type_parameters: [] }), Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: "", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], special: false }, type_parameters: [] })] }) --- -Line 38: s = {1,2,3} +Line 39: s = {1,2,3} Expr types in the line --->: - "{1,2,3}" => Class(ClassType { details: Class { name: "set", declaration_path: DeclarationPath { module_name: [TYPESHED].stdlib/builtins.pyi", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], attributes: {}, special: false }, type_parameters: [] })] }) - ---- -Line 40: l.append(1) - -Expr types in the line --->: - "(1)" => Unknown - "1" => Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: [TYPESHED].stdlib/builtins.pyi", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], attributes: {}, special: false }, type_parameters: [] }) + "{1,2,3}" => Class(ClassType { details: Class { name: "set", declaration_path: DeclarationPath { module_name: "", node: Node { start: 49982, end: 52187 } }, methods: ["__init__", "__init__", "add", "copy", "difference", "difference_update", "discard", "intersection", "intersection_update", "isdisjoint", "issubset", "issuperset", "remove", "symmetric_difference", "symmetric_difference_update", "union", "update", "__len__", "__contains__", "__iter__", "__and__", "__iand__", "__or__", "__ior__", "__sub__", "__isub__", "__xor__", "__ixor__", "__le__", "__lt__", "__ge__", "__gt__", "__eq__"], special: false }, type_parameters: [Class(ClassType { details: Class { name: "int", declaration_path: DeclarationPath { module_name: "", node: Node { start: 7961, end: 12343 } }, methods: ["__new__", "__new__", "real", "imag", "numerator", "denominator", "conjugate", "bit_length", "__add__", "__sub__", "__mul__", "__floordiv__", "__truediv__", "__mod__", "__divmod__", "__radd__", "__rsub__", "__rmul__", "__rfloordiv__", "__rtruediv__", "__rmod__", "__rdivmod__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__pow__", "__rpow__", "__and__", "__or__", "__xor__", "__lshift__", "__rshift__", "__rand__", "__ror__", "__rxor__", "__rlshift__", "__rrshift__", "__neg__", "__pos__", "__invert__", "__trunc__", "__ceil__", "__floor__", "__round__", "__getnewargs__", "__eq__", "__ne__", "__lt__", "__le__", "__gt__", "__ge__", "__float__", "__int__", "__abs__", "__hash__", "__bool__", "__index__"], special: false }, type_parameters: [] })] }) --- From 35d06e1cc654bf92b247ddfc42ab3176ea9ae8af Mon Sep 17 00:00:00 2001 From: Glyphack Date: Sat, 17 Feb 2024 18:29:08 +0100 Subject: [PATCH 2/3] Cargo clippy fix --- typechecker/src/semantic_analyzer.rs | 6 +++--- typechecker/src/type_check/type_evaluator.rs | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/typechecker/src/semantic_analyzer.rs b/typechecker/src/semantic_analyzer.rs index 4735fc86..d9e544e4 100644 --- a/typechecker/src/semantic_analyzer.rs +++ b/typechecker/src/semantic_analyzer.rs @@ -257,7 +257,7 @@ impl SemanticAnalyzer { return true; } } - return false; + false } } @@ -472,7 +472,7 @@ impl TraversalVisitor for SemanticAnalyzer { module_name: self.file.path(), node: f.node, }; - if f.type_params.len() > 0 { + if !f.type_params.is_empty() { // TODO // Push a PEP 695 scope // https://www.python.org/dev/peps/pep-0695/ @@ -660,7 +660,7 @@ impl TraversalVisitor for SemanticAnalyzer { fn visit_dict_comp(&mut self, _d: &parser::ast::DictComp) {} // Imagine it's always store - 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) {} diff --git a/typechecker/src/type_check/type_evaluator.rs b/typechecker/src/type_check/type_evaluator.rs index 8c1c84de..ba700d7a 100755 --- a/typechecker/src/type_check/type_evaluator.rs +++ b/typechecker/src/type_check/type_evaluator.rs @@ -2,11 +2,11 @@ #![allow(unused_variables)] use core::panic; -use std::{collections::HashMap, path::Path}; +use std::{path::Path}; use enderpy_python_parser as parser; use enderpy_python_parser::ast; -use log::debug; + use miette::{bail, Result}; use parser::ast::{Expression, GetNode, Statement}; @@ -217,9 +217,9 @@ impl TypeEvaluator { if let Some(enclosing_parent_class) = enclosing_parent_class { let symbol_table_node = self .symbol_table - .lookup_attribute(&a.attr, &enclosing_parent_class); + .lookup_attribute(&a.attr, enclosing_parent_class); let res = match symbol_table_node { - Some(node) => self.get_symbol_node_type(&node, None), + Some(node) => self.get_symbol_node_type(node, None), None => panic!("cannot find symbol table node for attribute access"), }; @@ -253,7 +253,7 @@ impl TypeEvaluator { self.symbol_table.lookup_attribute(&a.attr, class_scope); log::debug!("found symbol table node: {:#?}", symbol_table_node); let result = match symbol_table_node { - Some(node) => self.get_symbol_node_type(&node, None), + Some(node) => self.get_symbol_node_type(node, None), None => Ok(PythonType::Unknown), }; @@ -1367,7 +1367,7 @@ mod tests { } let module = manager.get_state("test-file".into()).unwrap(); - let mut symbol_table = module.get_symbol_table(); + let symbol_table = module.get_symbol_table(); let type_eval = TypeEvaluator { symbol_table, From 395a6ad6b8293d8586d21a180d93e3d38764af51 Mon Sep 17 00:00:00 2001 From: Glyphack Date: Sat, 17 Feb 2024 18:51:58 +0100 Subject: [PATCH 3/3] Remove redundant code --- typechecker/src/symbol_table.rs | 11 ++--------- typechecker/test_data/inputs/base.py | 1 - 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/typechecker/src/symbol_table.rs b/typechecker/src/symbol_table.rs index 193c702c..ca6a6c75 100644 --- a/typechecker/src/symbol_table.rs +++ b/typechecker/src/symbol_table.rs @@ -368,9 +368,7 @@ impl SymbolTable { /// TODO: This function does not work on the literal test pub fn lookup_in_scope(&self, lookup_request: LookupSymbolRequest) -> Option<&SymbolTableNode> { let mut scope = self.current_scope(); - log::debug!("All symbols in scope: {:?}", scope.symbols.keys()); loop { - // log::debug!("looking in scope: {:?}", scope.name); if let Some(symbol) = scope.symbols.get(&lookup_request.name) { return Some(symbol); } @@ -428,7 +426,7 @@ impl SymbolTable { } pub fn add_symbol(&mut self, mut symbol_node: SymbolTableNode) { - log::debug!("Adding symbol: {:?}", symbol_node.name); + log::debug!("Adding symbol: {}", symbol_node); let scope = if symbol_node.flags.contains(SymbolFlags::CLASS_MEMBER) || symbol_node.flags.contains(SymbolFlags::INSTANCE_MEMBER) { @@ -445,7 +443,7 @@ impl SymbolTable { self.current_scope_mut() }; - log::debug!("Adding symbol {} to scope: {:?}", symbol_node, scope.name); + log::debug!("Adding symbol {} to scope: {}", symbol_node, scope.name); if let Some(existing_symbol) = scope.symbols.get(&symbol_node.name) { symbol_node .declarations @@ -473,11 +471,6 @@ impl SymbolTable { &scope.name ); if let Some(symbol) = scope.symbols.get(attr) { - // if symbol.flags.contains(SymbolFlags::CLASS_MEMBER) - // || symbol.flags.contains(SymbolFlags::INSTANCE_MEMBER) - // { - // return Some(symbol); - // } return Some(symbol); } log::debug!("attribute not found"); diff --git a/typechecker/test_data/inputs/base.py b/typechecker/test_data/inputs/base.py index a7b2bb33..7a1415eb 100644 --- a/typechecker/test_data/inputs/base.py +++ b/typechecker/test_data/inputs/base.py @@ -38,4 +38,3 @@ def get_x(self) -> float: d = {"a": 1, "b": 2} s = {1,2,3} -# l.append(1)