forked from M-Labs/nac3
1
0
Fork 0

nac3core: top level fix duplicate def, start adding tests

This commit is contained in:
ychenfo 2021-08-31 15:22:45 +08:00
parent 7bbd608492
commit 98d032b72a
2 changed files with 93 additions and 5 deletions

View File

@ -22,6 +22,8 @@ pub struct DefinitionId(pub usize);
mod type_annotation; mod type_annotation;
use type_annotation::*; use type_annotation::*;
mod helper; mod helper;
#[cfg(test)]
mod test;
#[derive(Clone)] #[derive(Clone)]
pub struct FunInstance { pub struct FunInstance {
@ -88,6 +90,10 @@ pub struct TopLevelComposer {
pub primitives_ty: PrimitiveStore, pub primitives_ty: PrimitiveStore,
// keyword list to prevent same user-defined name // keyword list to prevent same user-defined name
pub keyword_list: HashSet<String>, pub keyword_list: HashSet<String>,
// to prevent duplicate definition
pub defined_class_name: HashSet<String>,
pub defined_class_method_name: HashSet<String>,
pub defined_function_name: HashSet<String>,
} }
impl Default for TopLevelComposer { impl Default for TopLevelComposer {
@ -130,13 +136,16 @@ impl TopLevelComposer {
"none".into(), "none".into(),
"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 { pub fn make_top_level_context(self) -> TopLevelContext {
TopLevelContext { TopLevelContext {
definitions: RwLock::new( definitions: RwLock::new(
self.definition_ast_list.into_iter().map(|(x, ..)| x).collect::<Vec<_>>(), self.definition_ast_list.into_iter().map(|(x, ..)| x).collect_vec(),
) )
.into(), .into(),
// FIXME: all the big unifier or? // FIXME: all the big unifier or?
@ -148,16 +157,16 @@ impl TopLevelComposer {
self.definition_ast_list.iter().map(|(def, ..)| def.clone()).collect_vec() 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 /// and check duplicate class/method/function definition
pub fn register_top_level( pub fn register_top_level(
&mut self, &mut self,
ast: ast::Stmt<()>, ast: ast::Stmt<()>,
resolver: Option<Arc<Box<dyn SymbolResolver + Send + Sync>>>, resolver: Option<Arc<Box<dyn SymbolResolver + Send + Sync>>>,
) -> Result<(String, DefinitionId), String> { ) -> Result<(String, DefinitionId), String> {
let mut defined_class_name: HashSet<String> = HashSet::new(); let defined_class_name = &mut self.defined_class_name;
let mut defined_class_method_name: HashSet<String> = HashSet::new(); let defined_class_method_name = &mut self.defined_class_method_name;
let mut defined_function_name: HashSet<String> = HashSet::new(); let defined_function_name = &mut self.defined_function_name;
match &ast.node { match &ast.node {
ast::StmtKind::ClassDef { name, body, .. } => { ast::StmtKind::ClassDef { name, body, .. } => {
if self.keyword_list.contains(name) { 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 /// step 1, analyze the type vars associated with top level class
fn analyze_top_level_class_type_var(&mut self) -> Result<(), String> { fn analyze_top_level_class_type_var(&mut self) -> Result<(), String> {
let def_list = &self.definition_ast_list; let def_list = &self.definition_ast_list;

View File

@ -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<String, Type>,
id_to_def: HashMap<String, DefinitionId>,
class_names: HashMap<String, Type>,
}
impl SymbolResolver for Resolver {
fn get_symbol_type(&self, _: &mut Unifier, _: &PrimitiveStore, str: &str) -> Option<Type> {
self.id_to_type.get(str).cloned()
}
fn get_symbol_value(&self, _: &str) -> Option<SymbolValue> {
unimplemented!()
}
fn get_symbol_location(&self, _: &str) -> Option<Location> {
unimplemented!()
}
fn get_identifier_def(&self, id: &str) -> Option<DefinitionId> {
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();
}
}