bool expr_fun(pass_opt_t* opt, ast_t* ast) { typecheck_t* t = &opt->check; AST_GET_CHILDREN(ast, cap, id, typeparams, params, type, can_error, body); if(ast_id(body) == TK_NONE) return true; if(!coerce_literals(&body, type, opt)) return false; bool is_trait = (ast_id(t->frame->type) == TK_TRAIT) || (ast_id(t->frame->type) == TK_INTERFACE) || (ast_id((ast_t*)ast_data(ast)) == TK_TRAIT) || (ast_id((ast_t*)ast_data(ast)) == TK_INTERFACE); // Check partial functions. if(ast_id(can_error) == TK_QUESTION) { // If a partial function, check that we might actually error. if(!is_trait && !ast_canerror(body)) { ast_error(can_error, "function body is not partial but the function is"); return false; } } else { // If not a partial function, check that we can't error. if(ast_canerror(body)) { ast_error(can_error, "function body is partial but the function is not"); show_partiality(body); return false; } } if(!check_primitive_init(t, ast) || !check_finaliser(ast)) return false; switch(ast_id(ast)) { case TK_NEW: return check_fields_defined(ast) && check_main_create(t, ast); case TK_FUN: return check_return_type(ast); default: {} } return true; }
bool expr_fun(pass_opt_t* opt, ast_t* ast) { typecheck_t* t = &opt->check; AST_GET_CHILDREN(ast, cap, id, typeparams, params, type, can_error, body); if(ast_id(body) == TK_NONE) return true; if(!coerce_literals(&body, type, opt)) return false; bool is_trait = (ast_id(t->frame->type) == TK_TRAIT) || (ast_id(t->frame->type) == TK_INTERFACE) || (ast_id((ast_t*)ast_data(ast)) == TK_TRAIT) || (ast_id((ast_t*)ast_data(ast)) == TK_INTERFACE); // Check partial functions. if(ast_id(can_error) == TK_QUESTION) { // If a partial function, check that we might actually error. ast_t* body_type = ast_type(body); if(body_type == NULL) { // An error has already occurred. assert(get_error_count() > 0); return false; } if(!is_trait && !ast_canerror(body) && (ast_id(body_type) != TK_COMPILE_INTRINSIC)) { ast_error(can_error, "function body is not partial but the function is"); return false; } } else { // If not a partial function, check that we can't error. if(ast_canerror(body)) { ast_error(can_error, "function body is partial but the function is not"); show_partiality(body); return false; } } if(!check_primitive_init(t, ast) || !check_finaliser(t, ast)) return false; switch(ast_id(ast)) { case TK_NEW: { bool ok = true; if(is_machine_word(type)) { if(!check_return_type(ast)) ok = false; } if(!check_fields_defined(ast)) ok = false; if(!check_main_create(t, ast)) ok = false; return ok; } case TK_FUN: return check_return_type(ast); default: {} } return true; }