| author | |
| committer | |
| log | 6b103324d2d935260138584877dbe1593790b953 |
| tree | 3d1dc5c5378ac41ab5ca24f549721a882583454f |
| parent | a7c3cec65f1639195e787b98900c3f126953f880 |
| parent | c5b7322319a9559423fcda5c20c3b2e22338b2b4 |
| signature |
stage2: introduce the concept of "trailer flags" to the AST9 files changed, 773 insertions(+), 421 deletions(-)
lib/std/meta.zig+1| ... | @@ -6,6 +6,7 @@ const math = std.math; | ... | @@ -6,6 +6,7 @@ const math = std.math; |
| 6 | const testing = std.testing; | 6 | const testing = std.testing; |
| 7 | 7 | ||
| 8 | pub const trait = @import("meta/trait.zig"); | 8 | pub const trait = @import("meta/trait.zig"); |
| 9 | pub const TrailerFlags = @import("meta/trailer_flags.zig").TrailerFlags; | ||
| 9 | 10 | ||
| 10 | const TypeInfo = builtin.TypeInfo; | 11 | const TypeInfo = builtin.TypeInfo; |
| 11 | 12 |
lib/std/meta/trailer_flags.zig created+145| ... | @@ -0,0 +1,145 @@ | ||
| 1 | const std = @import("../std.zig"); | ||
| 2 | const meta = std.meta; | ||
| 3 | const testing = std.testing; | ||
| 4 | const mem = std.mem; | ||
| 5 | const assert = std.debug.assert; | ||
| 6 | |||
| 7 | /// This is useful for saving memory when allocating an object that has many | ||
| 8 | /// optional components. The optional objects are allocated sequentially in | ||
| 9 | /// memory, and a single integer is used to represent each optional object | ||
| 10 | /// and whether it is present based on each corresponding bit. | ||
| 11 | pub fn TrailerFlags(comptime Fields: type) type { | ||
| 12 | return struct { | ||
| 13 | bits: Int, | ||
| 14 | |||
| 15 | pub const Int = @Type(.{ .Int = .{ .bits = bit_count, .is_signed = false } }); | ||
| 16 | pub const bit_count = @typeInfo(Fields).Struct.fields.len; | ||
| 17 | |||
| 18 | pub const Self = @This(); | ||
| 19 | |||
| 20 | pub fn has(self: Self, comptime name: []const u8) bool { | ||
| 21 | const field_index = meta.fieldIndex(Fields, name).?; | ||
| 22 | return (self.bits & (1 << field_index)) != 0; | ||
| 23 | } | ||
| 24 | |||
| 25 | pub fn get(self: Self, p: [*]align(@alignOf(Fields)) const u8, comptime name: []const u8) ?Field(name) { | ||
| 26 | if (!self.has(name)) | ||
| 27 | return null; | ||
| 28 | return self.ptrConst(p, name).*; | ||
| 29 | } | ||
| 30 | |||
| 31 | pub fn setFlag(self: *Self, comptime name: []const u8) void { | ||
| 32 | const field_index = meta.fieldIndex(Fields, name).?; | ||
| 33 | self.bits |= 1 << field_index; | ||
| 34 | } | ||
| 35 | |||
| 36 | /// `fields` is a struct with each field set to an optional value. | ||
| 37 | /// Missing fields are assumed to be `null`. | ||
| 38 | /// Only the non-null bits are observed and are used to set the flag bits. | ||
| 39 | pub fn init(fields: anytype) Self { | ||
| 40 | var self: Self = .{ .bits = 0 }; | ||
| 41 | inline for (@typeInfo(@TypeOf(fields)).Struct.fields) |field| { | ||
| 42 | const opt: ?Field(field.name) = @field(fields, field.name); | ||
| 43 | const field_index = meta.fieldIndex(Fields, field.name).?; | ||
| 44 | self.bits |= @as(Int, @boolToInt(opt != null)) << field_index; | ||
| 45 | } | ||
| 46 | return self; | ||
| 47 | } | ||
| 48 | |||
| 49 | /// `fields` is a struct with each field set to an optional value (same as `init`). | ||
| 50 | /// Missing fields are assumed to be `null`. | ||
| 51 | pub fn setMany(self: Self, p: [*]align(@alignOf(Fields)) u8, fields: anytype) void { | ||
| 52 | inline for (@typeInfo(@TypeOf(fields)).Struct.fields) |field| { | ||
| 53 | const opt: ?Field(field.name) = @field(fields, field.name); | ||
| 54 | if (opt) |value| { | ||
| 55 | self.set(p, field.name, value); | ||
| 56 | } | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 60 | pub fn set( | ||
| 61 | self: Self, | ||
| 62 | p: [*]align(@alignOf(Fields)) u8, | ||
| 63 | comptime name: []const u8, | ||
| 64 | value: Field(name), | ||
| 65 | ) void { | ||
| 66 | self.ptr(p, name).* = value; | ||
| 67 | } | ||
| 68 | |||
| 69 | pub fn ptr(self: Self, p: [*]align(@alignOf(Fields)) u8, comptime name: []const u8) *Field(name) { | ||
| 70 | if (@sizeOf(Field(name)) == 0) | ||
| 71 | return undefined; | ||
| 72 | const off = self.offset(p, name); | ||
| 73 | return @ptrCast(*Field(name), @alignCast(@alignOf(Field(name)), p + off)); | ||
| 74 | } | ||
| 75 | |||
| 76 | pub fn ptrConst(self: Self, p: [*]align(@alignOf(Fields)) const u8, comptime name: []const u8) *const Field(name) { | ||
| 77 | if (@sizeOf(Field(name)) == 0) | ||
| 78 | return undefined; | ||
| 79 | const off = self.offset(p, name); | ||
| 80 | return @ptrCast(*const Field(name), @alignCast(@alignOf(Field(name)), p + off)); | ||
| 81 | } | ||
| 82 | |||
| 83 | pub fn offset(self: Self, p: [*]align(@alignOf(Fields)) const u8, comptime name: []const u8) usize { | ||
| 84 | var off: usize = 0; | ||
| 85 | inline for (@typeInfo(Fields).Struct.fields) |field, i| { | ||
| 86 | const active = (self.bits & (1 << i)) != 0; | ||
| 87 | if (comptime mem.eql(u8, field.name, name)) { | ||
| 88 | assert(active); | ||
| 89 | return mem.alignForwardGeneric(usize, off, @alignOf(field.field_type)); | ||
| 90 | } else if (active) { | ||
| 91 | off = mem.alignForwardGeneric(usize, off, @alignOf(field.field_type)); | ||
| 92 | off += @sizeOf(field.field_type); | ||
| 93 | } | ||
| 94 | } | ||
| 95 | @compileError("no field named " ++ name ++ " in type " ++ @typeName(Fields)); | ||
| 96 | } | ||
| 97 | |||
| 98 | pub fn Field(comptime name: []const u8) type { | ||
| 99 | return meta.fieldInfo(Fields, name).field_type; | ||
| 100 | } | ||
| 101 | |||
| 102 | pub fn sizeInBytes(self: Self) usize { | ||
| 103 | var off: usize = 0; | ||
| 104 | inline for (@typeInfo(Fields).Struct.fields) |field, i| { | ||
| 105 | if (@sizeOf(field.field_type) == 0) | ||
| 106 | continue; | ||
| 107 | if ((self.bits & (1 << i)) != 0) { | ||
| 108 | off = mem.alignForwardGeneric(usize, off, @alignOf(field.field_type)); | ||
| 109 | off += @sizeOf(field.field_type); | ||
| 110 | } | ||
| 111 | } | ||
| 112 | return off; | ||
| 113 | } | ||
| 114 | }; | ||
| 115 | } | ||
| 116 | |||
| 117 | test "TrailerFlags" { | ||
| 118 | const Flags = TrailerFlags(struct { | ||
| 119 | a: i32, | ||
| 120 | b: bool, | ||
| 121 | c: u64, | ||
| 122 | }); | ||
| 123 | var flags = Flags.init(.{ | ||
| 124 | .b = true, | ||
| 125 | .c = 1234, | ||
| 126 | }); | ||
| 127 | const slice = try testing.allocator.allocAdvanced(u8, 8, flags.sizeInBytes(), .exact); | ||
| 128 | defer testing.allocator.free(slice); | ||
| 129 | |||
| 130 | flags.set(slice.ptr, "b", false); | ||
| 131 | flags.set(slice.ptr, "c", 12345678); | ||
| 132 | |||
| 133 | testing.expect(flags.get(slice.ptr, "a") == null); | ||
| 134 | testing.expect(!flags.get(slice.ptr, "b").?); | ||
| 135 | testing.expect(flags.get(slice.ptr, "c").? == 12345678); | ||
| 136 | |||
| 137 | flags.setMany(slice.ptr, .{ | ||
| 138 | .b = true, | ||
| 139 | .c = 5678, | ||
| 140 | }); | ||
| 141 | |||
| 142 | testing.expect(flags.get(slice.ptr, "a") == null); | ||
| 143 | testing.expect(flags.get(slice.ptr, "b").?); | ||
| 144 | testing.expect(flags.get(slice.ptr, "c").? == 5678); | ||
| 145 | } | ||
lib/std/zig/ast.zig+159-60| ... | @@ -675,42 +675,84 @@ pub const Node = struct { | ... | @@ -675,42 +675,84 @@ pub const Node = struct { |
| 675 | } | 675 | } |
| 676 | }; | 676 | }; |
| 677 | 677 | ||
| 678 | /// Trailed in memory by possibly many things, with each optional thing | ||
| 679 | /// determined by a bit in `trailer_flags`. | ||
| 678 | pub const VarDecl = struct { | 680 | pub const VarDecl = struct { |
| 679 | base: Node = Node{ .id = .VarDecl }, | 681 | base: Node = Node{ .id = .VarDecl }, |
| 680 | doc_comments: ?*DocComment, | 682 | trailer_flags: TrailerFlags, |
| 681 | visib_token: ?TokenIndex, | ||
| 682 | thread_local_token: ?TokenIndex, | ||
| 683 | name_token: TokenIndex, | ||
| 684 | eq_token: ?TokenIndex, | ||
| 685 | mut_token: TokenIndex, | 683 | mut_token: TokenIndex, |
| 686 | comptime_token: ?TokenIndex, | 684 | name_token: TokenIndex, |
| 687 | extern_export_token: ?TokenIndex, | ||
| 688 | lib_name: ?*Node, | ||
| 689 | type_node: ?*Node, | ||
| 690 | align_node: ?*Node, | ||
| 691 | section_node: ?*Node, | ||
| 692 | init_node: ?*Node, | ||
| 693 | semicolon_token: TokenIndex, | 685 | semicolon_token: TokenIndex, |
| 694 | 686 | ||
| 687 | pub const TrailerFlags = std.meta.TrailerFlags(struct { | ||
| 688 | doc_comments: *DocComment, | ||
| 689 | visib_token: TokenIndex, | ||
| 690 | thread_local_token: TokenIndex, | ||
| 691 | eq_token: TokenIndex, | ||
| 692 | comptime_token: TokenIndex, | ||
| 693 | extern_export_token: TokenIndex, | ||
| 694 | lib_name: *Node, | ||
| 695 | type_node: *Node, | ||
| 696 | align_node: *Node, | ||
| 697 | section_node: *Node, | ||
| 698 | init_node: *Node, | ||
| 699 | }); | ||
| 700 | |||
| 701 | pub const RequiredFields = struct { | ||
| 702 | mut_token: TokenIndex, | ||
| 703 | name_token: TokenIndex, | ||
| 704 | semicolon_token: TokenIndex, | ||
| 705 | }; | ||
| 706 | |||
| 707 | pub fn getTrailer(self: *const VarDecl, comptime name: []const u8) ?TrailerFlags.Field(name) { | ||
| 708 | const trailers_start = @ptrCast([*]const u8, self) + @sizeOf(VarDecl); | ||
| 709 | return self.trailer_flags.get(trailers_start, name); | ||
| 710 | } | ||
| 711 | |||
| 712 | pub fn setTrailer(self: *VarDecl, comptime name: []const u8, value: TrailerFlags.Field(name)) void { | ||
| 713 | const trailers_start = @ptrCast([*]u8, self) + @sizeOf(VarDecl); | ||
| 714 | self.trailer_flags.set(trailers_start, name, value); | ||
| 715 | } | ||
| 716 | |||
| 717 | pub fn create(allocator: *mem.Allocator, required: RequiredFields, trailers: anytype) !*VarDecl { | ||
| 718 | const trailer_flags = TrailerFlags.init(trailers); | ||
| 719 | const bytes = try allocator.alignedAlloc(u8, @alignOf(VarDecl), sizeInBytes(trailer_flags)); | ||
| 720 | const var_decl = @ptrCast(*VarDecl, bytes.ptr); | ||
| 721 | var_decl.* = .{ | ||
| 722 | .trailer_flags = trailer_flags, | ||
| 723 | .mut_token = required.mut_token, | ||
| 724 | .name_token = required.name_token, | ||
| 725 | .semicolon_token = required.semicolon_token, | ||
| 726 | }; | ||
| 727 | const trailers_start = bytes.ptr + @sizeOf(VarDecl); | ||
| 728 | trailer_flags.setMany(trailers_start, trailers); | ||
| 729 | return var_decl; | ||
| 730 | } | ||
| 731 | |||
| 732 | pub fn destroy(self: *VarDecl, allocator: *mem.Allocator) void { | ||
| 733 | const bytes = @ptrCast([*]u8, self)[0..sizeInBytes(self.trailer_flags)]; | ||
| 734 | allocator.free(bytes); | ||
| 735 | } | ||
| 736 | |||
| 695 | pub fn iterate(self: *const VarDecl, index: usize) ?*Node { | 737 | pub fn iterate(self: *const VarDecl, index: usize) ?*Node { |
| 696 | var i = index; | 738 | var i = index; |
| 697 | 739 | ||
| 698 | if (self.type_node) |type_node| { | 740 | if (self.getTrailer("type_node")) |type_node| { |
| 699 | if (i < 1) return type_node; | 741 | if (i < 1) return type_node; |
| 700 | i -= 1; | 742 | i -= 1; |
| 701 | } | 743 | } |
| 702 | 744 | ||
| 703 | if (self.align_node) |align_node| { | 745 | if (self.getTrailer("align_node")) |align_node| { |
| 704 | if (i < 1) return align_node; | 746 | if (i < 1) return align_node; |
| 705 | i -= 1; | 747 | i -= 1; |
| 706 | } | 748 | } |
| 707 | 749 | ||
| 708 | if (self.section_node) |section_node| { | 750 | if (self.getTrailer("section_node")) |section_node| { |
| 709 | if (i < 1) return section_node; | 751 | if (i < 1) return section_node; |
| 710 | i -= 1; | 752 | i -= 1; |
| 711 | } | 753 | } |
| 712 | 754 | ||
| 713 | if (self.init_node) |init_node| { | 755 | if (self.getTrailer("init_node")) |init_node| { |
| 714 | if (i < 1) return init_node; | 756 | if (i < 1) return init_node; |
| 715 | i -= 1; | 757 | i -= 1; |
| 716 | } | 758 | } |
| ... | @@ -719,17 +761,21 @@ pub const Node = struct { | ... | @@ -719,17 +761,21 @@ pub const Node = struct { |
| 719 | } | 761 | } |
| 720 | 762 | ||
| 721 | pub fn firstToken(self: *const VarDecl) TokenIndex { | 763 | pub fn firstToken(self: *const VarDecl) TokenIndex { |
| 722 | if (self.visib_token) |visib_token| return visib_token; | 764 | if (self.getTrailer("visib_token")) |visib_token| return visib_token; |
| 723 | if (self.thread_local_token) |thread_local_token| return thread_local_token; | 765 | if (self.getTrailer("thread_local_token")) |thread_local_token| return thread_local_token; |
| 724 | if (self.comptime_token) |comptime_token| return comptime_token; | 766 | if (self.getTrailer("comptime_token")) |comptime_token| return comptime_token; |
| 725 | if (self.extern_export_token) |extern_export_token| return extern_export_token; | 767 | if (self.getTrailer("extern_export_token")) |extern_export_token| return extern_export_token; |
| 726 | assert(self.lib_name == null); | 768 | assert(self.getTrailer("lib_name") == null); |
| 727 | return self.mut_token; | 769 | return self.mut_token; |
| 728 | } | 770 | } |
| 729 | 771 | ||
| 730 | pub fn lastToken(self: *const VarDecl) TokenIndex { | 772 | pub fn lastToken(self: *const VarDecl) TokenIndex { |
| 731 | return self.semicolon_token; | 773 | return self.semicolon_token; |
| 732 | } | 774 | } |
| 775 | |||
| 776 | fn sizeInBytes(trailer_flags: TrailerFlags) usize { | ||
| 777 | return @sizeOf(VarDecl) + trailer_flags.sizeInBytes(); | ||
| 778 | } | ||
| 733 | }; | 779 | }; |
| 734 | 780 | ||
| 735 | pub const Use = struct { | 781 | pub const Use = struct { |
| ... | @@ -972,25 +1018,34 @@ pub const Node = struct { | ... | @@ -972,25 +1018,34 @@ pub const Node = struct { |
| 972 | }; | 1018 | }; |
| 973 | 1019 | ||
| 974 | /// The params are directly after the FnProto in memory. | 1020 | /// The params are directly after the FnProto in memory. |
| 975 | /// TODO have a flags field for the optional nodes, and have them appended | 1021 | /// Next, each optional thing determined by a bit in `trailer_flags`. |
| 976 | /// before or after the parameters in memory. | ||
| 977 | pub const FnProto = struct { | 1022 | pub const FnProto = struct { |
| 978 | base: Node = Node{ .id = .FnProto }, | 1023 | base: Node = Node{ .id = .FnProto }, |
| 979 | doc_comments: ?*DocComment, | 1024 | trailer_flags: TrailerFlags, |
| 980 | visib_token: ?TokenIndex, | ||
| 981 | fn_token: TokenIndex, | 1025 | fn_token: TokenIndex, |
| 982 | name_token: ?TokenIndex, | ||
| 983 | params_len: NodeIndex, | 1026 | params_len: NodeIndex, |
| 984 | return_type: ReturnType, | 1027 | return_type: ReturnType, |
| 985 | var_args_token: ?TokenIndex, | 1028 | |
| 986 | extern_export_inline_token: ?TokenIndex, | 1029 | pub const TrailerFlags = std.meta.TrailerFlags(struct { |
| 987 | body_node: ?*Node, | 1030 | doc_comments: *DocComment, |
| 988 | lib_name: ?*Node, // populated if this is an extern declaration | 1031 | body_node: *Node, |
| 989 | align_expr: ?*Node, // populated if align(A) is present | 1032 | lib_name: *Node, // populated if this is an extern declaration |
| 990 | section_expr: ?*Node, // populated if linksection(A) is present | 1033 | align_expr: *Node, // populated if align(A) is present |
| 991 | callconv_expr: ?*Node, // populated if callconv(A) is present | 1034 | section_expr: *Node, // populated if linksection(A) is present |
| 992 | is_extern_prototype: bool = false, // TODO: Remove once extern fn rewriting is | 1035 | callconv_expr: *Node, // populated if callconv(A) is present |
| 993 | is_async: bool = false, // TODO: remove once async fn rewriting is | 1036 | visib_token: TokenIndex, |
| 1037 | name_token: TokenIndex, | ||
| 1038 | var_args_token: TokenIndex, | ||
| 1039 | extern_export_inline_token: TokenIndex, | ||
| 1040 | is_extern_prototype: void, // TODO: Remove once extern fn rewriting is | ||
| 1041 | is_async: void, // TODO: remove once async fn rewriting is | ||
| 1042 | }); | ||
| 1043 | |||
| 1044 | pub const RequiredFields = struct { | ||
| 1045 | fn_token: TokenIndex, | ||
| 1046 | params_len: NodeIndex, | ||
| 1047 | return_type: ReturnType, | ||
| 1048 | }; | ||
| 994 | 1049 | ||
| 995 | pub const ReturnType = union(enum) { | 1050 | pub const ReturnType = union(enum) { |
| 996 | Explicit: *Node, | 1051 | Explicit: *Node, |
| ... | @@ -1007,7 +1062,6 @@ pub const Node = struct { | ... | @@ -1007,7 +1062,6 @@ pub const Node = struct { |
| 1007 | 1062 | ||
| 1008 | pub const ParamType = union(enum) { | 1063 | pub const ParamType = union(enum) { |
| 1009 | any_type: *Node, | 1064 | any_type: *Node, |
| 1010 | var_args: TokenIndex, | ||
| 1011 | type_expr: *Node, | 1065 | type_expr: *Node, |
| 1012 | }; | 1066 | }; |
| 1013 | 1067 | ||
| ... | @@ -1016,7 +1070,6 @@ pub const Node = struct { | ... | @@ -1016,7 +1070,6 @@ pub const Node = struct { |
| 1016 | 1070 | ||
| 1017 | if (i < 1) { | 1071 | if (i < 1) { |
| 1018 | switch (self.param_type) { | 1072 | switch (self.param_type) { |
| 1019 | .var_args => return null, | ||
| 1020 | .any_type, .type_expr => |node| return node, | 1073 | .any_type, .type_expr => |node| return node, |
| 1021 | } | 1074 | } |
| 1022 | } | 1075 | } |
| ... | @@ -1030,34 +1083,79 @@ pub const Node = struct { | ... | @@ -1030,34 +1083,79 @@ pub const Node = struct { |
| 1030 | if (self.noalias_token) |noalias_token| return noalias_token; | 1083 | if (self.noalias_token) |noalias_token| return noalias_token; |
| 1031 | if (self.name_token) |name_token| return name_token; | 1084 | if (self.name_token) |name_token| return name_token; |
| 1032 | switch (self.param_type) { | 1085 | switch (self.param_type) { |
| 1033 | .var_args => |tok| return tok, | ||
| 1034 | .any_type, .type_expr => |node| return node.firstToken(), | 1086 | .any_type, .type_expr => |node| return node.firstToken(), |
| 1035 | } | 1087 | } |
| 1036 | } | 1088 | } |
| 1037 | 1089 | ||
| 1038 | pub fn lastToken(self: *const ParamDecl) TokenIndex { | 1090 | pub fn lastToken(self: *const ParamDecl) TokenIndex { |
| 1039 | switch (self.param_type) { | 1091 | switch (self.param_type) { |
| 1040 | .var_args => |tok| return tok, | ||
| 1041 | .any_type, .type_expr => |node| return node.lastToken(), | 1092 | .any_type, .type_expr => |node| return node.lastToken(), |
| 1042 | } | 1093 | } |
| 1043 | } | 1094 | } |
| 1044 | }; | 1095 | }; |
| 1045 | 1096 | ||
| 1097 | /// For debugging purposes. | ||
| 1098 | pub fn dump(self: *const FnProto) void { | ||
| 1099 | const trailers_start = @alignCast( | ||
| 1100 | @alignOf(ParamDecl), | ||
| 1101 | @ptrCast([*]const u8, self) + @sizeOf(FnProto) + @sizeOf(ParamDecl) * self.params_len, | ||
| 1102 | ); | ||
| 1103 | std.debug.print("{*} flags: {b} name_token: {} {*} params_len: {}\n", .{ | ||
| 1104 | self, | ||
| 1105 | self.trailer_flags.bits, | ||
| 1106 | self.getTrailer("name_token"), | ||
| 1107 | self.trailer_flags.ptrConst(trailers_start, "name_token"), | ||
| 1108 | self.params_len, | ||
| 1109 | }); | ||
| 1110 | } | ||
| 1111 | |||
| 1112 | pub fn getTrailer(self: *const FnProto, comptime name: []const u8) ?TrailerFlags.Field(name) { | ||
| 1113 | const trailers_start = @alignCast( | ||
| 1114 | @alignOf(ParamDecl), | ||
| 1115 | @ptrCast([*]const u8, self) + @sizeOf(FnProto) + @sizeOf(ParamDecl) * self.params_len, | ||
| 1116 | ); | ||
| 1117 | return self.trailer_flags.get(trailers_start, name); | ||
| 1118 | } | ||
| 1119 | |||
| 1120 | pub fn setTrailer(self: *FnProto, comptime name: []const u8, value: TrailerFlags.Field(name)) void { | ||
| 1121 | const trailers_start = @alignCast( | ||
| 1122 | @alignOf(ParamDecl), | ||
| 1123 | @ptrCast([*]u8, self) + @sizeOf(FnProto) + @sizeOf(ParamDecl) * self.params_len, | ||
| 1124 | ); | ||
| 1125 | self.trailer_flags.set(trailers_start, name, value); | ||
| 1126 | } | ||
| 1127 | |||
| 1046 | /// After this the caller must initialize the params list. | 1128 | /// After this the caller must initialize the params list. |
| 1047 | pub fn alloc(allocator: *mem.Allocator, params_len: NodeIndex) !*FnProto { | 1129 | pub fn create(allocator: *mem.Allocator, required: RequiredFields, trailers: anytype) !*FnProto { |
| 1048 | const bytes = try allocator.alignedAlloc(u8, @alignOf(FnProto), sizeInBytes(params_len)); | 1130 | const trailer_flags = TrailerFlags.init(trailers); |
| 1049 | return @ptrCast(*FnProto, bytes.ptr); | 1131 | const bytes = try allocator.alignedAlloc(u8, @alignOf(FnProto), sizeInBytes( |
| 1132 | required.params_len, | ||
| 1133 | trailer_flags, | ||
| 1134 | )); | ||
| 1135 | const fn_proto = @ptrCast(*FnProto, bytes.ptr); | ||
| 1136 | fn_proto.* = .{ | ||
| 1137 | .trailer_flags = trailer_flags, | ||
| 1138 | .fn_token = required.fn_token, | ||
| 1139 | .params_len = required.params_len, | ||
| 1140 | .return_type = required.return_type, | ||
| 1141 | }; | ||
| 1142 | const trailers_start = @alignCast( | ||
| 1143 | @alignOf(ParamDecl), | ||
| 1144 | bytes.ptr + @sizeOf(FnProto) + @sizeOf(ParamDecl) * required.params_len, | ||
| 1145 | ); | ||
| 1146 | trailer_flags.setMany(trailers_start, trailers); | ||
| 1147 | return fn_proto; | ||
| 1050 | } | 1148 | } |
| 1051 | 1149 | ||
| 1052 | pub fn free(self: *FnProto, allocator: *mem.Allocator) void { | 1150 | pub fn destroy(self: *FnProto, allocator: *mem.Allocator) void { |
| 1053 | const bytes = @ptrCast([*]u8, self)[0..sizeInBytes(self.params_len)]; | 1151 | const bytes = @ptrCast([*]u8, self)[0..sizeInBytes(self.params_len, self.trailer_flags)]; |
| 1054 | allocator.free(bytes); | 1152 | allocator.free(bytes); |
| 1055 | } | 1153 | } |
| 1056 | 1154 | ||
| 1057 | pub fn iterate(self: *const FnProto, index: usize) ?*Node { | 1155 | pub fn iterate(self: *const FnProto, index: usize) ?*Node { |
| 1058 | var i = index; | 1156 | var i = index; |
| 1059 | 1157 | ||
| 1060 | if (self.lib_name) |lib_name| { | 1158 | if (self.getTrailer("lib_name")) |lib_name| { |
| 1061 | if (i < 1) return lib_name; | 1159 | if (i < 1) return lib_name; |
| 1062 | i -= 1; | 1160 | i -= 1; |
| 1063 | } | 1161 | } |
| ... | @@ -1066,23 +1164,21 @@ pub const Node = struct { | ... | @@ -1066,23 +1164,21 @@ pub const Node = struct { |
| 1066 | 0 | 1164 | 0 |
| 1067 | else switch (self.paramsConst()[self.params_len - 1].param_type) { | 1165 | else switch (self.paramsConst()[self.params_len - 1].param_type) { |
| 1068 | .any_type, .type_expr => self.params_len, | 1166 | .any_type, .type_expr => self.params_len, |
| 1069 | .var_args => self.params_len - 1, | ||
| 1070 | }; | 1167 | }; |
| 1071 | if (i < params_len) { | 1168 | if (i < params_len) { |
| 1072 | switch (self.paramsConst()[i].param_type) { | 1169 | switch (self.paramsConst()[i].param_type) { |
| 1073 | .any_type => |n| return n, | 1170 | .any_type => |n| return n, |
| 1074 | .var_args => unreachable, | ||
| 1075 | .type_expr => |n| return n, | 1171 | .type_expr => |n| return n, |
| 1076 | } | 1172 | } |
| 1077 | } | 1173 | } |
| 1078 | i -= params_len; | 1174 | i -= params_len; |
| 1079 | 1175 | ||
| 1080 | if (self.align_expr) |align_expr| { | 1176 | if (self.getTrailer("align_expr")) |align_expr| { |
| 1081 | if (i < 1) return align_expr; | 1177 | if (i < 1) return align_expr; |
| 1082 | i -= 1; | 1178 | i -= 1; |
| 1083 | } | 1179 | } |
| 1084 | 1180 | ||
| 1085 | if (self.section_expr) |section_expr| { | 1181 | if (self.getTrailer("section_expr")) |section_expr| { |
| 1086 | if (i < 1) return section_expr; | 1182 | if (i < 1) return section_expr; |
| 1087 | i -= 1; | 1183 | i -= 1; |
| 1088 | } | 1184 | } |
| ... | @@ -1095,7 +1191,7 @@ pub const Node = struct { | ... | @@ -1095,7 +1191,7 @@ pub const Node = struct { |
| 1095 | .Invalid => {}, | 1191 | .Invalid => {}, |
| 1096 | } | 1192 | } |
| 1097 | 1193 | ||
| 1098 | if (self.body_node) |body_node| { | 1194 | if (self.getTrailer("body_node")) |body_node| { |
| 1099 | if (i < 1) return body_node; | 1195 | if (i < 1) return body_node; |
| 1100 | i -= 1; | 1196 | i -= 1; |
| 1101 | } | 1197 | } |
| ... | @@ -1104,14 +1200,14 @@ pub const Node = struct { | ... | @@ -1104,14 +1200,14 @@ pub const Node = struct { |
| 1104 | } | 1200 | } |
| 1105 | 1201 | ||
| 1106 | pub fn firstToken(self: *const FnProto) TokenIndex { | 1202 | pub fn firstToken(self: *const FnProto) TokenIndex { |
| 1107 | if (self.visib_token) |visib_token| return visib_token; | 1203 | if (self.getTrailer("visib_token")) |visib_token| return visib_token; |
| 1108 | if (self.extern_export_inline_token) |extern_export_inline_token| return extern_export_inline_token; | 1204 | if (self.getTrailer("extern_export_inline_token")) |extern_export_inline_token| return extern_export_inline_token; |
| 1109 | assert(self.lib_name == null); | 1205 | assert(self.getTrailer("lib_name") == null); |
| 1110 | return self.fn_token; | 1206 | return self.fn_token; |
| 1111 | } | 1207 | } |
| 1112 | 1208 | ||
| 1113 | pub fn lastToken(self: *const FnProto) TokenIndex { | 1209 | pub fn lastToken(self: *const FnProto) TokenIndex { |
| 1114 | if (self.body_node) |body_node| return body_node.lastToken(); | 1210 | if (self.getTrailer("body_node")) |body_node| return body_node.lastToken(); |
| 1115 | switch (self.return_type) { | 1211 | switch (self.return_type) { |
| 1116 | .Explicit, .InferErrorSet => |node| return node.lastToken(), | 1212 | .Explicit, .InferErrorSet => |node| return node.lastToken(), |
| 1117 | .Invalid => |tok| return tok, | 1213 | .Invalid => |tok| return tok, |
| ... | @@ -1119,17 +1215,17 @@ pub const Node = struct { | ... | @@ -1119,17 +1215,17 @@ pub const Node = struct { |
| 1119 | } | 1215 | } |
| 1120 | 1216 | ||
| 1121 | pub fn params(self: *FnProto) []ParamDecl { | 1217 | pub fn params(self: *FnProto) []ParamDecl { |
| 1122 | const decls_start = @ptrCast([*]u8, self) + @sizeOf(FnProto); | 1218 | const params_start = @ptrCast([*]u8, self) + @sizeOf(FnProto); |
| 1123 | return @ptrCast([*]ParamDecl, decls_start)[0..self.params_len]; | 1219 | return @ptrCast([*]ParamDecl, params_start)[0..self.params_len]; |
| 1124 | } | 1220 | } |
| 1125 | 1221 | ||
| 1126 | pub fn paramsConst(self: *const FnProto) []const ParamDecl { | 1222 | pub fn paramsConst(self: *const FnProto) []const ParamDecl { |
| 1127 | const decls_start = @ptrCast([*]const u8, self) + @sizeOf(FnProto); | 1223 | const params_start = @ptrCast([*]const u8, self) + @sizeOf(FnProto); |
| 1128 | return @ptrCast([*]const ParamDecl, decls_start)[0..self.params_len]; | 1224 | return @ptrCast([*]const ParamDecl, params_start)[0..self.params_len]; |
| 1129 | } | 1225 | } |
| 1130 | 1226 | ||
| 1131 | fn sizeInBytes(params_len: NodeIndex) usize { | 1227 | fn sizeInBytes(params_len: NodeIndex, trailer_flags: TrailerFlags) usize { |
| 1132 | return @sizeOf(FnProto) + @sizeOf(ParamDecl) * @as(usize, params_len); | 1228 | return @sizeOf(FnProto) + @sizeOf(ParamDecl) * @as(usize, params_len) + trailer_flags.sizeInBytes(); |
| 1133 | } | 1229 | } |
| 1134 | }; | 1230 | }; |
| 1135 | 1231 | ||
| ... | @@ -2829,6 +2925,9 @@ pub const Node = struct { | ... | @@ -2829,6 +2925,9 @@ pub const Node = struct { |
| 2829 | } | 2925 | } |
| 2830 | }; | 2926 | }; |
| 2831 | 2927 | ||
| 2928 | /// TODO remove from the Node base struct | ||
| 2929 | /// TODO actually maybe remove entirely in favor of iterating backward from Node.firstToken() | ||
| 2930 | /// and forwards to find same-line doc comments. | ||
| 2832 | pub const DocComment = struct { | 2931 | pub const DocComment = struct { |
| 2833 | base: Node = Node{ .id = .DocComment }, | 2932 | base: Node = Node{ .id = .DocComment }, |
| 2834 | /// Points to the first doc comment token. API users are expected to iterate over the | 2933 | /// Points to the first doc comment token. API users are expected to iterate over the |
lib/std/zig/parse.zig+92-100| ... | @@ -150,7 +150,7 @@ const Parser = struct { | ... | @@ -150,7 +150,7 @@ const Parser = struct { |
| 150 | 150 | ||
| 151 | const visib_token = p.eatToken(.Keyword_pub); | 151 | const visib_token = p.eatToken(.Keyword_pub); |
| 152 | 152 | ||
| 153 | if (p.parseTopLevelDecl() catch |err| switch (err) { | 153 | if (p.parseTopLevelDecl(doc_comments, visib_token) catch |err| switch (err) { |
| 154 | error.OutOfMemory => return error.OutOfMemory, | 154 | error.OutOfMemory => return error.OutOfMemory, |
| 155 | error.ParseError => { | 155 | error.ParseError => { |
| 156 | p.findNextContainerMember(); | 156 | p.findNextContainerMember(); |
| ... | @@ -160,30 +160,7 @@ const Parser = struct { | ... | @@ -160,30 +160,7 @@ const Parser = struct { |
| 160 | if (field_state == .seen) { | 160 | if (field_state == .seen) { |
| 161 | field_state = .{ .end = visib_token orelse node.firstToken() }; | 161 | field_state = .{ .end = visib_token orelse node.firstToken() }; |
| 162 | } | 162 | } |
| 163 | switch (node.id) { | ||
| 164 | .FnProto => { | ||
| 165 | node.cast(Node.FnProto).?.doc_comments = doc_comments; | ||
| 166 | node.cast(Node.FnProto).?.visib_token = visib_token; | ||
| 167 | }, | ||
| 168 | .VarDecl => { | ||
| 169 | node.cast(Node.VarDecl).?.doc_comments = doc_comments; | ||
| 170 | node.cast(Node.VarDecl).?.visib_token = visib_token; | ||
| 171 | }, | ||
| 172 | .Use => { | ||
| 173 | node.cast(Node.Use).?.doc_comments = doc_comments; | ||
| 174 | node.cast(Node.Use).?.visib_token = visib_token; | ||
| 175 | }, | ||
| 176 | else => unreachable, | ||
| 177 | } | ||
| 178 | try list.append(node); | 163 | try list.append(node); |
| 179 | if (try p.parseAppendedDocComment(node.lastToken())) |appended_comment| { | ||
| 180 | switch (node.id) { | ||
| 181 | .FnProto => {}, | ||
| 182 | .VarDecl => node.cast(Node.VarDecl).?.doc_comments = appended_comment, | ||
| 183 | .Use => node.cast(Node.Use).?.doc_comments = appended_comment, | ||
| 184 | else => unreachable, | ||
| 185 | } | ||
| 186 | } | ||
| 187 | continue; | 164 | continue; |
| 188 | } | 165 | } |
| 189 | 166 | ||
| ... | @@ -417,7 +394,7 @@ const Parser = struct { | ... | @@ -417,7 +394,7 @@ const Parser = struct { |
| 417 | /// <- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block) | 394 | /// <- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block) |
| 418 | /// / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl | 395 | /// / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl |
| 419 | /// / KEYWORD_usingnamespace Expr SEMICOLON | 396 | /// / KEYWORD_usingnamespace Expr SEMICOLON |
| 420 | fn parseTopLevelDecl(p: *Parser) !?*Node { | 397 | fn parseTopLevelDecl(p: *Parser, doc_comments: ?*Node.DocComment, visib_token: ?TokenIndex) !?*Node { |
| 421 | var lib_name: ?*Node = null; | 398 | var lib_name: ?*Node = null; |
| 422 | const extern_export_inline_token = blk: { | 399 | const extern_export_inline_token = blk: { |
| 423 | if (p.eatToken(.Keyword_export)) |token| break :blk token; | 400 | if (p.eatToken(.Keyword_export)) |token| break :blk token; |
| ... | @@ -430,20 +407,12 @@ const Parser = struct { | ... | @@ -430,20 +407,12 @@ const Parser = struct { |
| 430 | break :blk null; | 407 | break :blk null; |
| 431 | }; | 408 | }; |
| 432 | 409 | ||
| 433 | if (try p.parseFnProto()) |node| { | 410 | if (try p.parseFnProto(.top_level, .{ |
| 434 | const fn_node = node.cast(Node.FnProto).?; | 411 | .doc_comments = doc_comments, |
| 435 | fn_node.*.extern_export_inline_token = extern_export_inline_token; | 412 | .visib_token = visib_token, |
| 436 | fn_node.*.lib_name = lib_name; | 413 | .extern_export_inline_token = extern_export_inline_token, |
| 437 | if (p.eatToken(.Semicolon)) |_| return node; | 414 | .lib_name = lib_name, |
| 438 | 415 | })) |node| { | |
| 439 | if (try p.expectNodeRecoverable(parseBlock, .{ | ||
| 440 | // since parseBlock only return error.ParseError on | ||
| 441 | // a missing '}' we can assume this function was | ||
| 442 | // supposed to end here. | ||
| 443 | .ExpectedSemiOrLBrace = .{ .token = p.tok_i }, | ||
| 444 | })) |body_node| { | ||
| 445 | fn_node.body_node = body_node; | ||
| 446 | } | ||
| 447 | return node; | 416 | return node; |
| 448 | } | 417 | } |
| 449 | 418 | ||
| ... | @@ -460,12 +429,13 @@ const Parser = struct { | ... | @@ -460,12 +429,13 @@ const Parser = struct { |
| 460 | 429 | ||
| 461 | const thread_local_token = p.eatToken(.Keyword_threadlocal); | 430 | const thread_local_token = p.eatToken(.Keyword_threadlocal); |
| 462 | 431 | ||
| 463 | if (try p.parseVarDecl()) |node| { | 432 | if (try p.parseVarDecl(.{ |
| 464 | var var_decl = node.cast(Node.VarDecl).?; | 433 | .doc_comments = doc_comments, |
| 465 | var_decl.*.thread_local_token = thread_local_token; | 434 | .visib_token = visib_token, |
| 466 | var_decl.*.comptime_token = null; | 435 | .thread_local_token = thread_local_token, |
| 467 | var_decl.*.extern_export_token = extern_export_inline_token; | 436 | .extern_export_token = extern_export_inline_token, |
| 468 | var_decl.*.lib_name = lib_name; | 437 | .lib_name = lib_name, |
| 438 | })) |node| { | ||
| 469 | return node; | 439 | return node; |
| 470 | } | 440 | } |
| 471 | 441 | ||
| ... | @@ -485,21 +455,41 @@ const Parser = struct { | ... | @@ -485,21 +455,41 @@ const Parser = struct { |
| 485 | return error.ParseError; | 455 | return error.ParseError; |
| 486 | } | 456 | } |
| 487 | 457 | ||
| 488 | return p.parseUse(); | 458 | const use_token = p.eatToken(.Keyword_usingnamespace) orelse return null; |
| 459 | const expr = try p.expectNode(parseExpr, .{ | ||
| 460 | .ExpectedExpr = .{ .token = p.tok_i }, | ||
| 461 | }); | ||
| 462 | const semicolon_token = try p.expectToken(.Semicolon); | ||
| 463 | |||
| 464 | const node = try p.arena.allocator.create(Node.Use); | ||
| 465 | node.* = .{ | ||
| 466 | .doc_comments = doc_comments orelse try p.parseAppendedDocComment(semicolon_token), | ||
| 467 | .visib_token = visib_token, | ||
| 468 | .use_token = use_token, | ||
| 469 | .expr = expr, | ||
| 470 | .semicolon_token = semicolon_token, | ||
| 471 | }; | ||
| 472 | |||
| 473 | return &node.base; | ||
| 489 | } | 474 | } |
| 490 | 475 | ||
| 491 | /// FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (Keyword_anytype / TypeExpr) | 476 | /// FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (Keyword_anytype / TypeExpr) |
| 492 | fn parseFnProto(p: *Parser) !?*Node { | 477 | fn parseFnProto(p: *Parser, level: enum { top_level, as_type }, fields: struct { |
| 478 | doc_comments: ?*Node.DocComment = null, | ||
| 479 | visib_token: ?TokenIndex = null, | ||
| 480 | extern_export_inline_token: ?TokenIndex = null, | ||
| 481 | lib_name: ?*Node = null, | ||
| 482 | }) !?*Node { | ||
| 493 | // TODO: Remove once extern/async fn rewriting is | 483 | // TODO: Remove once extern/async fn rewriting is |
| 494 | var is_async = false; | 484 | var is_async: ?void = null; |
| 495 | var is_extern = false; | 485 | var is_extern_prototype: ?void = null; |
| 496 | const cc_token: ?TokenIndex = blk: { | 486 | const cc_token: ?TokenIndex = blk: { |
| 497 | if (p.eatToken(.Keyword_extern)) |token| { | 487 | if (p.eatToken(.Keyword_extern)) |token| { |
| 498 | is_extern = true; | 488 | is_extern_prototype = {}; |
| 499 | break :blk token; | 489 | break :blk token; |
| 500 | } | 490 | } |
| 501 | if (p.eatToken(.Keyword_async)) |token| { | 491 | if (p.eatToken(.Keyword_async)) |token| { |
| 502 | is_async = true; | 492 | is_async = {}; |
| 503 | break :blk token; | 493 | break :blk token; |
| 504 | } | 494 | } |
| 505 | break :blk null; | 495 | break :blk null; |
| ... | @@ -513,6 +503,7 @@ const Parser = struct { | ... | @@ -513,6 +503,7 @@ const Parser = struct { |
| 513 | const lparen = try p.expectToken(.LParen); | 503 | const lparen = try p.expectToken(.LParen); |
| 514 | const params = try p.parseParamDeclList(); | 504 | const params = try p.parseParamDeclList(); |
| 515 | defer p.gpa.free(params); | 505 | defer p.gpa.free(params); |
| 506 | const var_args_token = p.eatToken(.Ellipsis3); | ||
| 516 | const rparen = try p.expectToken(.RParen); | 507 | const rparen = try p.expectToken(.RParen); |
| 517 | const align_expr = try p.parseByteAlign(); | 508 | const align_expr = try p.parseByteAlign(); |
| 518 | const section_expr = try p.parseLinkSection(); | 509 | const section_expr = try p.parseLinkSection(); |
| ... | @@ -535,37 +526,53 @@ const Parser = struct { | ... | @@ -535,37 +526,53 @@ const Parser = struct { |
| 535 | else | 526 | else |
| 536 | R{ .Explicit = return_type_expr.? }; | 527 | R{ .Explicit = return_type_expr.? }; |
| 537 | 528 | ||
| 538 | const var_args_token = if (params.len > 0) blk: { | 529 | const body_node: ?*Node = switch (level) { |
| 539 | const param_type = params[params.len - 1].param_type; | 530 | .top_level => blk: { |
| 540 | break :blk if (param_type == .var_args) param_type.var_args else null; | 531 | if (p.eatToken(.Semicolon)) |_| { |
| 541 | } else | 532 | break :blk null; |
| 542 | null; | 533 | } |
| 534 | break :blk try p.expectNodeRecoverable(parseBlock, .{ | ||
| 535 | // Since parseBlock only return error.ParseError on | ||
| 536 | // a missing '}' we can assume this function was | ||
| 537 | // supposed to end here. | ||
| 538 | .ExpectedSemiOrLBrace = .{ .token = p.tok_i }, | ||
| 539 | }); | ||
| 540 | }, | ||
| 541 | .as_type => null, | ||
| 542 | }; | ||
| 543 | 543 | ||
| 544 | const fn_proto_node = try Node.FnProto.alloc(&p.arena.allocator, params.len); | 544 | const fn_proto_node = try Node.FnProto.create(&p.arena.allocator, .{ |
| 545 | fn_proto_node.* = .{ | ||
| 546 | .doc_comments = null, | ||
| 547 | .visib_token = null, | ||
| 548 | .fn_token = fn_token, | ||
| 549 | .name_token = name_token, | ||
| 550 | .params_len = params.len, | 545 | .params_len = params.len, |
| 546 | .fn_token = fn_token, | ||
| 551 | .return_type = return_type, | 547 | .return_type = return_type, |
| 548 | }, .{ | ||
| 549 | .doc_comments = fields.doc_comments, | ||
| 550 | .visib_token = fields.visib_token, | ||
| 551 | .name_token = name_token, | ||
| 552 | .var_args_token = var_args_token, | 552 | .var_args_token = var_args_token, |
| 553 | .extern_export_inline_token = null, | 553 | .extern_export_inline_token = fields.extern_export_inline_token, |
| 554 | .body_node = null, | 554 | .body_node = body_node, |
| 555 | .lib_name = null, | 555 | .lib_name = fields.lib_name, |
| 556 | .align_expr = align_expr, | 556 | .align_expr = align_expr, |
| 557 | .section_expr = section_expr, | 557 | .section_expr = section_expr, |
| 558 | .callconv_expr = callconv_expr, | 558 | .callconv_expr = callconv_expr, |
| 559 | .is_extern_prototype = is_extern, | 559 | .is_extern_prototype = is_extern_prototype, |
| 560 | .is_async = is_async, | 560 | .is_async = is_async, |
| 561 | }; | 561 | }); |
| 562 | std.mem.copy(Node.FnProto.ParamDecl, fn_proto_node.params(), params); | 562 | std.mem.copy(Node.FnProto.ParamDecl, fn_proto_node.params(), params); |
| 563 | 563 | ||
| 564 | return &fn_proto_node.base; | 564 | return &fn_proto_node.base; |
| 565 | } | 565 | } |
| 566 | 566 | ||
| 567 | /// VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON | 567 | /// VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON |
| 568 | fn parseVarDecl(p: *Parser) !?*Node { | 568 | fn parseVarDecl(p: *Parser, fields: struct { |
| 569 | doc_comments: ?*Node.DocComment = null, | ||
| 570 | visib_token: ?TokenIndex = null, | ||
| 571 | thread_local_token: ?TokenIndex = null, | ||
| 572 | extern_export_token: ?TokenIndex = null, | ||
| 573 | lib_name: ?*Node = null, | ||
| 574 | comptime_token: ?TokenIndex = null, | ||
| 575 | }) !?*Node { | ||
| 569 | const mut_token = p.eatToken(.Keyword_const) orelse | 576 | const mut_token = p.eatToken(.Keyword_const) orelse |
| 570 | p.eatToken(.Keyword_var) orelse | 577 | p.eatToken(.Keyword_var) orelse |
| 571 | return null; | 578 | return null; |
| ... | @@ -587,23 +594,25 @@ const Parser = struct { | ... | @@ -587,23 +594,25 @@ const Parser = struct { |
| 587 | } else null; | 594 | } else null; |
| 588 | const semicolon_token = try p.expectToken(.Semicolon); | 595 | const semicolon_token = try p.expectToken(.Semicolon); |
| 589 | 596 | ||
| 590 | const node = try p.arena.allocator.create(Node.VarDecl); | 597 | const doc_comments = fields.doc_comments orelse try p.parseAppendedDocComment(semicolon_token); |
| 591 | node.* = .{ | 598 | |
| 592 | .doc_comments = null, | 599 | const node = try Node.VarDecl.create(&p.arena.allocator, .{ |
| 593 | .visib_token = null, | 600 | .mut_token = mut_token, |
| 594 | .thread_local_token = null, | ||
| 595 | .name_token = name_token, | 601 | .name_token = name_token, |
| 602 | .semicolon_token = semicolon_token, | ||
| 603 | }, .{ | ||
| 604 | .doc_comments = doc_comments, | ||
| 605 | .visib_token = fields.visib_token, | ||
| 606 | .thread_local_token = fields.thread_local_token, | ||
| 596 | .eq_token = eq_token, | 607 | .eq_token = eq_token, |
| 597 | .mut_token = mut_token, | 608 | .comptime_token = fields.comptime_token, |
| 598 | .comptime_token = null, | 609 | .extern_export_token = fields.extern_export_token, |
| 599 | .extern_export_token = null, | 610 | .lib_name = fields.lib_name, |
| 600 | .lib_name = null, | ||
| 601 | .type_node = type_node, | 611 | .type_node = type_node, |
| 602 | .align_node = align_node, | 612 | .align_node = align_node, |
| 603 | .section_node = section_node, | 613 | .section_node = section_node, |
| 604 | .init_node = init_node, | 614 | .init_node = init_node, |
| 605 | .semicolon_token = semicolon_token, | 615 | }); |
| 606 | }; | ||
| 607 | return &node.base; | 616 | return &node.base; |
| 608 | } | 617 | } |
| 609 | 618 | ||
| ... | @@ -663,10 +672,9 @@ const Parser = struct { | ... | @@ -663,10 +672,9 @@ const Parser = struct { |
| 663 | fn parseStatement(p: *Parser) Error!?*Node { | 672 | fn parseStatement(p: *Parser) Error!?*Node { |
| 664 | const comptime_token = p.eatToken(.Keyword_comptime); | 673 | const comptime_token = p.eatToken(.Keyword_comptime); |
| 665 | 674 | ||
| 666 | const var_decl_node = try p.parseVarDecl(); | 675 | if (try p.parseVarDecl(.{ |
| 667 | if (var_decl_node) |node| { | 676 | .comptime_token = comptime_token, |
| 668 | const var_decl = node.cast(Node.VarDecl).?; | 677 | })) |node| { |
| 669 | var_decl.comptime_token = comptime_token; | ||
| 670 | return node; | 678 | return node; |
| 671 | } | 679 | } |
| 672 | 680 | ||
| ... | @@ -1527,7 +1535,7 @@ const Parser = struct { | ... | @@ -1527,7 +1535,7 @@ const Parser = struct { |
| 1527 | if (try p.parseAnonLiteral()) |node| return node; | 1535 | if (try p.parseAnonLiteral()) |node| return node; |
| 1528 | if (try p.parseErrorSetDecl()) |node| return node; | 1536 | if (try p.parseErrorSetDecl()) |node| return node; |
| 1529 | if (try p.parseFloatLiteral()) |node| return node; | 1537 | if (try p.parseFloatLiteral()) |node| return node; |
| 1530 | if (try p.parseFnProto()) |node| return node; | 1538 | if (try p.parseFnProto(.as_type, .{})) |node| return node; |
| 1531 | if (try p.parseGroupedExpr()) |node| return node; | 1539 | if (try p.parseGroupedExpr()) |node| return node; |
| 1532 | if (try p.parseLabeledTypeExpr()) |node| return node; | 1540 | if (try p.parseLabeledTypeExpr()) |node| return node; |
| 1533 | if (try p.parseIdentifier()) |node| return node; | 1541 | if (try p.parseIdentifier()) |node| return node; |
| ... | @@ -2028,7 +2036,6 @@ const Parser = struct { | ... | @@ -2028,7 +2036,6 @@ const Parser = struct { |
| 2028 | // TODO cast from tuple to error union is broken | 2036 | // TODO cast from tuple to error union is broken |
| 2029 | const P = Node.FnProto.ParamDecl.ParamType; | 2037 | const P = Node.FnProto.ParamDecl.ParamType; |
| 2030 | if (try p.parseAnyType()) |node| return P{ .any_type = node }; | 2038 | if (try p.parseAnyType()) |node| return P{ .any_type = node }; |
| 2031 | if (p.eatToken(.Ellipsis3)) |token| return P{ .var_args = token }; | ||
| 2032 | if (try p.parseTypeExpr()) |node| return P{ .type_expr = node }; | 2039 | if (try p.parseTypeExpr()) |node| return P{ .type_expr = node }; |
| 2033 | return null; | 2040 | return null; |
| 2034 | } | 2041 | } |
| ... | @@ -3149,21 +3156,6 @@ const Parser = struct { | ... | @@ -3149,21 +3156,6 @@ const Parser = struct { |
| 3149 | return &node.base; | 3156 | return &node.base; |
| 3150 | } | 3157 | } |
| 3151 | 3158 | ||
| 3152 | fn parseUse(p: *Parser) !?*Node { | ||
| 3153 | const token = p.eatToken(.Keyword_usingnamespace) orelse return null; | ||
| 3154 | const node = try p.arena.allocator.create(Node.Use); | ||
| 3155 | node.* = .{ | ||
| 3156 | .doc_comments = null, | ||
| 3157 | .visib_token = null, | ||
| 3158 | .use_token = token, | ||
| 3159 | .expr = try p.expectNode(parseExpr, .{ | ||
| 3160 | .ExpectedExpr = .{ .token = p.tok_i }, | ||
| 3161 | }), | ||
| 3162 | .semicolon_token = try p.expectToken(.Semicolon), | ||
| 3163 | }; | ||
| 3164 | return &node.base; | ||
| 3165 | } | ||
| 3166 | |||
| 3167 | /// IfPrefix Body (KEYWORD_else Payload? Body)? | 3159 | /// IfPrefix Body (KEYWORD_else Payload? Body)? |
| 3168 | fn parseIf(p: *Parser, bodyParseFn: NodeParseFn) !?*Node { | 3160 | fn parseIf(p: *Parser, bodyParseFn: NodeParseFn) !?*Node { |
| 3169 | const node = (try p.parseIfPrefix()) orelse return null; | 3161 | const node = (try p.parseIfPrefix()) orelse return null; |
lib/std/zig/parser_test.zig+32-27| ... | @@ -1,4 +1,32 @@ | ... | @@ -1,4 +1,32 @@ |
| 1 | const builtin = @import("builtin"); | 1 | test "zig fmt: convert var to anytype" { |
| 2 | // TODO remove in next release cycle | ||
| 3 | try testTransform( | ||
| 4 | \\pub fn main( | ||
| 5 | \\ a: var, | ||
| 6 | \\ bar: var, | ||
| 7 | \\) void {} | ||
| 8 | , | ||
| 9 | \\pub fn main( | ||
| 10 | \\ a: anytype, | ||
| 11 | \\ bar: anytype, | ||
| 12 | \\) void {} | ||
| 13 | \\ | ||
| 14 | ); | ||
| 15 | } | ||
| 16 | |||
| 17 | test "zig fmt: noasync to nosuspend" { | ||
| 18 | // TODO: remove this | ||
| 19 | try testTransform( | ||
| 20 | \\pub fn main() void { | ||
| 21 | \\ noasync call(); | ||
| 22 | \\} | ||
| 23 | , | ||
| 24 | \\pub fn main() void { | ||
| 25 | \\ nosuspend call(); | ||
| 26 | \\} | ||
| 27 | \\ | ||
| 28 | ); | ||
| 29 | } | ||
| 2 | 30 | ||
| 3 | test "recovery: top level" { | 31 | test "recovery: top level" { |
| 4 | try testError( | 32 | try testError( |
| ... | @@ -3146,20 +3174,6 @@ test "zig fmt: hexadeciaml float literals with underscore separators" { | ... | @@ -3146,20 +3174,6 @@ test "zig fmt: hexadeciaml float literals with underscore separators" { |
| 3146 | ); | 3174 | ); |
| 3147 | } | 3175 | } |
| 3148 | 3176 | ||
| 3149 | test "zig fmt: noasync to nosuspend" { | ||
| 3150 | // TODO: remove this | ||
| 3151 | try testTransform( | ||
| 3152 | \\pub fn main() void { | ||
| 3153 | \\ noasync call(); | ||
| 3154 | \\} | ||
| 3155 | , | ||
| 3156 | \\pub fn main() void { | ||
| 3157 | \\ nosuspend call(); | ||
| 3158 | \\} | ||
| 3159 | \\ | ||
| 3160 | ); | ||
| 3161 | } | ||
| 3162 | |||
| 3163 | test "zig fmt: convert async fn into callconv(.Async)" { | 3177 | test "zig fmt: convert async fn into callconv(.Async)" { |
| 3164 | try testTransform( | 3178 | try testTransform( |
| 3165 | \\async fn foo() void {} | 3179 | \\async fn foo() void {} |
| ... | @@ -3180,18 +3194,9 @@ test "zig fmt: convert extern fn proto into callconv(.C)" { | ... | @@ -3180,18 +3194,9 @@ test "zig fmt: convert extern fn proto into callconv(.C)" { |
| 3180 | ); | 3194 | ); |
| 3181 | } | 3195 | } |
| 3182 | 3196 | ||
| 3183 | test "zig fmt: convert var to anytype" { | 3197 | test "zig fmt: C var args" { |
| 3184 | // TODO remove in next release cycle | 3198 | try testCanonical( |
| 3185 | try testTransform( | 3199 | \\pub extern "c" fn printf(format: [*:0]const u8, ...) c_int; |
| 3186 | \\pub fn main( | ||
| 3187 | \\ a: var, | ||
| 3188 | \\ bar: var, | ||
| 3189 | \\) void {} | ||
| 3190 | , | ||
| 3191 | \\pub fn main( | ||
| 3192 | \\ a: anytype, | ||
| 3193 | \\ bar: anytype, | ||
| 3194 | \\) void {} | ||
| 3195 | \\ | 3200 | \\ |
| 3196 | ); | 3201 | ); |
| 3197 | } | 3202 | } |
lib/std/zig/render.zig+52-40| ... | @@ -227,9 +227,9 @@ fn renderContainerDecl(allocator: *mem.Allocator, stream: anytype, tree: *ast.Tr | ... | @@ -227,9 +227,9 @@ fn renderContainerDecl(allocator: *mem.Allocator, stream: anytype, tree: *ast.Tr |
| 227 | .FnProto => { | 227 | .FnProto => { |
| 228 | const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl); | 228 | const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl); |
| 229 | 229 | ||
| 230 | try renderDocComments(tree, stream, fn_proto, indent, start_col); | 230 | try renderDocComments(tree, stream, fn_proto, fn_proto.getTrailer("doc_comments"), indent, start_col); |
| 231 | 231 | ||
| 232 | if (fn_proto.body_node) |body_node| { | 232 | if (fn_proto.getTrailer("body_node")) |body_node| { |
| 233 | try renderExpression(allocator, stream, tree, indent, start_col, decl, .Space); | 233 | try renderExpression(allocator, stream, tree, indent, start_col, decl, .Space); |
| 234 | try renderExpression(allocator, stream, tree, indent, start_col, body_node, space); | 234 | try renderExpression(allocator, stream, tree, indent, start_col, body_node, space); |
| 235 | } else { | 235 | } else { |
| ... | @@ -252,14 +252,14 @@ fn renderContainerDecl(allocator: *mem.Allocator, stream: anytype, tree: *ast.Tr | ... | @@ -252,14 +252,14 @@ fn renderContainerDecl(allocator: *mem.Allocator, stream: anytype, tree: *ast.Tr |
| 252 | .VarDecl => { | 252 | .VarDecl => { |
| 253 | const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", decl); | 253 | const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", decl); |
| 254 | 254 | ||
| 255 | try renderDocComments(tree, stream, var_decl, indent, start_col); | 255 | try renderDocComments(tree, stream, var_decl, var_decl.getTrailer("doc_comments"), indent, start_col); |
| 256 | try renderVarDecl(allocator, stream, tree, indent, start_col, var_decl); | 256 | try renderVarDecl(allocator, stream, tree, indent, start_col, var_decl); |
| 257 | }, | 257 | }, |
| 258 | 258 | ||
| 259 | .TestDecl => { | 259 | .TestDecl => { |
| 260 | const test_decl = @fieldParentPtr(ast.Node.TestDecl, "base", decl); | 260 | const test_decl = @fieldParentPtr(ast.Node.TestDecl, "base", decl); |
| 261 | 261 | ||
| 262 | try renderDocComments(tree, stream, test_decl, indent, start_col); | 262 | try renderDocComments(tree, stream, test_decl, test_decl.doc_comments, indent, start_col); |
| 263 | try renderToken(tree, stream, test_decl.test_token, indent, start_col, .Space); | 263 | try renderToken(tree, stream, test_decl.test_token, indent, start_col, .Space); |
| 264 | try renderExpression(allocator, stream, tree, indent, start_col, test_decl.name, .Space); | 264 | try renderExpression(allocator, stream, tree, indent, start_col, test_decl.name, .Space); |
| 265 | try renderExpression(allocator, stream, tree, indent, start_col, test_decl.body_node, space); | 265 | try renderExpression(allocator, stream, tree, indent, start_col, test_decl.body_node, space); |
| ... | @@ -268,7 +268,7 @@ fn renderContainerDecl(allocator: *mem.Allocator, stream: anytype, tree: *ast.Tr | ... | @@ -268,7 +268,7 @@ fn renderContainerDecl(allocator: *mem.Allocator, stream: anytype, tree: *ast.Tr |
| 268 | .ContainerField => { | 268 | .ContainerField => { |
| 269 | const field = @fieldParentPtr(ast.Node.ContainerField, "base", decl); | 269 | const field = @fieldParentPtr(ast.Node.ContainerField, "base", decl); |
| 270 | 270 | ||
| 271 | try renderDocComments(tree, stream, field, indent, start_col); | 271 | try renderDocComments(tree, stream, field, field.doc_comments, indent, start_col); |
| 272 | if (field.comptime_token) |t| { | 272 | if (field.comptime_token) |t| { |
| 273 | try renderToken(tree, stream, t, indent, start_col, .Space); // comptime | 273 | try renderToken(tree, stream, t, indent, start_col, .Space); // comptime |
| 274 | } | 274 | } |
| ... | @@ -1409,7 +1409,7 @@ fn renderExpression( | ... | @@ -1409,7 +1409,7 @@ fn renderExpression( |
| 1409 | .ErrorTag => { | 1409 | .ErrorTag => { |
| 1410 | const tag = @fieldParentPtr(ast.Node.ErrorTag, "base", base); | 1410 | const tag = @fieldParentPtr(ast.Node.ErrorTag, "base", base); |
| 1411 | 1411 | ||
| 1412 | try renderDocComments(tree, stream, tag, indent, start_col); | 1412 | try renderDocComments(tree, stream, tag, tag.doc_comments, indent, start_col); |
| 1413 | return renderToken(tree, stream, tag.name_token, indent, start_col, space); // name | 1413 | return renderToken(tree, stream, tag.name_token, indent, start_col, space); // name |
| 1414 | }, | 1414 | }, |
| 1415 | 1415 | ||
| ... | @@ -1483,23 +1483,23 @@ fn renderExpression( | ... | @@ -1483,23 +1483,23 @@ fn renderExpression( |
| 1483 | .FnProto => { | 1483 | .FnProto => { |
| 1484 | const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", base); | 1484 | const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", base); |
| 1485 | 1485 | ||
| 1486 | if (fn_proto.visib_token) |visib_token_index| { | 1486 | if (fn_proto.getTrailer("visib_token")) |visib_token_index| { |
| 1487 | const visib_token = tree.token_ids[visib_token_index]; | 1487 | const visib_token = tree.token_ids[visib_token_index]; |
| 1488 | assert(visib_token == .Keyword_pub or visib_token == .Keyword_export); | 1488 | assert(visib_token == .Keyword_pub or visib_token == .Keyword_export); |
| 1489 | 1489 | ||
| 1490 | try renderToken(tree, stream, visib_token_index, indent, start_col, Space.Space); // pub | 1490 | try renderToken(tree, stream, visib_token_index, indent, start_col, Space.Space); // pub |
| 1491 | } | 1491 | } |
| 1492 | 1492 | ||
| 1493 | if (fn_proto.extern_export_inline_token) |extern_export_inline_token| { | 1493 | if (fn_proto.getTrailer("extern_export_inline_token")) |extern_export_inline_token| { |
| 1494 | if (!fn_proto.is_extern_prototype) | 1494 | if (fn_proto.getTrailer("is_extern_prototype") == null) |
| 1495 | try renderToken(tree, stream, extern_export_inline_token, indent, start_col, Space.Space); // extern/export/inline | 1495 | try renderToken(tree, stream, extern_export_inline_token, indent, start_col, Space.Space); // extern/export/inline |
| 1496 | } | 1496 | } |
| 1497 | 1497 | ||
| 1498 | if (fn_proto.lib_name) |lib_name| { | 1498 | if (fn_proto.getTrailer("lib_name")) |lib_name| { |
| 1499 | try renderExpression(allocator, stream, tree, indent, start_col, lib_name, Space.Space); | 1499 | try renderExpression(allocator, stream, tree, indent, start_col, lib_name, Space.Space); |
| 1500 | } | 1500 | } |
| 1501 | 1501 | ||
| 1502 | const lparen = if (fn_proto.name_token) |name_token| blk: { | 1502 | const lparen = if (fn_proto.getTrailer("name_token")) |name_token| blk: { |
| 1503 | try renderToken(tree, stream, fn_proto.fn_token, indent, start_col, Space.Space); // fn | 1503 | try renderToken(tree, stream, fn_proto.fn_token, indent, start_col, Space.Space); // fn |
| 1504 | try renderToken(tree, stream, name_token, indent, start_col, Space.None); // name | 1504 | try renderToken(tree, stream, name_token, indent, start_col, Space.None); // name |
| 1505 | break :blk tree.nextToken(name_token); | 1505 | break :blk tree.nextToken(name_token); |
| ... | @@ -1512,11 +1512,11 @@ fn renderExpression( | ... | @@ -1512,11 +1512,11 @@ fn renderExpression( |
| 1512 | const rparen = tree.prevToken( | 1512 | const rparen = tree.prevToken( |
| 1513 | // the first token for the annotation expressions is the left | 1513 | // the first token for the annotation expressions is the left |
| 1514 | // parenthesis, hence the need for two prevToken | 1514 | // parenthesis, hence the need for two prevToken |
| 1515 | if (fn_proto.align_expr) |align_expr| | 1515 | if (fn_proto.getTrailer("align_expr")) |align_expr| |
| 1516 | tree.prevToken(tree.prevToken(align_expr.firstToken())) | 1516 | tree.prevToken(tree.prevToken(align_expr.firstToken())) |
| 1517 | else if (fn_proto.section_expr) |section_expr| | 1517 | else if (fn_proto.getTrailer("section_expr")) |section_expr| |
| 1518 | tree.prevToken(tree.prevToken(section_expr.firstToken())) | 1518 | tree.prevToken(tree.prevToken(section_expr.firstToken())) |
| 1519 | else if (fn_proto.callconv_expr) |callconv_expr| | 1519 | else if (fn_proto.getTrailer("callconv_expr")) |callconv_expr| |
| 1520 | tree.prevToken(tree.prevToken(callconv_expr.firstToken())) | 1520 | tree.prevToken(tree.prevToken(callconv_expr.firstToken())) |
| 1521 | else switch (fn_proto.return_type) { | 1521 | else switch (fn_proto.return_type) { |
| 1522 | .Explicit => |node| node.firstToken(), | 1522 | .Explicit => |node| node.firstToken(), |
| ... | @@ -1537,11 +1537,14 @@ fn renderExpression( | ... | @@ -1537,11 +1537,14 @@ fn renderExpression( |
| 1537 | for (fn_proto.params()) |param_decl, i| { | 1537 | for (fn_proto.params()) |param_decl, i| { |
| 1538 | try renderParamDecl(allocator, stream, tree, indent, start_col, param_decl, Space.None); | 1538 | try renderParamDecl(allocator, stream, tree, indent, start_col, param_decl, Space.None); |
| 1539 | 1539 | ||
| 1540 | if (i + 1 < fn_proto.params_len) { | 1540 | if (i + 1 < fn_proto.params_len or fn_proto.getTrailer("var_args_token") != null) { |
| 1541 | const comma = tree.nextToken(param_decl.lastToken()); | 1541 | const comma = tree.nextToken(param_decl.lastToken()); |
| 1542 | try renderToken(tree, stream, comma, indent, start_col, Space.Space); // , | 1542 | try renderToken(tree, stream, comma, indent, start_col, Space.Space); // , |
| 1543 | } | 1543 | } |
| 1544 | } | 1544 | } |
| 1545 | if (fn_proto.getTrailer("var_args_token")) |var_args_token| { | ||
| 1546 | try renderToken(tree, stream, var_args_token, indent, start_col, Space.None); | ||
| 1547 | } | ||
| 1545 | } else { | 1548 | } else { |
| 1546 | // one param per line | 1549 | // one param per line |
| 1547 | const new_indent = indent + indent_delta; | 1550 | const new_indent = indent + indent_delta; |
| ... | @@ -1551,12 +1554,16 @@ fn renderExpression( | ... | @@ -1551,12 +1554,16 @@ fn renderExpression( |
| 1551 | try stream.writeByteNTimes(' ', new_indent); | 1554 | try stream.writeByteNTimes(' ', new_indent); |
| 1552 | try renderParamDecl(allocator, stream, tree, new_indent, start_col, param_decl, Space.Comma); | 1555 | try renderParamDecl(allocator, stream, tree, new_indent, start_col, param_decl, Space.Comma); |
| 1553 | } | 1556 | } |
| 1557 | if (fn_proto.getTrailer("var_args_token")) |var_args_token| { | ||
| 1558 | try stream.writeByteNTimes(' ', new_indent); | ||
| 1559 | try renderToken(tree, stream, var_args_token, new_indent, start_col, Space.Comma); | ||
| 1560 | } | ||
| 1554 | try stream.writeByteNTimes(' ', indent); | 1561 | try stream.writeByteNTimes(' ', indent); |
| 1555 | } | 1562 | } |
| 1556 | 1563 | ||
| 1557 | try renderToken(tree, stream, rparen, indent, start_col, Space.Space); // ) | 1564 | try renderToken(tree, stream, rparen, indent, start_col, Space.Space); // ) |
| 1558 | 1565 | ||
| 1559 | if (fn_proto.align_expr) |align_expr| { | 1566 | if (fn_proto.getTrailer("align_expr")) |align_expr| { |
| 1560 | const align_rparen = tree.nextToken(align_expr.lastToken()); | 1567 | const align_rparen = tree.nextToken(align_expr.lastToken()); |
| 1561 | const align_lparen = tree.prevToken(align_expr.firstToken()); | 1568 | const align_lparen = tree.prevToken(align_expr.firstToken()); |
| 1562 | const align_kw = tree.prevToken(align_lparen); | 1569 | const align_kw = tree.prevToken(align_lparen); |
| ... | @@ -1567,7 +1574,7 @@ fn renderExpression( | ... | @@ -1567,7 +1574,7 @@ fn renderExpression( |
| 1567 | try renderToken(tree, stream, align_rparen, indent, start_col, Space.Space); // ) | 1574 | try renderToken(tree, stream, align_rparen, indent, start_col, Space.Space); // ) |
| 1568 | } | 1575 | } |
| 1569 | 1576 | ||
| 1570 | if (fn_proto.section_expr) |section_expr| { | 1577 | if (fn_proto.getTrailer("section_expr")) |section_expr| { |
| 1571 | const section_rparen = tree.nextToken(section_expr.lastToken()); | 1578 | const section_rparen = tree.nextToken(section_expr.lastToken()); |
| 1572 | const section_lparen = tree.prevToken(section_expr.firstToken()); | 1579 | const section_lparen = tree.prevToken(section_expr.firstToken()); |
| 1573 | const section_kw = tree.prevToken(section_lparen); | 1580 | const section_kw = tree.prevToken(section_lparen); |
| ... | @@ -1578,7 +1585,7 @@ fn renderExpression( | ... | @@ -1578,7 +1585,7 @@ fn renderExpression( |
| 1578 | try renderToken(tree, stream, section_rparen, indent, start_col, Space.Space); // ) | 1585 | try renderToken(tree, stream, section_rparen, indent, start_col, Space.Space); // ) |
| 1579 | } | 1586 | } |
| 1580 | 1587 | ||
| 1581 | if (fn_proto.callconv_expr) |callconv_expr| { | 1588 | if (fn_proto.getTrailer("callconv_expr")) |callconv_expr| { |
| 1582 | const callconv_rparen = tree.nextToken(callconv_expr.lastToken()); | 1589 | const callconv_rparen = tree.nextToken(callconv_expr.lastToken()); |
| 1583 | const callconv_lparen = tree.prevToken(callconv_expr.firstToken()); | 1590 | const callconv_lparen = tree.prevToken(callconv_expr.firstToken()); |
| 1584 | const callconv_kw = tree.prevToken(callconv_lparen); | 1591 | const callconv_kw = tree.prevToken(callconv_lparen); |
| ... | @@ -1587,9 +1594,9 @@ fn renderExpression( | ... | @@ -1587,9 +1594,9 @@ fn renderExpression( |
| 1587 | try renderToken(tree, stream, callconv_lparen, indent, start_col, Space.None); // ( | 1594 | try renderToken(tree, stream, callconv_lparen, indent, start_col, Space.None); // ( |
| 1588 | try renderExpression(allocator, stream, tree, indent, start_col, callconv_expr, Space.None); | 1595 | try renderExpression(allocator, stream, tree, indent, start_col, callconv_expr, Space.None); |
| 1589 | try renderToken(tree, stream, callconv_rparen, indent, start_col, Space.Space); // ) | 1596 | try renderToken(tree, stream, callconv_rparen, indent, start_col, Space.Space); // ) |
| 1590 | } else if (fn_proto.is_extern_prototype) { | 1597 | } else if (fn_proto.getTrailer("is_extern_prototype") != null) { |
| 1591 | try stream.writeAll("callconv(.C) "); | 1598 | try stream.writeAll("callconv(.C) "); |
| 1592 | } else if (fn_proto.is_async) { | 1599 | } else if (fn_proto.getTrailer("is_async") != null) { |
| 1593 | try stream.writeAll("callconv(.Async) "); | 1600 | try stream.writeAll("callconv(.Async) "); |
| 1594 | } | 1601 | } |
| 1595 | 1602 | ||
| ... | @@ -2177,64 +2184,69 @@ fn renderVarDecl( | ... | @@ -2177,64 +2184,69 @@ fn renderVarDecl( |
| 2177 | start_col: *usize, | 2184 | start_col: *usize, |
| 2178 | var_decl: *ast.Node.VarDecl, | 2185 | var_decl: *ast.Node.VarDecl, |
| 2179 | ) (@TypeOf(stream).Error || Error)!void { | 2186 | ) (@TypeOf(stream).Error || Error)!void { |
| 2180 | if (var_decl.visib_token) |visib_token| { | 2187 | if (var_decl.getTrailer("visib_token")) |visib_token| { |
| 2181 | try renderToken(tree, stream, visib_token, indent, start_col, Space.Space); // pub | 2188 | try renderToken(tree, stream, visib_token, indent, start_col, Space.Space); // pub |
| 2182 | } | 2189 | } |
| 2183 | 2190 | ||
| 2184 | if (var_decl.extern_export_token) |extern_export_token| { | 2191 | if (var_decl.getTrailer("extern_export_token")) |extern_export_token| { |
| 2185 | try renderToken(tree, stream, extern_export_token, indent, start_col, Space.Space); // extern | 2192 | try renderToken(tree, stream, extern_export_token, indent, start_col, Space.Space); // extern |
| 2186 | 2193 | ||
| 2187 | if (var_decl.lib_name) |lib_name| { | 2194 | if (var_decl.getTrailer("lib_name")) |lib_name| { |
| 2188 | try renderExpression(allocator, stream, tree, indent, start_col, lib_name, Space.Space); // "lib" | 2195 | try renderExpression(allocator, stream, tree, indent, start_col, lib_name, Space.Space); // "lib" |
| 2189 | } | 2196 | } |
| 2190 | } | 2197 | } |
| 2191 | 2198 | ||
| 2192 | if (var_decl.comptime_token) |comptime_token| { | 2199 | if (var_decl.getTrailer("comptime_token")) |comptime_token| { |
| 2193 | try renderToken(tree, stream, comptime_token, indent, start_col, Space.Space); // comptime | 2200 | try renderToken(tree, stream, comptime_token, indent, start_col, Space.Space); // comptime |
| 2194 | } | 2201 | } |
| 2195 | 2202 | ||
| 2196 | if (var_decl.thread_local_token) |thread_local_token| { | 2203 | if (var_decl.getTrailer("thread_local_token")) |thread_local_token| { |
| 2197 | try renderToken(tree, stream, thread_local_token, indent, start_col, Space.Space); // threadlocal | 2204 | try renderToken(tree, stream, thread_local_token, indent, start_col, Space.Space); // threadlocal |
| 2198 | } | 2205 | } |
| 2199 | try renderToken(tree, stream, var_decl.mut_token, indent, start_col, Space.Space); // var | 2206 | try renderToken(tree, stream, var_decl.mut_token, indent, start_col, Space.Space); // var |
| 2200 | 2207 | ||
| 2201 | const name_space = if (var_decl.type_node == null and (var_decl.align_node != null or | 2208 | const name_space = if (var_decl.getTrailer("type_node") == null and |
| 2202 | var_decl.section_node != null or var_decl.init_node != null)) Space.Space else Space.None; | 2209 | (var_decl.getTrailer("align_node") != null or |
| 2210 | var_decl.getTrailer("section_node") != null or | ||
| 2211 | var_decl.getTrailer("init_node") != null)) | ||
| 2212 | Space.Space | ||
| 2213 | else | ||
| 2214 | Space.None; | ||
| 2203 | try renderToken(tree, stream, var_decl.name_token, indent, start_col, name_space); | 2215 | try renderToken(tree, stream, var_decl.name_token, indent, start_col, name_space); |
| 2204 | 2216 | ||
| 2205 | if (var_decl.type_node) |type_node| { | 2217 | if (var_decl.getTrailer("type_node")) |type_node| { |
| 2206 | try renderToken(tree, stream, tree.nextToken(var_decl.name_token), indent, start_col, Space.Space); | 2218 | try renderToken(tree, stream, tree.nextToken(var_decl.name_token), indent, start_col, Space.Space); |
| 2207 | const s = if (var_decl.align_node != null or | 2219 | const s = if (var_decl.getTrailer("align_node") != null or |
| 2208 | var_decl.section_node != null or | 2220 | var_decl.getTrailer("section_node") != null or |
| 2209 | var_decl.init_node != null) Space.Space else Space.None; | 2221 | var_decl.getTrailer("init_node") != null) Space.Space else Space.None; |
| 2210 | try renderExpression(allocator, stream, tree, indent, start_col, type_node, s); | 2222 | try renderExpression(allocator, stream, tree, indent, start_col, type_node, s); |
| 2211 | } | 2223 | } |
| 2212 | 2224 | ||
| 2213 | if (var_decl.align_node) |align_node| { | 2225 | if (var_decl.getTrailer("align_node")) |align_node| { |
| 2214 | const lparen = tree.prevToken(align_node.firstToken()); | 2226 | const lparen = tree.prevToken(align_node.firstToken()); |
| 2215 | const align_kw = tree.prevToken(lparen); | 2227 | const align_kw = tree.prevToken(lparen); |
| 2216 | const rparen = tree.nextToken(align_node.lastToken()); | 2228 | const rparen = tree.nextToken(align_node.lastToken()); |
| 2217 | try renderToken(tree, stream, align_kw, indent, start_col, Space.None); // align | 2229 | try renderToken(tree, stream, align_kw, indent, start_col, Space.None); // align |
| 2218 | try renderToken(tree, stream, lparen, indent, start_col, Space.None); // ( | 2230 | try renderToken(tree, stream, lparen, indent, start_col, Space.None); // ( |
| 2219 | try renderExpression(allocator, stream, tree, indent, start_col, align_node, Space.None); | 2231 | try renderExpression(allocator, stream, tree, indent, start_col, align_node, Space.None); |
| 2220 | const s = if (var_decl.section_node != null or var_decl.init_node != null) Space.Space else Space.None; | 2232 | const s = if (var_decl.getTrailer("section_node") != null or var_decl.getTrailer("init_node") != null) Space.Space else Space.None; |
| 2221 | try renderToken(tree, stream, rparen, indent, start_col, s); // ) | 2233 | try renderToken(tree, stream, rparen, indent, start_col, s); // ) |
| 2222 | } | 2234 | } |
| 2223 | 2235 | ||
| 2224 | if (var_decl.section_node) |section_node| { | 2236 | if (var_decl.getTrailer("section_node")) |section_node| { |
| 2225 | const lparen = tree.prevToken(section_node.firstToken()); | 2237 | const lparen = tree.prevToken(section_node.firstToken()); |
| 2226 | const section_kw = tree.prevToken(lparen); | 2238 | const section_kw = tree.prevToken(lparen); |
| 2227 | const rparen = tree.nextToken(section_node.lastToken()); | 2239 | const rparen = tree.nextToken(section_node.lastToken()); |
| 2228 | try renderToken(tree, stream, section_kw, indent, start_col, Space.None); // linksection | 2240 | try renderToken(tree, stream, section_kw, indent, start_col, Space.None); // linksection |
| 2229 | try renderToken(tree, stream, lparen, indent, start_col, Space.None); // ( | 2241 | try renderToken(tree, stream, lparen, indent, start_col, Space.None); // ( |
| 2230 | try renderExpression(allocator, stream, tree, indent, start_col, section_node, Space.None); | 2242 | try renderExpression(allocator, stream, tree, indent, start_col, section_node, Space.None); |
| 2231 | const s = if (var_decl.init_node != null) Space.Space else Space.None; | 2243 | const s = if (var_decl.getTrailer("init_node") != null) Space.Space else Space.None; |
| 2232 | try renderToken(tree, stream, rparen, indent, start_col, s); // ) | 2244 | try renderToken(tree, stream, rparen, indent, start_col, s); // ) |
| 2233 | } | 2245 | } |
| 2234 | 2246 | ||
| 2235 | if (var_decl.init_node) |init_node| { | 2247 | if (var_decl.getTrailer("init_node")) |init_node| { |
| 2236 | const s = if (init_node.id == .MultilineStringLiteral) Space.None else Space.Space; | 2248 | const s = if (init_node.id == .MultilineStringLiteral) Space.None else Space.Space; |
| 2237 | try renderToken(tree, stream, var_decl.eq_token.?, indent, start_col, s); // = | 2249 | try renderToken(tree, stream, var_decl.getTrailer("eq_token").?, indent, start_col, s); // = |
| 2238 | try renderExpression(allocator, stream, tree, indent, start_col, init_node, Space.None); | 2250 | try renderExpression(allocator, stream, tree, indent, start_col, init_node, Space.None); |
| 2239 | } | 2251 | } |
| 2240 | 2252 | ||
| ... | @@ -2250,7 +2262,7 @@ fn renderParamDecl( | ... | @@ -2250,7 +2262,7 @@ fn renderParamDecl( |
| 2250 | param_decl: ast.Node.FnProto.ParamDecl, | 2262 | param_decl: ast.Node.FnProto.ParamDecl, |
| 2251 | space: Space, | 2263 | space: Space, |
| 2252 | ) (@TypeOf(stream).Error || Error)!void { | 2264 | ) (@TypeOf(stream).Error || Error)!void { |
| 2253 | try renderDocComments(tree, stream, param_decl, indent, start_col); | 2265 | try renderDocComments(tree, stream, param_decl, param_decl.doc_comments, indent, start_col); |
| 2254 | 2266 | ||
| 2255 | if (param_decl.comptime_token) |comptime_token| { | 2267 | if (param_decl.comptime_token) |comptime_token| { |
| 2256 | try renderToken(tree, stream, comptime_token, indent, start_col, Space.Space); | 2268 | try renderToken(tree, stream, comptime_token, indent, start_col, Space.Space); |
| ... | @@ -2263,7 +2275,6 @@ fn renderParamDecl( | ... | @@ -2263,7 +2275,6 @@ fn renderParamDecl( |
| 2263 | try renderToken(tree, stream, tree.nextToken(name_token), indent, start_col, Space.Space); // : | 2275 | try renderToken(tree, stream, tree.nextToken(name_token), indent, start_col, Space.Space); // : |
| 2264 | } | 2276 | } |
| 2265 | switch (param_decl.param_type) { | 2277 | switch (param_decl.param_type) { |
| 2266 | .var_args => |token| try renderToken(tree, stream, token, indent, start_col, space), | ||
| 2267 | .any_type, .type_expr => |node| try renderExpression(allocator, stream, tree, indent, start_col, node, space), | 2278 | .any_type, .type_expr => |node| try renderExpression(allocator, stream, tree, indent, start_col, node, space), |
| 2268 | } | 2279 | } |
| 2269 | } | 2280 | } |
| ... | @@ -2519,10 +2530,11 @@ fn renderDocComments( | ... | @@ -2519,10 +2530,11 @@ fn renderDocComments( |
| 2519 | tree: *ast.Tree, | 2530 | tree: *ast.Tree, |
| 2520 | stream: anytype, | 2531 | stream: anytype, |
| 2521 | node: anytype, | 2532 | node: anytype, |
| 2533 | doc_comments: ?*ast.Node.DocComment, | ||
| 2522 | indent: usize, | 2534 | indent: usize, |
| 2523 | start_col: *usize, | 2535 | start_col: *usize, |
| 2524 | ) (@TypeOf(stream).Error || Error)!void { | 2536 | ) (@TypeOf(stream).Error || Error)!void { |
| 2525 | const comment = node.doc_comments orelse return; | 2537 | const comment = doc_comments orelse return; |
| 2526 | return renderDocCommentsToken(tree, stream, comment, node.firstToken(), indent, start_col); | 2538 | return renderDocCommentsToken(tree, stream, comment, node.firstToken(), indent, start_col); |
| 2527 | } | 2539 | } |
| 2528 | 2540 |
src-self-hosted/Module.zig+12-10| ... | @@ -1130,7 +1130,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { | ... | @@ -1130,7 +1130,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1130 | }; | 1130 | }; |
| 1131 | defer fn_type_scope.instructions.deinit(self.gpa); | 1131 | defer fn_type_scope.instructions.deinit(self.gpa); |
| 1132 | 1132 | ||
| 1133 | const body_node = fn_proto.body_node orelse | 1133 | const body_node = fn_proto.getTrailer("body_node") orelse |
| 1134 | return self.failTok(&fn_type_scope.base, fn_proto.fn_token, "TODO implement extern functions", .{}); | 1134 | return self.failTok(&fn_type_scope.base, fn_proto.fn_token, "TODO implement extern functions", .{}); |
| 1135 | 1135 | ||
| 1136 | const param_decls = fn_proto.params(); | 1136 | const param_decls = fn_proto.params(); |
| ... | @@ -1138,21 +1138,23 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { | ... | @@ -1138,21 +1138,23 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1138 | for (param_decls) |param_decl, i| { | 1138 | for (param_decls) |param_decl, i| { |
| 1139 | const param_type_node = switch (param_decl.param_type) { | 1139 | const param_type_node = switch (param_decl.param_type) { |
| 1140 | .any_type => |node| return self.failNode(&fn_type_scope.base, node, "TODO implement anytype parameter", .{}), | 1140 | .any_type => |node| return self.failNode(&fn_type_scope.base, node, "TODO implement anytype parameter", .{}), |
| 1141 | .var_args => |tok| return self.failTok(&fn_type_scope.base, tok, "TODO implement var args", .{}), | ||
| 1142 | .type_expr => |node| node, | 1141 | .type_expr => |node| node, |
| 1143 | }; | 1142 | }; |
| 1144 | param_types[i] = try self.astGenExpr(&fn_type_scope.base, param_type_node); | 1143 | param_types[i] = try self.astGenExpr(&fn_type_scope.base, param_type_node); |
| 1145 | } | 1144 | } |
| 1146 | if (fn_proto.lib_name) |lib_name| { | 1145 | if (fn_proto.getTrailer("var_args_token")) |var_args_token| { |
| 1146 | return self.failTok(&fn_type_scope.base, var_args_token, "TODO implement var args", .{}); | ||
| 1147 | } | ||
| 1148 | if (fn_proto.getTrailer("lib_name")) |lib_name| { | ||
| 1147 | return self.failNode(&fn_type_scope.base, lib_name, "TODO implement function library name", .{}); | 1149 | return self.failNode(&fn_type_scope.base, lib_name, "TODO implement function library name", .{}); |
| 1148 | } | 1150 | } |
| 1149 | if (fn_proto.align_expr) |align_expr| { | 1151 | if (fn_proto.getTrailer("align_expr")) |align_expr| { |
| 1150 | return self.failNode(&fn_type_scope.base, align_expr, "TODO implement function align expression", .{}); | 1152 | return self.failNode(&fn_type_scope.base, align_expr, "TODO implement function align expression", .{}); |
| 1151 | } | 1153 | } |
| 1152 | if (fn_proto.section_expr) |sect_expr| { | 1154 | if (fn_proto.getTrailer("section_expr")) |sect_expr| { |
| 1153 | return self.failNode(&fn_type_scope.base, sect_expr, "TODO implement function section expression", .{}); | 1155 | return self.failNode(&fn_type_scope.base, sect_expr, "TODO implement function section expression", .{}); |
| 1154 | } | 1156 | } |
| 1155 | if (fn_proto.callconv_expr) |callconv_expr| { | 1157 | if (fn_proto.getTrailer("callconv_expr")) |callconv_expr| { |
| 1156 | return self.failNode( | 1158 | return self.failNode( |
| 1157 | &fn_type_scope.base, | 1159 | &fn_type_scope.base, |
| 1158 | callconv_expr, | 1160 | callconv_expr, |
| ... | @@ -1265,10 +1267,10 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { | ... | @@ -1265,10 +1267,10 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1265 | self.bin_file.freeDecl(decl); | 1267 | self.bin_file.freeDecl(decl); |
| 1266 | } | 1268 | } |
| 1267 | 1269 | ||
| 1268 | if (fn_proto.extern_export_inline_token) |maybe_export_token| { | 1270 | if (fn_proto.getTrailer("extern_export_inline_token")) |maybe_export_token| { |
| 1269 | if (tree.token_ids[maybe_export_token] == .Keyword_export) { | 1271 | if (tree.token_ids[maybe_export_token] == .Keyword_export) { |
| 1270 | const export_src = tree.token_locs[maybe_export_token].start; | 1272 | const export_src = tree.token_locs[maybe_export_token].start; |
| 1271 | const name_loc = tree.token_locs[fn_proto.name_token.?]; | 1273 | const name_loc = tree.token_locs[fn_proto.getTrailer("name_token").?]; |
| 1272 | const name = tree.tokenSliceLoc(name_loc); | 1274 | const name = tree.tokenSliceLoc(name_loc); |
| 1273 | // The scope needs to have the decl in it. | 1275 | // The scope needs to have the decl in it. |
| 1274 | try self.analyzeExport(&block_scope.base, export_src, name, decl); | 1276 | try self.analyzeExport(&block_scope.base, export_src, name, decl); |
| ... | @@ -1867,7 +1869,7 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void { | ... | @@ -1867,7 +1869,7 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void { |
| 1867 | for (decls) |src_decl, decl_i| { | 1869 | for (decls) |src_decl, decl_i| { |
| 1868 | if (src_decl.cast(ast.Node.FnProto)) |fn_proto| { | 1870 | if (src_decl.cast(ast.Node.FnProto)) |fn_proto| { |
| 1869 | // We will create a Decl for it regardless of analysis status. | 1871 | // We will create a Decl for it regardless of analysis status. |
| 1870 | const name_tok = fn_proto.name_token orelse { | 1872 | const name_tok = fn_proto.getTrailer("name_token") orelse { |
| 1871 | @panic("TODO missing function name"); | 1873 | @panic("TODO missing function name"); |
| 1872 | }; | 1874 | }; |
| 1873 | 1875 | ||
| ... | @@ -1893,7 +1895,7 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void { | ... | @@ -1893,7 +1895,7 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void { |
| 1893 | } else { | 1895 | } else { |
| 1894 | const new_decl = try self.createNewDecl(&root_scope.base, name, decl_i, name_hash, contents_hash); | 1896 | const new_decl = try self.createNewDecl(&root_scope.base, name, decl_i, name_hash, contents_hash); |
| 1895 | root_scope.decls.appendAssumeCapacity(new_decl); | 1897 | root_scope.decls.appendAssumeCapacity(new_decl); |
| 1896 | if (fn_proto.extern_export_inline_token) |maybe_export_token| { | 1898 | if (fn_proto.getTrailer("extern_export_inline_token")) |maybe_export_token| { |
| 1897 | if (tree.token_ids[maybe_export_token] == .Keyword_export) { | 1899 | if (tree.token_ids[maybe_export_token] == .Keyword_export) { |
| 1898 | self.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl }); | 1900 | self.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl }); |
| 1899 | } | 1901 | } |
src-self-hosted/translate_c.zig+279-183| ... | @@ -586,11 +586,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { | ... | @@ -586,11 +586,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { |
| 586 | for (proto_node.params()) |*param, i| { | 586 | for (proto_node.params()) |*param, i| { |
| 587 | const param_name = if (param.name_token) |name_tok| | 587 | const param_name = if (param.name_token) |name_tok| |
| 588 | tokenSlice(c, name_tok) | 588 | tokenSlice(c, name_tok) |
| 589 | else if (param.param_type == .var_args) { | 589 | else |
| 590 | assert(i + 1 == proto_node.params_len); | ||
| 591 | proto_node.params_len -= 1; | ||
| 592 | break; | ||
| 593 | } else | ||
| 594 | return failDecl(c, fn_decl_loc, fn_name, "function {} parameter has no name", .{fn_name}); | 590 | return failDecl(c, fn_decl_loc, fn_name, "function {} parameter has no name", .{fn_name}); |
| 595 | 591 | ||
| 596 | const c_param = ZigClangFunctionDecl_getParamDecl(fn_decl, param_id); | 592 | const c_param = ZigClangFunctionDecl_getParamDecl(fn_decl, param_id); |
| ... | @@ -602,10 +598,20 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { | ... | @@ -602,10 +598,20 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { |
| 602 | if (!is_const) { | 598 | if (!is_const) { |
| 603 | const bare_arg_name = try std.fmt.allocPrint(c.arena, "arg_{}", .{mangled_param_name}); | 599 | const bare_arg_name = try std.fmt.allocPrint(c.arena, "arg_{}", .{mangled_param_name}); |
| 604 | const arg_name = try block_scope.makeMangledName(c, bare_arg_name); | 600 | const arg_name = try block_scope.makeMangledName(c, bare_arg_name); |
| 605 | const node = try transCreateNodeVarDecl(c, false, false, mangled_param_name); | 601 | |
| 606 | node.eq_token = try appendToken(c, .Equal, "="); | 602 | const mut_tok = try appendToken(c, .Keyword_var, "var"); |
| 607 | node.init_node = try transCreateNodeIdentifier(c, arg_name); | 603 | const name_tok = try appendIdentifier(c, mangled_param_name); |
| 608 | node.semicolon_token = try appendToken(c, .Semicolon, ";"); | 604 | const eq_token = try appendToken(c, .Equal, "="); |
| 605 | const init_node = try transCreateNodeIdentifier(c, arg_name); | ||
| 606 | const semicolon_token = try appendToken(c, .Semicolon, ";"); | ||
| 607 | const node = try ast.Node.VarDecl.create(c.arena, .{ | ||
| 608 | .mut_token = mut_tok, | ||
| 609 | .name_token = name_tok, | ||
| 610 | .semicolon_token = semicolon_token, | ||
| 611 | }, .{ | ||
| 612 | .eq_token = eq_token, | ||
| 613 | .init_node = init_node, | ||
| 614 | }); | ||
| 609 | try block_scope.statements.append(&node.base); | 615 | try block_scope.statements.append(&node.base); |
| 610 | param.name_token = try appendIdentifier(c, arg_name); | 616 | param.name_token = try appendIdentifier(c, arg_name); |
| 611 | _ = try appendToken(c, .Colon, ":"); | 617 | _ = try appendToken(c, .Colon, ":"); |
| ... | @@ -622,7 +628,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { | ... | @@ -622,7 +628,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { |
| 622 | => return failDecl(c, fn_decl_loc, fn_name, "unable to translate function", .{}), | 628 | => return failDecl(c, fn_decl_loc, fn_name, "unable to translate function", .{}), |
| 623 | }; | 629 | }; |
| 624 | const body_node = try block_scope.complete(rp.c); | 630 | const body_node = try block_scope.complete(rp.c); |
| 625 | proto_node.body_node = &body_node.base; | 631 | proto_node.setTrailer("body_node", &body_node.base); |
| 626 | return addTopLevelDecl(c, fn_name, &proto_node.base); | 632 | return addTopLevelDecl(c, fn_name, &proto_node.base); |
| 627 | } | 633 | } |
| 628 | 634 | ||
| ... | @@ -725,23 +731,20 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { | ... | @@ -725,23 +731,20 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { |
| 725 | break :blk null; | 731 | break :blk null; |
| 726 | }; | 732 | }; |
| 727 | 733 | ||
| 728 | const node = try c.arena.create(ast.Node.VarDecl); | 734 | const node = try ast.Node.VarDecl.create(c.arena, .{ |
| 729 | node.* = .{ | 735 | .name_token = name_tok, |
| 730 | .doc_comments = null, | 736 | .mut_token = mut_tok, |
| 737 | .semicolon_token = try appendToken(c, .Semicolon, ";"), | ||
| 738 | }, .{ | ||
| 731 | .visib_token = visib_tok, | 739 | .visib_token = visib_tok, |
| 732 | .thread_local_token = thread_local_token, | 740 | .thread_local_token = thread_local_token, |
| 733 | .name_token = name_tok, | ||
| 734 | .eq_token = eq_tok, | 741 | .eq_token = eq_tok, |
| 735 | .mut_token = mut_tok, | ||
| 736 | .comptime_token = null, | ||
| 737 | .extern_export_token = extern_tok, | 742 | .extern_export_token = extern_tok, |
| 738 | .lib_name = null, | ||
| 739 | .type_node = type_node, | 743 | .type_node = type_node, |
| 740 | .align_node = align_expr, | 744 | .align_node = align_expr, |
| 741 | .section_node = linksection_expr, | 745 | .section_node = linksection_expr, |
| 742 | .init_node = init_node, | 746 | .init_node = init_node, |
| 743 | .semicolon_token = try appendToken(c, .Semicolon, ";"), | 747 | }); |
| 744 | }; | ||
| 745 | return addTopLevelDecl(c, checked_name, &node.base); | 748 | return addTopLevelDecl(c, checked_name, &node.base); |
| 746 | } | 749 | } |
| 747 | 750 | ||
| ... | @@ -795,26 +798,41 @@ fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, top_l | ... | @@ -795,26 +798,41 @@ fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, top_l |
| 795 | 798 | ||
| 796 | _ = try c.decl_table.put(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)), checked_name); | 799 | _ = try c.decl_table.put(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)), checked_name); |
| 797 | const node = (try transCreateNodeTypedef(rp, typedef_decl, true, checked_name)) orelse return null; | 800 | const node = (try transCreateNodeTypedef(rp, typedef_decl, true, checked_name)) orelse return null; |
| 798 | try addTopLevelDecl(c, checked_name, &node.base); | 801 | try addTopLevelDecl(c, checked_name, node); |
| 799 | return transCreateNodeIdentifier(c, checked_name); | 802 | return transCreateNodeIdentifier(c, checked_name); |
| 800 | } | 803 | } |
| 801 | 804 | ||
| 802 | fn transCreateNodeTypedef(rp: RestorePoint, typedef_decl: *const ZigClangTypedefNameDecl, toplevel: bool, checked_name: []const u8) Error!?*ast.Node.VarDecl { | 805 | fn transCreateNodeTypedef( |
| 803 | const node = try transCreateNodeVarDecl(rp.c, toplevel, true, checked_name); | 806 | rp: RestorePoint, |
| 804 | node.eq_token = try appendToken(rp.c, .Equal, "="); | 807 | typedef_decl: *const ZigClangTypedefNameDecl, |
| 805 | 808 | toplevel: bool, | |
| 809 | checked_name: []const u8, | ||
| 810 | ) Error!?*ast.Node { | ||
| 811 | const visib_tok = if (toplevel) try appendToken(rp.c, .Keyword_pub, "pub") else null; | ||
| 812 | const mut_tok = try appendToken(rp.c, .Keyword_const, "const"); | ||
| 813 | const name_tok = try appendIdentifier(rp.c, checked_name); | ||
| 814 | const eq_token = try appendToken(rp.c, .Equal, "="); | ||
| 806 | const child_qt = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl); | 815 | const child_qt = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl); |
| 807 | const typedef_loc = ZigClangTypedefNameDecl_getLocation(typedef_decl); | 816 | const typedef_loc = ZigClangTypedefNameDecl_getLocation(typedef_decl); |
| 808 | node.init_node = transQualType(rp, child_qt, typedef_loc) catch |err| switch (err) { | 817 | const init_node = transQualType(rp, child_qt, typedef_loc) catch |err| switch (err) { |
| 809 | error.UnsupportedType => { | 818 | error.UnsupportedType => { |
| 810 | try failDecl(rp.c, typedef_loc, checked_name, "unable to resolve typedef child type", .{}); | 819 | try failDecl(rp.c, typedef_loc, checked_name, "unable to resolve typedef child type", .{}); |
| 811 | return null; | 820 | return null; |
| 812 | }, | 821 | }, |
| 813 | error.OutOfMemory => |e| return e, | 822 | error.OutOfMemory => |e| return e, |
| 814 | }; | 823 | }; |
| 824 | const semicolon_token = try appendToken(rp.c, .Semicolon, ";"); | ||
| 815 | 825 | ||
| 816 | node.semicolon_token = try appendToken(rp.c, .Semicolon, ";"); | 826 | const node = try ast.Node.VarDecl.create(rp.c.arena, .{ |
| 817 | return node; | 827 | .name_token = name_tok, |
| 828 | .mut_token = mut_tok, | ||
| 829 | .semicolon_token = semicolon_token, | ||
| 830 | }, .{ | ||
| 831 | .visib_token = visib_tok, | ||
| 832 | .eq_token = eq_token, | ||
| 833 | .init_node = init_node, | ||
| 834 | }); | ||
| 835 | return &node.base; | ||
| 818 | } | 836 | } |
| 819 | 837 | ||
| 820 | fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*ast.Node { | 838 | fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*ast.Node { |
| ... | @@ -847,12 +865,14 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?* | ... | @@ -847,12 +865,14 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?* |
| 847 | const name = try std.fmt.allocPrint(c.arena, "{}_{}", .{ container_kind_name, bare_name }); | 865 | const name = try std.fmt.allocPrint(c.arena, "{}_{}", .{ container_kind_name, bare_name }); |
| 848 | _ = try c.decl_table.put(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)), name); | 866 | _ = try c.decl_table.put(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)), name); |
| 849 | 867 | ||
| 850 | const node = try transCreateNodeVarDecl(c, !is_unnamed, true, name); | 868 | const visib_tok = if (!is_unnamed) try appendToken(c, .Keyword_pub, "pub") else null; |
| 869 | const mut_tok = try appendToken(c, .Keyword_const, "const"); | ||
| 870 | const name_tok = try appendIdentifier(c, name); | ||
| 851 | 871 | ||
| 852 | node.eq_token = try appendToken(c, .Equal, "="); | 872 | const eq_token = try appendToken(c, .Equal, "="); |
| 853 | 873 | ||
| 854 | var semicolon: ast.TokenIndex = undefined; | 874 | var semicolon: ast.TokenIndex = undefined; |
| 855 | node.init_node = blk: { | 875 | const init_node = blk: { |
| 856 | const rp = makeRestorePoint(c); | 876 | const rp = makeRestorePoint(c); |
| 857 | const record_def = ZigClangRecordDecl_getDefinition(record_decl) orelse { | 877 | const record_def = ZigClangRecordDecl_getDefinition(record_decl) orelse { |
| 858 | const opaque = try transCreateNodeOpaqueType(c); | 878 | const opaque = try transCreateNodeOpaqueType(c); |
| ... | @@ -959,7 +979,16 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?* | ... | @@ -959,7 +979,16 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?* |
| 959 | semicolon = try appendToken(c, .Semicolon, ";"); | 979 | semicolon = try appendToken(c, .Semicolon, ";"); |
| 960 | break :blk &container_node.base; | 980 | break :blk &container_node.base; |
| 961 | }; | 981 | }; |
| 962 | node.semicolon_token = semicolon; | 982 | |
| 983 | const node = try ast.Node.VarDecl.create(c.arena, .{ | ||
| 984 | .name_token = name_tok, | ||
| 985 | .mut_token = mut_tok, | ||
| 986 | .semicolon_token = semicolon, | ||
| 987 | }, .{ | ||
| 988 | .visib_token = visib_tok, | ||
| 989 | .eq_token = eq_token, | ||
| 990 | .init_node = init_node, | ||
| 991 | }); | ||
| 963 | 992 | ||
| 964 | try addTopLevelDecl(c, name, &node.base); | 993 | try addTopLevelDecl(c, name, &node.base); |
| 965 | if (!is_unnamed) | 994 | if (!is_unnamed) |
| ... | @@ -982,10 +1011,13 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No | ... | @@ -982,10 +1011,13 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No |
| 982 | 1011 | ||
| 983 | const name = try std.fmt.allocPrint(c.arena, "enum_{}", .{bare_name}); | 1012 | const name = try std.fmt.allocPrint(c.arena, "enum_{}", .{bare_name}); |
| 984 | _ = try c.decl_table.put(@ptrToInt(ZigClangEnumDecl_getCanonicalDecl(enum_decl)), name); | 1013 | _ = try c.decl_table.put(@ptrToInt(ZigClangEnumDecl_getCanonicalDecl(enum_decl)), name); |
| 985 | const node = try transCreateNodeVarDecl(c, !is_unnamed, true, name); | ||
| 986 | node.eq_token = try appendToken(c, .Equal, "="); | ||
| 987 | 1014 | ||
| 988 | node.init_node = if (ZigClangEnumDecl_getDefinition(enum_decl)) |enum_def| blk: { | 1015 | const visib_tok = if (!is_unnamed) try appendToken(c, .Keyword_pub, "pub") else null; |
| 1016 | const mut_tok = try appendToken(c, .Keyword_const, "const"); | ||
| 1017 | const name_tok = try appendIdentifier(c, name); | ||
| 1018 | const eq_token = try appendToken(c, .Equal, "="); | ||
| 1019 | |||
| 1020 | const init_node = if (ZigClangEnumDecl_getDefinition(enum_decl)) |enum_def| blk: { | ||
| 989 | var pure_enum = true; | 1021 | var pure_enum = true; |
| 990 | var it = ZigClangEnumDecl_enumerator_begin(enum_def); | 1022 | var it = ZigClangEnumDecl_enumerator_begin(enum_def); |
| 991 | var end_it = ZigClangEnumDecl_enumerator_end(enum_def); | 1023 | var end_it = ZigClangEnumDecl_enumerator_end(enum_def); |
| ... | @@ -1063,8 +1095,10 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No | ... | @@ -1063,8 +1095,10 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No |
| 1063 | 1095 | ||
| 1064 | // In C each enum value is in the global namespace. So we put them there too. | 1096 | // In C each enum value is in the global namespace. So we put them there too. |
| 1065 | // At this point we can rely on the enum emitting successfully. | 1097 | // At this point we can rely on the enum emitting successfully. |
| 1066 | const tld_node = try transCreateNodeVarDecl(c, true, true, enum_val_name); | 1098 | const tld_visib_tok = try appendToken(c, .Keyword_pub, "pub"); |
| 1067 | tld_node.eq_token = try appendToken(c, .Equal, "="); | 1099 | const tld_mut_tok = try appendToken(c, .Keyword_const, "const"); |
| 1100 | const tld_name_tok = try appendIdentifier(c, enum_val_name); | ||
| 1101 | const tld_eq_token = try appendToken(c, .Equal, "="); | ||
| 1068 | const cast_node = try rp.c.createBuiltinCall("@enumToInt", 1); | 1102 | const cast_node = try rp.c.createBuiltinCall("@enumToInt", 1); |
| 1069 | const enum_ident = try transCreateNodeIdentifier(c, name); | 1103 | const enum_ident = try transCreateNodeIdentifier(c, name); |
| 1070 | const period_tok = try appendToken(c, .Period, "."); | 1104 | const period_tok = try appendToken(c, .Period, "."); |
| ... | @@ -1078,8 +1112,17 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No | ... | @@ -1078,8 +1112,17 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No |
| 1078 | }; | 1112 | }; |
| 1079 | cast_node.params()[0] = &field_access_node.base; | 1113 | cast_node.params()[0] = &field_access_node.base; |
| 1080 | cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | 1114 | cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| 1081 | tld_node.init_node = &cast_node.base; | 1115 | const tld_init_node = &cast_node.base; |
| 1082 | tld_node.semicolon_token = try appendToken(c, .Semicolon, ";"); | 1116 | const tld_semicolon_token = try appendToken(c, .Semicolon, ";"); |
| 1117 | const tld_node = try ast.Node.VarDecl.create(c.arena, .{ | ||
| 1118 | .name_token = tld_name_tok, | ||
| 1119 | .mut_token = tld_mut_tok, | ||
| 1120 | .semicolon_token = tld_semicolon_token, | ||
| 1121 | }, .{ | ||
| 1122 | .visib_token = tld_visib_tok, | ||
| 1123 | .eq_token = tld_eq_token, | ||
| 1124 | .init_node = tld_init_node, | ||
| 1125 | }); | ||
| 1083 | try addTopLevelDecl(c, field_name, &tld_node.base); | 1126 | try addTopLevelDecl(c, field_name, &tld_node.base); |
| 1084 | } | 1127 | } |
| 1085 | // make non exhaustive | 1128 | // make non exhaustive |
| ... | @@ -1109,7 +1152,16 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No | ... | @@ -1109,7 +1152,16 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No |
| 1109 | } else | 1152 | } else |
| 1110 | try transCreateNodeOpaqueType(c); | 1153 | try transCreateNodeOpaqueType(c); |
| 1111 | 1154 | ||
| 1112 | node.semicolon_token = try appendToken(c, .Semicolon, ";"); | 1155 | const semicolon_token = try appendToken(c, .Semicolon, ";"); |
| 1156 | const node = try ast.Node.VarDecl.create(c.arena, .{ | ||
| 1157 | .name_token = name_tok, | ||
| 1158 | .mut_token = mut_tok, | ||
| 1159 | .semicolon_token = semicolon_token, | ||
| 1160 | }, .{ | ||
| 1161 | .visib_token = visib_tok, | ||
| 1162 | .eq_token = eq_token, | ||
| 1163 | .init_node = init_node, | ||
| 1164 | }); | ||
| 1113 | 1165 | ||
| 1114 | try addTopLevelDecl(c, name, &node.base); | 1166 | try addTopLevelDecl(c, name, &node.base); |
| 1115 | if (!is_unnamed) | 1167 | if (!is_unnamed) |
| ... | @@ -1118,10 +1170,22 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No | ... | @@ -1118,10 +1170,22 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No |
| 1118 | } | 1170 | } |
| 1119 | 1171 | ||
| 1120 | fn createAlias(c: *Context, alias: anytype) !void { | 1172 | fn createAlias(c: *Context, alias: anytype) !void { |
| 1121 | const node = try transCreateNodeVarDecl(c, true, true, alias.alias); | 1173 | const visib_tok = try appendToken(c, .Keyword_pub, "pub"); |
| 1122 | node.eq_token = try appendToken(c, .Equal, "="); | 1174 | const mut_tok = try appendToken(c, .Keyword_const, "const"); |
| 1123 | node.init_node = try transCreateNodeIdentifier(c, alias.name); | 1175 | const name_tok = try appendIdentifier(c, alias.alias); |
| 1124 | node.semicolon_token = try appendToken(c, .Semicolon, ";"); | 1176 | const eq_token = try appendToken(c, .Equal, "="); |
| 1177 | const init_node = try transCreateNodeIdentifier(c, alias.name); | ||
| 1178 | const semicolon_token = try appendToken(c, .Semicolon, ";"); | ||
| 1179 | |||
| 1180 | const node = try ast.Node.VarDecl.create(c.arena, .{ | ||
| 1181 | .name_token = name_tok, | ||
| 1182 | .mut_token = mut_tok, | ||
| 1183 | .semicolon_token = semicolon_token, | ||
| 1184 | }, .{ | ||
| 1185 | .visib_token = visib_tok, | ||
| 1186 | .eq_token = eq_token, | ||
| 1187 | .init_node = init_node, | ||
| 1188 | }); | ||
| 1125 | return addTopLevelDecl(c, alias.alias, &node.base); | 1189 | return addTopLevelDecl(c, alias.alias, &node.base); |
| 1126 | } | 1190 | } |
| 1127 | 1191 | ||
| ... | @@ -1461,13 +1525,17 @@ fn transDeclStmtOne( | ... | @@ -1461,13 +1525,17 @@ fn transDeclStmtOne( |
| 1461 | @ptrCast(*const ZigClangNamedDecl, var_decl), | 1525 | @ptrCast(*const ZigClangNamedDecl, var_decl), |
| 1462 | )); | 1526 | )); |
| 1463 | const mangled_name = try block_scope.makeMangledName(c, name); | 1527 | const mangled_name = try block_scope.makeMangledName(c, name); |
| 1464 | const node = try transCreateNodeVarDecl(c, false, ZigClangQualType_isConstQualified(qual_type), mangled_name); | 1528 | const mut_tok = if (ZigClangQualType_isConstQualified(qual_type)) |
| 1529 | try appendToken(c, .Keyword_const, "const") | ||
| 1530 | else | ||
| 1531 | try appendToken(c, .Keyword_var, "var"); | ||
| 1532 | const name_tok = try appendIdentifier(c, mangled_name); | ||
| 1465 | 1533 | ||
| 1466 | _ = try appendToken(c, .Colon, ":"); | 1534 | _ = try appendToken(c, .Colon, ":"); |
| 1467 | const loc = ZigClangDecl_getLocation(decl); | 1535 | const loc = ZigClangDecl_getLocation(decl); |
| 1468 | node.type_node = try transQualType(rp, qual_type, loc); | 1536 | const type_node = try transQualType(rp, qual_type, loc); |
| 1469 | 1537 | ||
| 1470 | node.eq_token = try appendToken(c, .Equal, "="); | 1538 | const eq_token = try appendToken(c, .Equal, "="); |
| 1471 | var init_node = if (ZigClangVarDecl_getInit(var_decl)) |expr| | 1539 | var init_node = if (ZigClangVarDecl_getInit(var_decl)) |expr| |
| 1472 | try transExprCoercing(rp, scope, expr, .used, .r_value) | 1540 | try transExprCoercing(rp, scope, expr, .used, .r_value) |
| 1473 | else | 1541 | else |
| ... | @@ -1478,8 +1546,17 @@ fn transDeclStmtOne( | ... | @@ -1478,8 +1546,17 @@ fn transDeclStmtOne( |
| 1478 | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | 1546 | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| 1479 | init_node = &builtin_node.base; | 1547 | init_node = &builtin_node.base; |
| 1480 | } | 1548 | } |
| 1481 | node.init_node = init_node; | 1549 | const semicolon_token = try appendToken(c, .Semicolon, ";"); |
| 1482 | node.semicolon_token = try appendToken(c, .Semicolon, ";"); | 1550 | const node = try ast.Node.VarDecl.create(c.arena, .{ |
| 1551 | .name_token = name_tok, | ||
| 1552 | .mut_token = mut_tok, | ||
| 1553 | .semicolon_token = semicolon_token, | ||
| 1554 | }, .{ | ||
| 1555 | .thread_local_token = thread_local_token, | ||
| 1556 | .eq_token = eq_token, | ||
| 1557 | .type_node = type_node, | ||
| 1558 | .init_node = init_node, | ||
| 1559 | }); | ||
| 1483 | return &node.base; | 1560 | return &node.base; |
| 1484 | }, | 1561 | }, |
| 1485 | .Typedef => { | 1562 | .Typedef => { |
| ... | @@ -1494,7 +1571,7 @@ fn transDeclStmtOne( | ... | @@ -1494,7 +1571,7 @@ fn transDeclStmtOne( |
| 1494 | const mangled_name = try block_scope.makeMangledName(c, name); | 1571 | const mangled_name = try block_scope.makeMangledName(c, name); |
| 1495 | const node = (try transCreateNodeTypedef(rp, typedef_decl, false, mangled_name)) orelse | 1572 | const node = (try transCreateNodeTypedef(rp, typedef_decl, false, mangled_name)) orelse |
| 1496 | return error.UnsupportedTranslation; | 1573 | return error.UnsupportedTranslation; |
| 1497 | return &node.base; | 1574 | return node; |
| 1498 | }, | 1575 | }, |
| 1499 | else => |kind| return revertAndWarn( | 1576 | else => |kind| return revertAndWarn( |
| 1500 | rp, | 1577 | rp, |
| ... | @@ -3105,12 +3182,21 @@ fn transCreatePreCrement( | ... | @@ -3105,12 +3182,21 @@ fn transCreatePreCrement( |
| 3105 | defer block_scope.deinit(); | 3182 | defer block_scope.deinit(); |
| 3106 | const ref = try block_scope.makeMangledName(rp.c, "ref"); | 3183 | const ref = try block_scope.makeMangledName(rp.c, "ref"); |
| 3107 | 3184 | ||
| 3108 | const node = try transCreateNodeVarDecl(rp.c, false, true, ref); | 3185 | const mut_tok = try appendToken(rp.c, .Keyword_const, "const"); |
| 3109 | node.eq_token = try appendToken(rp.c, .Equal, "="); | 3186 | const name_tok = try appendIdentifier(rp.c, ref); |
| 3187 | const eq_token = try appendToken(rp.c, .Equal, "="); | ||
| 3110 | const rhs_node = try transCreateNodeSimplePrefixOp(rp.c, .AddressOf, .Ampersand, "&"); | 3188 | const rhs_node = try transCreateNodeSimplePrefixOp(rp.c, .AddressOf, .Ampersand, "&"); |
| 3111 | rhs_node.rhs = try transExpr(rp, scope, op_expr, .used, .r_value); | 3189 | rhs_node.rhs = try transExpr(rp, scope, op_expr, .used, .r_value); |
| 3112 | node.init_node = &rhs_node.base; | 3190 | const init_node = &rhs_node.base; |
| 3113 | node.semicolon_token = try appendToken(rp.c, .Semicolon, ";"); | 3191 | const semicolon_token = try appendToken(rp.c, .Semicolon, ";"); |
| 3192 | const node = try ast.Node.VarDecl.create(rp.c.arena, .{ | ||
| 3193 | .name_token = name_tok, | ||
| 3194 | .mut_token = mut_tok, | ||
| 3195 | .semicolon_token = semicolon_token, | ||
| 3196 | }, .{ | ||
| 3197 | .eq_token = eq_token, | ||
| 3198 | .init_node = init_node, | ||
| 3199 | }); | ||
| 3114 | try block_scope.statements.append(&node.base); | 3200 | try block_scope.statements.append(&node.base); |
| 3115 | 3201 | ||
| 3116 | const lhs_node = try transCreateNodeIdentifier(rp.c, ref); | 3202 | const lhs_node = try transCreateNodeIdentifier(rp.c, ref); |
| ... | @@ -3171,12 +3257,21 @@ fn transCreatePostCrement( | ... | @@ -3171,12 +3257,21 @@ fn transCreatePostCrement( |
| 3171 | defer block_scope.deinit(); | 3257 | defer block_scope.deinit(); |
| 3172 | const ref = try block_scope.makeMangledName(rp.c, "ref"); | 3258 | const ref = try block_scope.makeMangledName(rp.c, "ref"); |
| 3173 | 3259 | ||
| 3174 | const node = try transCreateNodeVarDecl(rp.c, false, true, ref); | 3260 | const mut_tok = try appendToken(rp.c, .Keyword_const, "const"); |
| 3175 | node.eq_token = try appendToken(rp.c, .Equal, "="); | 3261 | const name_tok = try appendIdentifier(rp.c, ref); |
| 3262 | const eq_token = try appendToken(rp.c, .Equal, "="); | ||
| 3176 | const rhs_node = try transCreateNodeSimplePrefixOp(rp.c, .AddressOf, .Ampersand, "&"); | 3263 | const rhs_node = try transCreateNodeSimplePrefixOp(rp.c, .AddressOf, .Ampersand, "&"); |
| 3177 | rhs_node.rhs = try transExpr(rp, scope, op_expr, .used, .r_value); | 3264 | rhs_node.rhs = try transExpr(rp, scope, op_expr, .used, .r_value); |
| 3178 | node.init_node = &rhs_node.base; | 3265 | const init_node = &rhs_node.base; |
| 3179 | node.semicolon_token = try appendToken(rp.c, .Semicolon, ";"); | 3266 | const semicolon_token = try appendToken(rp.c, .Semicolon, ";"); |
| 3267 | const node = try ast.Node.VarDecl.create(rp.c.arena, .{ | ||
| 3268 | .name_token = name_tok, | ||
| 3269 | .mut_token = mut_tok, | ||
| 3270 | .semicolon_token = semicolon_token, | ||
| 3271 | }, .{ | ||
| 3272 | .eq_token = eq_token, | ||
| 3273 | .init_node = init_node, | ||
| 3274 | }); | ||
| 3180 | try block_scope.statements.append(&node.base); | 3275 | try block_scope.statements.append(&node.base); |
| 3181 | 3276 | ||
| 3182 | const lhs_node = try transCreateNodeIdentifier(rp.c, ref); | 3277 | const lhs_node = try transCreateNodeIdentifier(rp.c, ref); |
| ... | @@ -3184,10 +3279,19 @@ fn transCreatePostCrement( | ... | @@ -3184,10 +3279,19 @@ fn transCreatePostCrement( |
| 3184 | _ = try appendToken(rp.c, .Semicolon, ";"); | 3279 | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 3185 | 3280 | ||
| 3186 | const tmp = try block_scope.makeMangledName(rp.c, "tmp"); | 3281 | const tmp = try block_scope.makeMangledName(rp.c, "tmp"); |
| 3187 | const tmp_node = try transCreateNodeVarDecl(rp.c, false, true, tmp); | 3282 | const tmp_mut_tok = try appendToken(rp.c, .Keyword_const, "const"); |
| 3188 | tmp_node.eq_token = try appendToken(rp.c, .Equal, "="); | 3283 | const tmp_name_tok = try appendIdentifier(rp.c, tmp); |
| 3189 | tmp_node.init_node = ref_node; | 3284 | const tmp_eq_token = try appendToken(rp.c, .Equal, "="); |
| 3190 | tmp_node.semicolon_token = try appendToken(rp.c, .Semicolon, ";"); | 3285 | const tmp_init_node = ref_node; |
| 3286 | const tmp_semicolon_token = try appendToken(rp.c, .Semicolon, ";"); | ||
| 3287 | const tmp_node = try ast.Node.VarDecl.create(rp.c.arena, .{ | ||
| 3288 | .name_token = tmp_name_tok, | ||
| 3289 | .mut_token = tmp_mut_tok, | ||
| 3290 | .semicolon_token = semicolon_token, | ||
| 3291 | }, .{ | ||
| 3292 | .eq_token = tmp_eq_token, | ||
| 3293 | .init_node = tmp_init_node, | ||
| 3294 | }); | ||
| 3191 | try block_scope.statements.append(&tmp_node.base); | 3295 | try block_scope.statements.append(&tmp_node.base); |
| 3192 | 3296 | ||
| 3193 | const token = try appendToken(rp.c, op_tok_id, bytes); | 3297 | const token = try appendToken(rp.c, op_tok_id, bytes); |
| ... | @@ -3325,12 +3429,21 @@ fn transCreateCompoundAssign( | ... | @@ -3325,12 +3429,21 @@ fn transCreateCompoundAssign( |
| 3325 | defer block_scope.deinit(); | 3429 | defer block_scope.deinit(); |
| 3326 | const ref = try block_scope.makeMangledName(rp.c, "ref"); | 3430 | const ref = try block_scope.makeMangledName(rp.c, "ref"); |
| 3327 | 3431 | ||
| 3328 | const node = try transCreateNodeVarDecl(rp.c, false, true, ref); | 3432 | const mut_tok = try appendToken(rp.c, .Keyword_const, "const"); |
| 3329 | node.eq_token = try appendToken(rp.c, .Equal, "="); | 3433 | const name_tok = try appendIdentifier(rp.c, ref); |
| 3434 | const eq_token = try appendToken(rp.c, .Equal, "="); | ||
| 3330 | const addr_node = try transCreateNodeSimplePrefixOp(rp.c, .AddressOf, .Ampersand, "&"); | 3435 | const addr_node = try transCreateNodeSimplePrefixOp(rp.c, .AddressOf, .Ampersand, "&"); |
| 3331 | addr_node.rhs = try transExpr(rp, scope, lhs, .used, .l_value); | 3436 | addr_node.rhs = try transExpr(rp, scope, lhs, .used, .l_value); |
| 3332 | node.init_node = &addr_node.base; | 3437 | const init_node = &addr_node.base; |
| 3333 | node.semicolon_token = try appendToken(rp.c, .Semicolon, ";"); | 3438 | const semicolon_token = try appendToken(rp.c, .Semicolon, ";"); |
| 3439 | const node = try ast.Node.VarDecl.create(rp.c.arena, .{ | ||
| 3440 | .name_token = name_tok, | ||
| 3441 | .mut_token = mut_tok, | ||
| 3442 | .semicolon_token = semicolon_token, | ||
| 3443 | }, .{ | ||
| 3444 | .eq_token = eq_token, | ||
| 3445 | .init_node = init_node, | ||
| 3446 | }); | ||
| 3334 | try block_scope.statements.append(&node.base); | 3447 | try block_scope.statements.append(&node.base); |
| 3335 | 3448 | ||
| 3336 | const lhs_node = try transCreateNodeIdentifier(rp.c, ref); | 3449 | const lhs_node = try transCreateNodeIdentifier(rp.c, ref); |
| ... | @@ -3375,8 +3488,8 @@ fn transCreateCompoundAssign( | ... | @@ -3375,8 +3488,8 @@ fn transCreateCompoundAssign( |
| 3375 | const rhs_bin = try transCreateNodeInfixOp(rp, scope, ref_node, bin_op, bin_token, rhs_node, .used, false); | 3488 | const rhs_bin = try transCreateNodeInfixOp(rp, scope, ref_node, bin_op, bin_token, rhs_node, .used, false); |
| 3376 | _ = try appendToken(rp.c, .Semicolon, ";"); | 3489 | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 3377 | 3490 | ||
| 3378 | const eq_token = try appendToken(rp.c, .Equal, "="); | 3491 | const ass_eq_token = try appendToken(rp.c, .Equal, "="); |
| 3379 | const assign = try transCreateNodeInfixOp(rp, scope, ref_node, .Assign, eq_token, rhs_bin, .used, false); | 3492 | const assign = try transCreateNodeInfixOp(rp, scope, ref_node, .Assign, ass_eq_token, rhs_bin, .used, false); |
| 3380 | try block_scope.statements.append(assign); | 3493 | try block_scope.statements.append(assign); |
| 3381 | } | 3494 | } |
| 3382 | 3495 | ||
| ... | @@ -3494,10 +3607,19 @@ fn transBinaryConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const | ... | @@ -3494,10 +3607,19 @@ fn transBinaryConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const |
| 3494 | defer block_scope.deinit(); | 3607 | defer block_scope.deinit(); |
| 3495 | 3608 | ||
| 3496 | const mangled_name = try block_scope.makeMangledName(rp.c, "cond_temp"); | 3609 | const mangled_name = try block_scope.makeMangledName(rp.c, "cond_temp"); |
| 3497 | const tmp_var = try transCreateNodeVarDecl(rp.c, false, true, mangled_name); | 3610 | const mut_tok = try appendToken(rp.c, .Keyword_const, "const"); |
| 3498 | tmp_var.eq_token = try appendToken(rp.c, .Equal, "="); | 3611 | const name_tok = try appendIdentifier(rp.c, mangled_name); |
| 3499 | tmp_var.init_node = try transExpr(rp, &block_scope.base, cond_expr, .used, .r_value); | 3612 | const eq_token = try appendToken(rp.c, .Equal, "="); |
| 3500 | tmp_var.semicolon_token = try appendToken(rp.c, .Semicolon, ";"); | 3613 | const init_node = try transExpr(rp, &block_scope.base, cond_expr, .used, .r_value); |
| 3614 | const semicolon_token = try appendToken(rp.c, .Semicolon, ";"); | ||
| 3615 | const tmp_var = try ast.Node.VarDecl.create(rp.c.arena, .{ | ||
| 3616 | .name_token = name_tok, | ||
| 3617 | .mut_token = mut_tok, | ||
| 3618 | .semicolon_token = semicolon_token, | ||
| 3619 | }, .{ | ||
| 3620 | .eq_token = eq_token, | ||
| 3621 | .init_node = init_node, | ||
| 3622 | }); | ||
| 3501 | try block_scope.statements.append(&tmp_var.base); | 3623 | try block_scope.statements.append(&tmp_var.base); |
| 3502 | 3624 | ||
| 3503 | const break_node = try transCreateNodeBreakToken(rp.c, block_scope.label); | 3625 | const break_node = try transCreateNodeBreakToken(rp.c, block_scope.label); |
| ... | @@ -3932,9 +4054,9 @@ fn transCreateNodeAssign( | ... | @@ -3932,9 +4054,9 @@ fn transCreateNodeAssign( |
| 3932 | defer block_scope.deinit(); | 4054 | defer block_scope.deinit(); |
| 3933 | 4055 | ||
| 3934 | const tmp = try block_scope.makeMangledName(rp.c, "tmp"); | 4056 | const tmp = try block_scope.makeMangledName(rp.c, "tmp"); |
| 3935 | 4057 | const mut_tok = try appendToken(rp.c, .Keyword_const, "const"); | |
| 3936 | const node = try transCreateNodeVarDecl(rp.c, false, true, tmp); | 4058 | const name_tok = try appendIdentifier(rp.c, tmp); |
| 3937 | node.eq_token = try appendToken(rp.c, .Equal, "="); | 4059 | const eq_token = try appendToken(rp.c, .Equal, "="); |
| 3938 | var rhs_node = try transExpr(rp, &block_scope.base, rhs, .used, .r_value); | 4060 | var rhs_node = try transExpr(rp, &block_scope.base, rhs, .used, .r_value); |
| 3939 | if (!exprIsBooleanType(lhs) and isBoolRes(rhs_node)) { | 4061 | if (!exprIsBooleanType(lhs) and isBoolRes(rhs_node)) { |
| 3940 | const builtin_node = try rp.c.createBuiltinCall("@boolToInt", 1); | 4062 | const builtin_node = try rp.c.createBuiltinCall("@boolToInt", 1); |
| ... | @@ -3942,16 +4064,24 @@ fn transCreateNodeAssign( | ... | @@ -3942,16 +4064,24 @@ fn transCreateNodeAssign( |
| 3942 | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | 4064 | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| 3943 | rhs_node = &builtin_node.base; | 4065 | rhs_node = &builtin_node.base; |
| 3944 | } | 4066 | } |
| 3945 | node.init_node = rhs_node; | 4067 | const init_node = rhs_node; |
| 3946 | node.semicolon_token = try appendToken(rp.c, .Semicolon, ";"); | 4068 | const semicolon_token = try appendToken(rp.c, .Semicolon, ";"); |
| 4069 | const node = try ast.Node.VarDecl.create(rp.c.arena, .{ | ||
| 4070 | .name_token = name_tok, | ||
| 4071 | .mut_token = mut_tok, | ||
| 4072 | .semicolon_token = semicolon_token, | ||
| 4073 | }, .{ | ||
| 4074 | .eq_token = eq_token, | ||
| 4075 | .init_node = init_node, | ||
| 4076 | }); | ||
| 3947 | try block_scope.statements.append(&node.base); | 4077 | try block_scope.statements.append(&node.base); |
| 3948 | 4078 | ||
| 3949 | const lhs_node = try transExpr(rp, &block_scope.base, lhs, .used, .l_value); | 4079 | const lhs_node = try transExpr(rp, &block_scope.base, lhs, .used, .l_value); |
| 3950 | const eq_token = try appendToken(rp.c, .Equal, "="); | 4080 | const lhs_eq_token = try appendToken(rp.c, .Equal, "="); |
| 3951 | const ident = try transCreateNodeIdentifier(rp.c, tmp); | 4081 | const ident = try transCreateNodeIdentifier(rp.c, tmp); |
| 3952 | _ = try appendToken(rp.c, .Semicolon, ";"); | 4082 | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 3953 | 4083 | ||
| 3954 | const assign = try transCreateNodeInfixOp(rp, &block_scope.base, lhs_node, .Assign, eq_token, ident, .used, false); | 4084 | const assign = try transCreateNodeInfixOp(rp, &block_scope.base, lhs_node, .Assign, lhs_eq_token, ident, .used, false); |
| 3955 | try block_scope.statements.append(assign); | 4085 | try block_scope.statements.append(assign); |
| 3956 | 4086 | ||
| 3957 | const break_node = try transCreateNodeBreak(rp.c, label_name); | 4087 | const break_node = try transCreateNodeBreak(rp.c, label_name); |
| ... | @@ -4232,28 +4362,10 @@ fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: *ast.Node, proto_a | ... | @@ -4232,28 +4362,10 @@ fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: *ast.Node, proto_a |
| 4232 | 4362 | ||
| 4233 | _ = try appendToken(c, .RParen, ")"); | 4363 | _ = try appendToken(c, .RParen, ")"); |
| 4234 | 4364 | ||
| 4235 | const fn_proto = try ast.Node.FnProto.alloc(c.arena, fn_params.items.len); | ||
| 4236 | fn_proto.* = .{ | ||
| 4237 | .doc_comments = null, | ||
| 4238 | .visib_token = pub_tok, | ||
| 4239 | .fn_token = fn_tok, | ||
| 4240 | .name_token = name_tok, | ||
| 4241 | .params_len = fn_params.items.len, | ||
| 4242 | .return_type = proto_alias.return_type, | ||
| 4243 | .var_args_token = null, | ||
| 4244 | .extern_export_inline_token = inline_tok, | ||
| 4245 | .body_node = null, | ||
| 4246 | .lib_name = null, | ||
| 4247 | .align_expr = null, | ||
| 4248 | .section_expr = null, | ||
| 4249 | .callconv_expr = null, | ||
| 4250 | }; | ||
| 4251 | mem.copy(ast.Node.FnProto.ParamDecl, fn_proto.params(), fn_params.items); | ||
| 4252 | |||
| 4253 | const block_lbrace = try appendToken(c, .LBrace, "{"); | 4365 | const block_lbrace = try appendToken(c, .LBrace, "{"); |
| 4254 | 4366 | ||
| 4255 | const return_expr = try transCreateNodeReturnExpr(c); | 4367 | const return_expr = try transCreateNodeReturnExpr(c); |
| 4256 | const unwrap_expr = try transCreateNodeUnwrapNull(c, ref.cast(ast.Node.VarDecl).?.init_node.?); | 4368 | const unwrap_expr = try transCreateNodeUnwrapNull(c, ref.cast(ast.Node.VarDecl).?.getTrailer("init_node").?); |
| 4257 | 4369 | ||
| 4258 | const call_expr = try c.createCall(unwrap_expr, fn_params.items.len); | 4370 | const call_expr = try c.createCall(unwrap_expr, fn_params.items.len); |
| 4259 | const call_params = call_expr.params(); | 4371 | const call_params = call_expr.params(); |
| ... | @@ -4277,7 +4389,18 @@ fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: *ast.Node, proto_a | ... | @@ -4277,7 +4389,18 @@ fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: *ast.Node, proto_a |
| 4277 | .rbrace = try appendToken(c, .RBrace, "}"), | 4389 | .rbrace = try appendToken(c, .RBrace, "}"), |
| 4278 | }; | 4390 | }; |
| 4279 | block.statements()[0] = &return_expr.base; | 4391 | block.statements()[0] = &return_expr.base; |
| 4280 | fn_proto.body_node = &block.base; | 4392 | |
| 4393 | const fn_proto = try ast.Node.FnProto.create(c.arena, .{ | ||
| 4394 | .params_len = fn_params.items.len, | ||
| 4395 | .fn_token = fn_tok, | ||
| 4396 | .return_type = proto_alias.return_type, | ||
| 4397 | }, .{ | ||
| 4398 | .visib_token = pub_tok, | ||
| 4399 | .name_token = name_tok, | ||
| 4400 | .extern_export_inline_token = inline_tok, | ||
| 4401 | .body_node = &block.base, | ||
| 4402 | }); | ||
| 4403 | mem.copy(ast.Node.FnProto.ParamDecl, fn_proto.params(), fn_params.items); | ||
| 4281 | return &fn_proto.base; | 4404 | return &fn_proto.base; |
| 4282 | } | 4405 | } |
| 4283 | 4406 | ||
| ... | @@ -4356,31 +4479,6 @@ fn transCreateNodeBreak(c: *Context, label: ?[]const u8) !*ast.Node.ControlFlowE | ... | @@ -4356,31 +4479,6 @@ fn transCreateNodeBreak(c: *Context, label: ?[]const u8) !*ast.Node.ControlFlowE |
| 4356 | return node; | 4479 | return node; |
| 4357 | } | 4480 | } |
| 4358 | 4481 | ||
| 4359 | fn transCreateNodeVarDecl(c: *Context, is_pub: bool, is_const: bool, name: []const u8) !*ast.Node.VarDecl { | ||
| 4360 | const visib_tok = if (is_pub) try appendToken(c, .Keyword_pub, "pub") else null; | ||
| 4361 | const mut_tok = if (is_const) try appendToken(c, .Keyword_const, "const") else try appendToken(c, .Keyword_var, "var"); | ||
| 4362 | const name_tok = try appendIdentifier(c, name); | ||
| 4363 | |||
| 4364 | const node = try c.arena.create(ast.Node.VarDecl); | ||
| 4365 | node.* = .{ | ||
| 4366 | .doc_comments = null, | ||
| 4367 | .visib_token = visib_tok, | ||
| 4368 | .thread_local_token = null, | ||
| 4369 | .name_token = name_tok, | ||
| 4370 | .eq_token = undefined, | ||
| 4371 | .mut_token = mut_tok, | ||
| 4372 | .comptime_token = null, | ||
| 4373 | .extern_export_token = null, | ||
| 4374 | .lib_name = null, | ||
| 4375 | .type_node = null, | ||
| 4376 | .align_node = null, | ||
| 4377 | .section_node = null, | ||
| 4378 | .init_node = null, | ||
| 4379 | .semicolon_token = undefined, | ||
| 4380 | }; | ||
| 4381 | return node; | ||
| 4382 | } | ||
| 4383 | |||
| 4384 | fn transCreateNodeWhile(c: *Context) !*ast.Node.While { | 4482 | fn transCreateNodeWhile(c: *Context) !*ast.Node.While { |
| 4385 | const while_tok = try appendToken(c, .Keyword_while, "while"); | 4483 | const while_tok = try appendToken(c, .Keyword_while, "while"); |
| 4386 | _ = try appendToken(c, .LParen, "("); | 4484 | _ = try appendToken(c, .LParen, "("); |
| ... | @@ -4782,19 +4880,12 @@ fn finishTransFnProto( | ... | @@ -4782,19 +4880,12 @@ fn finishTransFnProto( |
| 4782 | } | 4880 | } |
| 4783 | } | 4881 | } |
| 4784 | 4882 | ||
| 4785 | if (is_var_args) { | 4883 | const var_args_token: ?ast.TokenIndex = if (is_var_args) blk: { |
| 4786 | if (param_count > 0) { | 4884 | if (param_count > 0) { |
| 4787 | _ = try appendToken(rp.c, .Comma, ","); | 4885 | _ = try appendToken(rp.c, .Comma, ","); |
| 4788 | } | 4886 | } |
| 4789 | 4887 | break :blk try appendToken(rp.c, .Ellipsis3, "..."); | |
| 4790 | fn_params.addOneAssumeCapacity().* = .{ | 4888 | } else null; |
| 4791 | .doc_comments = null, | ||
| 4792 | .comptime_token = null, | ||
| 4793 | .noalias_token = null, | ||
| 4794 | .name_token = null, | ||
| 4795 | .param_type = .{ .var_args = try appendToken(rp.c, .Ellipsis3, "...") }, | ||
| 4796 | }; | ||
| 4797 | } | ||
| 4798 | 4889 | ||
| 4799 | const rparen_tok = try appendToken(rp.c, .RParen, ")"); | 4890 | const rparen_tok = try appendToken(rp.c, .RParen, ")"); |
| 4800 | 4891 | ||
| ... | @@ -4860,22 +4951,31 @@ fn finishTransFnProto( | ... | @@ -4860,22 +4951,31 @@ fn finishTransFnProto( |
| 4860 | } | 4951 | } |
| 4861 | }; | 4952 | }; |
| 4862 | 4953 | ||
| 4863 | const fn_proto = try ast.Node.FnProto.alloc(rp.c.arena, fn_params.items.len); | 4954 | // We need to reserve an undefined (but non-null) body node to set later. |
| 4864 | fn_proto.* = .{ | 4955 | var body_node: ?*ast.Node = null; |
| 4865 | .doc_comments = null, | 4956 | if (fn_decl_context) |ctx| { |
| 4866 | .visib_token = pub_tok, | 4957 | if (ctx.has_body) { |
| 4867 | .fn_token = fn_tok, | 4958 | // TODO: we should be able to use undefined here but |
| 4868 | .name_token = name_tok, | 4959 | // it causes a bug. This is undefined without zig language |
| 4960 | // being aware of it. | ||
| 4961 | body_node = @intToPtr(*ast.Node, 0x08); | ||
| 4962 | } | ||
| 4963 | } | ||
| 4964 | |||
| 4965 | const fn_proto = try ast.Node.FnProto.create(rp.c.arena, .{ | ||
| 4869 | .params_len = fn_params.items.len, | 4966 | .params_len = fn_params.items.len, |
| 4870 | .return_type = .{ .Explicit = return_type_node }, | 4967 | .return_type = .{ .Explicit = return_type_node }, |
| 4871 | .var_args_token = null, // TODO this field is broken in the AST data model | 4968 | .fn_token = fn_tok, |
| 4969 | }, .{ | ||
| 4970 | .visib_token = pub_tok, | ||
| 4971 | .name_token = name_tok, | ||
| 4872 | .extern_export_inline_token = extern_export_inline_tok, | 4972 | .extern_export_inline_token = extern_export_inline_tok, |
| 4873 | .body_node = null, | ||
| 4874 | .lib_name = null, | ||
| 4875 | .align_expr = align_expr, | 4973 | .align_expr = align_expr, |
| 4876 | .section_expr = linksection_expr, | 4974 | .section_expr = linksection_expr, |
| 4877 | .callconv_expr = callconv_expr, | 4975 | .callconv_expr = callconv_expr, |
| 4878 | }; | 4976 | .body_node = body_node, |
| 4977 | .var_args_token = var_args_token, | ||
| 4978 | }); | ||
| 4879 | mem.copy(ast.Node.FnProto.ParamDecl, fn_proto.params(), fn_params.items); | 4979 | mem.copy(ast.Node.FnProto.ParamDecl, fn_proto.params(), fn_params.items); |
| 4880 | return fn_proto; | 4980 | return fn_proto; |
| 4881 | } | 4981 | } |
| ... | @@ -4923,23 +5023,15 @@ pub fn failDecl(c: *Context, loc: ZigClangSourceLocation, name: []const u8, comp | ... | @@ -4923,23 +5023,15 @@ pub fn failDecl(c: *Context, loc: ZigClangSourceLocation, name: []const u8, comp |
| 4923 | }; | 5023 | }; |
| 4924 | call_node.params()[0] = &msg_node.base; | 5024 | call_node.params()[0] = &msg_node.base; |
| 4925 | 5025 | ||
| 4926 | const var_decl_node = try c.arena.create(ast.Node.VarDecl); | 5026 | const var_decl_node = try ast.Node.VarDecl.create(c.arena, .{ |
| 4927 | var_decl_node.* = .{ | ||
| 4928 | .doc_comments = null, | ||
| 4929 | .visib_token = pub_tok, | ||
| 4930 | .thread_local_token = null, | ||
| 4931 | .name_token = name_tok, | 5027 | .name_token = name_tok, |
| 4932 | .eq_token = eq_tok, | ||
| 4933 | .mut_token = const_tok, | 5028 | .mut_token = const_tok, |
| 4934 | .comptime_token = null, | ||
| 4935 | .extern_export_token = null, | ||
| 4936 | .lib_name = null, | ||
| 4937 | .type_node = null, | ||
| 4938 | .align_node = null, | ||
| 4939 | .section_node = null, | ||
| 4940 | .init_node = &call_node.base, | ||
| 4941 | .semicolon_token = semi_tok, | 5029 | .semicolon_token = semi_tok, |
| 4942 | }; | 5030 | }, .{ |
| 5031 | .visib_token = pub_tok, | ||
| 5032 | .eq_token = eq_tok, | ||
| 5033 | .init_node = &call_node.base, | ||
| 5034 | }); | ||
| 4943 | try addTopLevelDecl(c, name, &var_decl_node.base); | 5035 | try addTopLevelDecl(c, name, &var_decl_node.base); |
| 4944 | } | 5036 | } |
| 4945 | 5037 | ||
| ... | @@ -5132,10 +5224,12 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void { | ... | @@ -5132,10 +5224,12 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void { |
| 5132 | fn transMacroDefine(c: *Context, it: *CTokenList.Iterator, source: []const u8, name: []const u8, source_loc: ZigClangSourceLocation) ParseError!void { | 5224 | fn transMacroDefine(c: *Context, it: *CTokenList.Iterator, source: []const u8, name: []const u8, source_loc: ZigClangSourceLocation) ParseError!void { |
| 5133 | const scope = &c.global_scope.base; | 5225 | const scope = &c.global_scope.base; |
| 5134 | 5226 | ||
| 5135 | const node = try transCreateNodeVarDecl(c, true, true, name); | 5227 | const visib_tok = try appendToken(c, .Keyword_pub, "pub"); |
| 5136 | node.eq_token = try appendToken(c, .Equal, "="); | 5228 | const mut_tok = try appendToken(c, .Keyword_const, "const"); |
| 5229 | const name_tok = try appendIdentifier(c, name); | ||
| 5230 | const eq_token = try appendToken(c, .Equal, "="); | ||
| 5137 | 5231 | ||
| 5138 | node.init_node = try parseCExpr(c, it, source, source_loc, scope); | 5232 | const init_node = try parseCExpr(c, it, source, source_loc, scope); |
| 5139 | const last = it.next().?; | 5233 | const last = it.next().?; |
| 5140 | if (last.id != .Eof and last.id != .Nl) | 5234 | if (last.id != .Eof and last.id != .Nl) |
| 5141 | return failDecl( | 5235 | return failDecl( |
| ... | @@ -5146,7 +5240,16 @@ fn transMacroDefine(c: *Context, it: *CTokenList.Iterator, source: []const u8, n | ... | @@ -5146,7 +5240,16 @@ fn transMacroDefine(c: *Context, it: *CTokenList.Iterator, source: []const u8, n |
| 5146 | .{@tagName(last.id)}, | 5240 | .{@tagName(last.id)}, |
| 5147 | ); | 5241 | ); |
| 5148 | 5242 | ||
| 5149 | node.semicolon_token = try appendToken(c, .Semicolon, ";"); | 5243 | const semicolon_token = try appendToken(c, .Semicolon, ";"); |
| 5244 | const node = try ast.Node.VarDecl.create(c.arena, .{ | ||
| 5245 | .name_token = name_tok, | ||
| 5246 | .mut_token = mut_tok, | ||
| 5247 | .semicolon_token = semicolon_token, | ||
| 5248 | }, .{ | ||
| 5249 | .visib_token = visib_tok, | ||
| 5250 | .eq_token = eq_token, | ||
| 5251 | .init_node = init_node, | ||
| 5252 | }); | ||
| 5150 | _ = try c.global_scope.macro_table.put(name, &node.base); | 5253 | _ = try c.global_scope.macro_table.put(name, &node.base); |
| 5151 | } | 5254 | } |
| 5152 | 5255 | ||
| ... | @@ -5223,24 +5326,6 @@ fn transMacroFnDefine(c: *Context, it: *CTokenList.Iterator, source: []const u8, | ... | @@ -5223,24 +5326,6 @@ fn transMacroFnDefine(c: *Context, it: *CTokenList.Iterator, source: []const u8, |
| 5223 | 5326 | ||
| 5224 | const type_of = try c.createBuiltinCall("@TypeOf", 1); | 5327 | const type_of = try c.createBuiltinCall("@TypeOf", 1); |
| 5225 | 5328 | ||
| 5226 | const fn_proto = try ast.Node.FnProto.alloc(c.arena, fn_params.items.len); | ||
| 5227 | fn_proto.* = .{ | ||
| 5228 | .visib_token = pub_tok, | ||
| 5229 | .extern_export_inline_token = inline_tok, | ||
| 5230 | .fn_token = fn_tok, | ||
| 5231 | .name_token = name_tok, | ||
| 5232 | .params_len = fn_params.items.len, | ||
| 5233 | .return_type = .{ .Explicit = &type_of.base }, | ||
| 5234 | .doc_comments = null, | ||
| 5235 | .var_args_token = null, | ||
| 5236 | .body_node = null, | ||
| 5237 | .lib_name = null, | ||
| 5238 | .align_expr = null, | ||
| 5239 | .section_expr = null, | ||
| 5240 | .callconv_expr = null, | ||
| 5241 | }; | ||
| 5242 | mem.copy(ast.Node.FnProto.ParamDecl, fn_proto.params(), fn_params.items); | ||
| 5243 | |||
| 5244 | const return_expr = try transCreateNodeReturnExpr(c); | 5329 | const return_expr = try transCreateNodeReturnExpr(c); |
| 5245 | const expr = try parseCExpr(c, it, source, source_loc, scope); | 5330 | const expr = try parseCExpr(c, it, source, source_loc, scope); |
| 5246 | const last = it.next().?; | 5331 | const last = it.next().?; |
| ... | @@ -5266,7 +5351,18 @@ fn transMacroFnDefine(c: *Context, it: *CTokenList.Iterator, source: []const u8, | ... | @@ -5266,7 +5351,18 @@ fn transMacroFnDefine(c: *Context, it: *CTokenList.Iterator, source: []const u8, |
| 5266 | 5351 | ||
| 5267 | try block_scope.statements.append(&return_expr.base); | 5352 | try block_scope.statements.append(&return_expr.base); |
| 5268 | const block_node = try block_scope.complete(c); | 5353 | const block_node = try block_scope.complete(c); |
| 5269 | fn_proto.body_node = &block_node.base; | 5354 | const fn_proto = try ast.Node.FnProto.create(c.arena, .{ |
| 5355 | .fn_token = fn_tok, | ||
| 5356 | .params_len = fn_params.items.len, | ||
| 5357 | .return_type = .{ .Explicit = &type_of.base }, | ||
| 5358 | }, .{ | ||
| 5359 | .visib_token = pub_tok, | ||
| 5360 | .extern_export_inline_token = inline_tok, | ||
| 5361 | .name_token = name_tok, | ||
| 5362 | .body_node = &block_node.base, | ||
| 5363 | }); | ||
| 5364 | mem.copy(ast.Node.FnProto.ParamDecl, fn_proto.params(), fn_params.items); | ||
| 5365 | |||
| 5270 | _ = try c.global_scope.macro_table.put(name, &fn_proto.base); | 5366 | _ = try c.global_scope.macro_table.put(name, &fn_proto.base); |
| 5271 | } | 5367 | } |
| 5272 | 5368 | ||
| ... | @@ -6030,7 +6126,7 @@ fn getContainer(c: *Context, node: *ast.Node) ?*ast.Node { | ... | @@ -6030,7 +6126,7 @@ fn getContainer(c: *Context, node: *ast.Node) ?*ast.Node { |
| 6030 | const ident = node.cast(ast.Node.Identifier).?; | 6126 | const ident = node.cast(ast.Node.Identifier).?; |
| 6031 | if (c.global_scope.sym_table.get(tokenSlice(c, ident.token))) |value| { | 6127 | if (c.global_scope.sym_table.get(tokenSlice(c, ident.token))) |value| { |
| 6032 | if (value.cast(ast.Node.VarDecl)) |var_decl| | 6128 | if (value.cast(ast.Node.VarDecl)) |var_decl| |
| 6033 | return getContainer(c, var_decl.init_node.?); | 6129 | return getContainer(c, var_decl.getTrailer("init_node").?); |
| 6034 | } | 6130 | } |
| 6035 | }, | 6131 | }, |
| 6036 | 6132 | ||
| ... | @@ -6060,7 +6156,7 @@ fn getContainerTypeOf(c: *Context, ref: *ast.Node) ?*ast.Node { | ... | @@ -6060,7 +6156,7 @@ fn getContainerTypeOf(c: *Context, ref: *ast.Node) ?*ast.Node { |
| 6060 | if (ref.cast(ast.Node.Identifier)) |ident| { | 6156 | if (ref.cast(ast.Node.Identifier)) |ident| { |
| 6061 | if (c.global_scope.sym_table.get(tokenSlice(c, ident.token))) |value| { | 6157 | if (c.global_scope.sym_table.get(tokenSlice(c, ident.token))) |value| { |
| 6062 | if (value.cast(ast.Node.VarDecl)) |var_decl| { | 6158 | if (value.cast(ast.Node.VarDecl)) |var_decl| { |
| 6063 | if (var_decl.type_node) |ty| | 6159 | if (var_decl.getTrailer("type_node")) |ty| |
| 6064 | return getContainer(c, ty); | 6160 | return getContainer(c, ty); |
| 6065 | } | 6161 | } |
| 6066 | } | 6162 | } |
| ... | @@ -6084,7 +6180,7 @@ fn getContainerTypeOf(c: *Context, ref: *ast.Node) ?*ast.Node { | ... | @@ -6084,7 +6180,7 @@ fn getContainerTypeOf(c: *Context, ref: *ast.Node) ?*ast.Node { |
| 6084 | } | 6180 | } |
| 6085 | 6181 | ||
| 6086 | fn getFnProto(c: *Context, ref: *ast.Node) ?*ast.Node.FnProto { | 6182 | fn getFnProto(c: *Context, ref: *ast.Node) ?*ast.Node.FnProto { |
| 6087 | const init = if (ref.cast(ast.Node.VarDecl)) |v| v.init_node.? else return null; | 6183 | const init = if (ref.cast(ast.Node.VarDecl)) |v| v.getTrailer("init_node").? else return null; |
| 6088 | if (getContainerTypeOf(c, init)) |ty_node| { | 6184 | if (getContainerTypeOf(c, init)) |ty_node| { |
| 6089 | if (ty_node.cast(ast.Node.OptionalType)) |prefix| { | 6185 | if (ty_node.cast(ast.Node.OptionalType)) |prefix| { |
| 6090 | if (prefix.rhs.cast(ast.Node.FnProto)) |fn_proto| { | 6186 | if (prefix.rhs.cast(ast.Node.FnProto)) |fn_proto| { |
test/translate_c.zig+1-1| ... | @@ -2797,7 +2797,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -2797,7 +2797,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2797 | \\pub fn a() callconv(.C) void {} | 2797 | \\pub fn a() callconv(.C) void {} |
| 2798 | \\pub fn b() callconv(.C) void {} | 2798 | \\pub fn b() callconv(.C) void {} |
| 2799 | \\pub export fn c() void {} | 2799 | \\pub export fn c() void {} |
| 2800 | \\pub fn foo() callconv(.C) void {} | 2800 | \\pub fn foo(...) callconv(.C) void {} |
| 2801 | }); | 2801 | }); |
| 2802 | 2802 | ||
| 2803 | cases.add("casting away const and volatile", | 2803 | cases.add("casting away const and volatile", |