Commit 83d27f71ef

Vexu <git@vexu.eu>
2020-03-06 10:03:56
translate-c more macro ops
1 parent 7df9169
Changed files (2)
src-self-hosted
test
src-self-hosted/translate_c.zig
@@ -610,7 +610,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
             try transCreateNodeUndefinedLiteral(c);
     } else if (storage_class != .Extern) {
         eq_tok = try appendToken(c, .Equal, "=");
-        init_node = try transCreateNodeTypeIdentifier(c, "undefined");
+        init_node = try transCreateNodeIdentifierUnchecked(c, "undefined");
     }
 
     const linksection_expr = blk: {
@@ -4814,7 +4814,7 @@ fn transCreateNodeIdentifier(c: *Context, name: []const u8) !*ast.Node {
     return &identifier.base;
 }
 
-fn transCreateNodeTypeIdentifier(c: *Context, name: []const u8) !*ast.Node {
+fn transCreateNodeIdentifierUnchecked(c: *Context, name: []const u8) !*ast.Node {
     const token_index = try appendTokenFmt(c, .Identifier, "{}", .{name});
     const identifier = try c.a().create(ast.Node.Identifier);
     identifier.* = .{
@@ -5368,15 +5368,15 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
             return parseCNumLit(c, tok, source, source_loc);
         },
         // eventually this will be replaced by std.c.parse which will handle these correctly
-        .Keyword_void => return transCreateNodeTypeIdentifier(c, "c_void"),
-        .Keyword_bool => return transCreateNodeTypeIdentifier(c, "bool"),
-        .Keyword_double => return transCreateNodeTypeIdentifier(c, "f64"),
-        .Keyword_long => return transCreateNodeTypeIdentifier(c, "c_long"),
-        .Keyword_int => return transCreateNodeTypeIdentifier(c, "c_int"),
-        .Keyword_float => return transCreateNodeTypeIdentifier(c, "f32"),
-        .Keyword_short => return transCreateNodeTypeIdentifier(c, "c_short"),
-        .Keyword_char => return transCreateNodeTypeIdentifier(c, "c_char"),
-        .Keyword_unsigned => return transCreateNodeTypeIdentifier(c, "c_uint"),
+        .Keyword_void => return transCreateNodeIdentifierUnchecked(c, "c_void"),
+        .Keyword_bool => return transCreateNodeIdentifierUnchecked(c, "bool"),
+        .Keyword_double => return transCreateNodeIdentifierUnchecked(c, "f64"),
+        .Keyword_long => return transCreateNodeIdentifierUnchecked(c, "c_long"),
+        .Keyword_int => return transCreateNodeIdentifierUnchecked(c, "c_int"),
+        .Keyword_float => return transCreateNodeIdentifierUnchecked(c, "f32"),
+        .Keyword_short => return transCreateNodeIdentifierUnchecked(c, "c_short"),
+        .Keyword_char => return transCreateNodeIdentifierUnchecked(c, "c_char"),
+        .Keyword_unsigned => return transCreateNodeIdentifierUnchecked(c, "c_uint"),
         .Identifier => {
             const mangled_name = scope.getAlias(source[tok.start..tok.end]);
             return transCreateNodeIdentifier(c, mangled_name);
@@ -5512,6 +5512,8 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
     var node = try parseCPrimaryExpr(c, it, source, source_loc, scope);
     while (true) {
         const tok = it.next().?;
+        var op_token: ast.TokenIndex = undefined;
+        var op_id: ast.Node.InfixOp.Op = undefined;
         switch (tok.id) {
             .Period => {
                 const name_tok = it.next().?;
@@ -5528,6 +5530,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
                 }
 
                 node = try transCreateNodeFieldAccess(c, node, source[name_tok.start..name_tok.end]);
+                continue;
             },
             .Arrow => {
                 const name_tok = it.next().?;
@@ -5542,9 +5545,16 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
                     );
                     return error.ParseError;
                 }
-
-                const deref = try transCreateNodePtrDeref(c, node);
+                // deref is often used together with casts so we group the lhs expression
+                const group = try c.a().create(ast.Node.GroupedExpression);
+                group.* = .{
+                    .lparen = try appendToken(c, .LParen, "("),
+                    .expr = node,
+                    .rparen = try appendToken(c, .RParen, ")"),
+                };
+                const deref = try transCreateNodePtrDeref(c, &group.base);
                 node = try transCreateNodeFieldAccess(c, deref, source[name_tok.start..name_tok.end]);
+                continue;
             },
             .Asterisk => {
                 if (it.peek().?.id == .RParen) {
@@ -5568,161 +5578,57 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
                     return &ptr.base;
                 } else {
                     // expr * expr
-                    const op_token = try appendToken(c, .Asterisk, "*");
-                    const rhs = try parseCPrimaryExpr(c, it, source, source_loc, scope);
-                    const mul_node = try c.a().create(ast.Node.InfixOp);
-                    mul_node.* = .{
-                        .op_token = op_token,
-                        .lhs = node,
-                        .op = .BitShiftLeft,
-                        .rhs = rhs,
-                    };
-                    node = &mul_node.base;
+                    op_token = try appendToken(c, .Asterisk, "*");
+                    op_id = .BitShiftLeft;
                 }
             },
             .AngleBracketAngleBracketLeft => {
-                const op_token = try appendToken(c, .AngleBracketAngleBracketLeft, "<<");
-                const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
-                const bitshift_node = try c.a().create(ast.Node.InfixOp);
-                bitshift_node.* = .{
-                    .op_token = op_token,
-                    .lhs = node,
-                    .op = .BitShiftLeft,
-                    .rhs = rhs,
-                };
-                node = &bitshift_node.base;
+                op_token = try appendToken(c, .AngleBracketAngleBracketLeft, "<<");
+                op_id = .BitShiftLeft;
             },
             .AngleBracketAngleBracketRight => {
-                const op_token = try appendToken(c, .AngleBracketAngleBracketRight, ">>");
-                const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
-                const bitshift_node = try c.a().create(ast.Node.InfixOp);
-                bitshift_node.* = .{
-                    .op_token = op_token,
-                    .lhs = node,
-                    .op = .BitShiftRight,
-                    .rhs = rhs,
-                };
-                node = &bitshift_node.base;
+                op_token = try appendToken(c, .AngleBracketAngleBracketRight, ">>");
+                op_id = .BitShiftRight;
             },
             .Pipe => {
-                const op_token = try appendToken(c, .Pipe, "|");
-                const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
-                const or_node = try c.a().create(ast.Node.InfixOp);
-                or_node.* = .{
-                    .op_token = op_token,
-                    .lhs = node,
-                    .op = .BitOr,
-                    .rhs = rhs,
-                };
-                node = &or_node.base;
+                op_token = try appendToken(c, .Pipe, "|");
+                op_id = .BitOr;
             },
             .Ampersand => {
-                const op_token = try appendToken(c, .Ampersand, "&");
-                const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
-                const bitand_node = try c.a().create(ast.Node.InfixOp);
-                bitand_node.* = .{
-                    .op_token = op_token,
-                    .lhs = node,
-                    .op = .BitAnd,
-                    .rhs = rhs,
-                };
-                node = &bitand_node.base;
+                op_token = try appendToken(c, .Ampersand, "&");
+                op_id .BitAnd;
             },
             .Plus => {
-                const op_token = try appendToken(c, .Plus, "+");
-                const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
-                const add_node = try c.a().create(ast.Node.InfixOp);
-                add_node.* = .{
-                    .op_token = op_token,
-                    .lhs = node,
-                    .op = .Add,
-                    .rhs = rhs,
-                };
-                node = &add_node.base;
+                op_token = try appendToken(c, .Plus, "+");
+                op_id = .Add;
             },
             .Minus => {
-                const op_token = try appendToken(c, .Minus, "-");
-                const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
-                const sub_node = try c.a().create(ast.Node.InfixOp);
-                sub_node.* = .{
-                    .op_token = op_token,
-                    .lhs = node,
-                    .op = .Sub,
-                    .rhs = rhs,
-                };
-                node = &sub_node.base;
+                op_token = try appendToken(c, .Minus, "-");
+                op_id .Sub;
             },
             .AmpersandAmpersand => {
-                const op_token = try appendToken(c, .Keyword_and, "and");
-                const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
-                const and_node = try c.a().create(ast.Node.InfixOp);
-                and_node.* = .{
-                    .op_token = op_token,
-                    .lhs = node,
-                    .op = .BoolAnd,
-                    .rhs = rhs,
-                };
-                node = &and_node.base;
+                op_token = try appendToken(c, .Keyword_and, "and");
+                op_id = .BoolAnd;
             },
             .PipePipe => {
-                const op_token = try appendToken(c, .Keyword_or, "or");
-                const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
-                const or_node = try c.a().create(ast.Node.InfixOp);
-                or_node.* = .{
-                    .op_token = op_token,
-                    .lhs = node,
-                    .op = .BoolOr,
-                    .rhs = rhs,
-                };
-                node = &or_node.base;
+                op_token = try appendToken(c, .Keyword_or, "or");
+                op_id = .BoolOr;
             },
             .AngleBracketRight => {
-                const op_token = try appendToken(c, .AngleBracketRight, ">");
-                const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
-                const and_node = try c.a().create(ast.Node.InfixOp);
-                and_node.* = .{
-                    .op_token = op_token,
-                    .lhs = node,
-                    .op = .GreaterThan,
-                    .rhs = rhs,
-                };
-                node = &and_node.base;
+                op_token = try appendToken(c, .AngleBracketRight, ">");
+                op_id = .GreaterThan;
             },
             .AngleBracketRightEqual => {
-                const op_token = try appendToken(c, .AngleBracketRightEqual, ">=");
-                const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
-                const and_node = try c.a().create(ast.Node.InfixOp);
-                and_node.* = .{
-                    .op_token = op_token,
-                    .lhs = node,
-                    .op = .GreaterOrEqual,
-                    .rhs = rhs,
-                };
-                node = &and_node.base;
+                op_token = try appendToken(c, .AngleBracketRightEqual, ">=");
+                op_id = .GreaterOrEqual;
             },
             .AngleBracketLeft => {
-                const op_token = try appendToken(c, .AngleBracketLeft, "<");
-                const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
-                const and_node = try c.a().create(ast.Node.InfixOp);
-                and_node.* = .{
-                    .op_token = op_token,
-                    .lhs = node,
-                    .op = .LessThan,
-                    .rhs = rhs,
-                };
-                node = &and_node.base;
+                op_token = try appendToken(c, .AngleBracketLeft, "<");
+                op_id = .LessThan;
             },
             .AngleBracketLeftEqual => {
-                const op_token = try appendToken(c, .AngleBracketLeftEqual, "<=");
-                const rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
-                const and_node = try c.a().create(ast.Node.InfixOp);
-                and_node.* = .{
-                    .op_token = op_token,
-                    .lhs = node,
-                    .op = .LessOrEqual,
-                    .rhs = rhs,
-                };
-                node = &and_node.base;
+                op_token = try appendToken(c, .AngleBracketLeftEqual, "<=");
+                op_id = .LessOrEqual;
             },
             .LBracket => {
                 const arr_node = try transCreateNodeArrayAccess(c, node);
@@ -5740,6 +5646,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
                     );
                     return error.ParseError;
                 }
+                continue;
             },
             .LParen => {
                 const call_node = try transCreateNodeFnCall(c, node);
@@ -5765,12 +5672,39 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
                 }
                 call_node.rtoken = try appendToken(c, .RParen, ")");
                 node = &call_node.base;
+                continue;
+            },
+            .BangEqual => {
+                op_token = try appendToken(c, .BangEqual, "!=");
+                op_id =  .BangEqual;
+            },
+            .EqualEqual => {
+                op_token = try appendToken(c, .EqualEqual, "==");
+                op_id = .EqualEqual;
+            },
+            .Slash => {
+                // unsigned/float division uses the operator
+                op_id = .Div;
+                op_token = try appendToken(c, .Slash, "/");
+            },
+            .Percent => {
+                // unsigned/float division uses the operator
+                op_id = .Mod;
+                op_token = try appendToken(c, .Percent, "%");
             },
             else => {
                 _ = it.prev();
                 return node;
             },
         }
