Commit c8c89648b0

Merlyn Morgan-Graham <kavika@gmail.com>
2019-12-15 07:04:07
Add comparison and bitwise binary ops in translate-c-2
1 parent 2c7a2ae
Changed files (2)
src-self-hosted
test
src-self-hosted/translate_c.zig
@@ -681,15 +681,85 @@ fn transBinaryOperator(
         },
         .Shl,
         .Shr,
-        .LT,
-        .GT,
-        .LE,
-        .GE,
-        .EQ,
-        .NE,
-        .And,
-        .Xor,
-        .Or,
+        => return revertAndWarn(
+            rp,
+            error.UnsupportedTranslation,
+            ZigClangBinaryOperator_getBeginLoc(stmt),
+            "TODO: handle more C binary operators: {}",
+            .{op},
+        ),
+        .LT => {
+            const node = try transCreateNodeInfixOp(rp, scope, stmt, .LessThan, .AngleBracketLeft, "<", true);
+            return maybeSuppressResult(rp, scope, result_used, TransResult{
+                .node = node,
+                .child_scope = scope,
+                .node_scope = scope,
+            });
+        },
+        .GT => {
+            const node = try transCreateNodeInfixOp(rp, scope, stmt, .GreaterThan, .AngleBracketRight, ">", true);
+            return maybeSuppressResult(rp, scope, result_used, TransResult{
+                .node = node,
+                .child_scope = scope,
+                .node_scope = scope,
+            });
+        },
+        .LE => {
+            const node = try transCreateNodeInfixOp(rp, scope, stmt, .LessOrEqual, .AngleBracketLeftEqual, "<=", true);
+            return maybeSuppressResult(rp, scope, result_used, TransResult{
+                .node = node,
+                .child_scope = scope,
+                .node_scope = scope,
+            });
+        },
+        .GE => {
+            const node = try transCreateNodeInfixOp(rp, scope, stmt, .GreaterOrEqual, .AngleBracketRightEqual, ">=", true);
+            return maybeSuppressResult(rp, scope, result_used, TransResult{
+                .node = node,
+                .child_scope = scope,
+                .node_scope = scope,
+            });
+        },
+        .EQ => {
+            const node = try transCreateNodeInfixOp(rp, scope, stmt, .EqualEqual, .EqualEqual, "==", true);
+            return maybeSuppressResult(rp, scope, result_used, TransResult{
+                .node = node,
+                .child_scope = scope,
+                .node_scope = scope,
+            });
+        },
+        .NE => {
+            const node = try transCreateNodeInfixOp(rp, scope, stmt, .BangEqual, .BangEqual, "!=", true);
+            return maybeSuppressResult(rp, scope, result_used, TransResult{
+                .node = node,
+                .child_scope = scope,
+                .node_scope = scope,
+            });
+        },
+        .And => {
+            const node = try transCreateNodeInfixOp(rp, scope, stmt, .BitAnd, .Ampersand, "&", true);
+            return maybeSuppressResult(rp, scope, result_used, TransResult{
+                .node = node,
+                .child_scope = scope,
+                .node_scope = scope,
+            });
+        },
+        .Xor => {
+            const node = try transCreateNodeInfixOp(rp, scope, stmt, .BitXor, .Caret, "^", true);
+            return maybeSuppressResult(rp, scope, result_used, TransResult{
+                .node = node,
+                .child_scope = scope,
+                .node_scope = scope,
+            });
+        },
+        .Or => {
+            const node = try transCreateNodeInfixOp(rp, scope, stmt, .BitOr, .Pipe, "|", true);
+            return maybeSuppressResult(rp, scope, result_used, TransResult{
+                .node = node,
+                .child_scope = scope,
+                .node_scope = scope,
+            });
+        },
         .LAnd,
         .LOr,
         .Comma,
test/translate_c.zig
@@ -871,6 +871,20 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\}
     });
 
+    cases.add_2("==, !=, no if", // TODO remove this test after `if` conversion supported, and switch "==, !=" to addC_both
+        \\int max(int a, int b) {
+        \\    int c = (a == b);
+        \\    int d = (a != b);
+        \\    return (c != d);
+        \\}
+    , &[_][]const u8{
+        \\pub export fn max(a: c_int, b: c_int) c_int {
+        \\    var c: c_int = (a == b);
+        \\    var d: c_int = (a != b);
+        \\    return (c != d);
+        \\}
+    });
+
     cases.addC("bitwise binary operators",
         \\int max(int a, int b) {
         \\    return (a & b) ^ (a | b);
@@ -881,6 +895,20 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\}
     });
 
+    cases.add_2("bitwise binary operators, simpler parens", // TODO can combine with "bitwise binary operators" when parens are correctly preserved/not added in translate-c-2
+        \\int max(int a, int b) {
+        \\    int c = (a & b);
+        \\    int d = (a | b);
+        \\    return (c ^ d);
+        \\}
+    , &[_][]const u8{
+        \\pub export fn max(a: c_int, b: c_int) c_int {
+        \\    var c: c_int = (a & b);
+        \\    var d: c_int = (a | b);
+        \\    return (c ^ d);
+        \\}
+    });
+
     cases.addC("logical and, logical or",
         \\int max(int a, int b) {
         \\    if (a < b || a == b)
@@ -897,6 +925,30 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\}
     });
 
+    cases.add_2("comparison operators (no if)", // TODO Come up with less contrived tests? Make sure to cover all these comparisons. Can use `if` after it is added to translate-c-2
+        \\int test_comparisons(int a, int b) {
+        \\    int c = (a < b);
+        \\    int d = (a > b);
+        \\    int e = (a <= b);
+        \\    int f = (a >= b);
+        \\    int g = (c < d);
+        \\    int h = (e < f);
+        \\    int i = (g < h);
+        \\    return i;
+        \\}
+    , &[_][]const u8{
+        \\pub export fn test_comparisons(a: c_int, b: c_int) c_int {
+        \\    var c: c_int = (a < b);
+        \\    var d: c_int = (a > b);
+        \\    var e: c_int = (a <= b);
+        \\    var f: c_int = (a >= b);
+        \\    var g: c_int = (c < d);
+        \\    var h: c_int = (e < f);
+        \\    var i: c_int = (g < h);
+        \\    return i;
+        \\}
+    });
+
     cases.addC("logical and, logical or on none bool values",
         \\int and_or_none_bool(int a, float b, void *c) {
         \\    if (a && b) return 0;