better error reporting for invalid binary operations
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 15 Dec 2020 01:32:13 +0000 (19:32 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 15 Dec 2020 01:32:13 +0000 (19:32 -0600)
include/onyxastnodes.h
onyx
src/onyxchecker.c
src/onyxwasm.c

index c752c68df9da89bbeca8950cd533978b6717da01..d331f280f6207c8fc5b947c6bd1e3e254437b682 100644 (file)
@@ -240,6 +240,8 @@ typedef enum BinaryOp {
 
     Binary_Op_Pipe            = 33,
     Binary_Op_Range           = 34,
+
+    Binary_Op_Count
 } BinaryOp;
 
 typedef enum OnyxIntrinsic {
diff --git a/onyx b/onyx
index 82f9930ce153e6dd4e3b3d7b100d5e26cd5db2cf..8f9659c1a627dae859409d54e42933c12c68ebdf 100755 (executable)
Binary files a/onyx and b/onyx differ
index 98133c321f4d1c0e52317fdd032c5d37887eedd8..01c95e42c2af37a0681b83c9a862a41bbfd69a32 100644 (file)
@@ -796,8 +796,64 @@ b32 check_binaryop(AstBinaryOp** pbinop, b32 assignment_is_ok) {
         }
     }
 
+    static const u8 binop_allowed[Binary_Op_Count] = {
+        /* Add */             Basic_Flag_Numeric | Basic_Flag_Pointer,
+        /* Minus */           Basic_Flag_Numeric | Basic_Flag_Pointer,
+        /* Multiply */        Basic_Flag_Numeric,
+        /* Divide */          Basic_Flag_Numeric,
+        /* Modulus */         Basic_Flag_Integer,
+
+        /* Equal */           Basic_Flag_Ordered,
+        /* Not_Equal */       Basic_Flag_Ordered,
+        /* Less */            Basic_Flag_Ordered,
+        /* Less_Equal */      Basic_Flag_Ordered,
+        /* Greater */         Basic_Flag_Ordered,
+        /* Greater_Equal */   Basic_Flag_Ordered,
+
+        /* And */             Basic_Flag_Integer,
+        /* Or */              Basic_Flag_Integer,
+        /* Xor */             Basic_Flag_Integer,
+        /* Shl */             Basic_Flag_Integer,
+        /* Shr */             Basic_Flag_Integer,
+        /* Sar */             Basic_Flag_Integer,
+
+        /* Bool_And */        Basic_Flag_Boolean,
+        /* Bool_Or */         Basic_Flag_Boolean,
+
+        /* Assign_Start */    0,
+        /* Assign */          0,
+        /* Assign_Add */      0,
+        /* Assign_Minus */    0,
+        /* Assign_Multiply */ 0,
+        /* Assign_Divide */   0,
+        /* Assign_Modulus */  0,
+        /* Assign_And */      0,
+        /* Assign_Or */       0,
+        /* Assign_Xor */      0,
+        /* Assign_Shl */      0,
+        /* Assign_Shr */      0,
+        /* Assign_Sar */      0,
+        /* Assign_End */      0,
+
+        /* Pipe */            0,
+        /* Range */           0,
+    };
+
     binop->type = binop->left->type;
 
+    enum BasicFlag effective_flags = 0;
+    switch (binop->type->kind) {
+        case Type_Kind_Basic:   effective_flags = binop->type->Basic.flags; break;
+        case Type_Kind_Pointer: effective_flags = Basic_Flag_Pointer;       break;
+        case Type_Kind_Enum:    effective_flags = Basic_Flag_Integer;       break;
+    }
+
+    if ((binop_allowed[binop->operation] & effective_flags) == 0) {
+        onyx_report_error(binop->token->pos, "Binary operator not allowed for arguments of type '%s'.",
+                type_get_name(binop->type));
+        return 1;
+    }
+
     if (binop->flags & Ast_Flag_Comptime) {
         // NOTE: Not a binary op
         *pbinop = (AstBinaryOp *) ast_reduce(semstate.node_allocator, (AstTyped *) binop);
index 894c4b4e65d1ffc4d3f6b7d5e9e5ae3ef796af66..be107baff3483b0fe90274b0ca5d3ddc42673bc7 100644 (file)
@@ -1230,9 +1230,7 @@ EMIT_FUNC(binop, AstBinaryOp* binop) {
 
     WasmInstructionType binop_instr = binop_map[(i32) binop->operation][optype];
 
-    if (binop_instr == WI_NOP) {
-        assert(("Invalid type and operation", 0));
-    }
+    assert(binop_instr != WI_NOP);
 
     // NOTE: Use unsigned variant if needed
     // Unsigned instructions are always right after