From: Brendan Hansen Date: Mon, 30 Aug 2021 12:13:49 +0000 (-0500) Subject: added overloadable assignment operators X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=220e5789d532a775fc8df4a0c28b083b191c42af;p=onyx.git added overloadable assignment operators --- diff --git a/bin/onyx b/bin/onyx index a5bf1b64..646b0024 100755 Binary files a/bin/onyx and b/bin/onyx differ diff --git a/core/container/array.onyx b/core/container/array.onyx index 88e5180d..2998fcb4 100644 --- a/core/container/array.onyx +++ b/core/container/array.onyx @@ -107,7 +107,7 @@ remove :: (arr: ^[..] $T, elem: T) { while i := 0; i < arr.count - move { defer i += 1; - + if arr.data[i + move] == elem do move += 1; if move != 0 do arr.data[i] = arr.data[i + move]; } diff --git a/core/io/writer.onyx b/core/io/writer.onyx index da730eae..6f956358 100644 --- a/core/io/writer.onyx +++ b/core/io/writer.onyx @@ -118,4 +118,9 @@ write :: #match { write_range, write_format, + + // Catch all for any type. Has a high precedence so you can easily override it. + #precedence 1000 (w: ^Writer, a: $T) { + write_format(w, "{}", a); + } } diff --git a/modules/ui/ui.onyx b/modules/ui/ui.onyx index 4fb159f6..da3cc025 100644 --- a/modules/ui/ui.onyx +++ b/modules/ui/ui.onyx @@ -161,7 +161,7 @@ Rectangle :: struct { Text_Theme :: struct { text_color := gfx.Color4.{ 1, 1, 1 }; - font : i32 = 0; // Default to font index 0 + font := 0; // Default to font index 0 font_size := 1.0f; } diff --git a/src/onyxchecker.c b/src/onyxchecker.c index dd8b2d4a..c7ec01e3 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -735,7 +735,54 @@ static void report_bad_binaryop(AstBinaryOp* binop) { node_get_type_name(binop->right)); } -CheckStatus check_binaryop_assignment(AstBinaryOp* binop) { +static AstCall* binaryop_try_operator_overload(AstBinaryOp* binop) { + if (bh_arr_length(operator_overloads[binop->operation]) == 0) return NULL; + + Arguments args = ((Arguments) { NULL, NULL }); + bh_arr_new(global_heap_allocator, args.values, 2); + bh_arr_push(args.values, binop->left); + bh_arr_push(args.values, binop->right); + + if (binop_is_assignment(binop->operation)) { + args.values[0] = (AstTyped *) make_address_of(context.ast_alloc, binop->left); + + u32 current_checking_level_store = current_checking_level; + CheckStatus cs = check_address_of((AstAddressOf *) args.values[0]); + current_checking_level = current_checking_level_store; + + if (cs == Check_Yield_Macro) return (AstCall *) &node_that_signals_a_yield; + if (cs == Check_Error) { + return NULL; + } + } + + b32 should_yield = 0; + AstTyped* overload = find_matching_overload_by_arguments(operator_overloads[binop->operation], &args, &should_yield); + if (should_yield) { + bh_arr_free(args.values); + return (AstCall *) &node_that_signals_a_yield; + } + + if (overload == NULL) { + bh_arr_free(args.values); + return NULL; + } + + AstCall* implicit_call = onyx_ast_node_new(context.ast_alloc, sizeof(AstCall), Ast_Kind_Call); + implicit_call->token = binop->token; + implicit_call->callee = overload; + implicit_call->va_kind = VA_Kind_Not_VA; + + bh_arr_each(AstTyped *, arg, args.values) + *arg = (AstTyped *) make_argument(context.ast_alloc, *arg); + + implicit_call->args = args; + return implicit_call; +} + + +CheckStatus check_binaryop_assignment(AstBinaryOp** pbinop) { + AstBinaryOp* binop = *pbinop; if (current_checking_level == EXPRESSION_LEVEL) ERROR(binop->token->pos, "Assignment not valid in expression."); @@ -947,38 +994,6 @@ CheckStatus check_binaryop_bool(AstBinaryOp** pbinop) { return Check_Success; } -static AstCall* binaryop_try_operator_overload(AstBinaryOp* binop) { - if (bh_arr_length(operator_overloads[binop->operation]) == 0) return NULL; - - Arguments args = ((Arguments) { NULL, NULL }); - bh_arr_new(global_heap_allocator, args.values, 2); - bh_arr_push(args.values, binop->left); - bh_arr_push(args.values, binop->right); - - b32 should_yield = 0; - AstTyped* overload = find_matching_overload_by_arguments(operator_overloads[binop->operation], &args, &should_yield); - if (should_yield) { - bh_arr_free(args.values); - return (AstCall *) &node_that_signals_a_yield; - } - - if (overload == NULL) { - bh_arr_free(args.values); - return NULL; - } - - AstCall* implicit_call = onyx_ast_node_new(context.ast_alloc, sizeof(AstCall), Ast_Kind_Call); - implicit_call->token = binop->token; - implicit_call->callee = overload; - implicit_call->va_kind = VA_Kind_Not_VA; - - bh_arr_each(AstTyped *, arg, args.values) - *arg = (AstTyped *) make_argument(context.ast_alloc, *arg); - - implicit_call->args = args; - return implicit_call; -} - CheckStatus check_binaryop(AstBinaryOp** pbinop) { AstBinaryOp* binop = *pbinop; @@ -993,8 +1008,6 @@ CheckStatus check_binaryop(AstBinaryOp** pbinop) { binop->flags |= Ast_Flag_Comptime; } - if (binop_is_assignment(binop->operation)) return check_binaryop_assignment(binop); - if (expression_types_must_be_known) { if (binop->left->type == NULL || binop->right->type == NULL) { ERROR(binop->token->pos, "Internal compiler error: one of the operands types is unknown here."); @@ -1029,6 +1042,8 @@ CheckStatus check_binaryop(AstBinaryOp** pbinop) { } } + if (binop_is_assignment(binop->operation)) return check_binaryop_assignment(pbinop); + // NOTE: Comparision operators and boolean operators are handled separately. if (binop_is_compare(binop->operation)) return check_binaryop_compare(pbinop); diff --git a/src/onyxparser.c b/src/onyxparser.c index 74126e77..58c34b40 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -251,7 +251,7 @@ static b32 parse_possible_struct_literal(OnyxParser* parser, AstTyped* left, Ast static b32 parse_possible_array_literal(OnyxParser* parser, AstTyped* left, AstTyped** ret) { if (!next_tokens_are(parser, 2, '.', '[')) return 0; - + AstArrayLiteral* al = make_node(AstArrayLiteral, Ast_Kind_Array_Literal); al->token = parser->curr; al->atnode = left; @@ -263,7 +263,7 @@ static b32 parse_possible_array_literal(OnyxParser* parser, AstTyped* left, AstT expect_token(parser, '['); while (!consume_token_if_next(parser, ']')) { if (parser->hit_unexpected_token) return 1; - + AstTyped* value = parse_expression(parser, 0); bh_arr_push(al->values, value); @@ -451,9 +451,9 @@ static AstTyped* parse_factor(OnyxParser* parser) { str_node->token = expect_token(parser, Token_Type_Literal_String); str_node->addr = 0; str_node->flags |= Ast_Flag_Comptime; - + ENTITY_SUBMIT(str_node); - + retval = (AstTyped *) str_node; break; } @@ -523,9 +523,9 @@ static AstTyped* parse_factor(OnyxParser* parser) { fc->token = parser->prev - 1; fc->filename_token = expect_token(parser, Token_Type_Literal_String); fc->type = type_make_slice(parser->allocator, &basic_types[Basic_Kind_U8]); - + ENTITY_SUBMIT(fc); - + retval = (AstTyped *) fc; break; } @@ -541,7 +541,7 @@ static AstTyped* parse_factor(OnyxParser* parser) { AstStrLit* filename = make_node(AstStrLit, Ast_Kind_StrLit); filename->token = str_token; filename->addr = 0; - + ENTITY_SUBMIT(filename); retval = (AstTyped *) filename; break; @@ -692,7 +692,7 @@ static AstTyped* parse_factor(OnyxParser* parser) { case '.': { if (parse_possible_struct_literal(parser, retval, &retval)) return retval; if (parse_possible_array_literal(parser, retval, &retval)) return retval; - + consume_token(parser); AstFieldAccess* field = make_node(AstFieldAccess, Ast_Kind_Field_Access); field->token = expect_token(parser, Token_Type_Symbol); @@ -943,7 +943,7 @@ static AstTyped* parse_expression(OnyxParser* parser, b32 assignment_allowed) { right = parse_factor(parser); bin_op->right = right; } - + expression_done: bh_arr_free(tree_stack); return root; @@ -1869,7 +1869,7 @@ static AstStructType* parse_struct(OnyxParser* parser) { while (!consume_token_if_next(parser, '}')) { if (parser->hit_unexpected_token) return s_node; - + member_is_used = consume_token_if_next(parser, Token_Type_Keyword_Use); if (next_tokens_are(parser, 3, Token_Type_Symbol, ':', ':')) { @@ -2069,7 +2069,7 @@ static AstOverloadedFunction* parse_overloaded_function(OnyxParser* parser, Onyx if (parser->curr->type != '}') expect_token(parser, ','); } - + ENTITY_SUBMIT(ofunc); return ofunc; } @@ -2132,7 +2132,7 @@ static AstFunction* parse_function_definition(OnyxParser* parser, OnyxToken* tok pp->token = func_def->token; pp->poly_params = polymorphic_vars; pp->base_func = func_def; - + return (AstFunction *) pp; } else { @@ -2522,7 +2522,7 @@ static void parse_top_level_statement(OnyxParser* parser) { else if (parse_possible_directive(parser, "private_file")) private_kind = Ast_Flag_Private_File; AstBinding* binding = NULL; - + switch ((u16) parser->curr->type) { case Token_Type_Keyword_Use: { AstNode* use_node = parse_use_stmt(parser); @@ -2545,19 +2545,19 @@ static void parse_top_level_statement(OnyxParser* parser) { goto submit_binding_to_entities; } - + AstMemRes* memres = make_node(AstMemRes, Ast_Kind_Memres); memres->token = symbol; if (parser->curr->type != '=') memres->type_node = parse_type(parser); - + if (consume_token_if_next(parser, '=')) memres->initial_value = parse_expression(parser, 1); - - + + ENTITY_SUBMIT(memres); - + binding = make_node(AstBinding, Ast_Kind_Binding); binding->token = symbol; binding->flags |= private_kind; @@ -2585,28 +2585,28 @@ static void parse_top_level_statement(OnyxParser* parser) { include->name = bh_strdup(parser->allocator, str_token->text); token_toggle_end(str_token); } - + ENTITY_SUBMIT(include); return; } else if (parse_possible_directive(parser, "load_path")) { AstInclude* include = make_node(AstInclude, Ast_Kind_Load_Path); include->token = dir_token; - + OnyxToken* str_token = expect_token(parser, Token_Type_Literal_String); if (str_token != NULL) { token_toggle_end(str_token); include->name = bh_strdup(parser->allocator, str_token->text); token_toggle_end(str_token); } - + ENTITY_SUBMIT(include); return; } else if (parse_possible_directive(parser, "error")) { AstDirectiveError *error = make_node(AstDirectiveError, Ast_Kind_Directive_Error); error->token = dir_token; - error->error_msg = expect_token(parser, Token_Type_Literal_String); + error->error_msg = expect_token(parser, Token_Type_Literal_String); ENTITY_SUBMIT(error); return; @@ -2618,7 +2618,7 @@ static void parse_top_level_statement(OnyxParser* parser) { BinaryOp op = binary_op_from_token_type(parser->curr->type); consume_token(parser); if (op == Binary_Op_Subscript) expect_token(parser, ']'); // #operator [] ... needs to consume the other ']' - + if (op == Binary_Op_Count) { onyx_report_error(parser->curr->pos, "Invalid binary operator."); } else { @@ -2686,7 +2686,7 @@ submit_binding_to_entities: target_scope = parser->package->private_scope; if (binding->flags & Ast_Flag_Private_File) target_scope = parser->file_scope; - + ENTITY_SUBMIT_IN_SCOPE(binding, target_scope); } } @@ -2703,7 +2703,7 @@ static AstPackage* parse_package_expression(OnyxParser* parser) { OnyxToken* symbol = expect_token(parser, Token_Type_Symbol); bh_arr_push(package_node->path, symbol); - + if (consume_token_if_next(parser, '.')); else break; } @@ -2713,7 +2713,7 @@ static AstPackage* parse_package_expression(OnyxParser* parser) { total_package_name_length += (*token)->length + 1; } - char* package_name = bh_alloc_array(context.ast_alloc, char, total_package_name_length); + char* package_name = bh_alloc_array(context.ast_alloc, char, total_package_name_length); *package_name = '\0'; bh_arr_each(OnyxToken *, token, package_node->path) { @@ -2738,7 +2738,7 @@ static Package* parse_file_package(OnyxParser* parser) { } AstPackage* package_node = parse_package_expression(parser); - + char aggregate_name[2048]; aggregate_name[0] = '\0'; @@ -2749,7 +2749,7 @@ static Package* parse_file_package(OnyxParser* parser) { strncat(aggregate_name, (*symbol)->text, 2047); Package* newpackage = package_lookup_or_create(aggregate_name, context.global_scope, parser->allocator); - + AstPackage* pnode = make_node(AstPackage, Ast_Kind_Package); pnode->token = *symbol; pnode->package = newpackage; @@ -2767,7 +2767,7 @@ static Package* parse_file_package(OnyxParser* parser) { } package_node->package = prevpackage; - + return package_node->package; } diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 18f6ef5e..d853a4d3 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -68,7 +68,7 @@ static void scope_leave() { static SymresStatus symres_symbol(AstNode** symbol_node) { OnyxToken* token = (*symbol_node)->token; - AstNode* res = symbol_resolve(curr_scope, token); + AstNode* res = symbol_resolve(curr_scope, token); if (!res) { // :SymresStall if (report_unresolved_symbols) { @@ -906,7 +906,7 @@ SymresStatus symres_function(AstFunction* func) { // // Foo :: struct (T: type_expr) { // use t : T; - // + // // something_else := 5 + 6 * 8; // } // @@ -1078,7 +1078,7 @@ static SymresStatus symres_polyproc(AstPolyProc* pp) { // because I think the following should be possible: // // baked_proc :: (x: $T, $f: (T) -> T) -> T ... - // + // // The type of 'f' depends on resolving the value for the polyvar 'T'. SYMRES(type, ¶m->type_expr); } @@ -1127,10 +1127,10 @@ static SymresStatus symres_process_directive(AstNode* directive) { return Symres_Error; } - if (binop_is_assignment(operator->operator)) { + /*if (binop_is_assignment(operator->operator)) { onyx_report_error(overload->token->pos, "'%s' is not currently overloadable.", binaryop_string[operator->operator]); return Symres_Error; - } + }*/ add_overload_option(&operator_overloads[operator->operator], 0, operator->overload); break; @@ -1207,7 +1207,7 @@ void symres_entity(Entity* ent) { } case Entity_Type_Static_If: ss = symres_static_if(ent->static_if); break; - + case Entity_Type_Foreign_Function_Header: case Entity_Type_Function_Header: ss = symres_function_header(ent->function); break; case Entity_Type_Function: ss = symres_function(ent->function); break;