+        const op_node = try c.a().create(ast.Node.InfixOp);
+        op_node.* = .{
+            .op_token = op_token,
+            .lhs = node,
+            .op = op_id,
+            .rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope),
+        };
+        node = &op_node.base;
     }
 }
 
@@ -5788,14 +5722,33 @@ fn parseCPrefixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
             node.rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
             return &node.base;
         },
+        .Plus => return try parseCPrefixOpExpr(c, it, source, source_loc, scope),
         .Tilde => {
             const node = try transCreateNodePrefixOp(c, .BitNot, .Tilde, "~");
             node.rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
             return &node.base;
         },
         .Asterisk => {
-            const prefix_op_expr = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
-            return try transCreateNodePtrDeref(c, prefix_op_expr);
+            // deref is often used together with casts so we group the lhs expression
+            const group = try c.a().create(ast.Node.GroupedExpression);
+            group.* = .{
+                .lparen = try appendToken(c, .LParen, "("),
+                .expr = try parseCPrefixOpExpr(c, it, source, source_loc, scope),
+                .rparen = try appendToken(c, .RParen, ")"),
+            };
+            return try transCreateNodePtrDeref(c, &group.base);
+        },
+        .Ampersand => {
+            // address of is often used together with casts so we group the rhs expression
+            const node = try transCreateNodePrefixOp(c, .AddressOf, .Ampersand, "&");
+            const group = try c.a().create(ast.Node.GroupedExpression);
+            group.* = .{
+                .lparen = try appendToken(c, .LParen, "("),
+                .expr = try parseCPrefixOpExpr(c, it, source, source_loc, scope),
+                .rparen = try appendToken(c, .RParen, ")"),
+            };
+            node.rhs = &group.base;
+            return &node.base;
         },
         else => {
             _ = it.prev();
test/translate_c.zig
@@ -5,7 +5,7 @@ const CrossTarget = std.zig.CrossTarget;
 pub fn addCases(cases: *tests.TranslateCContext) void {
     cases.add("macro comma operator",
         \\#define foo (foo, bar)
-        \\#define bar(x) (x, 3, 4, 5 * 6, baz(1, 2), 2, baz(1,2))
+        \\#define bar(x) (&x, +3, 4 == 4, 5 * 6, baz(1, 2), 2 % 2, baz(1,2))
     , &[_][]const u8{
         \\pub const foo = blk: {
         \\    _ = foo;
@@ -14,12 +14,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
     ,
         \\pub inline fn bar(x: var) @TypeOf(baz(1, 2)) {
         \\    return blk: {
-        \\        _ = x;
+        \\        _ = &(x);
         \\        _ = 3;
-        \\        _ = 4;
+        \\        _ = 4 == 4;
         \\        _ = 5 * 6;
         \\        _ = baz(1, 2);
-        \\        _ = 2;
+        \\        _ = 2 % 2;
         \\        break :blk baz(1, 2);
         \\    };
         \\}
@@ -1993,7 +1993,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
     ,
         \\pub const DOT = a.b;
     ,
-        \\pub const ARROW = a.*.b;
+        \\pub const ARROW = (a).*.b;
     });
 
     cases.add("array access",