1
0
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:
David Mak 2024-03-04 23:38:52 +08:00
parent 234a6bde2a
commit 77de24ef74
19 changed files with 129 additions and 116 deletions

View File

@ -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) {

View File

@ -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;

View File

@ -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 {

View File

@ -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(),

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -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(),

View File

@ -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)
}) })

View File

@ -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 {

View File

@ -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,
} }

View File

@ -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);
} }

View File

@ -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 } => {

View File

@ -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,

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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;

View File

@ -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);