forked from M-Labs/nac3
core: Use BTreeMap for type variable mapping
There have been multiple instances where I had the need to iterate over type variables, only to discover that the traversal order is arbitrary. This commit fixes that by adding SortedMapping, which utilizes BTreeMap internally to guarantee a traversal order. All instances of VarMap are now refactored to use this to ensure that type variables are iterated in the order of its variable ID, which should be monotonically incremented by the unifier.
This commit is contained in:
parent
234a6bde2a
commit
77de24ef74
|
@ -7,7 +7,7 @@ use nac3core::{
|
||||||
},
|
},
|
||||||
symbol_resolver::ValueEnum,
|
symbol_resolver::ValueEnum,
|
||||||
toplevel::{DefinitionId, GenCall, helper::PRIMITIVE_DEF_IDS},
|
toplevel::{DefinitionId, GenCall, helper::PRIMITIVE_DEF_IDS},
|
||||||
typecheck::typedef::{FunSignature, FuncArg, Type, TypeEnum}
|
typecheck::typedef::{FunSignature, FuncArg, Type, TypeEnum, VarMap}
|
||||||
};
|
};
|
||||||
|
|
||||||
use nac3parser::ast::{Expr, ExprKind, Located, Stmt, StmtKind, StrRef};
|
use nac3parser::ast::{Expr, ExprKind, Located, Stmt, StmtKind, StrRef};
|
||||||
|
@ -667,7 +667,7 @@ pub fn attributes_writeback(
|
||||||
default_value: None
|
default_value: None
|
||||||
}).collect(),
|
}).collect(),
|
||||||
ret: ctx.primitives.none,
|
ret: ctx.primitives.none,
|
||||||
vars: HashMap::default()
|
vars: VarMap::default()
|
||||||
};
|
};
|
||||||
let args: Vec<_> = values.into_iter().map(|(_, val)| (None, ValueEnum::Dynamic(val))).collect();
|
let args: Vec<_> = values.into_iter().map(|(_, val)| (None, ValueEnum::Dynamic(val))).collect();
|
||||||
if let Err(e) = rpc_codegen_callback_fn(ctx, None, (&fun, PRIMITIVE_DEF_IDS.int32), args, generator) {
|
if let Err(e) = rpc_codegen_callback_fn(ctx, None, (&fun, PRIMITIVE_DEF_IDS.int32), args, generator) {
|
||||||
|
|
|
@ -16,7 +16,7 @@ use inkwell::{
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use nac3core::codegen::{CodeGenLLVMOptions, CodeGenTargetMachineOptions, gen_func_impl};
|
use nac3core::codegen::{CodeGenLLVMOptions, CodeGenTargetMachineOptions, gen_func_impl};
|
||||||
use nac3core::toplevel::builtins::get_exn_constructor;
|
use nac3core::toplevel::builtins::get_exn_constructor;
|
||||||
use nac3core::typecheck::typedef::{TypeEnum, Unifier};
|
use nac3core::typecheck::typedef::{TypeEnum, Unifier, VarMap};
|
||||||
use nac3parser::{
|
use nac3parser::{
|
||||||
ast::{ExprKind, Stmt, StmtKind, StrRef},
|
ast::{ExprKind, Stmt, StmtKind, StrRef},
|
||||||
parser::parse_program,
|
parser::parse_program,
|
||||||
|
@ -476,7 +476,7 @@ impl Nac3 {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let fun_signature =
|
let fun_signature =
|
||||||
FunSignature { args: vec![], ret: self.primitive.none, vars: HashMap::new() };
|
FunSignature { args: vec![], ret: self.primitive.none, vars: VarMap::new() };
|
||||||
let mut store = ConcreteTypeStore::new();
|
let mut store = ConcreteTypeStore::new();
|
||||||
let mut cache = HashMap::new();
|
let mut cache = HashMap::new();
|
||||||
let signature =
|
let signature =
|
||||||
|
@ -816,7 +816,7 @@ impl Nac3 {
|
||||||
let builtins = vec![
|
let builtins = vec![
|
||||||
(
|
(
|
||||||
"now_mu".into(),
|
"now_mu".into(),
|
||||||
FunSignature { args: vec![], ret: primitive.int64, vars: HashMap::new() },
|
FunSignature { args: vec![], ret: primitive.int64, vars: VarMap::new() },
|
||||||
Arc::new(GenCall::new(Box::new(move |ctx, _, _, _, _| {
|
Arc::new(GenCall::new(Box::new(move |ctx, _, _, _, _| {
|
||||||
Ok(Some(time_fns.emit_now_mu(ctx)))
|
Ok(Some(time_fns.emit_now_mu(ctx)))
|
||||||
}))),
|
}))),
|
||||||
|
@ -830,7 +830,7 @@ impl Nac3 {
|
||||||
default_value: None,
|
default_value: None,
|
||||||
}],
|
}],
|
||||||
ret: primitive.none,
|
ret: primitive.none,
|
||||||
vars: HashMap::new(),
|
vars: VarMap::new(),
|
||||||
},
|
},
|
||||||
Arc::new(GenCall::new(Box::new(move |ctx, _, fun, args, generator| {
|
Arc::new(GenCall::new(Box::new(move |ctx, _, fun, args, generator| {
|
||||||
let arg_ty = fun.0.args[0].ty;
|
let arg_ty = fun.0.args[0].ty;
|
||||||
|
@ -848,7 +848,7 @@ impl Nac3 {
|
||||||
default_value: None,
|
default_value: None,
|
||||||
}],
|
}],
|
||||||
ret: primitive.none,
|
ret: primitive.none,
|
||||||
vars: HashMap::new(),
|
vars: VarMap::new(),
|
||||||
},
|
},
|
||||||
Arc::new(GenCall::new(Box::new(move |ctx, _, fun, args, generator| {
|
Arc::new(GenCall::new(Box::new(move |ctx, _, fun, args, generator| {
|
||||||
let arg_ty = fun.0.args[0].ty;
|
let arg_ty = fun.0.args[0].ty;
|
||||||
|
|
|
@ -10,7 +10,7 @@ use nac3core::{
|
||||||
},
|
},
|
||||||
typecheck::{
|
typecheck::{
|
||||||
type_inferencer::PrimitiveStore,
|
type_inferencer::PrimitiveStore,
|
||||||
typedef::{Type, TypeEnum, Unifier},
|
typedef::{Type, TypeEnum, Unifier, VarMap},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use nac3parser::ast::{self, StrRef};
|
use nac3parser::ast::{self, StrRef};
|
||||||
|
@ -519,7 +519,7 @@ impl InnerResolver {
|
||||||
.iter()
|
.iter()
|
||||||
.zip(args.iter())
|
.zip(args.iter())
|
||||||
.map(|((id, _), ty)| (*id, *ty))
|
.map(|((id, _), ty)| (*id, *ty))
|
||||||
.collect::<HashMap<_, _>>()
|
.collect::<VarMap>()
|
||||||
};
|
};
|
||||||
Ok(Ok((unifier.subst(origin_ty, &subst).unwrap_or(origin_ty), true)))
|
Ok(Ok((unifier.subst(origin_ty, &subst).unwrap_or(origin_ty), true)))
|
||||||
}
|
}
|
||||||
|
@ -722,7 +722,7 @@ impl InnerResolver {
|
||||||
assert_eq!(*id, *id_var);
|
assert_eq!(*id, *id_var);
|
||||||
(*id, unifier.get_fresh_var_with_range(range, *name, *loc).0)
|
(*id, unifier.get_fresh_var_with_range(range, *name, *loc).0)
|
||||||
})
|
})
|
||||||
.collect::<HashMap<_, _>>();
|
.collect::<VarMap>();
|
||||||
return Ok(Ok(unifier.subst(primitives.option, &var_map).unwrap()))
|
return Ok(Ok(unifier.subst(primitives.option, &var_map).unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -734,7 +734,7 @@ impl InnerResolver {
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let new_var_map: HashMap<_, _> = params.iter().map(|(id, _)| (*id, ty)).collect();
|
let new_var_map: VarMap = params.iter().map(|(id, _)| (*id, ty)).collect();
|
||||||
let res = unifier.subst(extracted_ty, &new_var_map).unwrap_or(extracted_ty);
|
let res = unifier.subst(extracted_ty, &new_var_map).unwrap_or(extracted_ty);
|
||||||
Ok(Ok(res))
|
Ok(Ok(res))
|
||||||
}
|
}
|
||||||
|
@ -751,7 +751,7 @@ impl InnerResolver {
|
||||||
assert_eq!(*id, *id_var);
|
assert_eq!(*id, *id_var);
|
||||||
(*id, unifier.get_fresh_var_with_range(range, *name, *loc).0)
|
(*id, unifier.get_fresh_var_with_range(range, *name, *loc).0)
|
||||||
})
|
})
|
||||||
.collect::<HashMap<_, _>>();
|
.collect::<VarMap>();
|
||||||
let mut instantiate_obj = || {
|
let mut instantiate_obj = || {
|
||||||
// loop through non-function fields of the class to get the instantiated value
|
// loop through non-function fields of the class to get the instantiated value
|
||||||
for field in fields {
|
for field in fields {
|
||||||
|
|
|
@ -3,7 +3,7 @@ use crate::{
|
||||||
toplevel::DefinitionId,
|
toplevel::DefinitionId,
|
||||||
typecheck::{
|
typecheck::{
|
||||||
type_inferencer::PrimitiveStore,
|
type_inferencer::PrimitiveStore,
|
||||||
typedef::{FunSignature, FuncArg, Type, TypeEnum, Unifier},
|
typedef::{FunSignature, FuncArg, Type, TypeEnum, Unifier, VarMap},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -274,7 +274,7 @@ impl ConcreteTypeStore {
|
||||||
params: params
|
params: params
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(id, cty)| (*id, self.to_unifier_type(unifier, primitives, *cty, cache)))
|
.map(|(id, cty)| (*id, self.to_unifier_type(unifier, primitives, *cty, cache)))
|
||||||
.collect::<HashMap<_, _>>(),
|
.collect::<VarMap>(),
|
||||||
},
|
},
|
||||||
ConcreteTypeEnum::TFunc { args, ret, vars } => TypeEnum::TFunc(FunSignature {
|
ConcreteTypeEnum::TFunc { args, ret, vars } => TypeEnum::TFunc(FunSignature {
|
||||||
args: args
|
args: args
|
||||||
|
@ -289,7 +289,7 @@ impl ConcreteTypeStore {
|
||||||
vars: vars
|
vars: vars
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(id, cty)| (*id, self.to_unifier_type(unifier, primitives, *cty, cache)))
|
.map(|(id, cty)| (*id, self.to_unifier_type(unifier, primitives, *cty, cache)))
|
||||||
.collect::<HashMap<_, _>>(),
|
.collect::<VarMap>(),
|
||||||
}),
|
}),
|
||||||
ConcreteTypeEnum::TLiteral { values, .. } => TypeEnum::TLiteral {
|
ConcreteTypeEnum::TLiteral { values, .. } => TypeEnum::TLiteral {
|
||||||
values: values.clone(),
|
values: values.clone(),
|
||||||
|
|
|
@ -20,7 +20,7 @@ use crate::{
|
||||||
TopLevelDef,
|
TopLevelDef,
|
||||||
},
|
},
|
||||||
typecheck::{
|
typecheck::{
|
||||||
typedef::{FunSignature, FuncArg, Type, TypeEnum, Unifier},
|
typedef::{FunSignature, FuncArg, Type, TypeEnum, Unifier, VarMap},
|
||||||
magic_methods::{binop_name, binop_assign_name},
|
magic_methods::{binop_name, binop_assign_name},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -41,7 +41,7 @@ use super::{CodeGenerator, llvm_intrinsics::call_memcpy_generic, need_sret};
|
||||||
pub fn get_subst_key(
|
pub fn get_subst_key(
|
||||||
unifier: &mut Unifier,
|
unifier: &mut Unifier,
|
||||||
obj: Option<Type>,
|
obj: Option<Type>,
|
||||||
fun_vars: &HashMap<u32, Type>,
|
fun_vars: &VarMap,
|
||||||
filter: Option<&Vec<u32>>,
|
filter: Option<&Vec<u32>>,
|
||||||
) -> String {
|
) -> String {
|
||||||
let mut vars = obj
|
let mut vars = obj
|
||||||
|
|
|
@ -25,6 +25,7 @@ use nac3parser::{
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use crate::typecheck::typedef::VarMap;
|
||||||
|
|
||||||
struct Resolver {
|
struct Resolver {
|
||||||
id_to_type: HashMap<StrRef, Type>,
|
id_to_type: HashMap<StrRef, Type>,
|
||||||
|
@ -111,7 +112,7 @@ fn test_primitives() {
|
||||||
FuncArg { name: "b".into(), ty: primitives.int32, default_value: None },
|
FuncArg { name: "b".into(), ty: primitives.int32, default_value: None },
|
||||||
],
|
],
|
||||||
ret: primitives.int32,
|
ret: primitives.int32,
|
||||||
vars: HashMap::new(),
|
vars: VarMap::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut store = ConcreteTypeStore::new();
|
let mut store = ConcreteTypeStore::new();
|
||||||
|
@ -258,7 +259,7 @@ fn test_simple_call() {
|
||||||
let signature = FunSignature {
|
let signature = FunSignature {
|
||||||
args: vec![FuncArg { name: "a".into(), ty: primitives.int32, default_value: None }],
|
args: vec![FuncArg { name: "a".into(), ty: primitives.int32, default_value: None }],
|
||||||
ret: primitives.int32,
|
ret: primitives.int32,
|
||||||
vars: HashMap::new(),
|
vars: VarMap::new(),
|
||||||
};
|
};
|
||||||
let fun_ty = unifier.add_ty(TypeEnum::TFunc(signature.clone()));
|
let fun_ty = unifier.add_ty(TypeEnum::TFunc(signature.clone()));
|
||||||
let mut store = ConcreteTypeStore::new();
|
let mut store = ConcreteTypeStore::new();
|
||||||
|
|
|
@ -8,7 +8,7 @@ use crate::{
|
||||||
toplevel::{DefinitionId, TopLevelDef, type_annotation::TypeAnnotation},
|
toplevel::{DefinitionId, TopLevelDef, type_annotation::TypeAnnotation},
|
||||||
typecheck::{
|
typecheck::{
|
||||||
type_inferencer::PrimitiveStore,
|
type_inferencer::PrimitiveStore,
|
||||||
typedef::{Type, TypeEnum, Unifier},
|
typedef::{Type, TypeEnum, Unifier, VarMap},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use inkwell::values::{BasicValueEnum, FloatValue, IntValue, PointerValue, StructValue};
|
use inkwell::values::{BasicValueEnum, FloatValue, IntValue, PointerValue, StructValue};
|
||||||
|
@ -426,7 +426,7 @@ pub fn parse_type_annotation<T>(
|
||||||
Ok(unifier.add_ty(TypeEnum::TObj {
|
Ok(unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id,
|
obj_id,
|
||||||
fields,
|
fields,
|
||||||
params: HashMap::default(),
|
params: VarMap::default(),
|
||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
Err(HashSet::from([
|
Err(HashSet::from([
|
||||||
|
@ -515,7 +515,7 @@ pub fn parse_type_annotation<T>(
|
||||||
),
|
),
|
||||||
]))
|
]))
|
||||||
}
|
}
|
||||||
let mut subst = HashMap::new();
|
let mut subst = VarMap::new();
|
||||||
for (var, ty) in izip!(type_vars.iter(), types.iter()) {
|
for (var, ty) in izip!(type_vars.iter(), types.iter()) {
|
||||||
let id = if let TypeEnum::TVar { id, .. } = &*unifier.get_ty(*var) {
|
let id = if let TypeEnum::TVar { id, .. } = &*unifier.get_ty(*var) {
|
||||||
*id
|
*id
|
||||||
|
|
|
@ -10,6 +10,7 @@ use crate::{
|
||||||
symbol_resolver::SymbolValue,
|
symbol_resolver::SymbolValue,
|
||||||
toplevel::helper::PRIMITIVE_DEF_IDS,
|
toplevel::helper::PRIMITIVE_DEF_IDS,
|
||||||
toplevel::numpy::*,
|
toplevel::numpy::*,
|
||||||
|
typecheck::typedef::VarMap,
|
||||||
};
|
};
|
||||||
use inkwell::{
|
use inkwell::{
|
||||||
attributes::{Attribute, AttributeLoc},
|
attributes::{Attribute, AttributeLoc},
|
||||||
|
@ -56,12 +57,12 @@ pub fn get_exn_constructor(
|
||||||
let exn_type = unifier.add_ty(TypeEnum::TObj {
|
let exn_type = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: DefinitionId(class_id),
|
obj_id: DefinitionId(class_id),
|
||||||
fields: exception_fields.iter().map(|(a, b, c)| (*a, (*b, *c))).collect(),
|
fields: exception_fields.iter().map(|(a, b, c)| (*a, (*b, *c))).collect(),
|
||||||
params: HashMap::default(),
|
params: VarMap::default(),
|
||||||
});
|
});
|
||||||
let signature = unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
let signature = unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
||||||
args: exn_cons_args,
|
args: exn_cons_args,
|
||||||
ret: exn_type,
|
ret: exn_type,
|
||||||
vars: HashMap::default(),
|
vars: VarMap::default(),
|
||||||
}));
|
}));
|
||||||
let fun_def = TopLevelDef::Function {
|
let fun_def = TopLevelDef::Function {
|
||||||
name: format!("{name}.__init__"),
|
name: format!("{name}.__init__"),
|
||||||
|
@ -100,7 +101,7 @@ pub fn get_exn_constructor(
|
||||||
/// * `codegen_callback`: A lambda generating LLVM IR for the implementation of this function.
|
/// * `codegen_callback`: A lambda generating LLVM IR for the implementation of this function.
|
||||||
fn create_fn_by_codegen(
|
fn create_fn_by_codegen(
|
||||||
primitives: &mut (PrimitiveStore, Unifier),
|
primitives: &mut (PrimitiveStore, Unifier),
|
||||||
var_map: &HashMap<u32, Type>,
|
var_map: &VarMap,
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
ret_ty: Type,
|
ret_ty: Type,
|
||||||
param_ty: &[(Type, &'static str)],
|
param_ty: &[(Type, &'static str)],
|
||||||
|
@ -136,7 +137,7 @@ fn create_fn_by_codegen(
|
||||||
/// * `intrinsic_fn`: The fully-qualified name of the LLVM intrinsic function.
|
/// * `intrinsic_fn`: The fully-qualified name of the LLVM intrinsic function.
|
||||||
fn create_fn_by_intrinsic(
|
fn create_fn_by_intrinsic(
|
||||||
primitives: &mut (PrimitiveStore, Unifier),
|
primitives: &mut (PrimitiveStore, Unifier),
|
||||||
var_map: &HashMap<u32, Type>,
|
var_map: &VarMap,
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
ret_ty: Type,
|
ret_ty: Type,
|
||||||
params: &[(Type, &'static str)],
|
params: &[(Type, &'static str)],
|
||||||
|
@ -200,7 +201,7 @@ fn create_fn_by_intrinsic(
|
||||||
/// already implied by the C ABI.
|
/// already implied by the C ABI.
|
||||||
fn create_fn_by_extern(
|
fn create_fn_by_extern(
|
||||||
primitives: &mut (PrimitiveStore, Unifier),
|
primitives: &mut (PrimitiveStore, Unifier),
|
||||||
var_map: &HashMap<u32, Type>,
|
var_map: &VarMap,
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
ret_ty: Type,
|
ret_ty: Type,
|
||||||
params: &[(Type, &'static str)],
|
params: &[(Type, &'static str)],
|
||||||
|
@ -295,7 +296,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
||||||
Some("N".into()),
|
Some("N".into()),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
let var_map: HashMap<_, _> = vec![(num_ty.1, num_ty.0)].into_iter().collect();
|
let var_map: VarMap = vec![(num_ty.1, num_ty.0)].into_iter().collect();
|
||||||
let exception_fields = vec![
|
let exception_fields = vec![
|
||||||
("__name__".into(), int32, true),
|
("__name__".into(), int32, true),
|
||||||
("__file__".into(), string, true),
|
("__file__".into(), string, true),
|
||||||
|
@ -1057,7 +1058,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
ret: range,
|
ret: range,
|
||||||
vars: HashMap::default(),
|
vars: VarMap::default(),
|
||||||
})),
|
})),
|
||||||
var_id: Vec::default(),
|
var_id: Vec::default(),
|
||||||
instance_to_symbol: HashMap::default(),
|
instance_to_symbol: HashMap::default(),
|
||||||
|
@ -1149,7 +1150,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
||||||
signature: primitives.1.add_ty(TypeEnum::TFunc(FunSignature {
|
signature: primitives.1.add_ty(TypeEnum::TFunc(FunSignature {
|
||||||
args: vec![FuncArg { name: "s".into(), ty: string, default_value: None }],
|
args: vec![FuncArg { name: "s".into(), ty: string, default_value: None }],
|
||||||
ret: string,
|
ret: string,
|
||||||
vars: HashMap::default(),
|
vars: VarMap::default(),
|
||||||
})),
|
})),
|
||||||
var_id: Vec::default(),
|
var_id: Vec::default(),
|
||||||
instance_to_symbol: HashMap::default(),
|
instance_to_symbol: HashMap::default(),
|
||||||
|
@ -1971,7 +1972,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
||||||
signature: primitives.1.add_ty(TypeEnum::TFunc(FunSignature {
|
signature: primitives.1.add_ty(TypeEnum::TFunc(FunSignature {
|
||||||
args: vec![FuncArg { name: "n".into(), ty: option_ty_var, default_value: None }],
|
args: vec![FuncArg { name: "n".into(), ty: option_ty_var, default_value: None }],
|
||||||
ret: primitives.0.option,
|
ret: primitives.0.option,
|
||||||
vars: HashMap::from([(option_ty_var_id, option_ty_var)]),
|
vars: VarMap::from([(option_ty_var_id, option_ty_var)]),
|
||||||
})),
|
})),
|
||||||
var_id: vec![option_ty_var_id],
|
var_id: vec![option_ty_var_id],
|
||||||
instance_to_symbol: HashMap::default(),
|
instance_to_symbol: HashMap::default(),
|
||||||
|
|
|
@ -4,7 +4,10 @@ use std::rc::Rc;
|
||||||
use crate::{
|
use crate::{
|
||||||
codegen::{expr::get_subst_key, stmt::exn_constructor},
|
codegen::{expr::get_subst_key, stmt::exn_constructor},
|
||||||
symbol_resolver::SymbolValue,
|
symbol_resolver::SymbolValue,
|
||||||
typecheck::type_inferencer::{FunctionData, Inferencer},
|
typecheck::{
|
||||||
|
type_inferencer::{FunctionData, Inferencer},
|
||||||
|
typedef::VarMap,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -844,7 +847,7 @@ impl TopLevelComposer {
|
||||||
let resolver = resolver.unwrap();
|
let resolver = resolver.unwrap();
|
||||||
let resolver = &**resolver;
|
let resolver = &**resolver;
|
||||||
|
|
||||||
let mut function_var_map: HashMap<u32, Type> = HashMap::new();
|
let mut function_var_map = VarMap::new();
|
||||||
let arg_types = {
|
let arg_types = {
|
||||||
// make sure no duplicate parameter
|
// make sure no duplicate parameter
|
||||||
let mut defined_parameter_name: HashSet<_> = HashSet::new();
|
let mut defined_parameter_name: HashSet<_> = HashSet::new();
|
||||||
|
@ -1082,7 +1085,7 @@ impl TopLevelComposer {
|
||||||
let (method_dummy_ty, method_id) =
|
let (method_dummy_ty, method_id) =
|
||||||
Self::get_class_method_def_info(class_methods_def, *name)?;
|
Self::get_class_method_def_info(class_methods_def, *name)?;
|
||||||
|
|
||||||
let mut method_var_map: HashMap<u32, Type> = HashMap::new();
|
let mut method_var_map = VarMap::new();
|
||||||
|
|
||||||
let arg_types: Vec<FuncArg> = {
|
let arg_types: Vec<FuncArg> = {
|
||||||
// check method parameters cannot have same name
|
// check method parameters cannot have same name
|
||||||
|
@ -1574,7 +1577,7 @@ impl TopLevelComposer {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
ret: self_type,
|
ret: self_type,
|
||||||
vars: HashMap::default(),
|
vars: VarMap::default(),
|
||||||
}));
|
}));
|
||||||
let cons_fun = TopLevelDef::Function {
|
let cons_fun = TopLevelDef::Function {
|
||||||
name: format!("{}.{}", class_name, "__init__"),
|
name: format!("{}.{}", class_name, "__init__"),
|
||||||
|
@ -1598,7 +1601,7 @@ impl TopLevelComposer {
|
||||||
// get the class constructor type correct
|
// get the class constructor type correct
|
||||||
let (contor_args, contor_type_vars) = {
|
let (contor_args, contor_type_vars) = {
|
||||||
let mut constructor_args: Vec<FuncArg> = Vec::new();
|
let mut constructor_args: Vec<FuncArg> = Vec::new();
|
||||||
let mut type_vars: HashMap<u32, Type> = HashMap::new();
|
let mut type_vars = VarMap::new();
|
||||||
for (name, func_sig, id) in methods {
|
for (name, func_sig, id) in methods {
|
||||||
if *name == init_str_id {
|
if *name == init_str_id {
|
||||||
init_id = Some(*id);
|
init_id = Some(*id);
|
||||||
|
@ -1749,13 +1752,13 @@ impl TopLevelComposer {
|
||||||
})
|
})
|
||||||
.multi_cartesian_product()
|
.multi_cartesian_product()
|
||||||
.collect_vec();
|
.collect_vec();
|
||||||
let mut result: Vec<HashMap<u32, Type>> = Vec::default();
|
let mut result: Vec<VarMap> = Vec::default();
|
||||||
for comb in var_combs {
|
for comb in var_combs {
|
||||||
result.push(vars.keys().copied().zip(comb).collect());
|
result.push(vars.keys().copied().zip(comb).collect());
|
||||||
}
|
}
|
||||||
// NOTE: if is empty, means no type var, append a empty subst, ok to do this?
|
// NOTE: if is empty, means no type var, append a empty subst, ok to do this?
|
||||||
if result.is_empty() {
|
if result.is_empty() {
|
||||||
result.push(HashMap::new());
|
result.push(VarMap::new());
|
||||||
}
|
}
|
||||||
(result, no_ranges)
|
(result, no_ranges)
|
||||||
};
|
};
|
||||||
|
@ -1795,7 +1798,7 @@ impl TopLevelComposer {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<HashMap<_, _>>()
|
.collect::<VarMap>()
|
||||||
};
|
};
|
||||||
unifier.subst(self_type, &subst_for_self).unwrap_or(self_type)
|
unifier.subst(self_type, &subst_for_self).unwrap_or(self_type)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
use crate::symbol_resolver::SymbolValue;
|
use crate::symbol_resolver::SymbolValue;
|
||||||
use crate::typecheck::typedef::Mapping;
|
use crate::typecheck::typedef::{Mapping, VarMap};
|
||||||
use nac3parser::ast::{Constant, Location};
|
use nac3parser::ast::{Constant, Location};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -112,37 +112,37 @@ impl TopLevelComposer {
|
||||||
let int32 = unifier.add_ty(TypeEnum::TObj {
|
let int32 = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.int32,
|
obj_id: PRIMITIVE_DEF_IDS.int32,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let int64 = unifier.add_ty(TypeEnum::TObj {
|
let int64 = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.int64,
|
obj_id: PRIMITIVE_DEF_IDS.int64,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let float = unifier.add_ty(TypeEnum::TObj {
|
let float = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.float,
|
obj_id: PRIMITIVE_DEF_IDS.float,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let bool = unifier.add_ty(TypeEnum::TObj {
|
let bool = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.bool,
|
obj_id: PRIMITIVE_DEF_IDS.bool,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let none = unifier.add_ty(TypeEnum::TObj {
|
let none = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.none,
|
obj_id: PRIMITIVE_DEF_IDS.none,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let range = unifier.add_ty(TypeEnum::TObj {
|
let range = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.range,
|
obj_id: PRIMITIVE_DEF_IDS.range,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let str = unifier.add_ty(TypeEnum::TObj {
|
let str = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.str,
|
obj_id: PRIMITIVE_DEF_IDS.str,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let exception = unifier.add_ty(TypeEnum::TObj {
|
let exception = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.exception,
|
obj_id: PRIMITIVE_DEF_IDS.exception,
|
||||||
|
@ -159,29 +159,29 @@ impl TopLevelComposer {
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<HashMap<_, _>>(),
|
.collect::<HashMap<_, _>>(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let uint32 = unifier.add_ty(TypeEnum::TObj {
|
let uint32 = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.uint32,
|
obj_id: PRIMITIVE_DEF_IDS.uint32,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let uint64 = unifier.add_ty(TypeEnum::TObj {
|
let uint64 = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.uint64,
|
obj_id: PRIMITIVE_DEF_IDS.uint64,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
|
|
||||||
let option_type_var = unifier.get_fresh_var(Some("option_type_var".into()), None);
|
let option_type_var = unifier.get_fresh_var(Some("option_type_var".into()), None);
|
||||||
let is_some_type_fun_ty = unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
let is_some_type_fun_ty = unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
||||||
args: vec![],
|
args: vec![],
|
||||||
ret: bool,
|
ret: bool,
|
||||||
vars: HashMap::from([(option_type_var.1, option_type_var.0)]),
|
vars: VarMap::from([(option_type_var.1, option_type_var.0)]),
|
||||||
}));
|
}));
|
||||||
let unwrap_fun_ty = unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
let unwrap_fun_ty = unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
||||||
args: vec![],
|
args: vec![],
|
||||||
ret: option_type_var.0,
|
ret: option_type_var.0,
|
||||||
vars: HashMap::from([(option_type_var.1, option_type_var.0)]),
|
vars: VarMap::from([(option_type_var.1, option_type_var.0)]),
|
||||||
}));
|
}));
|
||||||
let option = unifier.add_ty(TypeEnum::TObj {
|
let option = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.option,
|
obj_id: PRIMITIVE_DEF_IDS.option,
|
||||||
|
@ -192,7 +192,7 @@ impl TopLevelComposer {
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<HashMap<_, _>>(),
|
.collect::<HashMap<_, _>>(),
|
||||||
params: HashMap::from([(option_type_var.1, option_type_var.0)]),
|
params: VarMap::from([(option_type_var.1, option_type_var.0)]),
|
||||||
});
|
});
|
||||||
|
|
||||||
let size_t_ty = match size_t {
|
let size_t_ty = match size_t {
|
||||||
|
@ -206,10 +206,10 @@ impl TopLevelComposer {
|
||||||
let ndarray = unifier.add_ty(TypeEnum::TObj {
|
let ndarray = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.ndarray,
|
obj_id: PRIMITIVE_DEF_IDS.ndarray,
|
||||||
fields: Mapping::new(),
|
fields: Mapping::new(),
|
||||||
params: Mapping::from([
|
params: VarMap::from([
|
||||||
(ndarray_dtype_tvar.1, ndarray_dtype_tvar.0),
|
(ndarray_dtype_tvar.1, ndarray_dtype_tvar.0),
|
||||||
(ndarray_ndims_tvar.1, ndarray_ndims_tvar.0),
|
(ndarray_ndims_tvar.1, ndarray_ndims_tvar.0),
|
||||||
])
|
]),
|
||||||
});
|
});
|
||||||
|
|
||||||
let primitives = PrimitiveStore {
|
let primitives = PrimitiveStore {
|
||||||
|
|
|
@ -8,7 +8,7 @@ use std::{
|
||||||
|
|
||||||
use super::codegen::CodeGenContext;
|
use super::codegen::CodeGenContext;
|
||||||
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, VarMap};
|
||||||
use crate::{
|
use crate::{
|
||||||
codegen::CodeGenerator,
|
codegen::CodeGenerator,
|
||||||
symbol_resolver::{SymbolResolver, ValueEnum},
|
symbol_resolver::{SymbolResolver, ValueEnum},
|
||||||
|
@ -76,7 +76,7 @@ impl Debug for GenCall {
|
||||||
pub struct FunInstance {
|
pub struct FunInstance {
|
||||||
pub body: Arc<Vec<Stmt<Option<Type>>>>,
|
pub body: Arc<Vec<Stmt<Option<Type>>>>,
|
||||||
pub calls: Arc<HashMap<CodeLocation, CallId>>,
|
pub calls: Arc<HashMap<CodeLocation, CallId>>,
|
||||||
pub subst: HashMap<u32, Type>,
|
pub subst: VarMap,
|
||||||
pub unifier_id: usize,
|
pub unifier_id: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ use crate::{
|
||||||
toplevel::{DefinitionId, helper::PRIMITIVE_DEF_IDS},
|
toplevel::{DefinitionId, helper::PRIMITIVE_DEF_IDS},
|
||||||
typecheck::{
|
typecheck::{
|
||||||
type_inferencer::PrimitiveStore,
|
type_inferencer::PrimitiveStore,
|
||||||
typedef::{FunSignature, Mapping, Type, TypeEnum, Unifier},
|
typedef::{FunSignature, Type, TypeEnum, Unifier, VarMap},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ pub fn make_ndarray_ty(
|
||||||
.collect_vec();
|
.collect_vec();
|
||||||
debug_assert_eq!(tvar_ids.len(), 2);
|
debug_assert_eq!(tvar_ids.len(), 2);
|
||||||
|
|
||||||
let mut tvar_subst = Mapping::new();
|
let mut tvar_subst = VarMap::new();
|
||||||
if let Some(dtype) = dtype {
|
if let Some(dtype) = dtype {
|
||||||
tvar_subst.insert(tvar_ids[0], dtype);
|
tvar_subst.insert(tvar_ids[0], dtype);
|
||||||
}
|
}
|
||||||
|
|
|
@ -415,7 +415,7 @@ pub fn get_type_from_type_annotation_kinds(
|
||||||
let subst = {
|
let subst = {
|
||||||
// check for compatible range
|
// check for compatible range
|
||||||
// TODO: if allow type var to be applied(now this disallowed in the parse_to_type_annotation), need more check
|
// TODO: if allow type var to be applied(now this disallowed in the parse_to_type_annotation), need more check
|
||||||
let mut result: HashMap<u32, Type> = HashMap::new();
|
let mut result = VarMap::new();
|
||||||
for (tvar, p) in type_vars.iter().zip(param_ty) {
|
for (tvar, p) in type_vars.iter().zip(param_ty) {
|
||||||
match unifier.get_ty(*tvar).as_ref() {
|
match unifier.get_ty(*tvar).as_ref() {
|
||||||
TypeEnum::TVar { id, range, fields: None, name, loc, is_const_generic: false } => {
|
TypeEnum::TVar { id, range, fields: None, name, loc, is_const_generic: false } => {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::typecheck::{
|
use crate::typecheck::{
|
||||||
type_inferencer::*,
|
type_inferencer::*,
|
||||||
typedef::{FunSignature, FuncArg, Type, TypeEnum, Unifier},
|
typedef::{FunSignature, FuncArg, Type, TypeEnum, Unifier, VarMap},
|
||||||
};
|
};
|
||||||
use nac3parser::ast::StrRef;
|
use nac3parser::ast::StrRef;
|
||||||
use nac3parser::ast::{Cmpop, Operator, Unaryop};
|
use nac3parser::ast::{Cmpop, Operator, Unaryop};
|
||||||
|
@ -102,9 +102,9 @@ pub fn impl_binop(
|
||||||
};
|
};
|
||||||
|
|
||||||
let function_vars = if let Some(var_id) = other_var_id {
|
let function_vars = if let Some(var_id) = other_var_id {
|
||||||
vec![(var_id, other_ty)].into_iter().collect::<HashMap<_, _>>()
|
vec![(var_id, other_ty)].into_iter().collect::<VarMap>()
|
||||||
} else {
|
} else {
|
||||||
HashMap::new()
|
VarMap::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
for op in ops {
|
for op in ops {
|
||||||
|
@ -149,7 +149,7 @@ pub fn impl_unaryop(unifier: &mut Unifier, ty: Type, ret_ty: Type, ops: &[Unaryo
|
||||||
(
|
(
|
||||||
unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
||||||
ret: ret_ty,
|
ret: ret_ty,
|
||||||
vars: HashMap::new(),
|
vars: VarMap::new(),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
})),
|
})),
|
||||||
false,
|
false,
|
||||||
|
@ -173,7 +173,7 @@ pub fn impl_cmpop(
|
||||||
(
|
(
|
||||||
unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
||||||
ret: store.bool,
|
ret: store.bool,
|
||||||
vars: HashMap::new(),
|
vars: VarMap::new(),
|
||||||
args: vec![FuncArg {
|
args: vec![FuncArg {
|
||||||
ty: other_ty,
|
ty: other_ty,
|
||||||
default_value: None,
|
default_value: None,
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::convert::{From, TryInto};
|
||||||
use std::iter::once;
|
use std::iter::once;
|
||||||
use std::{cell::RefCell, sync::Arc};
|
use std::{cell::RefCell, sync::Arc};
|
||||||
|
|
||||||
use super::typedef::{Call, FunSignature, FuncArg, RecordField, Type, TypeEnum, Unifier};
|
use super::typedef::{Call, FunSignature, FuncArg, RecordField, Type, TypeEnum, Unifier, VarMap};
|
||||||
use super::{magic_methods::*, typedef::CallId};
|
use super::{magic_methods::*, typedef::CallId};
|
||||||
use crate::{
|
use crate::{
|
||||||
symbol_resolver::{SymbolResolver, SymbolValue},
|
symbol_resolver::{SymbolResolver, SymbolValue},
|
||||||
|
@ -425,13 +425,13 @@ impl<'a> Fold<()> for Inferencer<'a> {
|
||||||
|| self.unifier.get_dummy_var().0,
|
|| self.unifier.get_dummy_var().0,
|
||||||
|var| var.custom.unwrap(),
|
|var| var.custom.unwrap(),
|
||||||
),
|
),
|
||||||
vars: HashMap::default(),
|
vars: VarMap::default(),
|
||||||
});
|
});
|
||||||
let enter = self.unifier.add_ty(enter);
|
let enter = self.unifier.add_ty(enter);
|
||||||
let exit = TypeEnum::TFunc(FunSignature {
|
let exit = TypeEnum::TFunc(FunSignature {
|
||||||
args: vec![],
|
args: vec![],
|
||||||
ret: self.unifier.get_dummy_var().0,
|
ret: self.unifier.get_dummy_var().0,
|
||||||
vars: HashMap::default(),
|
vars: VarMap::default(),
|
||||||
});
|
});
|
||||||
let exit = self.unifier.add_ty(exit);
|
let exit = self.unifier.add_ty(exit);
|
||||||
let mut fields = HashMap::new();
|
let mut fields = HashMap::new();
|
||||||
|
@ -503,7 +503,7 @@ impl<'a> Fold<()> for Inferencer<'a> {
|
||||||
assert_eq!(*id, *id_var);
|
assert_eq!(*id, *id_var);
|
||||||
(*id, self.unifier.get_fresh_var_with_range(range, *name, *loc).0)
|
(*id, self.unifier.get_fresh_var_with_range(range, *name, *loc).0)
|
||||||
})
|
})
|
||||||
.collect::<HashMap<_, _>>();
|
.collect::<VarMap>();
|
||||||
Some(self.unifier.subst(self.primitives.option, &var_map).unwrap())
|
Some(self.unifier.subst(self.primitives.option, &var_map).unwrap())
|
||||||
} else {
|
} else {
|
||||||
unreachable!("must be tobj")
|
unreachable!("must be tobj")
|
||||||
|
@ -704,7 +704,7 @@ impl<'a> Inferencer<'a> {
|
||||||
.map(|(k, ty)| FuncArg { name: *k, ty: *ty, default_value: None })
|
.map(|(k, ty)| FuncArg { name: *k, ty: *ty, default_value: None })
|
||||||
.collect(),
|
.collect(),
|
||||||
ret,
|
ret,
|
||||||
vars: HashMap::default(),
|
vars: VarMap::default(),
|
||||||
};
|
};
|
||||||
let body = new_context.fold_expr(body)?;
|
let body = new_context.fold_expr(body)?;
|
||||||
new_context.unify(fun.ret, body.custom.unwrap(), &location)?;
|
new_context.unify(fun.ret, body.custom.unwrap(), &location)?;
|
||||||
|
@ -939,7 +939,7 @@ impl<'a> Inferencer<'a> {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
ret,
|
ret,
|
||||||
vars: HashMap::new(),
|
vars: VarMap::new(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return Ok(Some(Located {
|
return Ok(Some(Located {
|
||||||
|
@ -996,7 +996,7 @@ impl<'a> Inferencer<'a> {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
ret,
|
ret,
|
||||||
vars: HashMap::new(),
|
vars: VarMap::new(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return Ok(Some(Located {
|
return Ok(Some(Located {
|
||||||
|
|
|
@ -75,70 +75,70 @@ impl TestEnvironment {
|
||||||
let int32 = unifier.add_ty(TypeEnum::TObj {
|
let int32 = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.int32,
|
obj_id: PRIMITIVE_DEF_IDS.int32,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
with_fields(&mut unifier, int32, |unifier, fields| {
|
with_fields(&mut unifier, int32, |unifier, fields| {
|
||||||
let add_ty = unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
let add_ty = unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
||||||
args: vec![FuncArg { name: "other".into(), ty: int32, default_value: None }],
|
args: vec![FuncArg { name: "other".into(), ty: int32, default_value: None }],
|
||||||
ret: int32,
|
ret: int32,
|
||||||
vars: HashMap::new(),
|
vars: VarMap::new(),
|
||||||
}));
|
}));
|
||||||
fields.insert("__add__".into(), (add_ty, false));
|
fields.insert("__add__".into(), (add_ty, false));
|
||||||
});
|
});
|
||||||
let int64 = unifier.add_ty(TypeEnum::TObj {
|
let int64 = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.int64,
|
obj_id: PRIMITIVE_DEF_IDS.int64,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let float = unifier.add_ty(TypeEnum::TObj {
|
let float = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.float,
|
obj_id: PRIMITIVE_DEF_IDS.float,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let bool = unifier.add_ty(TypeEnum::TObj {
|
let bool = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.bool,
|
obj_id: PRIMITIVE_DEF_IDS.bool,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let none = unifier.add_ty(TypeEnum::TObj {
|
let none = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.none,
|
obj_id: PRIMITIVE_DEF_IDS.none,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let range = unifier.add_ty(TypeEnum::TObj {
|
let range = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.range,
|
obj_id: PRIMITIVE_DEF_IDS.range,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let str = unifier.add_ty(TypeEnum::TObj {
|
let str = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.str,
|
obj_id: PRIMITIVE_DEF_IDS.str,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let exception = unifier.add_ty(TypeEnum::TObj {
|
let exception = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.exception,
|
obj_id: PRIMITIVE_DEF_IDS.exception,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let uint32 = unifier.add_ty(TypeEnum::TObj {
|
let uint32 = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.uint32,
|
obj_id: PRIMITIVE_DEF_IDS.uint32,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let uint64 = unifier.add_ty(TypeEnum::TObj {
|
let uint64 = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.uint64,
|
obj_id: PRIMITIVE_DEF_IDS.uint64,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let option = unifier.add_ty(TypeEnum::TObj {
|
let option = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.option,
|
obj_id: PRIMITIVE_DEF_IDS.option,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let ndarray = unifier.add_ty(TypeEnum::TObj {
|
let ndarray = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.ndarray,
|
obj_id: PRIMITIVE_DEF_IDS.ndarray,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let primitives = PrimitiveStore {
|
let primitives = PrimitiveStore {
|
||||||
int32,
|
int32,
|
||||||
|
@ -208,70 +208,70 @@ impl TestEnvironment {
|
||||||
let int32 = unifier.add_ty(TypeEnum::TObj {
|
let int32 = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.int32,
|
obj_id: PRIMITIVE_DEF_IDS.int32,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
with_fields(&mut unifier, int32, |unifier, fields| {
|
with_fields(&mut unifier, int32, |unifier, fields| {
|
||||||
let add_ty = unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
let add_ty = unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
||||||
args: vec![FuncArg { name: "other".into(), ty: int32, default_value: None }],
|
args: vec![FuncArg { name: "other".into(), ty: int32, default_value: None }],
|
||||||
ret: int32,
|
ret: int32,
|
||||||
vars: HashMap::new(),
|
vars: VarMap::new(),
|
||||||
}));
|
}));
|
||||||
fields.insert("__add__".into(), (add_ty, false));
|
fields.insert("__add__".into(), (add_ty, false));
|
||||||
});
|
});
|
||||||
let int64 = unifier.add_ty(TypeEnum::TObj {
|
let int64 = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.int64,
|
obj_id: PRIMITIVE_DEF_IDS.int64,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let float = unifier.add_ty(TypeEnum::TObj {
|
let float = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.float,
|
obj_id: PRIMITIVE_DEF_IDS.float,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let bool = unifier.add_ty(TypeEnum::TObj {
|
let bool = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.bool,
|
obj_id: PRIMITIVE_DEF_IDS.bool,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let none = unifier.add_ty(TypeEnum::TObj {
|
let none = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.none,
|
obj_id: PRIMITIVE_DEF_IDS.none,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let range = unifier.add_ty(TypeEnum::TObj {
|
let range = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.range,
|
obj_id: PRIMITIVE_DEF_IDS.range,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let str = unifier.add_ty(TypeEnum::TObj {
|
let str = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.str,
|
obj_id: PRIMITIVE_DEF_IDS.str,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let exception = unifier.add_ty(TypeEnum::TObj {
|
let exception = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.exception,
|
obj_id: PRIMITIVE_DEF_IDS.exception,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let uint32 = unifier.add_ty(TypeEnum::TObj {
|
let uint32 = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.uint32,
|
obj_id: PRIMITIVE_DEF_IDS.uint32,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let uint64 = unifier.add_ty(TypeEnum::TObj {
|
let uint64 = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.uint64,
|
obj_id: PRIMITIVE_DEF_IDS.uint64,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let option = unifier.add_ty(TypeEnum::TObj {
|
let option = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.option,
|
obj_id: PRIMITIVE_DEF_IDS.option,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let ndarray = unifier.add_ty(TypeEnum::TObj {
|
let ndarray = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: PRIMITIVE_DEF_IDS.ndarray,
|
obj_id: PRIMITIVE_DEF_IDS.ndarray,
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
identifier_mapping.insert("None".into(), none);
|
identifier_mapping.insert("None".into(), none);
|
||||||
for (i, name) in ["int32", "int64", "float", "bool", "none", "range", "str", "Exception"]
|
for (i, name) in ["int32", "int64", "float", "bool", "none", "range", "str", "Exception"]
|
||||||
|
@ -318,7 +318,7 @@ impl TestEnvironment {
|
||||||
let foo_ty = unifier.add_ty(TypeEnum::TObj {
|
let foo_ty = unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: DefinitionId(defs + 1),
|
obj_id: DefinitionId(defs + 1),
|
||||||
fields: [("a".into(), (v0, true))].iter().cloned().collect::<HashMap<_, _>>(),
|
fields: [("a".into(), (v0, true))].iter().cloned().collect::<HashMap<_, _>>(),
|
||||||
params: [(id, v0)].iter().cloned().collect::<HashMap<_, _>>(),
|
params: [(id, v0)].iter().cloned().collect::<VarMap>(),
|
||||||
});
|
});
|
||||||
top_level_defs.push(
|
top_level_defs.push(
|
||||||
RwLock::new(TopLevelDef::Class {
|
RwLock::new(TopLevelDef::Class {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::{BTreeMap, HashMap};
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
@ -25,7 +25,14 @@ pub type Type = UnificationKey;
|
||||||
pub struct CallId(pub(super) usize);
|
pub struct CallId(pub(super) usize);
|
||||||
|
|
||||||
pub type Mapping<K, V = Type> = HashMap<K, V>;
|
pub type Mapping<K, V = Type> = HashMap<K, V>;
|
||||||
type VarMap = Mapping<u32>;
|
|
||||||
|
/// A [`Mapping`] sorted by its key.
|
||||||
|
///
|
||||||
|
/// This type is recommended for mappings that should be stored and/or iterated by its sorted key.
|
||||||
|
pub type SortedMapping<K, V = Type> = BTreeMap<K, V>;
|
||||||
|
|
||||||
|
/// A [`BTreeMap`] storing the mapping between type variable ID and [unifier type][`Type`].
|
||||||
|
pub type VarMap = SortedMapping<u32>;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Call {
|
pub struct Call {
|
||||||
|
@ -1276,12 +1283,12 @@ impl Unifier {
|
||||||
|
|
||||||
fn subst_map<K>(
|
fn subst_map<K>(
|
||||||
&mut self,
|
&mut self,
|
||||||
map: &Mapping<K>,
|
map: &SortedMapping<K>,
|
||||||
mapping: &VarMap,
|
mapping: &VarMap,
|
||||||
cache: &mut HashMap<Type, Option<Type>>,
|
cache: &mut HashMap<Type, Option<Type>>,
|
||||||
) -> Option<Mapping<K>>
|
) -> Option<SortedMapping<K>>
|
||||||
where
|
where
|
||||||
K: std::hash::Hash + Eq + Clone,
|
K: Ord + Eq + Clone,
|
||||||
{
|
{
|
||||||
let mut map2 = None;
|
let mut map2 = None;
|
||||||
for (k, v) in map {
|
for (k, v) in map {
|
||||||
|
|
|
@ -45,9 +45,9 @@ impl Unifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_eq<K>(&mut self, map1: &Mapping<K>, map2: &Mapping<K>) -> bool
|
fn map_eq<K>(&mut self, map1: &SortedMapping<K>, map2: &SortedMapping<K>) -> bool
|
||||||
where
|
where
|
||||||
K: std::hash::Hash + Eq + Clone,
|
K: Ord + Eq + Clone,
|
||||||
{
|
{
|
||||||
if map1.len() != map2.len() {
|
if map1.len() != map2.len() {
|
||||||
return false;
|
return false;
|
||||||
|
@ -91,7 +91,7 @@ impl TestEnvironment {
|
||||||
unifier.add_ty(TypeEnum::TObj {
|
unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: DefinitionId(0),
|
obj_id: DefinitionId(0),
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
type_mapping.insert(
|
type_mapping.insert(
|
||||||
|
@ -99,7 +99,7 @@ impl TestEnvironment {
|
||||||
unifier.add_ty(TypeEnum::TObj {
|
unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: DefinitionId(1),
|
obj_id: DefinitionId(1),
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
type_mapping.insert(
|
type_mapping.insert(
|
||||||
|
@ -107,7 +107,7 @@ impl TestEnvironment {
|
||||||
unifier.add_ty(TypeEnum::TObj {
|
unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: DefinitionId(2),
|
obj_id: DefinitionId(2),
|
||||||
fields: HashMap::new(),
|
fields: HashMap::new(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
let (v0, id) = unifier.get_dummy_var();
|
let (v0, id) = unifier.get_dummy_var();
|
||||||
|
@ -116,7 +116,7 @@ impl TestEnvironment {
|
||||||
unifier.add_ty(TypeEnum::TObj {
|
unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: DefinitionId(3),
|
obj_id: DefinitionId(3),
|
||||||
fields: [("a".into(), (v0, true))].iter().cloned().collect::<HashMap<_, _>>(),
|
fields: [("a".into(), (v0, true))].iter().cloned().collect::<HashMap<_, _>>(),
|
||||||
params: [(id, v0)].iter().cloned().collect::<HashMap<_, _>>(),
|
params: [(id, v0)].iter().cloned().collect::<VarMap>(),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -363,7 +363,7 @@ fn test_virtual() {
|
||||||
let fun = env.unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
let fun = env.unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
||||||
args: vec![],
|
args: vec![],
|
||||||
ret: int,
|
ret: int,
|
||||||
vars: HashMap::new(),
|
vars: VarMap::new(),
|
||||||
}));
|
}));
|
||||||
let bar = env.unifier.add_ty(TypeEnum::TObj {
|
let bar = env.unifier.add_ty(TypeEnum::TObj {
|
||||||
obj_id: DefinitionId(5),
|
obj_id: DefinitionId(5),
|
||||||
|
@ -371,7 +371,7 @@ fn test_virtual() {
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect::<HashMap<StrRef, _>>(),
|
.collect::<HashMap<StrRef, _>>(),
|
||||||
params: HashMap::new(),
|
params: VarMap::new(),
|
||||||
});
|
});
|
||||||
let v0 = env.unifier.get_dummy_var().0;
|
let v0 = env.unifier.get_dummy_var().0;
|
||||||
let v1 = env.unifier.get_dummy_var().0;
|
let v1 = env.unifier.get_dummy_var().0;
|
||||||
|
|
|
@ -17,12 +17,14 @@ use nac3core::{
|
||||||
},
|
},
|
||||||
symbol_resolver::SymbolResolver,
|
symbol_resolver::SymbolResolver,
|
||||||
toplevel::{
|
toplevel::{
|
||||||
composer::TopLevelComposer, helper::parse_parameter_default_value, type_annotation::*,
|
composer::{ComposerConfig, TopLevelComposer},
|
||||||
|
helper::parse_parameter_default_value,
|
||||||
|
type_annotation::*,
|
||||||
TopLevelDef,
|
TopLevelDef,
|
||||||
},
|
},
|
||||||
typecheck::{
|
typecheck::{
|
||||||
type_inferencer::PrimitiveStore,
|
type_inferencer::PrimitiveStore,
|
||||||
typedef::{FunSignature, Type, Unifier},
|
typedef::{FunSignature, Type, Unifier, VarMap},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use nac3parser::{
|
use nac3parser::{
|
||||||
|
@ -32,7 +34,6 @@ use nac3parser::{
|
||||||
|
|
||||||
mod basic_symbol_resolver;
|
mod basic_symbol_resolver;
|
||||||
use basic_symbol_resolver::*;
|
use basic_symbol_resolver::*;
|
||||||
use nac3core::toplevel::composer::ComposerConfig;
|
|
||||||
|
|
||||||
/// Command-line argument parser definition.
|
/// Command-line argument parser definition.
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
|
@ -345,7 +346,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let signature = FunSignature { args: vec![], ret: primitive.int32, vars: HashMap::new() };
|
let signature = FunSignature { args: vec![], ret: primitive.int32, vars: VarMap::new() };
|
||||||
let mut store = ConcreteTypeStore::new();
|
let mut store = ConcreteTypeStore::new();
|
||||||
let mut cache = HashMap::new();
|
let mut cache = HashMap::new();
|
||||||
let signature = store.from_signature(&mut composer.unifier, &primitive, &signature, &mut cache);
|
let signature = store.from_signature(&mut composer.unifier, &primitive, &signature, &mut cache);
|
||||||
|
|
Loading…
Reference in New Issue