parse/specialize.c
/*
 * Duplicates the type 't', with all bound type
 * parameters substituted with the substitions
 * described in 'tsmap'
 *
 * Returns a fresh type with all unbound type
 * parameters (type schemes in most literature)
 * replaced with type variables that we can unify
 * against */
Duplicates the type 't', with all bound type
parameters substituted with the substitions
described in 'tsmap'

Returns a fresh type with all unbound type
parameters (type schemes in most literature)
replaced with type variables that we can unify
against
Duplicates the type ' t ' with all bound type parameters substituted with the substitions described in ' tsmap ' Returns a fresh type with all unbound type parameters ( type schemes in most literature ) replaced with type variables that we can unify against
Type *tyspecialize(Type *t, Htab *tsmap, Htab *delayed)
{
    Type *ret, *tmp, **arg;
    size_t i, narg;
    t = tysearch(t);
    if (hthas(tsmap, t))
        return htget(tsmap, t);
    arg = NULL;
    narg = 0;
    switch (t->type) {
        case Typaram:
            ret = mktyvar(t->loc);
            addtraits(ret, t->traits);
            htput(tsmap, t, ret);
            break;
        case Tygeneric:
            ret = mktyname(t->loc, t->name, tyspecialize(t->sub[0], tsmap, delayed));
            ret->issynth = 1;
            htput(tsmap, t, ret);
            for (i = 0; i < t->ngparam; i++)
                lappend(&ret->arg, &ret->narg, tyspecialize(t->gparam[i], tsmap, delayed));
            break;
        case Tyname:
            if (!hasparams(t))
                return t;
            for (i = 0; i < t->narg; i++)
                lappend(&arg, &narg, tyspecialize(t->arg[i], tsmap, delayed));
            ret = mktyname(t->loc, t->name, tyspecialize(t->sub[0], tsmap, delayed));
            ret->arg = arg;
            ret->narg = narg;
            break;
        case Tystruct:
            ret = tydup(t);
            htput(tsmap, t, ret);
            pushstab(NULL);
            for (i = 0; i < t->nmemb; i++)
                ret->sdecls[i] = specializenode(t->sdecls[i], tsmap);
            popstab();
            break;
        case Tyunion:
            ret = tydup(t);
            htput(tsmap, t, ret);
            for (i = 0; i < t->nmemb; i++) {
                tmp = NULL;
                if (ret->udecls[i]->etype)
                    tmp = tyspecialize(t->udecls[i]->etype, tsmap, delayed);
                ret->udecls[i] = mkucon(t->loc, t->udecls[i]->name, ret, tmp);
                ret->udecls[i]->utype = ret;
                ret->udecls[i]->id = i;
                ret->udecls[i]->synth = 1;
            }
            break;
        case Tyvar:
            if (delayed && hthas(delayed, t)) {
                ret = tydup(t);
                tmp = htget(delayed, t);
                htput(delayed, ret, tyspecialize(tmp, tsmap, delayed));
            } else {
                ret = t;
            }
            break;
        default:
            if (t->nsub > 0) {
                ret = tydup(t);
                htput(tsmap, t, ret);
                for (i = 0; i < t->nsub; i++)
                    ret->sub[i] = tyspecialize(t->sub[i], tsmap, delayed);
            } else {
                ret = t;
            }
            break;
    }
    return ret;
}
Type * tyspecialize ( Type * t , Htab * tsmap , Htab * delayed ) { Type * ret , * tmp , * * arg ; size_t i , narg ; t = tysearch ( t ) ; if ( hthas ( tsmap , t ) ) return htget ( tsmap , t ) ; arg = NULL ; narg = 0 ; switch ( t -> type ) { case Typaram : ret = mktyvar ( t -> loc ) ; addtraits ( ret , t -> traits ) ; htput ( tsmap , t , ret ) ; break ; case Tygeneric : ret = mktyname ( t -> loc , t -> name , tyspecialize ( t -> sub [ 0 ] , tsmap , delayed ) ) ; ret -> issynth = 1 ; htput ( tsmap , t , ret ) ; for ( i = 0 ; i < t -> ngparam ; i ++ ) lappend ( & ret -> arg , & ret -> narg , tyspecialize ( t -> gparam [ i ] , tsmap , delayed ) ) ; break ; case Tyname : if ( ! hasparams ( t ) ) return t ; for ( i = 0 ; i < t -> narg ; i ++ ) lappend ( & arg , & narg , tyspecialize ( t -> arg [ i ] , tsmap , delayed ) ) ; ret = mktyname ( t -> loc , t -> name , tyspecialize ( t -> sub [ 0 ] , tsmap , delayed ) ) ; ret -> arg = arg ; ret -> narg = narg ; break ; case Tystruct : ret = tydup ( t ) ; htput ( tsmap , t , ret ) ; pushstab ( NULL ) ; for ( i = 0 ; i < t -> nmemb ; i ++ ) ret -> sdecls [ i ] = specializenode ( t -> sdecls [ i ] , tsmap ) ; popstab ( ) ; break ; case Tyunion : ret = tydup ( t ) ; htput ( tsmap , t , ret ) ; for ( i = 0 ; i < t -> nmemb ; i ++ ) { tmp = NULL ; if ( ret -> udecls [ i ] -> etype ) tmp = tyspecialize ( t -> udecls [ i ] -> etype , tsmap , delayed ) ; ret -> udecls [ i ] = mkucon ( t -> loc , t -> udecls [ i ] -> name , ret , tmp ) ; ret -> udecls [ i ] -> utype = ret ; ret -> udecls [ i ] -> id = i ; ret -> udecls [ i ] -> synth = 1 ; } break ; case Tyvar : if ( delayed && hthas ( delayed , t ) ) { ret = tydup ( t ) ; tmp = htget ( delayed , t ) ; htput ( delayed , ret , tyspecialize ( tmp , tsmap , delayed ) ) ; } else { ret = t ; } break ; default : if ( t -> nsub > 0 ) { ret = tydup ( t ) ; htput ( tsmap , t , ret ) ; for ( i = 0 ; i < t -> nsub ; i ++ ) ret -> sub [ i ] = tyspecialize ( t -> sub [ i ] , tsmap , delayed ) ; } else { ret = t ; } break ; } return ret ; }
Duplicates the type 't', with all bound type
 parameters substituted with the substitions
 described in 'tsmap'
Duplicates the type ' t ' with all bound type parameters substituted with the substitions described in ' tsmap '