From acf7efded440be52d015dd13d8382c53421612ab Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Thu, 28 Nov 2019 22:24:10 +0100 Subject: [PATCH] Initial work on throws. Cleanup of AST printout (incomplete!). Fixed issues with dead code after return. --- README.md | 6 +- resources/testfragments/parsertest.c3 | 2 +- resources/testfragments/super_simple.c3 | 15 ++++ src/compiler/ast.c | 102 +++++++++++++----------- src/compiler/casts.c | 2 + src/compiler/compiler_internal.h | 6 +- src/compiler/context.c | 8 +- src/compiler/enums.h | 2 + src/compiler/expr_analysis.c | 1 + src/compiler/lexer.c | 2 +- src/compiler/llvm_codegen_debug_info.c | 3 + src/compiler/llvm_codegen_function.c | 21 ++++- src/compiler/llvm_codegen_internal.h | 1 + src/compiler/llvm_codegen_stmt.c | 6 ++ src/compiler/llvm_codegen_type.c | 3 + src/compiler/parser.c | 20 +++-- src/compiler/semantic_analyser.c | 9 +++ src/compiler/types.c | 5 ++ 18 files changed, 146 insertions(+), 68 deletions(-) diff --git a/README.md b/README.md index 2751652f7..0e3f6645a 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ There are some small work being done on the parser here, but most of the structu - `attribute` not analysed. - `$switch` and `$for` not handled. - Enums not correctly handled. -- Errors not correctly handles. +- Errors not correctly handled. - Type resolution not complete for all types. - `type` not handled. - `?:` not handled. @@ -62,9 +62,7 @@ under discussion. #### What's working? -- The compiler can compile simple programs, but integration with C is mostly -missing, which means that little can be *displayed* outwards. - Lexing and parsing works (except for the exceptions noted above). - +- Simple "hello world" If you wish to contribute with ideas, please file issues on the c3docs: https://github.com/c3lang/c3docs instead of the compiler. diff --git a/resources/testfragments/parsertest.c3 b/resources/testfragments/parsertest.c3 index 0073e7ac6..fee00d926 100644 --- a/resources/testfragments/parsertest.c3 +++ b/resources/testfragments/parsertest.c3 @@ -158,7 +158,7 @@ func void hello() throws Errors type(foo::y) z; type(int) * 2; $error = type(int); - int[4] a; + double[4] a; foo[1 + 2] * b; type((i > 0) ? type(int) : type(double)) doek; $e = type(type(type(Bar))); diff --git a/resources/testfragments/super_simple.c3 b/resources/testfragments/super_simple.c3 index 68d8c91b7..11cdd573c 100644 --- a/resources/testfragments/super_simple.c3 +++ b/resources/testfragments/super_simple.c3 @@ -69,10 +69,25 @@ typedef func void(int) as Foo; func void printf(char *hello); +macro @hello() +{ + printf("Hello world!\n"); +} + func int main(int x) { +int i = 0; +JUMP: + i = i + 1; + //@hello(); printf("Hello worldABC" "D" "E\u2701\n"); + if (i < 10) goto JUMP; + goto EX; + YEF: return 4 * test3(); + EX: + printf("EX\n"); + goto YEF; } func void test2(int* x, int y, int z) diff --git a/src/compiler/ast.c b/src/compiler/ast.c index bc567f6d4..8569d28d5 100644 --- a/src/compiler/ast.c +++ b/src/compiler/ast.c @@ -43,6 +43,7 @@ Decl *decl_new_with_type(Token name, DeclKind decl_type, Visibility visibility) case DECL_TYPEDEF: kind = TYPE_TYPEDEF; break; + case DECL_THROWS: case DECL_POISONED: case DECL_VAR: case DECL_ENUM_CONSTANT: @@ -369,6 +370,9 @@ void fprint_type_recursive(FILE *file, Type *type, int indent) fprintf_indented(file, indent, "(comp time float)\n"); break; case TYPE_STRING: + fprintf_indented(file, indent, "(string)\n"); + break; + case TYPE_ERROR_UNION: TODO } } @@ -390,72 +394,72 @@ const char *resolve_status_to_string(ResolveStatus status) void fprint_type_info_recursive(FILE *file, TypeInfo *type_info, int indent) { - fprint_indent(file, indent); if (!type_info) { - fprintf(file, "(type_info missing)\n"); + fprintf_indented(file, indent, "(type_info missing)\n"); return; } - fprintf(file, "(type_info\n"); - fprint_indent(file, indent + 1); - fprintf(file, "(resolve_status %s)\n", resolve_status_to_string(type_info->resolve_status)); + fprintf_indented(file, indent, "(type_info\n"); + fprintf_indented(file, indent + 1, "(resolve_status %s)\n", resolve_status_to_string(type_info->resolve_status)); if (type_info->resolve_status == RESOLVE_DONE) { fprint_type_recursive(file, type_info->type, indent + 1); - fprint_indent(file, indent); - fprintf(file, ")\n"); + fprint_endparen(file, indent); return; } switch (type_info->kind) { case TYPE_INFO_POISON: - fprintf(file, "(POISON)\n"); - return; + fprintf_indented(file, indent + 1, "(POISON)\n"); + break; case TYPE_INFO_IDENTIFIER: if (type_info->unresolved.path) { if (type_info->unresolved.path->module.string) { - fprintf(file, "(unresolved %s::%s::%s)\n", type_info->unresolved.path->module.string, type_info->unresolved.path->module.string, type_info->unresolved.name_loc.string); + fprintf_indented(file, indent + 1, "(unresolved %s::%s::%s)\n", type_info->unresolved.path->module.string, type_info->unresolved.path->module.string, type_info->unresolved.name_loc.string); } else { - fprintf(file, "(unresolved %s::%s)\n", type_info->unresolved.path->module.string, type_info->unresolved.name_loc.string); + fprintf_indented(file, indent + 1, "(unresolved %s::%s)\n", type_info->unresolved.path->module.string, type_info->unresolved.name_loc.string); } return; } - fprintf(file, "(unresolved %s)\n", type_info->unresolved.name_loc.string); + fprintf_indented(file, indent + 1, "(unresolved %s)\n", type_info->unresolved.name_loc.string); break; case TYPE_INFO_ARRAY: - fprintf(file, "(unresolved-array\n"); - fprint_type_info_recursive(file, type_info->array.base, indent + 1); - fprint_expr_recursive(file, type_info->array.len, indent + 1); + fprintf_indented(file, indent + 1, "(unresolved-array\n"); + fprint_type_info_recursive(file, type_info->array.base, indent + 2); + if (type_info->array.len) fprint_expr_recursive(file, type_info->array.len, indent + 1); + fprint_endparen(file, indent + 1); break; case TYPE_INFO_POINTER: - fprintf(file, "(pointer\n"); - fprint_type_info_recursive(file, type_info->pointer, indent + 1); + fprintf_indented(file, indent + 1, "(pointer\n"); + fprint_type_info_recursive(file, type_info->pointer, indent + 2); + fprint_endparen(file, indent + 1); break; case TYPE_INFO_INC_ARRAY: - fprintf(file, "(incarray\n"); - fprint_type_info_recursive(file, type_info->array.base, indent + 1); + fprintf_indented(file, indent + 1, "(incarray\n"); + fprint_type_info_recursive(file, type_info->array.base, indent + 2); + fprint_endparen(file, indent + 1); break; case TYPE_INFO_EXPRESSION: - fprintf(file, "(typexpr\n"); - fprint_expr_recursive(file, type_info->unresolved_type_expr, indent + 1); + fprintf_indented(file, indent + 1, "(typexpr\n"); + fprint_expr_recursive(file, type_info->unresolved_type_expr, indent + 2); + fprint_endparen(file, indent + 1); break; } fprint_endparen(file, indent); } void fprint_expr_recursive(FILE *file, Expr *expr, int indent) { - fprint_indent(file, indent); switch (expr->expr_kind) { case EXPR_IDENTIFIER: - fprintf(file, "(ident %s)\n", expr->identifier_expr.identifier.string); + fprintf_indented(file, indent, "(ident %s)\n", expr->identifier_expr.identifier.string); return; case EXPR_CONST: - fprintf(file, "(const "); + fprintf_indented(file, indent, "(const "); switch (expr->const_expr.type) { case CONST_NIL: @@ -483,37 +487,37 @@ void fprint_expr_recursive(FILE *file, Expr *expr, int indent) } return; case EXPR_BINARY: - fprintf(file, "(binary %s\n", token_type_to_string(expr->binary_expr.operator)); + fprintf_indented(file, indent, "(binary %s\n", token_type_to_string(expr->binary_expr.operator)); fprint_expr_recursive(file, expr->binary_expr.left, indent + 1); fprint_expr_recursive(file, expr->binary_expr.right, indent + 1); break; case EXPR_UNARY: - fprintf(file, "(unary %s\n", token_type_to_string(expr->unary_expr.operator)); + fprintf_indented(file, indent, "(unary %s\n", token_type_to_string(expr->unary_expr.operator)); fprint_expr_recursive(file, expr->unary_expr.expr, indent + 1); break; case EXPR_POST_UNARY: - fprintf(file, "(postunary %s\n", token_type_to_string(expr->post_expr.operator)); + fprintf_indented(file, indent, "(postunary %s\n", token_type_to_string(expr->post_expr.operator)); fprint_expr_recursive(file, expr->post_expr.expr, indent + 1); break; case EXPR_TYPE_ACCESS: - fprintf(file, "(typeaccess .%s\n", expr->type_access.name.string); + fprintf_indented(file, indent, "(typeaccess .%s\n", expr->type_access.name.string); fprint_type_info_recursive(file, expr->type_access.type, indent + 1); break; case EXPR_STRUCT_VALUE: - fprintf(file, "(structvalue\n"); + fprintf_indented(file, indent, "(structvalue\n"); fprint_type_info_recursive(file, expr->struct_value_expr.type, indent + 1); fprint_expr_recursive(file, expr->struct_value_expr.init_expr, indent + 1); break; case EXPR_ACCESS: - fprintf(file, "(access .%s\n", expr->access_expr.sub_element.string); + fprintf_indented(file, indent, "(access .%s\n", expr->access_expr.sub_element.string); fprint_expr_recursive(file, expr->access_expr.parent, indent + 1); break; case EXPR_TYPE: - fprintf(file, "(type\n"); + fprintf_indented(file, indent, "(type\n"); fprint_type_info_recursive(file, expr->type_expr.type, indent + 1); break; case EXPR_CALL: - fprintf(file, "(call\n"); + fprintf_indented(file, indent, "(call\n"); fprint_expr_recursive(file, expr->call_expr.function, indent + 1); { VECEACH(expr->call_expr.arguments, i) @@ -525,19 +529,19 @@ void fprint_expr_recursive(FILE *file, Expr *expr, int indent) case EXPR_CONDITIONAL: if (!expr->conditional_expr.then_expr) { - fprintf(file, "(elvis\n"); + fprintf_indented(file, indent, "(elvis\n"); fprint_expr_recursive(file, expr->conditional_expr.cond, indent + 1); } else { - fprintf(file, "(cond\n"); + fprintf_indented(file, indent, "(cond\n"); fprint_expr_recursive(file, expr->conditional_expr.cond, indent + 1); fprint_expr_recursive(file, expr->conditional_expr.then_expr, indent + 1); } fprint_expr_recursive(file, expr->conditional_expr.else_expr, indent + 1); break; case EXPR_INITIALIZER_LIST: - fprintf(file, "(initializerlist\n"); + fprintf_indented(file, indent, "(initializerlist\n"); { VECEACH(expr->initializer_expr, i) { @@ -546,25 +550,25 @@ void fprint_expr_recursive(FILE *file, Expr *expr, int indent) } break; case EXPR_SUBSCRIPT: - fprintf(file, "(subscript\n"); + fprintf_indented(file, indent, "(subscript\n"); fprint_expr_recursive(file, expr->subscript_expr.expr, indent + 1); fprint_expr_recursive(file, expr->subscript_expr.index, indent + 1); break; case EXPR_TRY: if (!expr->try_expr.else_expr) { - fprintf(file, "(try\n"); + fprintf_indented(file, indent, "(try\n"); fprint_expr_recursive(file, expr->try_expr.expr, indent + 1); } else { - fprintf(file, "(try-else\n"); + fprintf_indented(file, indent, "(try-else\n"); fprint_expr_recursive(file, expr->try_expr.expr, indent + 1); fprint_expr_recursive(file, expr->try_expr.else_expr, indent + 1); } break; default: - fprintf(file, "(TODOEXPR)\n"); + fprintf_indented(file, indent, "(TODOEXPR)\n"); return; } fprint_endparen(file, indent); @@ -584,11 +588,12 @@ void fprint_func_signature(FILE *file, FunctionSignature *signature, int indent) fprintf_indented(file, indent, "(params\n"); fprint_decl_list(file, signature->params, indent + 1); fprint_endparen(file, indent); - // TODO throws, variable + fprintf_indented(file, indent, "(throws\n"); + fprint_decl_list(file, signature->throws, indent + 1); + fprint_endparen(file, indent); } void fprint_decl_recursive(FILE *file, Decl *decl, int indent) { - fprint_indent(file, indent); switch (decl->decl_kind) { case DECL_MULTI_DECL: @@ -597,7 +602,7 @@ void fprint_decl_recursive(FILE *file, Decl *decl, int indent) fprint_endparen(file, indent); break; case DECL_VAR: - fprintf(file, "(var-%s %s\n", decl_var_to_string(decl->var.kind), decl->name.string ?: ""); + fprintf_indented(file, indent, "(var-%s %s\n", decl_var_to_string(decl->var.kind), decl->name.string ?: ""); fprint_type_info_recursive(file, decl->var.type_info, indent + 1); if (decl->var.init_expr) { @@ -662,8 +667,7 @@ void fprint_decl_recursive(FILE *file, Decl *decl, int indent) break; case DECL_ERROR_CONSTANT: fprintf_indented(file, indent, "(error-constant %s)\n", decl->name.string); - fprint_endparen(file, indent); - return; + break; case DECL_GENERIC: fprintf_indented(file, indent, "(generic %s\n", decl->name.string); fprint_indent(file, indent + 1); @@ -728,8 +732,10 @@ void fprint_decl_recursive(FILE *file, Decl *decl, int indent) fprintf_indented(file, indent, "(poisoned-decl)\n"); return; case DECL_ARRAY_VALUE: - TODO - break; + fprintf_indented(file, indent, "(array value"); + fprint_expr_recursive(file, decl->incr_array_decl, indent + 1); + fprint_endparen(file, indent); + return; case DECL_IMPORT: fprintf_indented(file, indent, "(import %s", decl->name.string); TODO @@ -737,6 +743,8 @@ void fprint_decl_recursive(FILE *file, Decl *decl, int indent) break; case DECL_ATTRIBUTE: TODO + case DECL_THROWS: + TODO } } @@ -957,4 +965,4 @@ void fprint_decl(FILE *file, Decl *dec) fprint_decl_recursive(file, dec, 0); } Module poisoned_module = { .name = "INVALID" }; - +Decl all_error = { .decl_kind = DECL_ERROR, .name = { .type = TOKEN_INVALID_TOKEN, .string = NULL } }; diff --git a/src/compiler/casts.c b/src/compiler/casts.c index bc7c5f8bc..17d773b78 100644 --- a/src/compiler/casts.c +++ b/src/compiler/casts.c @@ -550,6 +550,8 @@ CastFunc conversion(TypeKind from, Type *to) if (type_is_integer(to)) return &boxi; if (type_is_float(to)) return &bofp; return &erro; + case TYPE_ERROR_UNION: + TODO case TYPE_I8: case TYPE_I16: case TYPE_I32: diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 3043b72ae..7e915d84d 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -143,7 +143,7 @@ struct _TypeInfo { TypeUnresolved unresolved; Expr *unresolved_type_expr; - union + struct { TypeInfo *base; Expr *len; @@ -224,7 +224,7 @@ typedef struct _FunctionSignature bool variadic : 1; TypeInfo *rtype; Decl** params; - Token *throws; + Decl** throws; const char *mangled_signature; } FunctionSignature; @@ -702,6 +702,7 @@ typedef struct _Context STable local_symbols; Decl **header_declarations; Decl **enums; + Decl **error_types; Decl **types; Decl **functions; Decl **struct_functions; @@ -741,6 +742,7 @@ extern Diagnostics diagnostics; extern Token next_tok; extern Token tok; +extern Decl all_error; extern Type *type_bool, *type_void, *type_string, *type_voidptr; extern Type *type_float, *type_double; diff --git a/src/compiler/context.c b/src/compiler/context.c index e4a22ac36..45e39b230 100644 --- a/src/compiler/context.c +++ b/src/compiler/context.c @@ -131,13 +131,12 @@ void context_register_global_decl(Context *context, Decl *decl) case DECL_UNION: case DECL_TYPEDEF: vec_add(context->types, decl); - break; case DECL_ENUM: vec_add(context->enums, decl); break; case DECL_ERROR: - TODO + vec_add(context->error_types, decl); break; case DECL_ENUM_CONSTANT: case DECL_ERROR_CONSTANT: @@ -147,6 +146,7 @@ void context_register_global_decl(Context *context, Decl *decl) case DECL_CT_ELSE: case DECL_CT_ELIF: case DECL_ATTRIBUTE: + case DECL_THROWS: UNREACHABLE break; case DECL_CT_IF: @@ -255,6 +255,10 @@ void context_print_ast(Context *context, FILE *file) { fprint_decl(file, context->types[i]); } + VECEACH(context->error_types, i) + { + fprint_decl(file, context->error_types[i]); + } VECEACH(context->functions, i) { fprint_decl(file, context->functions[i]); diff --git a/src/compiler/enums.h b/src/compiler/enums.h index 0ae5348a7..7b7ea4459 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -202,6 +202,7 @@ typedef enum DECL_CT_ELSE, DECL_CT_ELIF, DECL_ATTRIBUTE, + DECL_THROWS, } DeclKind; // Ordering here is in priority if two branches should have the same exit. @@ -519,6 +520,7 @@ typedef enum TYPE_FUNC, TYPE_STRUCT, TYPE_UNION, + TYPE_ERROR_UNION, TYPE_TYPEDEF, TYPE_STRING, TYPE_ARRAY, diff --git a/src/compiler/expr_analysis.c b/src/compiler/expr_analysis.c index 5295cf268..65ba60bf2 100644 --- a/src/compiler/expr_analysis.c +++ b/src/compiler/expr_analysis.c @@ -897,6 +897,7 @@ static bool sema_expr_analyse_not(Context *context, Expr *expr, Expr *inner) case TYPE_UXX: case TYPE_FXX: case TYPE_TYPEDEF: + case TYPE_ERROR_UNION: UNREACHABLE case TYPE_FUNC: case TYPE_ARRAY: diff --git a/src/compiler/lexer.c b/src/compiler/lexer.c index dc20587bf..913593a62 100644 --- a/src/compiler/lexer.c +++ b/src/compiler/lexer.c @@ -652,7 +652,7 @@ Token lexer_scan_token(void) case '^': return match('=') ? make_token(TOKEN_BIT_XOR_ASSIGN, "^=") : make_token(TOKEN_BIT_XOR, "^"); case '?': - return match(':') ? make_token(TOKEN_EQEQ, "?:") : make_token(TOKEN_EQ, "?"); + return match(':') ? make_token(TOKEN_ELVIS, "?:") : make_token(TOKEN_QUESTION, "?"); case '<': if (match('<')) return match('=') ? make_token(TOKEN_SHL_ASSIGN, "<<=") : make_token(TOKEN_SHL, "<<"); return match('=') ? make_token(TOKEN_LESS_EQ, "<=") : make_token(TOKEN_LESS, "<"); diff --git a/src/compiler/llvm_codegen_debug_info.c b/src/compiler/llvm_codegen_debug_info.c index 3368a6777..7d95c2410 100644 --- a/src/compiler/llvm_codegen_debug_info.c +++ b/src/compiler/llvm_codegen_debug_info.c @@ -9,6 +9,7 @@ static inline LLVMMetadataRef gencontext_create_debug_type_from_decl(GenContext static LLVMMetadataRef debug_params[512]; switch (decl->decl_kind) { + case DECL_THROWS: case DECL_ATTRIBUTE: case DECL_ENUM_CONSTANT: case DECL_POISONED: @@ -165,6 +166,8 @@ LLVMMetadataRef gencontext_get_debug_type(GenContext *context, Type *type) break; case TYPE_SUBARRAY: break; + case TYPE_ERROR_UNION: + TODO } TODO } diff --git a/src/compiler/llvm_codegen_function.c b/src/compiler/llvm_codegen_function.c index 44cf0a343..9eff9b7ce 100644 --- a/src/compiler/llvm_codegen_function.c +++ b/src/compiler/llvm_codegen_function.c @@ -12,7 +12,7 @@ static char *mangle_name(char *buffer, Decl *decl) return buffer; } -void gencontext_emit_br(GenContext *context, LLVMBasicBlockRef next_block) +bool gencontext_check_block_branch_emit(GenContext *context) { assert(context->current_block); // If it's not used, we can delete the previous block and skip the branch. @@ -40,12 +40,18 @@ void gencontext_emit_br(GenContext *context, LLVMBasicBlockRef next_block) // Consequently we will delete those and realize that // we then have no need for emitting a br. if (!context->current_block_is_target - && !LLVMGetFirstUse(LLVMBasicBlockAsValue(context->current_block))) + && !LLVMGetFirstUse(LLVMBasicBlockAsValue(context->current_block))) { LLVMDeleteBasicBlock(context->current_block); context->current_block = NULL; - return; + return false; } + return true; +}; + +void gencontext_emit_br(GenContext *context, LLVMBasicBlockRef next_block) +{ + if (!gencontext_check_block_branch_emit(context)) return; context->current_block = NULL; LLVMBuildBr(context->builder, next_block); } @@ -111,8 +117,15 @@ void gencontext_emit_function_body(GenContext *context, Decl *decl) gencontext_emit_compound_stmt(context, decl->func.body); + if (!LLVMGetFirstInstruction(context->current_block) && !LLVMGetFirstUse(LLVMBasicBlockAsValue(context->current_block))) + { + LLVMBasicBlockRef prev_block = LLVMGetPreviousBasicBlock(context->current_block); + LLVMDeleteBasicBlock(context->current_block); + context->current_block = prev_block; + LLVMPositionBuilderAtEnd(context->builder, context->current_block); + } // Insert a return if needed. - if (!LLVMGetBasicBlockTerminator(LLVMGetInsertBlock(context->builder))) + if (!LLVMGetBasicBlockTerminator(context->current_block)) { assert(decl->func.function_signature.rtype->type->type_kind == TYPE_VOID); LLVMBuildRetVoid(context->builder); diff --git a/src/compiler/llvm_codegen_internal.h b/src/compiler/llvm_codegen_internal.h index 01765e1fc..6e455f559 100644 --- a/src/compiler/llvm_codegen_internal.h +++ b/src/compiler/llvm_codegen_internal.h @@ -79,6 +79,7 @@ LLVMValueRef gencontext_emit_alloca(GenContext *context, Decl *decl); void gencontext_emit_compound_stmt(GenContext *context, Ast *ast); void gencontext_emit_block(GenContext *context, LLVMBasicBlockRef next_block); void gencontext_emit_br(GenContext *context, LLVMBasicBlockRef next_block); +bool gencontext_check_block_branch_emit(GenContext *context); void gencontext_emit_cond_br(GenContext *context, LLVMValueRef value, LLVMBasicBlockRef thenBlock, LLVMBasicBlockRef elseBlock); static inline LLVMBasicBlockRef gencontext_create_free_block(GenContext *context, const char *name) { diff --git a/src/compiler/llvm_codegen_stmt.c b/src/compiler/llvm_codegen_stmt.c index e117f4150..e0b5639b4 100644 --- a/src/compiler/llvm_codegen_stmt.c +++ b/src/compiler/llvm_codegen_stmt.c @@ -29,6 +29,8 @@ static inline void gencontext_emit_stmt_list(GenContext *context, Ast *ast) static inline void gencontext_emit_return(GenContext *context, Ast *ast) { + // Ensure we are on a branch that is non empty. + if (!gencontext_check_block_branch_emit(context)) return; if (!ast->return_stmt.expr) { LLVMBuildRetVoid(context->builder); @@ -36,6 +38,10 @@ static inline void gencontext_emit_return(GenContext *context, Ast *ast) } LLVMValueRef returnValue = gencontext_emit_expr(context, ast->return_stmt.expr); LLVMBuildRet(context->builder, returnValue); + context->current_block = NULL; + LLVMBasicBlockRef post_ret_block = gencontext_create_free_block(context, "ret"); + gencontext_emit_block(context, post_ret_block); + } static inline LLVMValueRef gencontext_emit_cond(GenContext *context, Ast *ast) diff --git a/src/compiler/llvm_codegen_type.c b/src/compiler/llvm_codegen_type.c index 3cab987ac..942e0c4d5 100644 --- a/src/compiler/llvm_codegen_type.c +++ b/src/compiler/llvm_codegen_type.c @@ -83,6 +83,8 @@ static inline LLVMTypeRef gencontext_create_llvm_type_from_decl(GenContext *cont context->error_type = error_type; } return context->error_type; + case DECL_THROWS: + UNREACHABLE } UNREACHABLE } @@ -142,6 +144,7 @@ LLVMTypeRef gencontext_get_llvm_type(GenContext *context, Type *type) case TYPE_UNION: case TYPE_ENUM: case TYPE_ERROR: + case TYPE_ERROR_UNION: return type->backend_type = gencontext_create_llvm_type_from_decl(context, type->decl); case TYPE_FUNC: return type->backend_type = gencontext_create_llvm_func_type(context, type); diff --git a/src/compiler/parser.c b/src/compiler/parser.c index 2600752a1..2549e6324 100644 --- a/src/compiler/parser.c +++ b/src/compiler/parser.c @@ -1948,7 +1948,7 @@ static inline Decl *parse_generics_declaration(Visibility visibility) rtype = TRY_TYPE_OR(parse_type_expression(), &poisoned_decl); } Path *path = parse_path(); - Decl *decl = decl_new_with_type(tok, DECL_GENERIC, visibility); + Decl *decl = decl_new(DECL_GENERIC, tok, visibility); decl->generic_decl.path = path; if (!consume_ident("generic function name")) return &poisoned_decl; decl->generic_decl.rtype = rtype; @@ -2066,7 +2066,7 @@ static inline bool parse_param_decl(Visibility parent_visibility, Decl*** parame * ; * */ -static inline bool parse_opt_throw_declaration(FunctionSignature *signature) +static inline bool parse_opt_throw_declaration(Visibility visibility, FunctionSignature *signature) { if (tok.type == TOKEN_THROW) { @@ -2075,11 +2075,17 @@ static inline bool parse_opt_throw_declaration(FunctionSignature *signature) } if (!try_consume(TOKEN_THROWS)) return true; - Token *throws = NULL; + if (tok.type != TOKEN_TYPE_IDENT) + { + VECADD(signature->throws, &all_error); + return true; + } + Decl **throws = NULL; while (tok.type == TOKEN_TYPE_IDENT) { - throws = VECADD(throws, tok); - advance(); + Decl *error = decl_new(DECL_ERROR, tok, visibility); + advance(); + VECADD(throws, error); if (!try_consume(TOKEN_COMMA)) break; } switch (tok.type) @@ -2228,7 +2234,7 @@ static inline bool parse_func_typedef(Decl *decl, Visibility visibility) { return false; } - return parse_opt_throw_declaration(&(decl->typedef_decl.function_signature)); + return parse_opt_throw_declaration(VISIBLE_PUBLIC, &(decl->typedef_decl.function_signature)); } @@ -2351,7 +2357,7 @@ static inline Decl *parse_func_definition(Visibility visibility, bool is_interfa if (!parse_opt_parameter_type_list(visibility, &(func->func.function_signature), is_interface)) return &poisoned_decl; - if (!parse_opt_throw_declaration(&(func->func.function_signature))) return &poisoned_decl; + if (!parse_opt_throw_declaration(visibility, &(func->func.function_signature))) return &poisoned_decl; // TODO remove is_interface = tok.type == TOKEN_EOS; diff --git a/src/compiler/semantic_analyser.c b/src/compiler/semantic_analyser.c index dc4239be8..a8b82da20 100644 --- a/src/compiler/semantic_analyser.c +++ b/src/compiler/semantic_analyser.c @@ -253,6 +253,7 @@ static inline Type *sema_analyse_function_signature(Context *context, FunctionSi buffer[buffer_write_offset++] = ')'; if (vec_size(signature->throws)) { + buffer[buffer_write_offset++] = '!'; VECEACH(signature->throws, i) { TODO @@ -1125,6 +1126,8 @@ bool sema_analyse_decl(Context *context, Decl *decl) decl->resolve_status = RESOLVE_RUNNING; switch (decl->decl_kind) { + case DECL_THROWS: + TODO case DECL_STRUCT: case DECL_UNION: if (!sema_analyse_struct_union(context, decl)) return decl_poison(decl); @@ -1240,6 +1243,10 @@ void sema_analysis_pass_decls(Context *context) { sema_analyse_decl(context, context->types[i]); } + VECEACH(context->error_types, i) + { + sema_analyse_decl(context, context->error_types[i]); + } VECEACH(context->struct_functions, i) { sema_analyse_decl(context, context->struct_functions[i]); @@ -1273,6 +1280,8 @@ static bool sema_resolve_type_identifier(Context *context, TypeInfo *type_info) switch (decl->decl_kind) { + case DECL_THROWS: + TODO case DECL_STRUCT: case DECL_UNION: case DECL_ERROR: diff --git a/src/compiler/types.c b/src/compiler/types.c index fdb5e0ed7..221bc052b 100644 --- a/src/compiler/types.c +++ b/src/compiler/types.c @@ -87,6 +87,8 @@ const char *type_to_error_string(Type *type) case TYPE_SUBARRAY: asprintf(&buffer, "%s[:]", type_to_error_string(type->array.base)); return buffer; + case TYPE_ERROR_UNION: + TODO } } @@ -102,6 +104,7 @@ static void type_append_signature_name_user_defined(Decl *decl, char *dst, size_ *offset += len; return; } + case DECL_THROWS: case DECL_POISONED: case DECL_VAR: case DECL_ENUM_CONSTANT: @@ -176,6 +179,8 @@ size_t type_size(Type *canonical) return type_size(canonical->array.base) * canonical->array.len; case TYPE_SUBARRAY: TODO + case TYPE_ERROR_UNION: + TODO } TODO }