forked from M-Labs/nac3
1
0
Fork 0

nac3core: top level derive fmt::Debug, fix dead lock

This commit is contained in:
ychenfo 2021-09-07 00:20:40 +08:00
parent 54b4572c5f
commit 235b6e34d1
5 changed files with 60 additions and 40 deletions

View File

@ -1,4 +1,5 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt::Debug;
use std::{cell::RefCell, sync::Arc}; use std::{cell::RefCell, sync::Arc};
use crate::toplevel::{DefinitionId, TopLevelDef}; use crate::toplevel::{DefinitionId, TopLevelDef};
@ -219,3 +220,9 @@ impl dyn SymbolResolver + Send + Sync {
parse_type_annotation(self, top_level_defs, unifier, primitives, expr) 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, "")
}
}

View File

@ -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::type_inferencer::PrimitiveStore;
use super::typecheck::typedef::{FunSignature, FuncArg, SharedUnifier, Type, TypeEnum, Unifier}; use super::typecheck::typedef::{FunSignature, FuncArg, SharedUnifier, Type, TypeEnum, Unifier};
@ -6,11 +6,11 @@ use crate::{
symbol_resolver::SymbolResolver, symbol_resolver::SymbolResolver,
typecheck::{type_inferencer::CodeLocation, typedef::CallId}, typecheck::{type_inferencer::CodeLocation, typedef::CallId},
}; };
use itertools::{izip, Itertools}; use itertools::Itertools;
use parking_lot::{Mutex, RwLock}; use parking_lot::{Mutex, RwLock};
use rustpython_parser::ast::{self, Stmt}; 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); pub struct DefinitionId(pub usize);
mod type_annotation; mod type_annotation;
@ -19,7 +19,7 @@ mod helper;
#[cfg(test)] #[cfg(test)]
mod test; mod test;
#[derive(Clone)] #[derive(Clone, Debug)]
pub struct FunInstance { pub struct FunInstance {
pub body: Vec<Stmt<Option<Type>>>, pub body: Vec<Stmt<Option<Type>>>,
pub calls: HashMap<CodeLocation, CallId>, pub calls: HashMap<CodeLocation, CallId>,
@ -27,6 +27,7 @@ pub struct FunInstance {
pub unifier_id: usize, pub unifier_id: usize,
} }
#[derive(Debug)]
pub enum TopLevelDef { pub enum TopLevelDef {
Class { Class {
// name for error messages and symbols // name for error messages and symbols

View File

@ -8,12 +8,12 @@ use crate::{
}, },
}; };
use indoc::indoc; use indoc::indoc;
use parking_lot::{Mutex, RwLock}; use parking_lot::Mutex;
use rustpython_parser::{ast::fold::Fold, parser::parse_program}; use rustpython_parser::parser::parse_program;
use std::{borrow::BorrowMut, collections::{HashMap, HashSet}, sync::Arc}; use std::{collections::HashMap, sync::Arc};
use test_case::test_case; use test_case::test_case;
use super::TopLevelComposer; use super::*;
struct Resolver { struct Resolver {
id_to_type: HashMap<String, Type>, id_to_type: HashMap<String, Type>,
@ -48,13 +48,13 @@ impl SymbolResolver for Resolver {
#[test_case( #[test_case(
vec![ vec![
indoc! {" indoc! {"
def fun(a: int) -> int: def fun(a: int32) -> int32:
return a return a
"}, "},
indoc! {" indoc! {"
class A: class A:
def __init__(self): def __init__(self):
self.a: int = 3 self.a: int32 = 3
"}, "},
indoc! {" indoc! {"
class B: class B:
@ -71,7 +71,7 @@ impl SymbolResolver for Resolver {
indoc! {" indoc! {"
class C(B): class C(B):
def __init__(self): def __init__(self):
self.c: int = 4 self.c: int32 = 4
self.a: bool = True self.a: bool = True
"} "}
] ]
@ -90,35 +90,30 @@ fn test_simple_register(source: Vec<&str>) {
#[test_case( #[test_case(
vec![ vec![
indoc! {" indoc! {"
def fun(a: int) -> int: def fun(a: int32) -> int32:
return a return a
"}, "},
// indoc! {" indoc! {"
// class A: def foo(a: float):
// def __init__(self): a + 1.0
// self.a: int = 3 "},
// "}, indoc! {"
// indoc! {" def f(b: int64) -> int32:
// class B: return 3
// def __init__(self): "},
// self.b: float = 4.3 ],
vec![
// def fun(self): "fn[[a=0], 0]",
// self.b = self.b + 3.0 "fn[[a=2], 4]",
// "}, "fn[[b=1], 0]",
// indoc! {" ],
// def foo(a: float): vec![
// a + 1.0 "fun",
// "}, "foo",
// indoc! {" "f"
// class C(B):
// def __init__(self):
// self.c: int = 4
// self.a: bool = True
// "}
] ]
)] )]
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 mut composer = TopLevelComposer::new();
let resolver = Arc::new(Mutex::new(Box::new(Resolver { let resolver = Arc::new(Mutex::new(Box::new(Resolver {
@ -136,4 +131,13 @@ fn test_simple_analyze(source: Vec<&str>) {
} }
composer.start_analysis().unwrap(); 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]);
}
}
} }

View File

@ -2,7 +2,7 @@ use crate::typecheck::typedef::TypeVarMeta;
use super::*; use super::*;
#[derive(Clone)] #[derive(Clone, Debug)]
pub enum TypeAnnotation { pub enum TypeAnnotation {
PrimitiveKind(Type), PrimitiveKind(Type),
// we use type vars kind at params to represent self 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)), "bool" => Ok(TypeAnnotation::PrimitiveKind(primitives.bool)),
"None" => Ok(TypeAnnotation::PrimitiveKind(primitives.none)), "None" => Ok(TypeAnnotation::PrimitiveKind(primitives.none)),
x => { 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(); let def = top_level_defs[obj_id.0].read();
if let TopLevelDef::Class { type_vars, .. } = &*def { if let TopLevelDef::Class { type_vars, .. } = &*def {
// also check param number here // also check param number here
@ -47,7 +52,10 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
} else { } else {
Err("function cannot be used as a type".into()) 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() { if let TypeEnum::TVar { .. } = unifier.get_ty(ty).as_ref() {
Ok(TypeAnnotation::TypeVarKind(ty)) Ok(TypeAnnotation::TypeVarKind(ty))
} else { } else {

View File

@ -16,7 +16,7 @@ mod test;
/// Handle for a type, implementated as a key in the unification table. /// Handle for a type, implementated as a key in the unification table.
pub type Type = UnificationKey; pub type Type = UnificationKey;
#[derive(Clone, Copy, PartialEq, Eq)] #[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct CallId(usize); pub struct CallId(usize);
pub type Mapping<K, V = Type> = HashMap<K, V>; pub type Mapping<K, V = Type> = HashMap<K, V>;