typegraph/scripts/typing/freshTypes.gml

117 lines
2.6 KiB
Plaintext

#define freshTypes
///freshTypes(block)
/**
* freshTypes :: Block -> ()
*
* Refreshes the anchor types of this block.
*
* @param block the block to refresh
*/
var block = argument0;
assertInstanceof(block, Block);
with (block) {
for (var i = 0; i < ds_list_size(self.children); i++)
if (instanceof(self.children[|i], Anchor)) {
var anchor = self.children[|i];
if (!ds_list_empty(anchor.children))
delete(anchor.children[|0]);
}
var tmap = ds_map_create();
var vmap = ds_map_create();
for (var i = 0; i < ds_list_size(children); i++)
if (instanceof(self.children[|i], Anchor)) {
var anchor = self.children[|i];
if (anchor.currentType != noone) {
if (!instanceof(anchor.currentType, TypeCon1Link))
removeType(anchor.currentType);
anchor.currentType = noone;
}
anchor.currentType = copyFreshCon(tmap, vmap, anchor.freshType);
addChild(anchor, createTypeInstance(anchor.currentType.to[|0]));
}
ds_map_destroy(tmap);
ds_map_destroy(vmap);
}
#define copyFreshCon
///copyFreshCon(cmap, vmap, id)
/**
* copyFreshCon :: Map TypeConLink TypeConLink -> Map FreeType FreeType -> TypeConLink -> TypeConLink
*
* Returns a deep copy of the given type structure with fresh type variables.
*
* @param cmap a map of old cons to fresh ones
* @param vmap a map of old free types to fresh ones
* @param id the type to copy
*/
var cmap = argument0;
var vmap = argument1;
var con = argument2;
assertInstanceof(con, TypeConLink);
if (!ds_map_exists(cmap, con)) {
if (instanceof(con, TypeCon1Link)) {
if (instanceof(con.type, FreeType))
with (new(TypeCon1Link)) {
self.type = copyFreshType(vmap, con.type);
cmap[?con] = id;
}
else
return con;
}
else if (instanceof(con, TypeConLink))
with (new(TypeConLink)) {
for (var i = 0; i < ds_list_size(con.to); i++)
addLink(id, copyFreshCon(cmap, vmap, con.to[|i]));
cmap[?con] = id;
}
}
return cmap[?con];
#define copyFreshType
///copyFreshType(vmap, id)
/**
* copyFreshType :: Map FreeType FreeType -> Type -> Type
*
* Returns a copy of the given type with a fresh type variable (if applicable).
*
* @param vmap a map of old free types to fresh ones
* @param id the type to copy
*/
var vmap = argument0;
var type = argument1;
assertInstanceof(type, Type);
if (instanceof(type, ConcreteType))
return type;
if (instanceof(type, FreeType)) {
if (!ds_map_exists(vmap, type))
with (new(FreeType)) {
ds_set_add_all(self.traits, type.traits);
vmap[?type] = id;
}
return vmap[?type];
}
assert(false, "Unknown type "+getInstObjName(type));