| ... | ... | @@ -717,10 +717,11 @@ pub const Payload = struct { |
| 717 | 717 | |
| 718 | 718 | /// Converts the nodes into a Zig Ast. |
| 719 | 719 | /// Caller must free the source slice. |
| 720 | | pub fn render(gpa: Allocator, nodes: []const Node) !std.zig.Ast { |
| 720 | pub fn render(gpa: Allocator, zig_is_stage1: bool, nodes: []const Node) !std.zig.Ast { |
| 721 | 721 | var ctx = Context{ |
| 722 | 722 | .gpa = gpa, |
| 723 | 723 | .buf = std.ArrayList(u8).init(gpa), |
| 724 | .zig_is_stage1 = zig_is_stage1, |
| 724 | 725 | }; |
| 725 | 726 | defer ctx.buf.deinit(); |
| 726 | 727 | defer ctx.nodes.deinit(gpa); |
| ... | ... | @@ -789,6 +790,11 @@ const Context = struct { |
| 789 | 790 | extra_data: std.ArrayListUnmanaged(std.zig.Ast.Node.Index) = .{}, |
| 790 | 791 | tokens: std.zig.Ast.TokenList = .{}, |
| 791 | 792 | |
| 793 | /// This is used to emit different code depending on whether |
| 794 | /// the output zig source code is intended to be compiled with stage1 or stage2. |
| 795 | /// Refer to the Context in translate_c.zig. |
| 796 | zig_is_stage1: bool, |
| 797 | |
| 792 | 798 | fn addTokenFmt(c: *Context, tag: TokenTag, comptime format: []const u8, args: anytype) Allocator.Error!TokenIndex { |
| 793 | 799 | const start_index = c.buf.items.len; |
| 794 | 800 | try c.buf.writer().print(format ++ " ", args); |
| ... | ... | @@ -910,7 +916,15 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 910 | 916 | }, |
| 911 | 917 | .call => { |
| 912 | 918 | const payload = node.castTag(.call).?.data; |
| 913 | | const lhs = try renderNodeGrouped(c, payload.lhs); |
| 919 | // Cosmetic: avoids an unnecesary address_of on most function calls. |
| 920 | const lhs = if (!c.zig_is_stage1 and payload.lhs.tag() == .fn_identifier) |
| 921 | try c.addNode(.{ |
| 922 | .tag = .identifier, |
| 923 | .main_token = try c.addIdentifier(payload.lhs.castTag(.fn_identifier).?.data), |
| 924 | .data = undefined, |
| 925 | }) |
| 926 | else |
| 927 | try renderNodeGrouped(c, payload.lhs); |
| 914 | 928 | return renderCall(c, lhs, payload.args); |
| 915 | 929 | }, |
| 916 | 930 | .null_literal => return c.addNode(.{ |
| ... | ... | @@ -1064,12 +1078,32 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1064 | 1078 | }); |
| 1065 | 1079 | }, |
| 1066 | 1080 | .fn_identifier => { |
| 1081 | // C semantics are that a function identifier has address |
| 1082 | // value (implicit in stage1, explicit in stage2), except in |
| 1083 | // the context of an address_of, which is handled there. |
| 1067 | 1084 | const payload = node.castTag(.fn_identifier).?.data; |
| 1068 | | return c.addNode(.{ |
| 1069 | | .tag = .identifier, |
| 1070 | | .main_token = try c.addIdentifier(payload), |
| 1071 | | .data = undefined, |
| 1072 | | }); |
| 1085 | if (c.zig_is_stage1) { |
| 1086 | return try c.addNode(.{ |
| 1087 | .tag = .identifier, |
| 1088 | .main_token = try c.addIdentifier(payload), |
| 1089 | .data = undefined, |
| 1090 | }); |
| 1091 | } else { |
| 1092 | const tok = try c.addToken(.ampersand, "&"); |
| 1093 | const arg = try c.addNode(.{ |
| 1094 | .tag = .identifier, |
| 1095 | .main_token = try c.addIdentifier(payload), |
| 1096 | .data = undefined, |
| 1097 | }); |
| 1098 | return c.addNode(.{ |
| 1099 | .tag = .address_of, |
| 1100 | .main_token = tok, |
| 1101 | .data = .{ |
| 1102 | .lhs = arg, |
| 1103 | .rhs = undefined, |
| 1104 | }, |
| 1105 | }); |
| 1106 | } |
| 1073 | 1107 | }, |
| 1074 | 1108 | .float_literal => { |
| 1075 | 1109 | const payload = node.castTag(.float_literal).?.data; |
| ... | ... | @@ -1391,7 +1425,33 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1391 | 1425 | .bit_not => return renderPrefixOp(c, node, .bit_not, .tilde, "~"), |
| 1392 | 1426 | .not => return renderPrefixOp(c, node, .bool_not, .bang, "!"), |
| 1393 | 1427 | .optional_type => return renderPrefixOp(c, node, .optional_type, .question_mark, "?"), |
| 1394 | | .address_of => return renderPrefixOp(c, node, .address_of, .ampersand, "&"), |
| 1428 | .address_of => { |
| 1429 | const payload = node.castTag(.address_of).?.data; |
| 1430 | if (c.zig_is_stage1 and payload.tag() == .fn_identifier) |
| 1431 | return try c.addNode(.{ |
| 1432 | .tag = .identifier, |
| 1433 | .main_token = try c.addIdentifier(payload.castTag(.fn_identifier).?.data), |
| 1434 | .data = undefined, |
| 1435 | }); |
| 1436 | |
| 1437 | const ampersand = try c.addToken(.ampersand, "&"); |
| 1438 | const base = if (payload.tag() == .fn_identifier) |
| 1439 | try c.addNode(.{ |
| 1440 | .tag = .identifier, |
| 1441 | .main_token = try c.addIdentifier(payload.castTag(.fn_identifier).?.data), |
| 1442 | .data = undefined, |
| 1443 | }) |
| 1444 | else |
| 1445 | try renderNodeGrouped(c, payload); |
| 1446 | return c.addNode(.{ |
| 1447 | .tag = .address_of, |
| 1448 | .main_token = ampersand, |
| 1449 | .data = .{ |
| 1450 | .lhs = base, |
| 1451 | .rhs = undefined, |
| 1452 | }, |
| 1453 | }); |
| 1454 | }, |
| 1395 | 1455 | .deref => { |
| 1396 | 1456 | const payload = node.castTag(.deref).?.data; |
| 1397 | 1457 | const operand = try renderNodeGrouped(c, payload); |