static void reify_one(ast_t** astp, ast_t* typeparam, ast_t* typearg) { ast_t* ast = *astp; ast_t* child = ast_child(ast); while(child != NULL) { reify_one(&child, typeparam, typearg); child = ast_sibling(child); } ast_t* type = ast_type(ast); if(type != NULL) reify_one(&type, typeparam, typearg); switch(ast_id(ast)) { case TK_TYPEPARAMREF: reify_typeparamref(astp, typeparam, typearg); break; case TK_ARROW: reify_arrow(astp); break; default: {} } }
ast_t* reify(ast_t* ast, ast_t* typeparams, ast_t* typeargs, pass_opt_t* opt) { (void)opt; assert( (ast_id(typeparams) == TK_TYPEPARAMS) || (ast_id(typeparams) == TK_NONE) ); assert( (ast_id(typeargs) == TK_TYPEARGS) || (ast_id(typeargs) == TK_NONE) ); // Duplicate the node. ast_t* r_ast = ast_dup(ast); // Iterate pairwise through the typeparams and typeargs. ast_t* typeparam = ast_child(typeparams); ast_t* typearg = ast_child(typeargs); while((typeparam != NULL) && (typearg != NULL)) { reify_one(&r_ast, typeparam, typearg); typeparam = ast_sibling(typeparam); typearg = ast_sibling(typearg); } assert(typeparam == NULL); assert(typearg == NULL); return r_ast; }
static ast_t* reify_without_defaults(ast_t* ast, ast_t* typeparams, ast_t* typeargs, ast_t** lastparam, ast_t** lastarg) { // Duplicate the node. ast_t* r_ast = ast_dup(ast); // Iterate pairwise through the params and the args. ast_t* typeparam = ast_child(typeparams); ast_t* typearg = ast_child(typeargs); while((typeparam != NULL) && (typearg != NULL)) { // Reify the typeparam with the typearg. reify_one(&r_ast, typeparam, typearg); typeparam = ast_sibling(typeparam); typearg = ast_sibling(typearg); } if(lastparam != NULL) *lastparam = typeparam; if(lastarg != NULL) *lastarg = typearg; return r_ast; }
static bool reify_one(ast_t** astp, ast_t* typeparam, ast_t* typearg) { ast_t* ast = *astp; ast_t* type = ast_type(ast); if(type != NULL) reify_one(&type, typeparam, typearg); if(ast_id(ast) == TK_TYPEPARAMREF) return reify_typeparamref(astp, typeparam, typearg); ast_t* child = ast_child(ast); bool flatten = false; while(child != NULL) { flatten |= reify_one(&child, typeparam, typearg); child = ast_sibling(child); } // Flatten type expressions after reifying them. if(flatten) { switch(ast_id(ast)) { case TK_ARROW: { AST_GET_CHILDREN(ast, left, right); ast = viewpoint_type(left, right); if(ast == NULL) return false; if(ast == right) ast = ast_dup(ast); ast_replace(astp, ast); return true; } default: {} } } return false; }
ast_t* reify(ast_t* orig, ast_t* ast, ast_t* typeparams, ast_t* typeargs) { assert( (ast_id(typeparams) == TK_TYPEPARAMS) || (ast_id(typeparams) == TK_NONE) ); assert( (ast_id(typeargs) == TK_TYPEARGS) || (ast_id(typeargs) == TK_NONE) ); // Duplicate the node. ast_t* typeparam; ast_t* typearg; ast_t* r_ast = reify_without_defaults(ast, typeparams, typeargs, &typeparam, &typearg); if(typearg != NULL) { ast_error(orig, "too many type arguments"); ast_error(typeparams, "definition is here"); ast_free(r_ast); return NULL; } // Pick up default type arguments if they exist. while(typeparam != NULL) { typearg = ast_childidx(typeparam, 2); if(ast_id(typearg) == TK_NONE) break; // Reify the default typearg with the typeargs we have so far. ast_t* r_typearg = reify_without_defaults(typearg, typeparams, typeargs, NULL, NULL); ast_append(typeargs, r_typearg); reify_one(&r_ast, typeparam, r_typearg); typeparam = ast_sibling(typeparam); } if(typeparam != NULL) { ast_error(orig, "not enough type arguments"); ast_error(typeparams, "definition is here"); ast_free(r_ast); return NULL; } return r_ast; }