typegraph/scripts/typing/unify.gml

85 lines
2.0 KiB
Plaintext
Raw Permalink Normal View History

#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;
}