From 235b6e34d1de0b71c2c8546030a53a4a85fc2f2c Mon Sep 17 00:00:00 2001 From: ychenfo <yc@m-labs.hk> Date: Tue, 7 Sep 2021 00:20:40 +0800 Subject: [PATCH] nac3core: top level derive fmt::Debug, fix dead lock --- nac3core/src/symbol_resolver.rs | 7 +++ nac3core/src/toplevel/mod.rs | 9 ++-- nac3core/src/toplevel/test.rs | 68 +++++++++++++----------- nac3core/src/toplevel/type_annotation.rs | 14 +++-- nac3core/src/typecheck/typedef/mod.rs | 2 +- 5 files changed, 60 insertions(+), 40 deletions(-) diff --git a/nac3core/src/symbol_resolver.rs b/nac3core/src/symbol_resolver.rs index ecf281e1..11ab75a5 100644 --- a/nac3core/src/symbol_resolver.rs +++ b/nac3core/src/symbol_resolver.rs @@ -1,4 +1,5 @@ use std::collections::HashMap; +use std::fmt::Debug; use std::{cell::RefCell, sync::Arc}; use crate::toplevel::{DefinitionId, TopLevelDef}; @@ -219,3 +220,9 @@ impl dyn SymbolResolver + Send + Sync { parse_type_annotation(self, top_level_defs, unifier, primitives, expr) } } + +impl Debug for dyn SymbolResolver + Send + Sync { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "") + } +} \ No newline at end of file diff --git a/nac3core/src/toplevel/mod.rs b/nac3core/src/toplevel/mod.rs index cf24c926..7e3b1329 100644 --- a/nac3core/src/toplevel/mod.rs +++ b/nac3core/src/toplevel/mod.rs @@ -1,4 +1,4 @@ -use std::{borrow::{Borrow, BorrowMut}, collections::{HashMap, HashSet}, iter::FromIterator, ops::{Deref, DerefMut}, sync::Arc}; +use std::{borrow::BorrowMut, collections::{HashMap, HashSet}, iter::FromIterator, ops::{Deref, DerefMut}, sync::Arc}; use super::typecheck::type_inferencer::PrimitiveStore; use super::typecheck::typedef::{FunSignature, FuncArg, SharedUnifier, Type, TypeEnum, Unifier}; @@ -6,11 +6,11 @@ use crate::{ symbol_resolver::SymbolResolver, typecheck::{type_inferencer::CodeLocation, typedef::CallId}, }; -use itertools::{izip, Itertools}; +use itertools::Itertools; use parking_lot::{Mutex, RwLock}; use rustpython_parser::ast::{self, Stmt}; -#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)] +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash, Debug)] pub struct DefinitionId(pub usize); mod type_annotation; @@ -19,7 +19,7 @@ mod helper; #[cfg(test)] mod test; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct FunInstance { pub body: Vec<Stmt<Option<Type>>>, pub calls: HashMap<CodeLocation, CallId>, @@ -27,6 +27,7 @@ pub struct FunInstance { pub unifier_id: usize, } +#[derive(Debug)] pub enum TopLevelDef { Class { // name for error messages and symbols diff --git a/nac3core/src/toplevel/test.rs b/nac3core/src/toplevel/test.rs index 36aabe05..d4b3538c 100644 --- a/nac3core/src/toplevel/test.rs +++ b/nac3core/src/toplevel/test.rs @@ -8,12 +8,12 @@ use crate::{ }, }; use indoc::indoc; -use parking_lot::{Mutex, RwLock}; -use rustpython_parser::{ast::fold::Fold, parser::parse_program}; -use std::{borrow::BorrowMut, collections::{HashMap, HashSet}, sync::Arc}; +use parking_lot::Mutex; +use rustpython_parser::parser::parse_program; +use std::{collections::HashMap, sync::Arc}; use test_case::test_case; -use super::TopLevelComposer; +use super::*; struct Resolver { id_to_type: HashMap<String, Type>, @@ -48,13 +48,13 @@ impl SymbolResolver for Resolver { #[test_case( vec![ indoc! {" - def fun(a: int) -> int: + def fun(a: int32) -> int32: return a "}, indoc! {" class A: def __init__(self): - self.a: int = 3 + self.a: int32 = 3 "}, indoc! {" class B: @@ -71,7 +71,7 @@ impl SymbolResolver for Resolver { indoc! {" class C(B): def __init__(self): - self.c: int = 4 + self.c: int32 = 4 self.a: bool = True "} ] @@ -90,35 +90,30 @@ fn test_simple_register(source: Vec<&str>) { #[test_case( vec![ indoc! {" - def fun(a: int) -> int: + def fun(a: int32) -> int32: 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 - // "}, - // indoc! {" - // def foo(a: float): - // a + 1.0 - // "}, - // indoc! {" - // class C(B): - // def __init__(self): - // self.c: int = 4 - // self.a: bool = True - // "} + indoc! {" + def foo(a: float): + a + 1.0 + "}, + indoc! {" + def f(b: int64) -> int32: + return 3 + "}, + ], + vec![ + "fn[[a=0], 0]", + "fn[[a=2], 4]", + "fn[[b=1], 0]", + ], + vec![ + "fun", + "foo", + "f" ] )] -fn test_simple_analyze(source: Vec<&str>) { +fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&str>) { let mut composer = TopLevelComposer::new(); let resolver = Arc::new(Mutex::new(Box::new(Resolver { @@ -136,4 +131,13 @@ fn test_simple_analyze(source: Vec<&str>) { } composer.start_analysis().unwrap(); + + for (i, (def, _)) in composer.definition_ast_list.into_iter().enumerate() { + let def = &*def.read(); + if let TopLevelDef::Function { signature, name, .. } = def { + let ty_str = composer.unifier.stringify(*signature, &mut |id| id.to_string(), &mut |id| id.to_string()); + assert_eq!(ty_str, tys[i]); + assert_eq!(name, names[i]); + } + } } diff --git a/nac3core/src/toplevel/type_annotation.rs b/nac3core/src/toplevel/type_annotation.rs index a38d99d4..eba78733 100644 --- a/nac3core/src/toplevel/type_annotation.rs +++ b/nac3core/src/toplevel/type_annotation.rs @@ -2,7 +2,7 @@ use crate::typecheck::typedef::TypeVarMeta; use super::*; -#[derive(Clone)] +#[derive(Clone, Debug)] pub enum TypeAnnotation { PrimitiveKind(Type), // we use type vars kind at params to represent self type @@ -33,7 +33,12 @@ pub fn parse_ast_to_type_annotation_kinds<T>( "bool" => Ok(TypeAnnotation::PrimitiveKind(primitives.bool)), "None" => Ok(TypeAnnotation::PrimitiveKind(primitives.none)), x => { - if let Some(obj_id) = resolver.lock().get_identifier_def(x) { + if let Some(obj_id) = { + // write this way because the lock in the if/let construct lives + // for the whole if let construct + let id = resolver.lock().get_identifier_def(x); + id + } { let def = top_level_defs[obj_id.0].read(); if let TopLevelDef::Class { type_vars, .. } = &*def { // also check param number here @@ -47,7 +52,10 @@ pub fn parse_ast_to_type_annotation_kinds<T>( } else { Err("function cannot be used as a type".into()) } - } else if let Some(ty) = resolver.lock().get_symbol_type(unifier, primitives, id) { + } else if let Some(ty) = { + let ty = resolver.lock().get_symbol_type(unifier, primitives, id); + ty + } { if let TypeEnum::TVar { .. } = unifier.get_ty(ty).as_ref() { Ok(TypeAnnotation::TypeVarKind(ty)) } else { diff --git a/nac3core/src/typecheck/typedef/mod.rs b/nac3core/src/typecheck/typedef/mod.rs index aea8642c..e4599945 100644 --- a/nac3core/src/typecheck/typedef/mod.rs +++ b/nac3core/src/typecheck/typedef/mod.rs @@ -16,7 +16,7 @@ mod test; /// Handle for a type, implementated as a key in the unification table. pub type Type = UnificationKey; -#[derive(Clone, Copy, PartialEq, Eq)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub struct CallId(usize); pub type Mapping<K, V = Type> = HashMap<K, V>;