forked from M-Labs/nac3
nac3core: top level derive fmt::Debug, fix dead lock
This commit is contained in:
parent
54b4572c5f
commit
235b6e34d1
|
@ -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, "")
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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>;
|
||||||
|
|
Loading…
Reference in New Issue