From: Brendan Hansen Date: Mon, 7 Jun 2021 01:30:07 +0000 (-0500) Subject: bugfixes and added '#callsite' for default members X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=e0283de12149e1448b827df3e9b2bd1e0c977cdf;p=onyx.git bugfixes and added '#callsite' for default members --- diff --git a/bin/onyx b/bin/onyx index daf1e170..dd29ce75 100755 Binary files a/bin/onyx and b/bin/onyx differ diff --git a/core/builtin.onyx b/core/builtin.onyx index 10f45735..664a617e 100644 --- a/core/builtin.onyx +++ b/core/builtin.onyx @@ -168,3 +168,10 @@ Iterator :: struct (T: type_expr) { next: (data: rawptr) -> (T, bool); close: (data: rawptr) -> void = null_proc; } + + +CallSite :: struct { + file : str; + line : u32; + column : u32; +} \ No newline at end of file diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index dae2a82a..e1aaed02 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -81,6 +81,7 @@ NODE(PolyProc) \ \ NODE(Note) \ + NODE(CallSite) \ \ NODE(Package) @@ -180,6 +181,7 @@ typedef enum AstKind { Ast_Kind_Directive_Add_Overload, Ast_Kind_Directive_Operator, Ast_Kind_Directive_Export, + Ast_Kind_Call_Site, Ast_Kind_Note, @@ -942,6 +944,16 @@ struct AstNote { AstNode_base; }; +struct AstCallSite { + AstTyped_base; + + OnyxToken* callsite_token; + + AstStrLit* filename; + AstNumLit* line; + AstNumLit* column; +}; + typedef enum EntityState { Entity_State_Error, @@ -1164,6 +1176,7 @@ extern Type *builtin_vararg_type_type; extern AstTyped *builtin_context_variable; extern AstType *builtin_allocator_type; extern AstType *builtin_iterator_type; +extern AstType *builtin_callsite_type; typedef struct BuiltinSymbol { char* package; diff --git a/modules/ui/ui.onyx b/modules/ui/ui.onyx index 90bbff38..13a72342 100644 --- a/modules/ui/ui.onyx +++ b/modules/ui/ui.onyx @@ -43,7 +43,7 @@ get_text_width :: (text: str, size := DEFAULT_TEXT_SIZE) -> f32 { } // 'x' and 'y' are the top-left coordinates of the text. 'y' is NOT the baseline. -draw_text :: (text: str, x: f32, y: f32, size := DEFAULT_TEXT_SIZE, color := gfx.Color4.{1,1,1}) { +draw_text_raw :: (text: str, x: f32, y: f32, size := DEFAULT_TEXT_SIZE, color := gfx.Color4.{1,1,1}) { gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, font_texture); gfx.set_texture(0); @@ -90,21 +90,26 @@ draw_rect :: proc { } @Themeing -draw_button :: (use r: Rectangle, text: str) -> bool { - gfx.set_texture(); +draw_text :: (use r: Rectangle, text: str, theme := ^default_text_theme) -> bool { + height := Rectangle.height(r); + draw_text_raw(text, x0, y0, theme.font_size * height, theme.text_color); +} - padding :: 10.0f @RawPixels +@Themeing +draw_button :: (use r: Rectangle, text: str, theme := ^default_button_theme) -> bool { + gfx.set_texture(); + border_width := theme.border_width; width, height := Rectangle.dimensions(r); - gfx.rect(.{ x0, y0 }, .{ width, height }, .{ 0.2, 0.2, 0.2 }); - gfx.rect(.{ x0 + padding, y0 + padding }, .{ width - padding * 2, height - padding * 2 }, .{ 0.1, 0.1, 0.1 }); + gfx.rect(.{ x0, y0 }, .{ width, height }, theme.border_color); + gfx.rect(.{ x0 + border_width, y0 + border_width }, .{ width - border_width * 2, height - border_width * 2 }, theme.background_color); - font_size := height * .4; + font_size := height * theme.font_size; text_width := font->get_width(text, font_size); text_height := font->get_height(text, font_size); - draw_text(text, x0 + (width - text_width) / 2, y0 + (height - text_height) / 2, font_size, .{ 1, 1, 1 }); + draw_text_raw(text, x0 + (width - text_width) / 2, y0 + (height - text_height) / 2, font_size, theme.text_color); return false; } @@ -115,7 +120,7 @@ Rectangle :: struct { // x0,y0 ------------+ // | | // | | - // +------------ x1, y1 + // +------------ x1,y1 // x0: f32 = 0; @@ -127,7 +132,7 @@ Rectangle :: struct { height :: (use r: Rectangle) -> f32 do return math.abs(y1 - y0); dimensions :: (use r: Rectangle) -> (width: f32, height: f32) { - return math.abs(x1 - x0), math.abs(y1 - y0); + return width(r), height(r); } top_left :: (use r: Rectangle) -> (x: f32, y: f32) do return math.min(x0, x1), math.min(y0, y1); @@ -136,3 +141,27 @@ Rectangle :: struct { + +@Relocate +Text_Theme :: struct { + text_color := gfx.Color4.{ 1, 1, 1 }; + font_size := .4f; // Percentage of height of button +} + +@Relocate +Button_Theme :: struct { + @Bug + // I accidentally left this as 'text_color', and there was not a compiler error, even through there + // should have been. Instead it looked like the wrong offset was being used for the members and that + // was affecting the generated code. + use text_theme := Text_Theme.{}; + + background_color := gfx.Color4.{ 0.1, 0.1, 0.1 }; + + border_color := gfx.Color4.{ 0.2, 0.2, 0.2 }; + border_width := 10.0f; @InPixels +} + +@Bug // there is a compile-time known bug if either of the 'Button_Theme's below are omitted. +default_button_theme: Button_Theme = Button_Theme.{}; +default_text_theme: Text_Theme = Text_Theme.{}; \ No newline at end of file diff --git a/src/onyxbuiltins.c b/src/onyxbuiltins.c index 04dd5f27..0a8abaf0 100644 --- a/src/onyxbuiltins.c +++ b/src/onyxbuiltins.c @@ -49,6 +49,7 @@ Type *builtin_vararg_type_type; AstTyped *builtin_context_variable; AstType *builtin_allocator_type; AstType *builtin_iterator_type; +AstType *builtin_callsite_type; const BuiltinSymbol builtin_symbols[] = { { NULL, "void", (AstNode *) &basic_type_void }, @@ -385,6 +386,12 @@ void initialize_builtins(bh_allocator a) { return; } + builtin_callsite_type = (AstType *) symbol_raw_resolve(p->scope, "CallSite"); + if (builtin_callsite_type == NULL) { + onyx_report_error((OnyxFilePos) { 0 }, "'CallSite' struct not found in builtin package."); + return; + } + fori (i, 0, Binary_Op_Count) { bh_arr_new(global_heap_allocator, operator_overloads[i], 4); diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 44f5d097..305f95af 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -473,6 +473,41 @@ CheckStatus check_call(AstCall* call) { return Check_Error; } + // HACK HACK HACK + // :CallSiteIsGross + bh_arr_each(AstArgument *, arg, arg_arr) { + AstTyped** arg_value = &(*arg)->value; + + if ((*arg_value)->kind == Ast_Kind_Call_Site) { + AstCallSite* callsite = (AstCallSite *) ast_clone(context.ast_alloc, *arg_value); + callsite->callsite_token = call->token; + + // HACK CLEANUP + OnyxToken* str_token = bh_alloc(context.ast_alloc, sizeof(OnyxToken)); + str_token->text = bh_strdup(global_heap_allocator, (char *) call->token->pos.filename); + str_token->length = strlen(call->token->pos.filename); + str_token->pos = call->token->pos; + str_token->type = Token_Type_Literal_String; + + AstStrLit* filename = bh_alloc_item(context.ast_alloc, AstStrLit); + memset(filename, 0, sizeof(AstStrLit)); + filename->kind = Ast_Kind_StrLit; + filename->token = str_token; + filename->addr = 0; + + add_entities_for_node(NULL, (AstNode *) filename, NULL, NULL); + callsite->filename = filename; + + callsite->line = make_int_literal(context.ast_alloc, call->token->pos.line); + callsite->column = make_int_literal(context.ast_alloc, call->token->pos.column); + + convert_numlit_to_type(callsite->line, &basic_types[Basic_Kind_U32]); + convert_numlit_to_type(callsite->column, &basic_types[Basic_Kind_U32]); + + *arg_value = (AstTyped *) callsite; + } + } + // NOTE: If we are calling an intrinsic function, translate the // call into an intrinsic call node. if (callee->flags & Ast_Flag_Intrinsic) { @@ -1509,6 +1544,8 @@ CheckStatus check_expression(AstTyped** pexpr) { CHECK(compound, (AstCompound *) expr); break; + case Ast_Kind_Call_Site: break; + case Ast_Kind_StrLit: break; case Ast_Kind_File_Contents: break; case Ast_Kind_Overloaded_Function: break; @@ -1573,7 +1610,14 @@ CheckStatus check_statement(AstNode** pstmt) { case Ast_Kind_Local: { AstTyped* typed_stmt = (AstTyped *) stmt; fill_in_type(typed_stmt); - if (typed_stmt->type_node != NULL && typed_stmt->type == NULL) return Check_Yield_Macro; + if (typed_stmt->type_node != NULL && typed_stmt->type == NULL) { + if (!node_is_type((AstNode *) typed_stmt->type_node)) { + onyx_report_error(stmt->token->pos, "Local's type is not a type."); + return Check_Error; + } + + return Check_Yield_Macro; + } return Check_Success; } @@ -1781,6 +1825,12 @@ CheckStatus check_function_header(AstFunction* func) { } if (local->type_node != NULL) CHECK(type, local->type_node); + if (local->type_node != NULL) { + if (!node_is_type((AstNode *) local->type_node)) { + onyx_report_error(local->token->pos, "Parameter type is not a type."); + return Check_Error; + } + } fill_in_type((AstTyped *) local); if (local->type == NULL) { diff --git a/src/onyxclone.c b/src/onyxclone.c index 26c46732..4e5e3a9b 100644 --- a/src/onyxclone.c +++ b/src/onyxclone.c @@ -90,6 +90,7 @@ static inline i32 ast_kind_to_size(AstNode* node) { case Ast_Kind_Directive_Solidify: return sizeof(AstDirectiveSolidify); case Ast_Kind_Compound: return sizeof(AstCompound); case Ast_Kind_Named_Value: return sizeof(AstNamedValue); + case Ast_Kind_Call_Site: return sizeof(AstCallSite); case Ast_Kind_Count: return 0; } diff --git a/src/onyxparser.c b/src/onyxparser.c index 8cebcf1f..38cec8f8 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -642,11 +642,15 @@ static AstTyped* parse_factor(OnyxParser* parser) { parse_arguments(parser, ')', &call_node->args); // Wrap expressions in AstArgument - bh_arr_each(AstTyped *, arg, call_node->args.values) + bh_arr_each(AstTyped *, arg, call_node->args.values) { + if ((*arg) == NULL) continue; *arg = (AstTyped *) make_argument(parser->allocator, *arg); + } - bh_arr_each(AstNamedValue *, named_value, call_node->args.named_values) + bh_arr_each(AstNamedValue *, named_value, call_node->args.named_values) { + if ((*named_value)->value == NULL) continue; (*named_value)->value = (AstTyped *) make_argument(parser->allocator, (AstTyped *) (*named_value)->value); + } retval = (AstTyped *) call_node; break; @@ -1862,8 +1866,20 @@ static void parse_function_params(OnyxParser* parser, AstFunction* func) { } } - if (curr_param.vararg_kind == VA_Kind_Not_VA && consume_token_if_next(parser, '=')) - curr_param.default_value = parse_expression(parser, 0); + if (curr_param.vararg_kind == VA_Kind_Not_VA && consume_token_if_next(parser, '=')) { + OnyxToken* directive_token = parser->curr; + + // :Callsite currently #callsite is only valid as a default value for a funciton parameter. + if (parse_possible_directive(parser, "callsite")) { + AstCallSite* cs = make_node(AstCallSite, Ast_Kind_Call_Site); + cs->token = directive_token; + cs->type_node = builtin_callsite_type; + curr_param.default_value = (AstTyped *) cs; + + } else { + curr_param.default_value = parse_expression(parser, 0); + } + } if (param_is_baked) { param_is_baked = 0; diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 73601791..8546ac7b 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -92,29 +92,6 @@ static SymresStatus symres_struct_type(AstStructType* s_node) { if (s_node->flags & Ast_Flag_Type_Is_Resolved) return Symres_Success; 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 Symres_Error; - } - - bh_table_put(i32, mem_set, (*member)->token->text, 1); - token_toggle_end((*member)->token); - } - - bh_table_free(mem_set); - } if (s_node->scope) { // FIX: This is probably wrong for the long term. diff --git a/src/onyxtypes.c b/src/onyxtypes.c index 800ff538..4074c0c8 100644 --- a/src/onyxtypes.c +++ b/src/onyxtypes.c @@ -349,6 +349,10 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { .used = (((*member)->flags & Ast_Flag_Struct_Mem_Used) != 0), }; + if (bh_table_has(StructMember, s_type->Struct.members, (*member)->token->text)) { + onyx_report_error((*member)->token->pos, "Duplicate struct member, '%s'.", (*member)->token->text); + return NULL; + } bh_table_put(StructMember, s_type->Struct.members, (*member)->token->text, smem); token_toggle_end((*member)->token); @@ -366,6 +370,10 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { .used = 0, }; + if (bh_table_has(StructMember, s_type->Struct.members, (*psmem)->name)) { + onyx_report_error((*member)->token->pos, "Duplicate struct member, '%s'.", (*psmem)->name); + return NULL; + } bh_table_put(StructMember, s_type->Struct.members, (*psmem)->name, new_smem); } } diff --git a/src/onyxutils.c b/src/onyxutils.c index 81a59d41..8d1d9ac9 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -182,6 +182,10 @@ AstNode* try_symbol_raw_resolve_from_node(AstNode* node, char* symbol) { package->package = package_lookup(package->package_name); } + if (package->package == NULL) { + return NULL; + } + return symbol_raw_resolve(package->package->scope, symbol); } diff --git a/src/onyxwasm.c b/src/onyxwasm.c index ed1824d5..732f9f24 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -2450,6 +2450,15 @@ EMIT_FUNC(expression, AstTyped* expr) { break; } + case Ast_Kind_Call_Site: { + AstCallSite* callsite = (AstCallSite *) expr; + + emit_expression(mod, &code, (AstTyped *) callsite->filename); + emit_expression(mod, &code, (AstTyped *) callsite->line); + emit_expression(mod, &code, (AstTyped *) callsite->column); + break; + } + default: bh_printf("Unhandled case: %d\n", expr->kind); DEBUG_HERE;