bool is_known(ast_t* type) { if(type == NULL) return false; switch(ast_id(type)) { case TK_UNIONTYPE: case TK_TUPLETYPE: return false; case TK_ISECTTYPE: { ast_t* child = ast_child(type); while(child != NULL) { if(is_known(child)) return true; child = ast_sibling(child); } return false; } case TK_NOMINAL: { ast_t* def = (ast_t*)ast_data(type); switch(ast_id(def)) { case TK_INTERFACE: case TK_TRAIT: return false; case TK_PRIMITIVE: case TK_STRUCT: case TK_CLASS: case TK_ACTOR: return true; default: {} } break; } case TK_ARROW: return is_known(ast_childidx(type, 1)); case TK_TYPEPARAMREF: return is_known(typeparam_constraint(type)); default: {} } assert(0); return false; }
bool is_entity(ast_t* type, token_id entity) { if(type == NULL) return false; switch(ast_id(type)) { case TK_TUPLETYPE: return false; case TK_UNIONTYPE: { ast_t* child = ast_child(type); while(child != NULL) { if(!is_entity(child, entity)) return false; child = ast_sibling(child); } return true; } case TK_ISECTTYPE: { ast_t* child = ast_child(type); while(child != NULL) { if(is_entity(child, entity)) return true; child = ast_sibling(child); } return false; } case TK_NOMINAL: { ast_t* def = (ast_t*)ast_data(type); return ast_id(def) == entity; } case TK_ARROW: return is_entity(ast_childidx(type, 1), entity); case TK_TYPEPARAMREF: return is_entity(typeparam_constraint(type), entity); default: {} } assert(0); return false; }
ast_result_t flatten_typeparamref(pass_opt_t* opt, ast_t* ast) { ast_t* cap_ast = cap_fetch(ast); token_id cap = ast_id(cap_ast); typeparam_set_cap(ast); token_id set_cap = ast_id(cap_ast); if((cap != TK_NONE) && (cap != set_cap)) { ast_t* def = (ast_t*)ast_data(ast); ast_t* constraint = typeparam_constraint(ast); if(constraint != NULL) { ast_error(opt->check.errors, cap_ast, "can't specify a capability on a " "type parameter that differs from the constraint"); ast_error_continue(opt->check.errors, constraint, "constraint definition is here"); if(ast_parent(constraint) != def) { ast_error_continue(opt->check.errors, def, "type parameter definition is here"); } } else { ast_error(opt->check.errors, cap_ast, "a type parameter with no " "constraint can only have #any as its capability"); ast_error_continue(opt->check.errors, def, "type parameter definition is here"); } return AST_ERROR; } return AST_OK; }