diff --git a/compile.c b/compile.c index 30e20e5..3f7380e 100644 --- a/compile.c +++ b/compile.c @@ -4108,8 +4108,12 @@ CORD compile_function(env_t *env, ast_t *ast, CORD *staticdefs) body_scope->fn_ret = ret_t; type_t *body_type = get_type(body_scope, fndef->body); - if (ret_t->tag != VoidType && ret_t->tag != AbortType && body_type->tag != AbortType && body_type->tag != ReturnType) + if (ret_t->tag == AbortType) { + if (body_type->tag != AbortType) + code_err(ast, "This function can reach the end without aborting!"); + } else if (ret_t->tag != VoidType && body_type->tag != ReturnType) { code_err(ast, "This function can reach the end without returning a %T value!", ret_t); + } CORD body = compile_statement(body_scope, fndef->body); if (streq(raw_name, "main")) diff --git a/environment.c b/environment.c index ca33ee4..1c8df4c 100644 --- a/environment.c +++ b/environment.c @@ -99,6 +99,7 @@ env_t *new_compilation_unit(CORD libname) Array_t namespace; } global_types[] = { {"Void", Type(VoidType), "Void_t", "Void$info", {}}, + {"Abort", Type(AbortType), "void", "Abort$info", {}}, {"Memory", Type(MemoryType), "Memory_t", "Memory$info", {}}, {"Bool", Type(BoolType), "Bool_t", "Bool$info", TypedArray(ns_entry_t, {"parse", "Bool$parse", "func(text:Text -> Bool?)"}, diff --git a/typecheck.c b/typecheck.c index 1ab2017..0530ff7 100644 --- a/typecheck.c +++ b/typecheck.c @@ -920,8 +920,18 @@ type_t *get_type(env_t *env, ast_t *ast) } env_t *block_env = fresh_scope(env); + for (ast_list_t *stmt = block->statements; stmt; stmt = stmt->next) { + prebind_statement(block_env, stmt->ast); + } for (ast_list_t *stmt = block->statements; stmt; stmt = stmt->next) { bind_statement(block_env, stmt->ast); + if (stmt->next) { // Check for unreachable code: + if (stmt->ast->tag == Return) + code_err(stmt->ast, "This statement will always return, so the rest of the code in this block is unreachable!"); + type_t *statement_type = get_type(block_env, stmt->ast); + if (statement_type && statement_type->tag == AbortType && stmt->next) + code_err(stmt->ast, "This statement will always abort, so the rest of the code in this block is unreachable!"); + } } return get_type(block_env, last->ast); }