From ab86bf459158996e181b0bf5af4fffd875113da9 Mon Sep 17 00:00:00 2001 From: wylited Date: Wed, 13 Apr 2022 10:35:18 +0800 Subject: [PATCH 1/3] nac3core: toplevel, fix for class constructors + spelling errors --- nac3core/src/toplevel/composer.rs | 19 +++++-------------- nac3standalone/demo/src/initless.py | 13 +++++++++++++ 2 files changed, 18 insertions(+), 14 deletions(-) create mode 100644 nac3standalone/demo/src/initless.py diff --git a/nac3core/src/toplevel/composer.rs b/nac3core/src/toplevel/composer.rs index 8568011..9f6d26a 100644 --- a/nac3core/src/toplevel/composer.rs +++ b/nac3core/src/toplevel/composer.rs @@ -167,7 +167,7 @@ impl TopLevelComposer { ) -> Result<(StrRef, DefinitionId, Option), String> { let defined_names = &mut self.defined_names; match &ast.node { - ast::StmtKind::ClassDef { name: class_name, bases, body, .. } => { + ast::StmtKind::ClassDef { name: class_name, body, .. } => { if self.keyword_list.contains(class_name) { return Err(format!( "cannot use keyword `{}` as a class name (at {})", @@ -221,18 +221,9 @@ impl TopLevelComposer { // we do not push anything to the def list, so we keep track of the index // and then push in the correct order after the for loop let mut class_method_index_offset = 0; - let init_id = "__init__".into(); - let exception_id = "Exception".into(); - // TODO: Fix this hack. We will generate constructor for classes that inherit - // from Exception class (directly or indirectly), but this code cannot handle - // subclass of other exception classes. - let mut contains_constructor = bases - .iter().any(|base| matches!(base.node, ast::ExprKind::Name { id, .. } if id == exception_id)); + for b in body { if let ast::StmtKind::FunctionDef { name: method_name, .. } = &b.node { - if method_name == &init_id { - contains_constructor = true; - } if self.keyword_list.contains(method_name) { return Err(format!( "cannot use keyword `{}` as a method name (at {})", @@ -298,7 +289,7 @@ impl TopLevelComposer { self.definition_ast_list.push((def, Some(ast))); } - let result_ty = if contains_constructor { Some(constructor_ty) } else { None }; + let result_ty = Some(constructor_ty); Ok((class_name, DefinitionId(class_def_id), result_ty)) } @@ -1470,7 +1461,7 @@ impl TopLevelComposer { /// step 5, analyze and call type inferecer to fill the `instance_to_stmt` of topleveldef::function fn analyze_function_instance(&mut self) -> Result<(), String> { - // first get the class contructor type correct for the following type check in function body + // first get the class constructor type correct for the following type check in function body // also do class field instantiation check let init_str_id = "__init__".into(); let mut definition_extension = Vec::new(); @@ -1581,7 +1572,7 @@ impl TopLevelComposer { return Ok(()); } let mut init_id: Option = None; - // get the class contructor type correct + // get the class constructor type correct let (contor_args, contor_type_vars) = { let mut constructor_args: Vec = Vec::new(); let mut type_vars: HashMap = HashMap::new(); diff --git a/nac3standalone/demo/src/initless.py b/nac3standalone/demo/src/initless.py new file mode 100644 index 0000000..abe6e50 --- /dev/null +++ b/nac3standalone/demo/src/initless.py @@ -0,0 +1,13 @@ +@extern +def output_int32(x: int32): + ... + +class A: + def foo(self): + output_int32(1) + +def run() -> int32: + inst = A() + inst.foo() + output_int32(1) + return 0 -- 2.44.1 From 1d32c44bf568fe3092bbfddba75b0ff3a7c193a5 Mon Sep 17 00:00:00 2001 From: wylited Date: Wed, 13 Apr 2022 11:23:03 +0800 Subject: [PATCH 2/3] spelling fixes --- nac3core/src/codegen/generator.rs | 2 +- nac3core/src/toplevel/composer.rs | 20 ++++++++++---------- nac3core/src/toplevel/helper.rs | 2 +- nac3core/src/toplevel/type_annotation.rs | 2 +- nac3core/src/typecheck/typedef/mod.rs | 2 +- nac3core/src/typecheck/typedef/test.rs | 6 +++--- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/nac3core/src/codegen/generator.rs b/nac3core/src/codegen/generator.rs index 4fcbfdb..22d0eac 100644 --- a/nac3core/src/codegen/generator.rs +++ b/nac3core/src/codegen/generator.rs @@ -36,7 +36,7 @@ pub trait CodeGenerator { } /// Generate object constructor and returns the constructed object. - /// - signature: Function signature of the contructor. + /// - signature: Function signature of the constructor. /// - def: Class definition for the constructor class. /// - params: Function parameters. fn gen_constructor<'ctx, 'a>( diff --git a/nac3core/src/toplevel/composer.rs b/nac3core/src/toplevel/composer.rs index 9f6d26a..b2f4cd2 100644 --- a/nac3core/src/toplevel/composer.rs +++ b/nac3core/src/toplevel/composer.rs @@ -425,11 +425,11 @@ impl TopLevelComposer { // check if all are unique type vars let all_unique_type_var = { - let mut occured_type_var_id: HashSet = HashSet::new(); + let mut occurred_type_var_id: HashSet = HashSet::new(); type_vars.iter().all(|x| { let ty = unifier.get_ty(*x); if let TypeEnum::TVar { id, .. } = ty.as_ref() { - occured_type_var_id.insert(*id) + occurred_type_var_id.insert(*id) } else { false } @@ -527,7 +527,7 @@ impl TopLevelComposer { } has_base = true; - // the function parse_ast_to make sure that no type var occured in + // the function parse_ast_to make sure that no type var occurred in // bast_ty if it is a CustomClassKind let base_ty = parse_ast_to_type_annotation_kinds( class_resolver, @@ -687,7 +687,7 @@ impl TopLevelComposer { return Err(errors.into_iter().sorted().join("\n----------\n")); } - // handle the inheritanced methods and fields + // handle the inherited methods and fields // Note: we cannot defer error handling til the end of the loop, because there is loop // carried dependency, ignoring the error (temporarily) will cause all assumptions to break // and produce weird error messages @@ -816,9 +816,9 @@ impl TopLevelComposer { let mut function_var_map: HashMap = HashMap::new(); let arg_types = { // make sure no duplicate parameter - let mut defined_paramter_name: HashSet<_> = HashSet::new(); + let mut defined_parameter_name: HashSet<_> = HashSet::new(); for x in args.args.iter() { - if !defined_paramter_name.insert(x.node.arg) + if !defined_parameter_name.insert(x.node.arg) || keyword_list.contains(&x.node.arg) { return Err(format!( @@ -1065,10 +1065,10 @@ impl TopLevelComposer { let arg_types: Vec = { // check method parameters cannot have same name - let mut defined_paramter_name: HashSet<_> = HashSet::new(); + let mut defined_parameter_name: HashSet<_> = HashSet::new(); let zelf: StrRef = "self".into(); for x in args.args.iter() { - if !defined_paramter_name.insert(x.node.arg) + if !defined_parameter_name.insert(x.node.arg) || (keyword_list.contains(&x.node.arg) && x.node.arg != zelf) { return Err(format!( @@ -1218,7 +1218,7 @@ impl TopLevelComposer { dummy_return_type } else { // if do not have return annotation, return none - // for uniform handling, still use type annoatation + // for uniform handling, still use type annotation let dummy_return_type = unifier.get_dummy_var().0; type_var_to_concrete_def.insert( dummy_return_type, @@ -1459,7 +1459,7 @@ impl TopLevelComposer { Ok(()) } - /// step 5, analyze and call type inferecer to fill the `instance_to_stmt` of topleveldef::function + /// step 5, analyze and call type inferencer to fill the `instance_to_stmt` of topleveldef::function fn analyze_function_instance(&mut self) -> Result<(), String> { // first get the class constructor type correct for the following type check in function body // also do class field instantiation check diff --git a/nac3core/src/toplevel/helper.rs b/nac3core/src/toplevel/helper.rs index 687e70b..c631186 100644 --- a/nac3core/src/toplevel/helper.rs +++ b/nac3core/src/toplevel/helper.rs @@ -149,7 +149,7 @@ impl TopLevelComposer { } /// already include the definition_id of itself inside the ancestors vector - /// when first regitering, the type_vars, fields, methods, ancestors are invalid + /// when first registering, the type_vars, fields, methods, ancestors are invalid pub fn make_top_level_class_def( index: usize, resolver: Option>, diff --git a/nac3core/src/toplevel/type_annotation.rs b/nac3core/src/toplevel/type_annotation.rs index bccd786..116a6b4 100644 --- a/nac3core/src/toplevel/type_annotation.rs +++ b/nac3core/src/toplevel/type_annotation.rs @@ -436,7 +436,7 @@ pub fn get_type_from_type_annotation_kinds( /// the type of `self` should be similar to `A[T, V]`, where `T`, `V` /// considered to be type variables associated with the class \ /// \ -/// But note that here we do not make a duplication of `T`, `V`, we direclty +/// But note that here we do not make a duplication of `T`, `V`, we directly /// use them as they are in the TopLevelDef::Class since those in the /// TopLevelDef::Class.type_vars will be substitute later when seeing applications/instantiations /// the Type of their fields and methods will also be subst when application/instantiation diff --git a/nac3core/src/typecheck/typedef/mod.rs b/nac3core/src/typecheck/typedef/mod.rs index 16248f8..f2e7b57 100644 --- a/nac3core/src/typecheck/typedef/mod.rs +++ b/nac3core/src/typecheck/typedef/mod.rs @@ -16,7 +16,7 @@ use crate::toplevel::{DefinitionId, TopLevelContext, TopLevelDef}; #[cfg(test)] mod test; -/// Handle for a type, implementated as a key in the unification table. +/// Handle for a type, implemented as a key in the unification table. pub type Type = UnificationKey; #[derive(Clone, Copy, PartialEq, Eq, Debug)] diff --git a/nac3core/src/typecheck/typedef/test.rs b/nac3core/src/typecheck/typedef/test.rs index 2e56a34..30c183b 100644 --- a/nac3core/src/typecheck/typedef/test.rs +++ b/nac3core/src/typecheck/typedef/test.rs @@ -309,7 +309,7 @@ fn test_unify( fn test_invalid_unification( variable_count: u32, unify_pairs: &[(&'static str, &'static str)], - errornous_pair: ((&'static str, &'static str), &'static str), + erroneous_pair: ((&'static str, &'static str), &'static str), ) { let mut env = TestEnvironment::new(); let mut mapping = HashMap::new(); @@ -326,11 +326,11 @@ fn test_invalid_unification( pairs.push((t1, t2)); } let (t1, t2) = - (env.parse(errornous_pair.0 .0, &mapping), env.parse(errornous_pair.0 .1, &mapping)); + (env.parse(erroneous_pair.0 .0, &mapping), env.parse(erroneous_pair.0 .1, &mapping)); for (a, b) in pairs { env.unifier.unify(a, b).unwrap(); } - assert_eq!(env.unify(t1, t2), Err(errornous_pair.1.to_string())); + assert_eq!(env.unify(t1, t2), Err(erroneous_pair.1.to_string())); } #[test] -- 2.44.1 From 56a37ce89d2c13b5f374ddc6f2ac75da223fd7c6 Mon Sep 17 00:00:00 2001 From: wylited Date: Wed, 13 Apr 2022 11:27:13 +0800 Subject: [PATCH 3/3] Revert "nac3core: toplevel, fix for class constructors + spelling errors" This reverts commit ab86bf459158996e181b0bf5af4fffd875113da9. --- nac3core/src/toplevel/composer.rs | 19 ++++++++++++++----- nac3standalone/demo/src/initless.py | 13 ------------- 2 files changed, 14 insertions(+), 18 deletions(-) delete mode 100644 nac3standalone/demo/src/initless.py diff --git a/nac3core/src/toplevel/composer.rs b/nac3core/src/toplevel/composer.rs index b2f4cd2..c002588 100644 --- a/nac3core/src/toplevel/composer.rs +++ b/nac3core/src/toplevel/composer.rs @@ -167,7 +167,7 @@ impl TopLevelComposer { ) -> Result<(StrRef, DefinitionId, Option), String> { let defined_names = &mut self.defined_names; match &ast.node { - ast::StmtKind::ClassDef { name: class_name, body, .. } => { + ast::StmtKind::ClassDef { name: class_name, bases, body, .. } => { if self.keyword_list.contains(class_name) { return Err(format!( "cannot use keyword `{}` as a class name (at {})", @@ -221,9 +221,18 @@ impl TopLevelComposer { // we do not push anything to the def list, so we keep track of the index // and then push in the correct order after the for loop let mut class_method_index_offset = 0; - + let init_id = "__init__".into(); + let exception_id = "Exception".into(); + // TODO: Fix this hack. We will generate constructor for classes that inherit + // from Exception class (directly or indirectly), but this code cannot handle + // subclass of other exception classes. + let mut contains_constructor = bases + .iter().any(|base| matches!(base.node, ast::ExprKind::Name { id, .. } if id == exception_id)); for b in body { if let ast::StmtKind::FunctionDef { name: method_name, .. } = &b.node { + if method_name == &init_id { + contains_constructor = true; + } if self.keyword_list.contains(method_name) { return Err(format!( "cannot use keyword `{}` as a method name (at {})", @@ -289,7 +298,7 @@ impl TopLevelComposer { self.definition_ast_list.push((def, Some(ast))); } - let result_ty = Some(constructor_ty); + let result_ty = if contains_constructor { Some(constructor_ty) } else { None }; Ok((class_name, DefinitionId(class_def_id), result_ty)) } @@ -1461,7 +1470,7 @@ impl TopLevelComposer { /// step 5, analyze and call type inferencer to fill the `instance_to_stmt` of topleveldef::function fn analyze_function_instance(&mut self) -> Result<(), String> { - // first get the class constructor type correct for the following type check in function body + // first get the class contructor type correct for the following type check in function body // also do class field instantiation check let init_str_id = "__init__".into(); let mut definition_extension = Vec::new(); @@ -1572,7 +1581,7 @@ impl TopLevelComposer { return Ok(()); } let mut init_id: Option = None; - // get the class constructor type correct + // get the class contructor type correct let (contor_args, contor_type_vars) = { let mut constructor_args: Vec = Vec::new(); let mut type_vars: HashMap = HashMap::new(); diff --git a/nac3standalone/demo/src/initless.py b/nac3standalone/demo/src/initless.py deleted file mode 100644 index abe6e50..0000000 --- a/nac3standalone/demo/src/initless.py +++ /dev/null @@ -1,13 +0,0 @@ -@extern -def output_int32(x: int32): - ... - -class A: - def foo(self): - output_int32(1) - -def run() -> int32: - inst = A() - inst.foo() - output_int32(1) - return 0 -- 2.44.1