From: Brendan Hansen Date: Mon, 21 Dec 2020 02:16:57 +0000 (-0600) Subject: better error reporting in many places X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=59d5f692f22fc879e559ea5860380fa4136b4893;p=onyx.git better error reporting in many places --- diff --git a/Makefile b/Makefile index 36c211d1..b923f94a 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ RELEASE=1 +USE_GCC=1 OBJ_FILES=\ build/onyxlex.o \ @@ -22,7 +23,11 @@ else ifeq ($(RELEASE), 0) CC=gcc else - CC=tcc + ifeq ($(USE_GCC),1) + CC=gcc + else + CC=tcc + endif endif endif diff --git a/core/alloc/heap.onyx b/core/alloc/heap.onyx index 24add474..94ff85b6 100644 --- a/core/alloc/heap.onyx +++ b/core/alloc/heap.onyx @@ -90,6 +90,8 @@ heap_free :: proc (ptr: rawptr) { #private_file heap_resize :: proc (ptr: rawptr, new_size: u32, align: u32) -> rawptr { + if ptr == null do return null; + hb_ptr := cast(^heap_block) (cast(u32) ptr - sizeof heap_block); old_size := hb_ptr.size - sizeof heap_block; diff --git a/core/conv.onyx b/core/conv.onyx index 3402baae..9f5a3c8e 100644 --- a/core/conv.onyx +++ b/core/conv.onyx @@ -180,6 +180,19 @@ str_format_va :: proc (format: str, buffer: [] u8, va: vararg) -> str { buffer[len] = c; len += 1; } + + case #char "b" { + b : bool; + if !vararg_get(va, ^b) do return; + + s := "false"; + if b do s = "true"; + + for a: s { + buffer[len] = a; + len += 1; + } + } } state = 0; diff --git a/core/map.onyx b/core/map.onyx index 997c0aff..15b3cbce 100644 --- a/core/map.onyx +++ b/core/map.onyx @@ -1,5 +1,6 @@ package core.map +use package core { printf } use package core.array as array use package core.string as string diff --git a/docs/bugs b/docs/bugs index 23fd0eb4..a0e9b3de 100644 --- a/docs/bugs +++ b/docs/bugs @@ -23,4 +23,35 @@ List of known bugs: and converted to a cast(f32). Then, when it doesn't match the first one and it tries the second, the parameter types are f32 and unsized int, which is doesn't match the second one, when the original parameters would - have matched correctly. \ No newline at end of file + have matched correctly. + +[ ] `TileData :: [TILE_DATA_WIDTH * TILE_DATA_HEIGHT] bool;` results in a + segfault because it is an invalid top level node, but that is not checked + before it is tried to be used. + +[X] `TileData :: #type [TILE_DATA_WIDTH * TILE_DATA_HEIGHT] bool;` produces the + following error: + ``` + (/home/brendan/dev/onyx/aoc/day20.onyx:25,19) Array type expects type 'i32' for size, got 'unsized int'. + 25 | TileData :: #type [TILE_DATA_WIDTH * TILE_DATA_HEIGHT] bool; + ``` + + This because the expression for the array size is not reducing and getting + converted to the fixed size integer. I suspect this is because for sizeof + and alignof expression, `fill_in_type` is not used, and that function has + the logic to handle the array subscript reduction and type resolution. + +[X] The following struct is causing a seg fault in the compiler. I believe it + is because of the duplicate struct member names and failing to get the position + in the file to report the error. + ``` + Tile :: struct { + id : u32; + orientation : TileOrientation; + data : [] bool; + edges : [] u32; + + pos_x : u32 = 0; + pos_x : u32 = 0; + } + ``` diff --git a/docs/todo b/docs/todo index 492dbe52..cce4d307 100644 --- a/docs/todo +++ b/docs/todo @@ -99,6 +99,15 @@ Language Cohesion: thought to remember that ranges in for-loops and slices are NOT inclusive on the upper end. + [ ] Functions should be polymorphic on the size of array parameters. For example, + foo :: proc (arr: [$N] $T) { ... } + should be polymorphic on both the type of the array elements and the array + size. This would allow for better support for fixed size arrays, as well + as some needed built in functions such as: + array_to_slice :: proc (arr: [$N] $T) -> [] T { + return arr[0 .. N]; + } + API Expansion: There are many different places where the standard API for WASI and JS backends could be improved. Here are some of the target areas. diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index 496890e0..ffb8c60d 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -448,8 +448,8 @@ struct AstAddressOf { AstTyped_base; AstTyped *expr; }; struct AstDereference { AstTyped_base; AstTyped *expr; }; struct AstArrayAccess { AstTyped_base; AstTyped *addr; AstTyped *expr; u64 elem_size; }; struct AstFieldAccess { AstTyped_base; AstTyped *expr; u32 offset; u32 idx; char* field; }; // If token is null, defer to field -struct AstSizeOf { AstTyped_base; AstType *so_type; u64 size; }; -struct AstAlignOf { AstTyped_base; AstType *ao_type; u64 alignment; }; +struct AstSizeOf { AstTyped_base; AstType *so_ast_type; Type *so_type; u64 size; }; +struct AstAlignOf { AstTyped_base; AstType *ao_ast_type; Type *ao_type; u64 alignment; }; struct AstFileContents { AstTyped_base; OnyxToken *filename; u32 addr, size; }; struct AstStructLiteral { AstTyped_base; diff --git a/onyx b/onyx index 7d215a93..c7d6c45a 100755 Binary files a/onyx and b/onyx differ diff --git a/src/onyxchecker.c b/src/onyxchecker.c index ba1324b4..e2722741 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -33,13 +33,23 @@ CHECK(struct, AstStructType* s_node); CHECK(function_header, AstFunction* func); CHECK(memres, AstMemRes* memres); -static inline void fill_in_type(AstTyped* node) { - if (node->type_node && node->type_node->kind == Ast_Kind_Array_Type) { - if (((AstArrayType *) node->type_node)->count_expr) { - check_expression(&((AstArrayType *) node->type_node)->count_expr); - resolve_expression_type(((AstArrayType *) node->type_node)->count_expr); +static inline void fill_in_array_count(AstType* type_node) { + if (type_node == NULL) return; + + if (type_node->kind == Ast_Kind_Type_Alias) { + fill_in_array_count(((AstTypeAlias *) type_node)->to); + } + + if (type_node->kind == Ast_Kind_Array_Type) { + if (((AstArrayType *) type_node)->count_expr) { + check_expression(&((AstArrayType *) type_node)->count_expr); + resolve_expression_type(((AstArrayType *) type_node)->count_expr); } } +} + +static inline void fill_in_type(AstTyped* node) { + fill_in_array_count(node->type_node); if (node->type == NULL) node->type = type_build_from_ast(semstate.allocator, node->type_node); @@ -1148,13 +1158,27 @@ b32 check_range_literal(AstBinaryOp** prange) { } b32 check_size_of(AstSizeOf* so) { - so->size = type_size_of(type_build_from_ast(semstate.allocator, so->so_type)); + fill_in_array_count(so->so_ast_type); + + so->so_type = type_build_from_ast(semstate.allocator, so->so_ast_type); + if (so->so_type == NULL) { + onyx_report_error(so->token->pos, "Error with type used here."); + return 1; + } + so->size = type_size_of(so->so_type); return 0; } b32 check_align_of(AstAlignOf* ao) { - ao->alignment = type_alignment_of(type_build_from_ast(semstate.allocator, ao->ao_type)); + fill_in_array_count(ao->ao_ast_type); + + ao->ao_type = type_build_from_ast(semstate.allocator, ao->ao_ast_type); + if (ao->ao_type == NULL) { + onyx_report_error(ao->token->pos, "Error with type used here."); + return 1; + } + ao->alignment = type_alignment_of(ao->ao_type); return 0; } @@ -1356,27 +1380,6 @@ b32 check_overloaded_function(AstOverloadedFunction* func) { } b32 check_struct(AstStructType* s_node) { - bh_table(i32) mem_set; - bh_table_init(global_heap_allocator, mem_set, bh_arr_length(s_node->members)); - - bh_arr_each(AstStructMember *, member, s_node->members) { - token_toggle_end((*member)->token); - - if (bh_table_has(i32, mem_set, (*member)->token->text)) { - onyx_report_error((*member)->token->pos, - "Duplicate struct member '%s'.", - (*member)->token->text); - - token_toggle_end((*member)->token); - return 1; - } - - bh_table_put(i32, mem_set, (*member)->token->text, 1); - token_toggle_end((*member)->token); - } - - bh_table_free(mem_set); - // NOTE: fills in the stcache type_build_from_ast(semstate.allocator, (AstType *) s_node); diff --git a/src/onyxclone.c b/src/onyxclone.c index 3cb73c20..355af0e2 100644 --- a/src/onyxclone.c +++ b/src/onyxclone.c @@ -167,11 +167,11 @@ AstNode* ast_clone(bh_allocator a, void* n) { break; case Ast_Kind_Size_Of: - ((AstSizeOf *) nn)->so_type = (AstType *) ast_clone(a, ((AstSizeOf *) node)->so_type); + ((AstSizeOf *) nn)->so_ast_type = (AstType *) ast_clone(a, ((AstSizeOf *) node)->so_ast_type); break; case Ast_Kind_Align_Of: - ((AstAlignOf *) nn)->ao_type = (AstType *) ast_clone(a, ((AstAlignOf *) node)->ao_type); + ((AstAlignOf *) nn)->ao_ast_type = (AstType *) ast_clone(a, ((AstAlignOf *) node)->ao_ast_type); break; case Ast_Kind_Struct_Literal: { diff --git a/src/onyxparser.c b/src/onyxparser.c index 3edac59a..bc890b6c 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -366,7 +366,7 @@ static AstTyped* parse_factor(OnyxParser* parser) { case Token_Type_Keyword_Sizeof: { AstSizeOf* so_node = make_node(AstSizeOf, Ast_Kind_Size_Of); so_node->token = expect_token(parser, Token_Type_Keyword_Sizeof); - so_node->so_type = (AstType *) parse_type(parser); + so_node->so_ast_type = (AstType *) parse_type(parser); so_node->type_node = (AstType *) &basic_type_i32; retval = (AstTyped *) so_node; @@ -376,7 +376,7 @@ static AstTyped* parse_factor(OnyxParser* parser) { case Token_Type_Keyword_Alignof: { AstAlignOf* ao_node = make_node(AstAlignOf, Ast_Kind_Align_Of); ao_node->token = expect_token(parser, Token_Type_Keyword_Alignof); - ao_node->ao_type = (AstType *) parse_type(parser); + ao_node->ao_ast_type = (AstType *) parse_type(parser); ao_node->type_node = (AstType *) &basic_type_i32; retval = (AstTyped *) ao_node; diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 5003c71a..873fa80e 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -97,6 +97,29 @@ AstType* symres_type(AstType* type) { if (s_node->flags & Ast_Flag_Type_Is_Resolved) return type; s_node->flags |= Ast_Flag_Type_Is_Resolved; + + { + bh_table(i32) mem_set; + bh_table_init(global_heap_allocator, mem_set, bh_arr_length(s_node->members)); + + bh_arr_each(AstStructMember *, member, s_node->members) { + token_toggle_end((*member)->token); + + if (bh_table_has(i32, mem_set, (*member)->token->text)) { + onyx_report_error((*member)->token->pos, + "Duplicate struct member '%s'.", + (*member)->token->text); + + token_toggle_end((*member)->token); + return type; + } + + bh_table_put(i32, mem_set, (*member)->token->text, 1); + token_toggle_end((*member)->token); + } + + bh_table_free(mem_set); + } fori (i, 0, bh_arr_length(s_node->members)) { AstStructMember *member = s_node->members[i]; @@ -220,12 +243,12 @@ static void symres_call(AstCall* call) { static void symres_size_of(AstSizeOf* so) { so->type_node = symres_type(so->type_node); - so->so_type = symres_type(so->so_type); + so->so_ast_type = symres_type(so->so_ast_type); } static void symres_align_of(AstAlignOf* ao) { ao->type_node = symres_type(ao->type_node); - ao->ao_type = symres_type(ao->ao_type); + ao->ao_ast_type = symres_type(ao->ao_ast_type); } static void symres_field_access(AstFieldAccess** fa) { @@ -353,7 +376,10 @@ static void symres_struct_literal(AstStructLiteral* sl) { } } - bh_arr_each(AstTyped *, expr, sl->values) symres_expression(expr); + bh_arr_each(AstTyped *, expr, sl->values) { + if (*expr == NULL) onyx_report_error(sl->token->pos, "Some kind of error occured with this struct literal."); + else symres_expression(expr); + } } static void symres_array_literal(AstArrayLiteral* al) { diff --git a/src/onyxtypes.c b/src/onyxtypes.c index 16eed850..0145f72e 100644 --- a/src/onyxtypes.c +++ b/src/onyxtypes.c @@ -313,6 +313,8 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { if (a_node->count_expr->kind != Ast_Kind_NumLit || a_node->count_expr->type->kind != Type_Kind_Basic || a_node->count_expr->type->Basic.kind != Basic_Kind_I32) { + onyx_report_error(type_node->token->pos, "Array type expects type 'i32' for size, got '%s'.", + type_get_name(a_node->count_expr->type)); return NULL; }