| ... | @@ -717,10 +717,11 @@ pub const Payload = struct { | ... | @@ -717,10 +717,11 @@ pub const Payload = struct { |
| 717 | | 717 | |
| 718 | /// Converts the nodes into a Zig Ast. | 718 | /// Converts the nodes into a Zig Ast. |
| 719 | /// Caller must free the source slice. | 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 | var ctx = Context{ | 721 | var ctx = Context{ |
| 722 | .gpa = gpa, | 722 | .gpa = gpa, |
| 723 | .buf = std.ArrayList(u8).init(gpa), | 723 | .buf = std.ArrayList(u8).init(gpa), |
| | 724 | .zig_is_stage1 = zig_is_stage1, |
| 724 | }; | 725 | }; |
| 725 | defer ctx.buf.deinit(); | 726 | defer ctx.buf.deinit(); |
| 726 | defer ctx.nodes.deinit(gpa); | 727 | defer ctx.nodes.deinit(gpa); |
| ... | @@ -789,6 +790,11 @@ const Context = struct { | ... | @@ -789,6 +790,11 @@ const Context = struct { |
| 789 | extra_data: std.ArrayListUnmanaged(std.zig.Ast.Node.Index) = .{}, | 790 | extra_data: std.ArrayListUnmanaged(std.zig.Ast.Node.Index) = .{}, |
| 790 | tokens: std.zig.Ast.TokenList = .{}, | 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 | fn addTokenFmt(c: *Context, tag: TokenTag, comptime format: []const u8, args: anytype) Allocator.Error!TokenIndex { | 798 | fn addTokenFmt(c: *Context, tag: TokenTag, comptime format: []const u8, args: anytype) Allocator.Error!TokenIndex { |
| 793 | const start_index = c.buf.items.len; | 799 | const start_index = c.buf.items.len; |
| 794 | try c.buf.writer().print(format ++ " ", args); | 800 | try c.buf.writer().print(format ++ " ", args); |
| ... | @@ -910,7 +916,15 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { | ... | @@ -910,7 +916,15 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 910 | }, | 916 | }, |
| 911 | .call => { | 917 | .call => { |
| 912 | const payload = node.castTag(.call).?.data; | 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 | return renderCall(c, lhs, payload.args); | 928 | return renderCall(c, lhs, payload.args); |
| 915 | }, | 929 | }, |
| 916 | .null_literal => return c.addNode(.{ | 930 | .null_literal => return c.addNode(.{ |
| ... | @@ -1064,12 +1078,32 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { | ... | @@ -1064,12 +1078,32 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1064 | }); | 1078 | }); |
| 1065 | }, | 1079 | }, |
| 1066 | .fn_identifier => { | 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 | const payload = node.castTag(.fn_identifier).?.data; | 1084 | const payload = node.castTag(.fn_identifier).?.data; |
| 1068 | return c.addNode(.{ | 1085 | if (c.zig_is_stage1) { |
| 1069 | .tag = .identifier, | 1086 | return try c.addNode(.{ |
| 1070 | .main_token = try c.addIdentifier(payload), | 1087 | .tag = .identifier, |
| 1071 | .data = undefined, | 1088 | .main_token = try c.addIdentifier(payload), |
| 1072 | }); | 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 | .float_literal => { | 1108 | .float_literal => { |
| 1075 | const payload = node.castTag(.float_literal).?.data; | 1109 | const payload = node.castTag(.float_literal).?.data; |
| ... | @@ -1391,7 +1425,33 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { | ... | @@ -1391,7 +1425,33 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1391 | .bit_not => return renderPrefixOp(c, node, .bit_not, .tilde, "~"), | 1425 | .bit_not => return renderPrefixOp(c, node, .bit_not, .tilde, "~"), |
| 1392 | .not => return renderPrefixOp(c, node, .bool_not, .bang, "!"), | 1426 | .not => return renderPrefixOp(c, node, .bool_not, .bang, "!"), |
| 1393 | .optional_type => return renderPrefixOp(c, node, .optional_type, .question_mark, "?"), | 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 | .deref => { | 1455 | .deref => { |
| 1396 | const payload = node.castTag(.deref).?.data; | 1456 | const payload = node.castTag(.deref).?.data; |
| 1397 | const operand = try renderNodeGrouped(c, payload); | 1457 | const operand = try renderNodeGrouped(c, payload); |