#define unify ///unify(a, b) /** * unify :: TypeConLink -> TypeConLink -> () * * Unifies types `a` and `b`. * * @param a the first type con * @param b the second type con */ var a = argument0; var b = argument1; assertInstanceof(a, TypeConLink); assertInstanceof(b, TypeConLink); if (instanceof(a, TypeCon1Link) && instanceof(b, TypeCon1Link)) unifyType(a, b); else if (instanceof(a, TypeCon1Link) && !instanceof(b, TypeCon1Link)) unify(b, a); else if (!instanceof(a, TypeCon1Link) && instanceof(b, TypeCon1Link)) { while (!ds_set_empty(b.from)) replaceLink(ds_set_first(b.from), b, a); delete(b.type); delete(b); exit; } else if (!instanceof(a, TypeCon1Link) && !instanceof(b, TypeCon1Link)) { for (var i = 0; i < ds_list_size(a.to); i++) unify(a.to[|i], b.to[|i]); } #define unifyType ///unifyType(a, b) /** * unifyType :: TypeConLink -> TypeConLink -> () * * Unifies types `a` and `b`. * * @param a the first type con * @param b the second type con */ var a = argument0; var b = argument1; assertInstanceof(a, TypeCon1Link); assertInstanceof(b, TypeCon1Link); assertInstanceof(a.type, Type); assertInstanceof(b.type, Type); if (a == b) exit; //unify free types by taking the union of their traits and destroying the second type if (instanceof(a.type, FreeType) && instanceof(b.type, FreeType)) { ds_set_add_all(a.type.traits, b.type.traits); for (var trait = ds_set_first(b.type.traits); ds_set_exists(b.type.traits, trait); trait = ds_set_next(b.type.traits, trait)) ds_set_add(a.type.traits, trait); while (!ds_set_empty(b.from)) replaceLink(ds_set_first(b.from), b, a); delete(b.type); delete(b); exit; } //unify free type with concrete type by replacing all occurrences with the concrete type if (instanceof(a.type, FreeType) && !instanceof(b.type, FreeType)) { unify(b, a); exit; } if (!instanceof(a.type, FreeType) && instanceof(b.type, FreeType)) { while (!ds_set_empty(b.from)) replaceLink(ds_set_first(b.from), b, a); delete(b.type); delete(b); exit; }