Commit 8088bdc6d5

Vexu <git@vexu.eu>
2020-03-05 10:22:50
translate-c macro comma operator
1 parent 378bf1c
Changed files (2)
src-self-hosted
test
src-self-hosted/translate_c.zig
@@ -5038,7 +5038,14 @@ fn transMacroFnDefine(c: *Context, it: *CTokenList.Iterator, source: []const u8,
             .{last.id},
         );
     _ = try appendToken(c, .Semicolon, ";");
-    try type_of.params.push(expr);
+    const type_of_arg = if (expr.id != .Block) expr else blk: {
+        const blk = @fieldParentPtr(ast.Node.Block, "base", expr);
+        const blk_last = blk.statements.at(blk.statements.len - 1).*;
+        std.debug.assert(blk_last.id == .ControlFlowExpression);
+        const br = @fieldParentPtr(ast.Node.ControlFlowExpression, "base", blk_last);
+        break :blk br.rhs.?;
+    };
+    try type_of.params.push(type_of_arg);
     return_expr.rhs = expr;
 
     block.rbrace = try appendToken(c, .RBrace, "}");
@@ -5073,6 +5080,39 @@ fn parseCExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, source_
             if_node.@"else".?.body = try parseCPrimaryExpr(c, it, source, source_loc, scope);
             return &if_node.base;
         },
+        .Comma => {
+            _ = try appendToken(c, .Semicolon, ";");
+            const block_scope = try Scope.Block.init(c, scope, "blk");
+            block_scope.block_node = try transCreateNodeBlock(c, block_scope.label);
+
+            var last = node;
+            while (true) {
+                // suppress result
+                const lhs = try transCreateNodeIdentifier(c, "_");
+                const op_token = try appendToken(c, .Equal, "=");
+                const op_node = try c.a().create(ast.Node.InfixOp);
+                op_node.* = .{
+                    .op_token = op_token,
+                    .lhs = lhs,
+                    .op = .Assign,
+                    .rhs = last,
+                };
+                try block_scope.block_node.statements.push(&op_node.base);
+
+                last = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
+                _ = try appendToken(c, .Semicolon, ";");
+                if (it.next().?.id != .Comma) {
+                    _ = it.prev();
+                    break;
+                }
+            }
+
+            const break_node = try transCreateNodeBreak(c, block_scope.label);
+            break_node.rhs = last;
+            try block_scope.block_node.statements.push(&break_node.base);
+            block_scope.block_node.rbrace = try appendToken(c, .RBrace, "}");
+            return &block_scope.block_node.base;
+        },
         else => {
             _ = it.prev();
             return node;
test/translate_c.zig
@@ -3,6 +3,28 @@ const std = @import("std");
 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))
+    , &[_][]const u8{
+        \\pub const foo = blk: {
+        \\    _ = foo;
+        \\    break :blk bar;
+        \\};
+    ,
+        \\pub inline fn bar(x: var) @TypeOf(baz(1, 2)) {
+        \\    return blk: {
+        \\        _ = x;
+        \\        _ = 3;
+        \\        _ = 4;
+        \\        _ = 5 * 6;
+        \\        _ = baz(1, 2);
+        \\        _ = 2;
+        \\        break :blk baz(1, 2);
+        \\    };
+        \\}
+    });
+
     cases.add("macro line continuation",
         \\#define FOO -\
         \\BAR