From: Brendan Hansen Date: Fri, 22 Oct 2021 12:56:47 +0000 (-0500) Subject: added '[]=' operator overload; bugfixes X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=15247bb90faf5fee2b2f11ccbbc0a79a3681b161;p=onyx.git added '[]=' operator overload; bugfixes --- diff --git a/core/container/map.onyx b/core/container/map.onyx index 883046ee..819460b8 100644 --- a/core/container/map.onyx +++ b/core/container/map.onyx @@ -84,7 +84,8 @@ get :: (use map: ^Map($K, $V), key: K) -> V { } #operator [] macro (map: Map($K, $V), key: K) -> V do return (package core.map).get(^map, key); -// #operator []= macro (map: Map($K, $V), key: K, value: V) do (package core.map).put(^map, key, value); +#operator []= macro (map: Map($K, $V), key: K, value: V) do (package core.map).put(^map, key, value); +#operator ^[] macro (map: Map($K, $V), key: K) -> ^V do return (package core.map).get_ptr(^map, key); get_ptr :: (use map: ^Map($K, $V), key: K) -> ^V { lr := lookup(map, key); diff --git a/docs/todo b/docs/todo index 0d98b7ce..af66de5e 100644 --- a/docs/todo +++ b/docs/todo @@ -201,8 +201,8 @@ Optimize the generation of multi-threaded modules when post-mvp features are ena [X] emit datacount section Wishlist: - [ ] #operator []= - [ ] #operator ^[] + [X] #operator []= + [X] #operator ^[] - Taking the pointer to an offset with a subscript - Useful for map.get_ptr (^arr[10] or ^people["John"]) [ ] Complete the set of combinations of procedure declaration syntaxes diff --git a/src/astnodes.c b/src/astnodes.c index c10b8976..e8a4356c 100644 --- a/src/astnodes.c +++ b/src/astnodes.c @@ -116,7 +116,7 @@ const char *binaryop_string[Binary_Op_Count] = { "|>", "..", "->", - "[]", + "[]", "[]=", "^[]", }; const char* entity_state_strings[Entity_State_Count] = { diff --git a/src/checker.c b/src/checker.c index 58525219..3ae0ae81 100644 --- a/src/checker.c +++ b/src/checker.c @@ -589,17 +589,17 @@ static void report_bad_binaryop(AstBinaryOp* binop) { node_get_type_name(binop->right)); } -static AstCall* binaryop_try_operator_overload(AstBinaryOp* binop) { +static AstCall* binaryop_try_operator_overload(AstBinaryOp* binop, AstTyped* third_argument) { 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_new(global_heap_allocator, args.values, third_argument ? 3 : 2); bh_arr_push(args.values, (AstTyped *) make_argument(context.ast_alloc, binop->left)); bh_arr_push(args.values, (AstTyped *) make_argument(context.ast_alloc, binop->right)); + if (third_argument) bh_arr_push(args.values, (AstTyped *) make_argument(context.ast_alloc, third_argument)); u32 current_checking_level_store = current_checking_level; - check_argument((AstArgument **) &args.values[0]); - check_argument((AstArgument **) &args.values[1]); + bh_arr_each(AstTyped *, v, args.values) check_argument((AstArgument **) v); current_checking_level = current_checking_level_store; if (binop_is_assignment(binop->operation)) { @@ -864,6 +864,25 @@ CheckStatus check_binaryop(AstBinaryOp** pbinop) { if (binop->flags & Ast_Flag_Has_Been_Checked) return Check_Success; + if (binop->operation == Binary_Op_Assign && binop->left->kind == Ast_Kind_Subscript && bh_arr_length(operator_overloads[Binary_Op_Subscript_Equals]) > 0) { + AstBinaryOp op; + op.kind = Ast_Kind_Binary_Op; + op.token = binop->token; + op.operation = Binary_Op_Subscript_Equals; + op.left = ((AstSubscript *) binop->left)->addr; + op.right = ((AstSubscript *) binop->left)->expr; + + AstCall* call = binaryop_try_operator_overload(&op, binop->right); + if (call == (AstCall *) &node_that_signals_a_yield) YIELD(op.token->pos, "Waiting on potential operator overload."); + if (call != NULL) { + call->next = binop->next; + *(AstCall **) pbinop = call; + + CHECK(call, (AstCall **) pbinop); + return Check_Success; + } + } + u32 current_checking_level_store = current_checking_level; CHECK(expression, &binop->left); CHECK(expression, &binop->right); @@ -892,7 +911,7 @@ CheckStatus check_binaryop(AstBinaryOp** pbinop) { // NOTE: Try operator overloading before checking everything else. if ((binop->left->type != NULL && binop->left->type->kind != Type_Kind_Basic) || (binop->right->type != NULL && binop->right->type->kind != Type_Kind_Basic)) { - AstCall *implicit_call = binaryop_try_operator_overload(binop); + AstCall *implicit_call = binaryop_try_operator_overload(binop, NULL); if (implicit_call == (AstCall *) &node_that_signals_a_yield) YIELD(binop->token->pos, "Trying to resolve operator overload."); @@ -1271,7 +1290,7 @@ CheckStatus check_address_of(AstAddressOf** paof) { op.right = ((AstSubscript *) expr)->expr; op.token = aof->token; - AstCall* call = binaryop_try_operator_overload(&op); + AstCall* call = binaryop_try_operator_overload(&op, NULL); if (call == (AstCall *) &node_that_signals_a_yield) YIELD(aof->token->pos, "Waiting for operator overload to possibly resolve."); if (call != NULL) { call->next = aof->next; @@ -1329,7 +1348,7 @@ CheckStatus check_subscript(AstSubscript** psub) { (sub->addr->type->kind != Type_Kind_Basic || sub->expr->type->kind != Type_Kind_Basic)) { // AstSubscript is the same as AstBinaryOp for the first sizeof(AstBinaryOp) bytes AstBinaryOp* binop = (AstBinaryOp *) sub; - AstCall *implicit_call = binaryop_try_operator_overload(binop); + AstCall *implicit_call = binaryop_try_operator_overload(binop, NULL); if (implicit_call == (AstCall *) &node_that_signals_a_yield) YIELD(sub->token->pos, "Trying to resolve operator overload."); diff --git a/src/symres.c b/src/symres.c index 40e0201c..172c6b6c 100644 --- a/src/symres.c +++ b/src/symres.c @@ -1147,8 +1147,8 @@ static SymresStatus symres_process_directive(AstNode* directive) { return Symres_Error; } - if (bh_arr_length(overload->params) != 2) { - onyx_report_error(operator->token->pos, "Expected 2 exactly arguments for binary operator overload."); + if (operator->operator != Binary_Op_Subscript_Equals && bh_arr_length(overload->params) != 2) { + onyx_report_error(operator->token->pos, "Expected exactly 2 arguments for binary operator overload."); return Symres_Error; }