ast_t* type_builtin(pass_opt_t* opt, ast_t* from, const char* name) { ast_t* ast = type_base(from, NULL, name); if(!names_nominal(opt, from, &ast, false)) { ast_error(from, "unable to validate '%s'", name); ast_free(ast); return NULL; } return ast; }
ast_result_t pass_names(ast_t** astp, pass_opt_t* options) { (void)options; ast_t* ast = *astp; switch(ast_id(ast)) { case TK_NOMINAL: if(!names_nominal(options, ast, astp)) return AST_ERROR; break; case TK_ARROW: if(!names_arrow(ast)) return AST_ERROR; break; default: {} } return AST_OK; }
ast_t* type_pointer_to(pass_opt_t* opt, ast_t* to) { BUILD(pointer, to, NODE(TK_NOMINAL, NONE // Package ID("Pointer") NODE(TK_TYPEARGS, TREE(to) ) NONE // Capability NONE // Ephemeral )); if(!names_nominal(opt, to, &pointer, false)) { ast_error(to, "unable to create Pointer[%s]", ast_print_type(to)); ast_free(pointer); return NULL; } return pointer; }
bool expr_nominal(pass_opt_t* opt, ast_t** astp) { // Resolve typealiases and typeparam references. if(!names_nominal(opt, *astp, astp)) return false; ast_t* ast = *astp; switch(ast_id(ast)) { case TK_TYPEPARAMREF: return flatten_typeparamref(ast) == AST_OK; case TK_NOMINAL: break; default: return true; } // If still nominal, check constraints. ast_t* def = (ast_t*)ast_data(ast); // Special case: don't check the constraint of a Pointer. This allows a // Pointer[Pointer[A]], which is normally not allowed, as a Pointer[A] is // not a subtype of Any. ast_t* id = ast_child(def); const char* name = ast_name(id); if(!strcmp(name, "Pointer")) return true; ast_t* typeparams = ast_childidx(def, 1); ast_t* typeargs = ast_childidx(ast, 2); return check_constraints(typeargs, typeparams, typeargs, true); }
bool expr_nominal(pass_opt_t* opt, ast_t** astp) { // Resolve type aliases and typeparam references. if(!names_nominal(opt, *astp, astp, true)) return false; ast_t* ast = *astp; switch(ast_id(ast)) { case TK_TYPEPARAMREF: return flatten_typeparamref(ast) == AST_OK; case TK_NOMINAL: break; default: return true; } // If still nominal, check constraints. ast_t* def = (ast_t*)ast_data(ast); // Special case: don't check the constraint of a Pointer. This allows a // Pointer[Pointer[A]], which is normally not allowed, as a Pointer[A] is // not a subtype of Any. ast_t* id = ast_child(def); const char* name = ast_name(id); if(!strcmp(name, "Pointer")) return true; ast_t* typeparams = ast_childidx(def, 1); ast_t* typeargs = ast_childidx(ast, 2); if(!reify_defaults(typeparams, typeargs, true)) return false; if(!strcmp(name, "MaybePointer")) { // MaybePointer[A] must be bound to a struct. assert(ast_childcount(typeargs) == 1); ast_t* typeparam = ast_child(typeparams); ast_t* typearg = ast_child(typeargs); bool ok = false; switch(ast_id(typearg)) { case TK_NOMINAL: { ast_t* def = (ast_t*)ast_data(typearg); ok = ast_id(def) == TK_STRUCT; break; } case TK_TYPEPARAMREF: { ast_t* def = (ast_t*)ast_data(typearg); ok = def == typeparam; break; } default: {} } if(!ok) { ast_error(ast, "%s is not allowed: the type argument to MaybePointer must be a struct", ast_print_type(ast)); return false; } } return check_constraints(typeargs, typeparams, typeargs, true); }
bool expr_nominal(pass_opt_t* opt, ast_t** astp) { // Resolve type aliases and typeparam references. if(!names_nominal(opt, *astp, astp, true)) return false; ast_t* ast = *astp; switch(ast_id(ast)) { case TK_TYPEPARAMREF: return flatten_typeparamref(opt, ast) == AST_OK; case TK_NOMINAL: break; default: return true; } // If still nominal, check constraints. ast_t* def = (ast_t*)ast_data(ast); // Special case: don't check the constraint of a Pointer or an Array. These // builtin types have no contraint on their type parameter, and it is safe // to bind a struct as a type argument (which is not safe on any user defined // type, as that type might then be used for pattern matching). if(is_pointer(ast) || is_literal(ast, "Array")) return true; ast_t* typeparams = ast_childidx(def, 1); ast_t* typeargs = ast_childidx(ast, 2); if(!reify_defaults(typeparams, typeargs, true, opt)) return false; if(is_maybe(ast)) { // MaybePointer[A] must be bound to a struct. assert(ast_childcount(typeargs) == 1); ast_t* typeparam = ast_child(typeparams); ast_t* typearg = ast_child(typeargs); bool ok = false; switch(ast_id(typearg)) { case TK_NOMINAL: { ast_t* def = (ast_t*)ast_data(typearg); ok = ast_id(def) == TK_STRUCT; break; } case TK_TYPEPARAMREF: { ast_t* def = (ast_t*)ast_data(typearg); ok = def == typeparam; break; } default: {} } if(!ok) { ast_error(opt->check.errors, ast, "%s is not allowed: " "the type argument to MaybePointer must be a struct", ast_print_type(ast)); return false; } return true; } return check_constraints(typeargs, typeparams, typeargs, true, opt); }