static bool is_fun_sub_fun(ast_t* sub, ast_t* super, ast_t* isub, ast_t* isuper) { token_id tsub = ast_id(sub); token_id tsuper = ast_id(super); switch(tsub) { case TK_NEW: case TK_BE: case TK_FUN: break; default: return false; } switch(tsuper) { case TK_NEW: case TK_BE: case TK_FUN: break; default: return false; } // A constructor can only be a subtype of a constructor. if(((tsub == TK_NEW) || (tsuper == TK_NEW)) && (tsub != tsuper)) return false; AST_GET_CHILDREN(sub, sub_cap, sub_id, sub_typeparams, sub_params); AST_GET_CHILDREN(super, super_cap, super_id, super_typeparams, super_params); // Must have the same name. if(ast_name(sub_id) != ast_name(super_id)) return false; // Must have the same number of type parameters and parameters. if((ast_childcount(sub_typeparams) != ast_childcount(super_typeparams)) || (ast_childcount(sub_params) != ast_childcount(super_params))) return false; ast_t* r_sub = sub; if(ast_id(super_typeparams) != TK_NONE) { // Reify sub with the type parameters of super. BUILD(typeargs, super_typeparams, NODE(TK_TYPEARGS)); ast_t* super_typeparam = ast_child(super_typeparams); while(super_typeparam != NULL) { AST_GET_CHILDREN(super_typeparam, super_id, super_constraint); token_id cap = cap_from_constraint(super_constraint); BUILD(typearg, super_typeparam, NODE(TK_TYPEPARAMREF, TREE(super_id) NODE(cap) NONE)); ast_t* def = ast_get(super_typeparam, ast_name(super_id), NULL); ast_setdata(typearg, def); ast_append(typeargs, typearg); super_typeparam = ast_sibling(super_typeparam); } r_sub = reify(sub, sub, sub_typeparams, typeargs); ast_free_unattached(typeargs); } bool ok = is_reified_fun_sub_fun(r_sub, super, isub, isuper); if(r_sub != sub) ast_free_unattached(r_sub); return ok; }
static bool is_fun_sub_fun(ast_t* sub, ast_t* super, errorframe_t* errors) { token_id tsub = ast_id(sub); token_id tsuper = ast_id(super); switch(tsub) { case TK_NEW: case TK_BE: case TK_FUN: break; default: return false; } switch(tsuper) { case TK_NEW: case TK_BE: case TK_FUN: break; default: return false; } AST_GET_CHILDREN(sub, sub_cap, sub_id, sub_typeparams, sub_params); AST_GET_CHILDREN(super, super_cap, super_id, super_typeparams, super_params); // Must have the same name. if(ast_name(sub_id) != ast_name(super_id)) { if(errors != NULL) { ast_error_frame(errors, sub, "method %s is not a subtype of method %s: they have different names", ast_name(sub_id), ast_name(super_id)); } return false; } // A constructor can only be a subtype of a constructor. if(((tsub == TK_NEW) || (tsuper == TK_NEW)) && (tsub != tsuper)) { if(errors != NULL) ast_error_frame(errors, sub, "only a constructor can be a subtype of a constructor"); return false; } // Must have the same number of type parameters. if(ast_childcount(sub_typeparams) != ast_childcount(super_typeparams)) { if(errors != NULL) ast_error_frame(errors, sub, "methods have a different number of type parameters"); return false; } // Must have the same number of parameters. if(ast_childcount(sub_params) != ast_childcount(super_params)) { if(errors != NULL) ast_error_frame(errors, sub, "methods have a different number of parameters"); return false; } ast_t* r_sub = sub; if(ast_id(super_typeparams) != TK_NONE) { // Reify sub with the type parameters of super. BUILD(typeargs, super_typeparams, NODE(TK_TYPEARGS)); ast_t* super_typeparam = ast_child(super_typeparams); while(super_typeparam != NULL) { AST_GET_CHILDREN(super_typeparam, super_id, super_constraint); BUILD(typearg, super_typeparam, NODE(TK_TYPEPARAMREF, TREE(super_id) NONE NONE)); ast_t* def = ast_get(super_typeparam, ast_name(super_id), NULL); ast_setdata(typearg, def); typeparam_set_cap(typearg); ast_append(typeargs, typearg); super_typeparam = ast_sibling(super_typeparam); } r_sub = reify(sub, sub_typeparams, typeargs); ast_free_unattached(typeargs); } bool ok = is_reified_fun_sub_fun(r_sub, super, errors); if(r_sub != sub) ast_free_unattached(r_sub); return ok; }