diff --git a/nac3artiq/src/lib.rs b/nac3artiq/src/lib.rs index edead542..8d9d1e12 100644 --- a/nac3artiq/src/lib.rs +++ b/nac3artiq/src/lib.rs @@ -19,7 +19,10 @@ use rustpython_parser::{ use parking_lot::{Mutex, RwLock}; use nac3core::{ - codegen::{CodeGenTask, DefaultCodeGenerator, WithCall, WorkerRegistry}, + codegen::{ + concrete_type::ConcreteTypeStore, CodeGenTask, DefaultCodeGenerator, WithCall, + WorkerRegistry, + }, symbol_resolver::SymbolResolver, toplevel::{composer::TopLevelComposer, DefinitionId, GenCall, TopLevelContext, TopLevelDef}, typecheck::typedef::{FunSignature, FuncArg}, @@ -354,6 +357,21 @@ impl Nac3 { ) .unwrap(); + let signature = FunSignature { + args: vec![], + ret: self.primitive.none, + vars: HashMap::new(), + }; + let mut store = ConcreteTypeStore::new(); + let mut cache = HashMap::new(); + let signature = store.from_signature( + &mut self.composer.unifier, + &self.primitive, + &signature, + &mut cache, + ); + let signature = store.add_cty(signature); + self.composer.start_analysis(true).unwrap(); self.top_level = Some(Arc::new(self.composer.make_top_level_context())); let top_level = self.top_level.as_ref().unwrap(); @@ -373,18 +391,14 @@ impl Nac3 { } }; - let signature = FunSignature { - args: vec![], - ret: self.primitive.none, - vars: HashMap::new(), - }; let task = CodeGenTask { subst: Default::default(), symbol_name: "__modinit__".to_string(), body: instance.body, signature, resolver, - unifier: top_level.unifiers.read()[instance.unifier_id].clone(), + store, + unifier_index: instance.unifier_id, calls: instance.calls, }; let isa = self.isa; diff --git a/nac3core/src/codegen/concrete_type.rs b/nac3core/src/codegen/concrete_type.rs new file mode 100644 index 00000000..347956af --- /dev/null +++ b/nac3core/src/codegen/concrete_type.rs @@ -0,0 +1,277 @@ +use crate::{ + symbol_resolver::SymbolValue, + toplevel::DefinitionId, + typecheck::{ + type_inferencer::PrimitiveStore, + typedef::{FunSignature, FuncArg, Type, TypeEnum, Unifier}, + }, +}; + +use rustpython_parser::ast::StrRef; +use std::collections::HashMap; + +pub struct ConcreteTypeStore { + store: Vec, +} + +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub struct ConcreteType(usize); + +#[derive(Clone, Debug)] +pub struct ConcreteFuncArg { + pub name: StrRef, + pub ty: ConcreteType, + pub default_value: Option, +} + +#[derive(Clone, Debug)] +pub enum Primitive { + Int32, + Int64, + Float, + Bool, + None, +} + +#[derive(Debug)] +pub enum ConcreteTypeEnum { + TPrimitive(Primitive), + TTuple { + ty: Vec, + }, + TList { + ty: ConcreteType, + }, + TObj { + obj_id: DefinitionId, + fields: HashMap, + params: HashMap, + }, + TVirtual { + ty: ConcreteType, + }, + TFunc { + args: Vec, + ret: ConcreteType, + vars: HashMap, + }, +} + +impl ConcreteTypeStore { + pub fn new() -> ConcreteTypeStore { + ConcreteTypeStore { + store: vec![ + ConcreteTypeEnum::TPrimitive(Primitive::Int32), + ConcreteTypeEnum::TPrimitive(Primitive::Int64), + ConcreteTypeEnum::TPrimitive(Primitive::Float), + ConcreteTypeEnum::TPrimitive(Primitive::Bool), + ConcreteTypeEnum::TPrimitive(Primitive::None), + ], + } + } + + pub fn get(&self, cty: ConcreteType) -> &ConcreteTypeEnum { + &self.store[cty.0] + } + + pub fn from_signature( + &mut self, + unifier: &mut Unifier, + primitives: &PrimitiveStore, + signature: &FunSignature, + cache: &mut HashMap>, + ) -> ConcreteTypeEnum { + ConcreteTypeEnum::TFunc { + args: signature + .args + .iter() + .map(|arg| ConcreteFuncArg { + name: arg.name, + ty: self.from_unifier_type(unifier, primitives, arg.ty, cache), + default_value: arg.default_value.clone(), + }) + .collect(), + ret: self.from_unifier_type(unifier, primitives, signature.ret, cache), + vars: signature + .vars + .iter() + .map(|(id, ty)| (*id, self.from_unifier_type(unifier, primitives, *ty, cache))) + .collect(), + } + } + + pub fn from_unifier_type( + &mut self, + unifier: &mut Unifier, + primitives: &PrimitiveStore, + ty: Type, + cache: &mut HashMap>, + ) -> ConcreteType { + let ty = unifier.get_representative(ty); + if unifier.unioned(ty, primitives.int32) { + ConcreteType(0) + } else if unifier.unioned(ty, primitives.int64) { + ConcreteType(1) + } else if unifier.unioned(ty, primitives.float) { + ConcreteType(2) + } else if unifier.unioned(ty, primitives.bool) { + ConcreteType(3) + } else if unifier.unioned(ty, primitives.none) { + ConcreteType(4) + } else if let Some(cty) = cache.get(&ty) { + if let Some(cty) = cty { + *cty + } else { + let index = self.store.len(); + // placeholder + self.store.push(ConcreteTypeEnum::TPrimitive(Primitive::Int32)); + let result = ConcreteType(index); + cache.insert(ty, Some(result)); + result + } + } else { + cache.insert(ty, None); + let ty_enum = unifier.get_ty(ty); + let result = match &*ty_enum { + TypeEnum::TTuple { ty } => ConcreteTypeEnum::TTuple { + ty: ty + .iter() + .map(|t| self.from_unifier_type(unifier, primitives, *t, cache)) + .collect(), + }, + TypeEnum::TList { ty } => ConcreteTypeEnum::TList { + ty: self.from_unifier_type(unifier, primitives, *ty, cache), + }, + TypeEnum::TObj { obj_id, fields, params } => ConcreteTypeEnum::TObj { + obj_id: *obj_id, + fields: fields + .borrow() + .iter() + .map(|(name, ty)| { + (*name, self.from_unifier_type(unifier, primitives, *ty, cache)) + }) + .collect(), + params: params + .borrow() + .iter() + .map(|(id, ty)| { + (*id, self.from_unifier_type(unifier, primitives, *ty, cache)) + }) + .collect(), + }, + TypeEnum::TVirtual { ty } => ConcreteTypeEnum::TVirtual { + ty: self.from_unifier_type(unifier, primitives, *ty, cache), + }, + TypeEnum::TFunc(signature) => { + let signature = signature.borrow(); + self.from_signature(unifier, primitives, &*signature, cache) + } + _ => unreachable!(), + }; + let index = if let Some(ConcreteType(index)) = cache.get(&ty).unwrap() { + self.store[*index] = result; + *index + } else { + self.store.push(result); + self.store.len() - 1 + }; + cache.insert(ty, Some(ConcreteType(index))); + ConcreteType(index) + } + } + + pub fn to_unifier_type( + &self, + unifier: &mut Unifier, + primitives: &PrimitiveStore, + cty: ConcreteType, + cache: &mut HashMap>, + ) -> Type { + if let Some(ty) = cache.get_mut(&cty) { + return if let Some(ty) = ty { + *ty + } else { + *ty = Some(unifier.get_fresh_var().0); + ty.unwrap() + }; + } + cache.insert(cty, None); + let result = match &self.store[cty.0] { + ConcreteTypeEnum::TPrimitive(primitive) => { + let ty = match primitive { + Primitive::Int32 => primitives.int32, + Primitive::Int64 => primitives.int64, + Primitive::Float => primitives.float, + Primitive::Bool => primitives.bool, + Primitive::None => primitives.none, + }; + *cache.get_mut(&cty).unwrap() = Some(ty); + return ty; + } + ConcreteTypeEnum::TTuple { ty } => TypeEnum::TTuple { + ty: ty + .iter() + .map(|cty| self.to_unifier_type(unifier, primitives, *cty, cache)) + .collect(), + }, + ConcreteTypeEnum::TList { ty } => { + TypeEnum::TList { ty: self.to_unifier_type(unifier, primitives, *ty, cache) } + } + ConcreteTypeEnum::TVirtual { ty } => { + TypeEnum::TVirtual { ty: self.to_unifier_type(unifier, primitives, *ty, cache) } + } + ConcreteTypeEnum::TObj { obj_id, fields, params } => TypeEnum::TObj { + obj_id: *obj_id, + fields: fields + .iter() + .map(|(name, cty)| { + (*name, self.to_unifier_type(unifier, primitives, *cty, cache)) + }) + .collect::>() + .into(), + params: params + .iter() + .map(|(id, cty)| (*id, self.to_unifier_type(unifier, primitives, *cty, cache))) + .collect::>() + .into(), + }, + ConcreteTypeEnum::TFunc { args, ret, vars } => TypeEnum::TFunc( + FunSignature { + args: args + .iter() + .map(|arg| FuncArg { + name: arg.name, + ty: self.to_unifier_type(unifier, primitives, arg.ty, cache), + default_value: arg.default_value.clone(), + }) + .collect(), + ret: self.to_unifier_type(unifier, primitives, *ret, cache), + vars: vars + .iter() + .map(|(id, cty)| { + (*id, self.to_unifier_type(unifier, primitives, *cty, cache)) + }) + .collect::>(), + } + .into(), + ), + }; + let result = unifier.add_ty(result); + if let Some(ty) = cache.get(&cty).unwrap() { + unifier.unify(*ty, result).unwrap(); + } + cache.insert(cty, Some(result)); + result + } + + pub fn add_cty(&mut self, cty: ConcreteTypeEnum) -> ConcreteType { + self.store.push(cty); + ConcreteType(self.store.len() - 1) + } +} + +impl Default for ConcreteTypeStore { + fn default() -> Self { + Self::new() + } +} diff --git a/nac3core/src/codegen/expr.rs b/nac3core/src/codegen/expr.rs index 7f319fd9..1dec50f0 100644 --- a/nac3core/src/codegen/expr.rs +++ b/nac3core/src/codegen/expr.rs @@ -1,10 +1,13 @@ use std::{collections::HashMap, convert::TryInto, iter::once}; use crate::{ - codegen::{get_llvm_type, CodeGenContext, CodeGenTask}, + codegen::{ + concrete_type::{ConcreteFuncArg, ConcreteTypeEnum, ConcreteTypeStore}, + get_llvm_type, CodeGenContext, CodeGenTask, + }, symbol_resolver::SymbolValue, toplevel::{DefinitionId, TopLevelDef}, - typecheck::typedef::{FunSignature, FuncArg, Type, TypeEnum, Unifier}, + typecheck::typedef::{FunSignature, FuncArg, Type, TypeEnum}, }; use inkwell::{ types::{BasicType, BasicTypeEnum}, @@ -265,20 +268,9 @@ pub fn gen_func_instance<'ctx, 'a>( instance_to_symbol.insert(key, symbol.clone()); let key = ctx.get_subst_key(obj.map(|a| a.0), sign, Some(var_id)); let instance = instance_to_stmt.get(&key).unwrap(); - let unifiers = ctx.top_level.unifiers.read(); - let (unifier, primitives) = &unifiers[instance.unifier_id]; - let mut unifier = Unifier::from_shared_unifier(unifier); - let mut type_cache = [ - (ctx.primitives.int32, primitives.int32), - (ctx.primitives.int64, primitives.int64), - (ctx.primitives.float, primitives.float), - (ctx.primitives.bool, primitives.bool), - (ctx.primitives.none, primitives.none), - ] - .iter() - .map(|(a, b)| (ctx.unifier.get_representative(*a), unifier.get_representative(*b))) - .collect(); + let mut store = ConcreteTypeStore::new(); + let mut cache = HashMap::new(); let subst = sign .vars @@ -286,38 +278,27 @@ pub fn gen_func_instance<'ctx, 'a>( .map(|(id, ty)| { ( *instance.subst.get(id).unwrap(), - unifier.copy_from(&mut ctx.unifier, *ty, &mut type_cache), + store.from_unifier_type(&mut ctx.unifier, &ctx.primitives, *ty, &mut cache), ) }) .collect(); - let mut signature = FunSignature { - args: sign - .args - .iter() - .map(|arg| FuncArg { - name: arg.name, - ty: unifier.copy_from(&mut ctx.unifier, arg.ty, &mut type_cache), - default_value: arg.default_value.clone(), - }) - .collect(), - ret: unifier.copy_from(&mut ctx.unifier, sign.ret, &mut type_cache), - vars: sign - .vars - .iter() - .map(|(id, ty)| { - (*id, unifier.copy_from(&mut ctx.unifier, *ty, &mut type_cache)) - }) - .collect(), - }; + let mut signature = + store.from_signature(&mut ctx.unifier, &ctx.primitives, sign, &mut cache); if let Some(obj) = &obj { - signature - .args - .insert(0, FuncArg { name: "self".into(), ty: obj.0, default_value: None }); + let zelf = + store.from_unifier_type(&mut ctx.unifier, &ctx.primitives, obj.0, &mut cache); + if let ConcreteTypeEnum::TFunc { args, .. } = &mut signature { + args.insert( + 0, + ConcreteFuncArg { name: "self".into(), ty: zelf, default_value: None }, + ) + } else { + unreachable!() + } } - - let unifier = (unifier.get_shared_unifier(), *primitives); + let signature = store.add_cty(signature); ctx.registry.add_task(CodeGenTask { symbol_name: symbol.clone(), @@ -326,7 +307,8 @@ pub fn gen_func_instance<'ctx, 'a>( calls: instance.calls.clone(), subst, signature, - unifier, + store, + unifier_index: instance.unifier_id, }); symbol }) diff --git a/nac3core/src/codegen/mod.rs b/nac3core/src/codegen/mod.rs index 34125efc..5db7c6f6 100644 --- a/nac3core/src/codegen/mod.rs +++ b/nac3core/src/codegen/mod.rs @@ -3,7 +3,7 @@ use crate::{ toplevel::{TopLevelContext, TopLevelDef}, typecheck::{ type_inferencer::{CodeLocation, PrimitiveStore}, - typedef::{CallId, FunSignature, SharedUnifier, Type, TypeEnum, Unifier}, + typedef::{CallId, FuncArg, Type, TypeEnum, Unifier}, }, }; use crossbeam::channel::{unbounded, Receiver, Sender}; @@ -27,6 +27,7 @@ use std::sync::{ }; use std::thread; +pub mod concrete_type; mod expr; mod generator; mod stmt; @@ -34,6 +35,7 @@ mod stmt; #[cfg(test)] mod test; +use concrete_type::{ConcreteType, ConcreteTypeEnum, ConcreteTypeStore}; pub use generator::{CodeGenerator, DefaultCodeGenerator}; pub struct CodeGenContext<'ctx, 'a> { @@ -198,12 +200,13 @@ impl WorkerRegistry { } pub struct CodeGenTask { - pub subst: Vec<(Type, Type)>, + pub subst: Vec<(Type, ConcreteType)>, + pub store: ConcreteTypeStore, pub symbol_name: String, - pub signature: FunSignature, + pub signature: ConcreteType, pub body: Arc>>>, pub calls: Arc>, - pub unifier: (SharedUnifier, PrimitiveStore), + pub unifier_index: usize, pub resolver: Arc, } @@ -218,7 +221,8 @@ fn get_llvm_type<'ctx>( // we assume the type cache should already contain primitive types, // and they should be passed by value instead of passing as pointer. type_cache.get(&unifier.get_representative(ty)).cloned().unwrap_or_else(|| { - match &*unifier.get_ty(ty) { + let ty = unifier.get_ty(ty); + match &*ty { TObj { obj_id, fields, .. } => { // a struct with fields in the order of declaration let top_level_defs = top_level.definitions.read(); @@ -252,7 +256,7 @@ fn get_llvm_type<'ctx>( ctx.struct_type(&fields, false).ptr_type(AddressSpace::Generic).into() } TVirtual { .. } => unimplemented!(), - _ => unreachable!(), + _ => unreachable!("{}", ty.get_type_name()), } }) } @@ -267,14 +271,16 @@ pub fn gen_func<'ctx, G: CodeGenerator + ?Sized>( top_level_ctx: Arc, ) -> (Builder<'ctx>, Module<'ctx>, FunctionValue<'ctx>) { let (mut unifier, primitives) = { - let (unifier, primitives) = task.unifier; - (Unifier::from_shared_unifier(&unifier), primitives) + let (unifier, primitives) = &top_level_ctx.unifiers.read()[task.unifier_index]; + (Unifier::from_shared_unifier(unifier), *primitives) }; + let mut cache = HashMap::new(); for (a, b) in task.subst.iter() { // this should be unification between variables and concrete types // and should not cause any problem... - unifier.unify(*a, *b).unwrap(); + let b = task.store.to_unifier_type(&mut unifier, &primitives, *b, &mut cache); + unifier.unify(*a, b).unwrap(); } // rebuild primitive store with unique representatives @@ -296,26 +302,34 @@ pub fn gen_func<'ctx, G: CodeGenerator + ?Sized>( .cloned() .collect(); - let params = task - .signature - .args + let (args, ret) = if let ConcreteTypeEnum::TFunc { args, ret, .. } = + task.store.get(task.signature) + { + ( + args.iter() + .map(|arg| FuncArg { + name: arg.name, + ty: task.store.to_unifier_type(&mut unifier, &primitives, arg.ty, &mut cache), + default_value: arg.default_value.clone(), + }) + .collect_vec(), + task.store.to_unifier_type(&mut unifier, &primitives, *ret, &mut cache), + ) + } else { + unreachable!() + }; + let params = args .iter() .map(|arg| { get_llvm_type(context, &mut unifier, top_level_ctx.as_ref(), &mut type_cache, arg.ty) }) .collect_vec(); - let fn_type = if unifier.unioned(task.signature.ret, primitives.none) { + let fn_type = if unifier.unioned(ret, primitives.none) { context.void_type().fn_type(¶ms, false) } else { - get_llvm_type( - context, - &mut unifier, - top_level_ctx.as_ref(), - &mut type_cache, - task.signature.ret, - ) - .fn_type(¶ms, false) + get_llvm_type(context, &mut unifier, top_level_ctx.as_ref(), &mut type_cache, ret) + .fn_type(¶ms, false) }; let symbol = &task.symbol_name; @@ -335,7 +349,7 @@ pub fn gen_func<'ctx, G: CodeGenerator + ?Sized>( let body_bb = context.append_basic_block(fn_val, "body"); let mut var_assignment = HashMap::new(); - for (n, arg) in task.signature.args.iter().enumerate() { + for (n, arg) in args.iter().enumerate() { let param = fn_val.get_nth_param(n as u32).unwrap(); let alloca = builder.build_alloca( get_llvm_type(context, &mut unifier, top_level_ctx.as_ref(), &mut type_cache, arg.ty), diff --git a/nac3core/src/codegen/test.rs b/nac3core/src/codegen/test.rs index 9682c69d..c31fda8a 100644 --- a/nac3core/src/codegen/test.rs +++ b/nac3core/src/codegen/test.rs @@ -1,5 +1,8 @@ use crate::{ - codegen::{CodeGenTask, WithCall, WorkerRegistry, CodeGenContext, DefaultCodeGenerator}, + codegen::{ + concrete_type::ConcreteTypeStore, CodeGenContext, CodeGenTask, DefaultCodeGenerator, + WithCall, WorkerRegistry, + }, location::Location, symbol_resolver::SymbolResolver, toplevel::{ @@ -34,11 +37,21 @@ impl Resolver { } impl SymbolResolver for Resolver { - fn get_symbol_type(&self, _: &mut Unifier, _: &[Arc>], _: &PrimitiveStore, str: StrRef) -> Option { + fn get_symbol_type( + &self, + _: &mut Unifier, + _: &[Arc>], + _: &PrimitiveStore, + str: StrRef, + ) -> Option { self.id_to_type.get(&str).cloned() } - fn get_symbol_value<'ctx, 'a>(&self, _: StrRef, _: &mut CodeGenContext<'ctx, 'a>) -> Option> { + fn get_symbol_value<'ctx, 'a>( + &self, + _: StrRef, + _: &mut CodeGenContext<'ctx, 'a>, + ) -> Option> { unimplemented!() } @@ -82,6 +95,11 @@ fn test_primitives() { vars: HashMap::new(), }; + let mut store = ConcreteTypeStore::new(); + let mut cache = HashMap::new(); + let signature = store.from_signature(&mut unifier, &primitives, &signature, &mut cache); + let signature = store.add_cty(signature); + let mut function_data = FunctionData { resolver: resolver.clone(), bound_variables: Vec::new(), @@ -116,15 +134,14 @@ fn test_primitives() { personality_symbol: None, }); - let unifier = (unifier.get_shared_unifier(), primitives); - let task = CodeGenTask { subst: Default::default(), symbol_name: "testing".into(), body: Arc::new(statements), - resolver, - unifier, + unifier_index: 0, calls: Arc::new(calls), + resolver, + store, signature, }; let f = Arc::new(WithCall::new(Box::new(|module| { @@ -216,6 +233,10 @@ fn test_simple_call() { vars: HashMap::new(), }; let fun_ty = unifier.add_ty(TypeEnum::TFunc(RefCell::new(signature.clone()))); + let mut store = ConcreteTypeStore::new(); + let mut cache = HashMap::new(); + let signature = store.from_signature(&mut unifier, &primitives, &signature, &mut cache); + let signature = store.add_cty(signature); let foo_id = top_level.definitions.read().len(); top_level.definitions.write().push(Arc::new(RwLock::new(TopLevelDef::Function { @@ -305,16 +326,15 @@ fn test_simple_call() { personality_symbol: None, }); - let unifier = (unifier.get_shared_unifier(), primitives); - let task = CodeGenTask { subst: Default::default(), symbol_name: "testing".to_string(), body: Arc::new(statements_1), - resolver, - unifier, calls: Arc::new(calls1), + unifier_index: 0, + resolver, signature, + store, }; let f = Arc::new(WithCall::new(Box::new(|module| { let expected = indoc! {" diff --git a/nac3core/src/symbol_resolver.rs b/nac3core/src/symbol_resolver.rs index 958757af..ac0bbaa7 100644 --- a/nac3core/src/symbol_resolver.rs +++ b/nac3core/src/symbol_resolver.rs @@ -13,7 +13,7 @@ use parking_lot::RwLock; use rustpython_parser::ast::{Expr, StrRef}; use inkwell::values::BasicValueEnum; -#[derive(Clone, PartialEq)] +#[derive(Clone, PartialEq, Debug)] pub enum SymbolValue { I32(i32), I64(i64), diff --git a/nac3core/src/typecheck/typedef/mod.rs b/nac3core/src/typecheck/typedef/mod.rs index 0391fa7b..f12980d2 100644 --- a/nac3core/src/typecheck/typedef/mod.rs +++ b/nac3core/src/typecheck/typedef/mod.rs @@ -125,78 +125,6 @@ impl Unifier { } } - // copy concrete type from a type in another unifier - // note that we are constructing a new type this way - // this can handle recursive types - pub fn copy_from( - &mut self, - unifier: &mut Unifier, - ty: Type, - type_cache: &mut HashMap, - ) -> Type { - let representative = unifier.get_representative(ty); - type_cache.get(&representative).cloned().unwrap_or_else(|| { - // put in a placeholder first to handle possible recursive type - let placeholder = self.get_fresh_var().0; - type_cache.insert(representative, placeholder); - let ty = match &*self.get_ty(ty) { - TypeEnum::TVar { .. } | TypeEnum::TRigidVar { .. } | TypeEnum::TCall(..) => { - unreachable!() - } - TypeEnum::TObj { obj_id, fields, params } => TypeEnum::TObj { - obj_id: *obj_id, - fields: RefCell::new( - fields - .borrow() - .iter() - .map(|(name, ty)| (*name, self.copy_from(unifier, *ty, type_cache))) - .collect(), - ), - params: RefCell::new( - params - .borrow() - .iter() - .map(|(id, ty)| (*id, self.copy_from(unifier, *ty, type_cache))) - .collect(), - ), - }, - TypeEnum::TList { ty } => { - TypeEnum::TList { ty: self.copy_from(unifier, *ty, type_cache) } - } - TypeEnum::TFunc(fun) => { - let fun = fun.borrow(); - TypeEnum::TFunc(RefCell::new(FunSignature { - args: fun - .args - .iter() - .map(|arg| FuncArg { - name: arg.name, - ty: self.copy_from(unifier, arg.ty, type_cache), - default_value: arg.default_value.clone(), - }) - .collect(), - ret: self.copy_from(unifier, fun.ret, type_cache), - vars: fun - .vars - .iter() - .map(|(id, ty)| (*id, self.copy_from(unifier, *ty, type_cache))) - .collect(), - })) - } - TypeEnum::TTuple { ty } => TypeEnum::TTuple { - ty: ty.iter().map(|ty| self.copy_from(unifier, *ty, type_cache)).collect(), - }, - TypeEnum::TVirtual { ty } => { - TypeEnum::TVirtual { ty: self.copy_from(unifier, *ty, type_cache) } - } - }; - let ty = self.add_ty(ty); - self.unify_impl(placeholder, ty, false).unwrap(); - type_cache.insert(representative, ty); - ty - }) - } - /// Determine if the two types are the same pub fn unioned(&mut self, a: Type, b: Type) -> bool { self.unification_table.unioned(a, b) diff --git a/nac3standalone/src/main.rs b/nac3standalone/src/main.rs index 83839edc..4fc9b8d5 100644 --- a/nac3standalone/src/main.rs +++ b/nac3standalone/src/main.rs @@ -10,7 +10,10 @@ use std::fs; use std::{collections::HashMap, path::Path, sync::Arc, time::SystemTime}; use nac3core::{ - codegen::{CodeGenTask, DefaultCodeGenerator, WithCall, WorkerRegistry}, + codegen::{ + concrete_type::ConcreteTypeStore, CodeGenTask, DefaultCodeGenerator, WithCall, + WorkerRegistry, + }, symbol_resolver::SymbolResolver, toplevel::{composer::TopLevelComposer, TopLevelDef}, typecheck::typedef::FunSignature, @@ -73,6 +76,16 @@ fn main() { } } + let signature = FunSignature { + args: vec![], + ret: primitive.int32, + vars: HashMap::new(), + }; + let mut store = ConcreteTypeStore::new(); + let mut cache = HashMap::new(); + let signature = store.from_signature(&mut composer.unifier, &primitive, &signature, &mut cache); + let signature = store.add_cty(signature); + composer.start_analysis(true).unwrap(); let analysis_time = SystemTime::now(); println!( @@ -100,11 +113,6 @@ fn main() { unreachable!() } }; - let signature = FunSignature { - args: vec![], - ret: primitive.int32, - vars: HashMap::new(), - }; let task = CodeGenTask { subst: Default::default(), @@ -112,7 +120,8 @@ fn main() { body: instance.body, signature, resolver, - unifier: top_level.unifiers.read()[instance.unifier_id].clone(), + store, + unifier_index: instance.unifier_id, calls: instance.calls, }; let f = Arc::new(WithCall::new(Box::new(move |module| {