From 98d032b72a94e011cede5cc79cad59dd064c29fd Mon Sep 17 00:00:00 2001 From: ychenfo Date: Tue, 31 Aug 2021 15:22:45 +0800 Subject: [PATCH] nac3core: top level fix duplicate def, start adding tests --- nac3core/src/toplevel/mod.rs | 27 ++++++++++--- nac3core/src/toplevel/test.rs | 71 +++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 nac3core/src/toplevel/test.rs diff --git a/nac3core/src/toplevel/mod.rs b/nac3core/src/toplevel/mod.rs index d31378d5..fbed5d3d 100644 --- a/nac3core/src/toplevel/mod.rs +++ b/nac3core/src/toplevel/mod.rs @@ -22,6 +22,8 @@ pub struct DefinitionId(pub usize); mod type_annotation; use type_annotation::*; mod helper; +#[cfg(test)] +mod test; #[derive(Clone)] pub struct FunInstance { @@ -88,6 +90,10 @@ pub struct TopLevelComposer { pub primitives_ty: PrimitiveStore, // keyword list to prevent same user-defined name pub keyword_list: HashSet, + // to prevent duplicate definition + pub defined_class_name: HashSet, + pub defined_class_method_name: HashSet, + pub defined_function_name: HashSet, } impl Default for TopLevelComposer { @@ -130,13 +136,16 @@ impl TopLevelComposer { "none".into(), "None".into(), ]), + defined_class_method_name: Default::default(), + defined_class_name: Default::default(), + defined_function_name: Default::default(), } } pub fn make_top_level_context(self) -> TopLevelContext { TopLevelContext { definitions: RwLock::new( - self.definition_ast_list.into_iter().map(|(x, ..)| x).collect::>(), + self.definition_ast_list.into_iter().map(|(x, ..)| x).collect_vec(), ) .into(), // FIXME: all the big unifier or? @@ -148,16 +157,16 @@ impl TopLevelComposer { self.definition_ast_list.iter().map(|(def, ..)| def.clone()).collect_vec() } - /// step 0, register, just remeber the names of top level classes/function + /// register, just remeber the names of top level classes/function /// and check duplicate class/method/function definition pub fn register_top_level( &mut self, ast: ast::Stmt<()>, resolver: Option>>, ) -> Result<(String, DefinitionId), String> { - let mut defined_class_name: HashSet = HashSet::new(); - let mut defined_class_method_name: HashSet = HashSet::new(); - let mut defined_function_name: HashSet = HashSet::new(); + let defined_class_name = &mut self.defined_class_name; + let defined_class_method_name = &mut self.defined_class_method_name; + let defined_function_name = &mut self.defined_function_name; match &ast.node { ast::StmtKind::ClassDef { name, body, .. } => { if self.keyword_list.contains(name) { @@ -294,6 +303,14 @@ impl TopLevelComposer { } } + pub fn start_analysis(&mut self) -> Result<(), String> { + self.analyze_top_level_class_type_var()?; + self.analyze_top_level_class_bases()?; + self.analyze_top_level_class_fields_methods()?; + self.analyze_top_level_function()?; + Ok(()) + } + /// step 1, analyze the type vars associated with top level class fn analyze_top_level_class_type_var(&mut self) -> Result<(), String> { let def_list = &self.definition_ast_list; diff --git a/nac3core/src/toplevel/test.rs b/nac3core/src/toplevel/test.rs new file mode 100644 index 00000000..df36ca99 --- /dev/null +++ b/nac3core/src/toplevel/test.rs @@ -0,0 +1,71 @@ +use crate::{ + location::Location, + symbol_resolver::{SymbolResolver, SymbolValue}, + toplevel::DefinitionId, + typecheck::{ + type_inferencer::PrimitiveStore, + typedef::{Type, Unifier}, + }, +}; +use indoc::indoc; +use rustpython_parser::{ast::fold::Fold, parser::parse_program}; +use std::collections::{HashMap, HashSet}; +use test_case::test_case; + +use super::TopLevelComposer; + +struct Resolver { + id_to_type: HashMap, + id_to_def: HashMap, + class_names: HashMap, +} + +impl SymbolResolver for Resolver { + fn get_symbol_type(&self, _: &mut Unifier, _: &PrimitiveStore, str: &str) -> Option { + self.id_to_type.get(str).cloned() + } + + fn get_symbol_value(&self, _: &str) -> Option { + unimplemented!() + } + + fn get_symbol_location(&self, _: &str) -> Option { + unimplemented!() + } + + fn get_identifier_def(&self, id: &str) -> Option { + self.id_to_def.get(id).cloned() + } +} + +#[test_case( + vec![ + indoc! {" + def fun(a: int) -> int: + return a + "}, + indoc! {" + class A: + def __init__(self): + self.a: int = 3 + "}, + indoc! {" + class B: + def __init__(self): + self.b: float = 4.3 + + def fun(self): + self.b = self.b + 3.0 + "} + ] +)] +fn test_simple_register(source: Vec<&str>) { + let mut composer = TopLevelComposer::new(); + + for s in source { + let ast = parse_program(s).unwrap(); + let ast = ast[0].clone(); + + composer.register_top_level(ast, None).unwrap(); + } +}