added '[]=' operator overload; bugfixes
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 22 Oct 2021 12:56:47 +0000 (07:56 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 22 Oct 2021 12:56:47 +0000 (07:56 -0500)
core/container/map.onyx
docs/todo
src/astnodes.c
src/checker.c
src/symres.c

index 883046eed0fe231c6ae3acfb608e008e5d897957..819460b82f3b3b843d4aa8591472cfb9860a2635 100644 (file)
@@ -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);
index 0d98b7ce2b5d944d68670dc5be805450cd38ad9a..af66de5e275409548e130ade1d7db967ef62a7cc 100644 (file)
--- 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
index c10b89762a057ca09b2f7bb8f74278f17b0e601d..e8a4356c8c13813efd6a8495e4eba4112c840b3a 100644 (file)
@@ -116,7 +116,7 @@ const char *binaryop_string[Binary_Op_Count] = {
 
     "|>", "..", "->",
 
-    "[]",
+    "[]", "[]=", "^[]",
 };
 
 const char* entity_state_strings[Entity_State_Count] = {
index 58525219b5a501516c96c942507b00af3ec498c2..3ae0ae81ee51979f2a6c8e950eeff586a210899d 100644 (file)
@@ -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.");
index 40e0201ce1beeadb548ceec8f1f45e6fc9e6e242..172c6b6c523caed99082d809e00be9c4b533a7ba 100644 (file)
@@ -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;
             }