added bitwise not operator
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 19 Sep 2020 12:52:12 +0000 (07:52 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 19 Sep 2020 12:52:12 +0000 (07:52 -0500)
CHANGELOG
include/onyxastnodes.h
onyx
src/onyxchecker.c
src/onyxparser.c
src/onyxutils.c
src/onyxwasm.c
tests/i32map.onyx

index 1b18ec8ee61fd5bda1b0c538e2f292e245f040af..8493ae48f4d655b96a40c9b044c62c57fe46e283 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,10 +2,13 @@ Release v0.0.4
 --------------
 Additions:
 * Ability to pass complicated structs by value. Very useful in polymorphic data types.
+* bitwise not operator, ~
 
 Removals:
 
 Changes:
+* Procedure definitions now require parentheses, even if there are no arguments. This was
+    done to allow for `proc { foo, bar }` to be the overload syntax.
 
 Bug fixes:
 
index 603b5a261a4cbe093e1a63dbf43737a87f824b89..995b927ee441a721d33a4c3bd14ea6878df8489f 100644 (file)
@@ -193,6 +193,7 @@ typedef enum AstFlags {
 typedef enum UnaryOp {
     Unary_Op_Negate,
     Unary_Op_Not,
+    Unary_Op_Bitwise_Not,
     Unary_Op_Cast,
 } UnaryOp;
 
diff --git a/onyx b/onyx
index cf7966737a3f0ed1b3c1dcf67cf50888f3e75535..9304849e4314e31947d6b40fb229bc73e2c290d0 100755 (executable)
Binary files a/onyx and b/onyx differ
index 7c238affa271bef7646169a3d8805575500b2c25..107e469b3ce6740910da0db51e7bd564088d8973 100644 (file)
@@ -762,6 +762,15 @@ b32 check_unaryop(AstUnaryOp** punop) {
         unaryop->type = unaryop->expr->type;
     }
 
+    if (unaryop->operation == Unary_Op_Bitwise_Not) {
+        if (!type_is_integer(unaryop->expr->type)) {
+            onyx_report_error(unaryop->token->pos,
+                    "Bitwise operator expected integer type, got '%s'.",
+                    type_get_name(unaryop->expr->type));
+            return 1;
+        }
+    }
+
     if (unaryop->expr->flags & Ast_Flag_Comptime) {
         unaryop->flags |= Ast_Flag_Comptime;
         // NOTE: Not a unary op
index 5519ee022fadd9c5a9dd245684473956648dfe53..bdc363f544f1cb1f63b7811fb099329193986fb0 100644 (file)
@@ -306,6 +306,16 @@ static AstTyped* parse_factor(OnyxParser* parser) {
             break;
         }
 
+        case '~': {
+            AstUnaryOp* not_node = make_node(AstUnaryOp, Ast_Kind_Unary_Op);
+            not_node->operation = Unary_Op_Bitwise_Not;
+            not_node->token = expect_token(parser, '~');
+            not_node->expr = parse_factor(parser);
+
+            retval = (AstTyped *) not_node;
+            break;
+        }
+
         case '*': {
             AstDereference* deref_node = make_node(AstDereference, Ast_Kind_Dereference);
             deref_node->token = expect_token(parser, '*');
index f1099fb8fea76382eaf6c7e496696562d78705b7..1d21ecba173532a35ed4fdb80fd7dff3b4889892 100644 (file)
@@ -293,6 +293,13 @@ AstNumLit* ast_reduce_binop(bh_allocator a, AstBinaryOp* node) {
     } \
     break;
 
+#define REDUCE_UNOP_INT(op) \
+    if (type_is_small_integer(unop->type) || type_is_bool(unop->type)) { \
+        res->value.i = op ((AstNumLit *) unop->expr)->value.i; \
+    } else if (type_is_integer(unop->type)) { \
+        res->value.l = op ((AstNumLit *) unop->expr)->value.l; \
+    }
+
 AstTyped* ast_reduce_unaryop(bh_allocator a, AstUnaryOp* unop) {
     unop->expr = ast_reduce(a, unop->expr);
 
@@ -312,6 +319,7 @@ AstTyped* ast_reduce_unaryop(bh_allocator a, AstUnaryOp* unop) {
             if (type_is_bool(res->type)) res->value.i = ! ((AstNumLit *) unop->expr)->value.i;
             break;
         }
+        case Unary_Op_Bitwise_Not: REDUCE_UNOP_INT(~);
 
         default: return (AstTyped *) unop;
     }
index 2ea7e1bc990645ca94713e5a437672cd8faf9e47..fa03b7d2dc1a9f7b96d58e021eb0f6381a7f6e32 100644 (file)
@@ -1289,6 +1289,26 @@ EMIT_FUNC(unaryop, AstUnaryOp* unop) {
             WI(WI_I32_EQZ);
             break;
 
+        case Unary_Op_Bitwise_Not: {
+            emit_expression(mod, &code, unop->expr);
+
+            TypeBasic* type = &unop->type->Basic;
+
+            if (type->kind == Basic_Kind_I32
+                    || type->kind == Basic_Kind_I16
+                    || type->kind == Basic_Kind_I8) {
+                WID(WI_I32_CONST, 0xffffffff);
+                WI(WI_I32_XOR);
+
+            }
+            else if (type->kind == Basic_Kind_I64) {
+                WIL(WI_I64_CONST, 0xffffffffffffffff);
+                WI(WI_I64_XOR);
+            }
+
+            break;
+        }
+
         case Unary_Op_Cast: emit_cast(mod, &code, unop); break;
     }
 
index 92385c875d1d63ad13b776072d67d1d39917adb4..a6f3e6f1d8ef74671742f97284131d4c475e5938 100644 (file)
@@ -11,7 +11,6 @@ main :: proc (args: [] cstring) {
         print("Freeing map\n");
         i32map_free(^imap);
     }
-
     i32map_put(^imap, 50, "Hello ");
     i32map_put(^imap, 1234, "World!");