@@ -2,14 +2,19 @@ const std = @import("std");
2
2
const Type = @import ("../type.zig" ).Type ;
3
3
4
4
pub const Node = struct {
5
- tag : Tag ,
6
- // type: Type = Type.initTag(.noreturn),
5
+ /// If the tag value is less than Tag.no_payload_count, then no pointer
6
+ /// dereference is needed.
7
+ tag_if_small_enough : usize ,
8
+ ptr_otherwise : * Payload ,
7
9
8
10
pub const Tag = enum {
9
11
null_literal ,
10
12
undefined_literal ,
11
13
opaque_literal ,
12
- bool_literal ,
14
+ true_literal ,
15
+ false_literal ,
16
+ // After this, the tag requires a payload.
17
+
13
18
int ,
14
19
float ,
15
20
string ,
@@ -39,12 +44,18 @@ pub const Node = struct {
39
44
discard ,
40
45
block ,
41
46
47
+ pub const last_no_payload_tag = Tag .false_literal ;
48
+ pub const no_payload_count = @enumToInt (last_no_payload_tag ) + 1 ;
49
+
42
50
pub fn Type (tag : Tag ) ? type {
43
51
return switch (tag ) {
44
- .null_literal = > null ,
45
- .undefined_literal = > null ,
46
- .opaque_literal = > null ,
47
- .bool_literal ,
52
+ .null_literal ,
53
+ .undefined_literal ,
54
+ .opaque_literal ,
55
+ .true_literal ,
56
+ .false_litral ,
57
+ = > @compileError ("Type Tag " ++ @tagName (t ) ++ " has no payload" ),
58
+
48
59
.int ,
49
60
.float ,
50
61
.string ,
@@ -54,144 +65,186 @@ pub const Node = struct {
54
65
.field_access_arrow ,
55
66
.warning ,
56
67
.failed_decl ,
57
- = > Value ,
58
- .@"if" = > If ,
59
- .@"while" = > While ,
60
- .@"switch" = > Switch ,
61
- .@"break" = > Break ,
62
- .call = > Call ,
68
+ = > Payload . Value ,
69
+ .@"if" = > Payload . If ,
70
+ .@"while" = > Payload . While ,
71
+ .@"switch" = > Payload . Switch ,
72
+ .@"break" = > Payload . Break ,
73
+ .call = > Payload . Call ,
63
74
.array_access ,
64
75
.std_mem_zeroes ,
65
76
.@"return" ,
66
77
.discard ,
67
- = > SingleArg ,
68
- .var_decl = > VarDecl ,
69
- .func = > Func ,
70
- .@"enum" = > Enum ,
71
- .@"struct" , .@"union" = > Record ,
72
- .array_init = > ArrayInit ,
73
- .container_init = > ContainerInit ,
74
- .std_meta_cast = > Infix ,
75
- .block = > Block ,
78
+ = > Payload .SingleArg ,
79
+ .var_decl = > Payload .VarDecl ,
80
+ .func = > Payload .Func ,
81
+ .@"enum" = > Payload .Enum ,
82
+ .@"struct" , .@"union" = > Payload .Record ,
83
+ .array_init = > Payload .ArrayInit ,
84
+ .container_init = > Payload .ContainerInit ,
85
+ .std_meta_cast = > Payload .Infix ,
86
+ .block = > Payload .Block ,
87
+ };
88
+ }
89
+
90
+ pub fn init (comptime t : Tag ) Node {
91
+ comptime std .debug .assert (@enumToInt (t ) < Tag .no_payload_count );
92
+ return .{ .tag_if_small_enough = @enumToInt (t ) };
93
+ }
94
+
95
+ pub fn create (comptime t : Tag , ally : * Allocator , data : Data (t )) error {OutOfMemory }! Node {
96
+ const ptr = try ally .create (t .Type ());
97
+ ptr .* = .{
98
+ .base = .{ .tag = t },
99
+ .data = data ,
76
100
};
101
+ return Node { .ptr_otherwise = & ptr .base };
102
+ }
103
+
104
+ pub fn Data (comptime t : Tag ) type {
105
+ return std .meta .fieldInfo (t .Type (), .data ).field_type ;
77
106
}
78
107
};
108
+ };
109
+
110
+ pub const Payload = struct {
111
+ tag : Tag ,
79
112
80
113
pub const Infix = struct {
81
114
base : Node ,
82
- lhs : * Node ,
83
- rhs : * Node ,
115
+ data : struct {
116
+ lhs : * Node ,
117
+ rhs : * Node ,
118
+ },
84
119
};
85
120
86
121
pub const Value = struct {
87
122
base : Node ,
88
- val : []const u8 ,
123
+ data : []const u8 ,
89
124
};
90
125
91
126
pub const SingleArg = struct {
92
127
base : Node ,
93
- index : * Node ,
128
+ data : * Node ,
94
129
};
95
130
96
131
pub const If = struct {
97
132
base : Node = .{ .tag = .@"if" },
98
- cond : * Node ,
99
- then : * Node ,
100
- @"else" : ? * Node ,
133
+ data : struct {
134
+ cond : * Node ,
135
+ then : * Node ,
136
+ @"else" : ? * Node ,
137
+ },
101
138
};
102
139
103
140
pub const While = struct {
104
141
base : Node = .{ .tag = .@"while" },
105
- cond : * Node ,
106
- body : * Node ,
142
+ data : struct {
143
+ cond : * Node ,
144
+ body : * Node ,
145
+ },
107
146
};
108
147
109
148
pub const Switch = struct {
110
149
base : Node = .{ .tag = .@"switch" },
111
- cond : * Node ,
112
- cases : []Prong ,
113
- default : ? []const u8 ,
150
+ data : struct {
151
+ cond : * Node ,
152
+ cases : []Prong ,
153
+ default : ? []const u8 ,
114
154
115
- pub const Prong = struct {
116
- lhs : * Node ,
117
- rhs : ? * Node ,
118
- label : []const u8 ,
119
- };
155
+ pub const Prong = struct {
156
+ lhs : * Node ,
157
+ rhs : ? * Node ,
158
+ label : []const u8 ,
159
+ };
160
+ },
120
161
};
121
162
122
163
pub const Break = struct {
123
164
base : Node = .{ .tag = .@"break" },
124
- label : ? []const u8 ,
125
- rhs : ? * Node ,
165
+ data : struct {
166
+ label : ? []const u8 ,
167
+ rhs : ? * Node ,
168
+ },
126
169
};
127
170
128
171
pub const Call = struct {
129
172
base : Node = .{.call },
130
- lhs : * Node ,
131
- args : []* Node ,
173
+ data : struct {
174
+ lhs : * Node ,
175
+ args : []* Node ,
176
+ },
132
177
};
133
178
134
179
pub const VarDecl = struct {
135
180
base : Node = .{ .tag = .var_decl },
136
- @"pub" : bool ,
137
- @"const" : bool ,
138
- @"extern" : bool ,
139
- @"export" : bool ,
140
- name : []const u8 ,
141
- type : Type ,
142
- init : * Node ,
181
+ data : struct {
182
+ @"pub" : bool ,
183
+ @"const" : bool ,
184
+ @"extern" : bool ,
185
+ @"export" : bool ,
186
+ name : []const u8 ,
187
+ type : Type ,
188
+ init : * Node ,
189
+ },
143
190
};
144
191
145
192
pub const Func = struct {
146
193
base : Node = .{.func },
147
- @"pub" : bool ,
148
- @"extern" : bool ,
149
- @"export" : bool ,
150
- name : []const u8 ,
151
- cc : std.builtin.CallingConvention ,
152
- params : []Param ,
153
- return_type : Type ,
154
- body : ? * Node ,
155
-
156
- pub const Param = struct {
157
- @"noalias" : bool ,
158
- name : ? []const u8 ,
159
- type : Type ,
160
- };
194
+ data : struct {
195
+ @"pub" : bool ,
196
+ @"extern" : bool ,
197
+ @"export" : bool ,
198
+ name : []const u8 ,
199
+ cc : std.builtin.CallingConvention ,
200
+ params : []Param ,
201
+ return_type : Type ,
202
+ body : ? * Node ,
203
+
204
+ pub const Param = struct {
205
+ @"noalias" : bool ,
206
+ name : ? []const u8 ,
207
+ type : Type ,
208
+ };
209
+ },
161
210
};
162
211
163
212
pub const Enum = struct {
164
213
base : Node = .{ .tag = .@"enum" },
165
- name : ? []const u8 ,
166
- fields : []Field ,
214
+ data : struct {
215
+ name : ? []const u8 ,
216
+ fields : []Field ,
167
217
168
- pub const Field = struct {
169
- name : []const u8 ,
170
- value : ? []const u8 ,
171
- };
218
+ pub const Field = struct {
219
+ name : []const u8 ,
220
+ value : ? []const u8 ,
221
+ };
222
+ },
172
223
};
173
224
174
225
pub const Record = struct {
175
226
base : Node ,
176
- name : ? []const u8 ,
177
- @"packed" : bool ,
178
- fields : []Field ,
227
+ data : struct {
228
+ name : ? []const u8 ,
229
+ @"packed" : bool ,
230
+ fields : []Field ,
179
231
180
- pub const Field = struct {
181
- name : []const u8 ,
182
- type : Type ,
183
- alignment : c_uint ,
184
- };
232
+ pub const Field = struct {
233
+ name : []const u8 ,
234
+ type : Type ,
235
+ alignment : c_uint ,
236
+ };
237
+ },
185
238
};
186
239
187
240
pub const ArrayInit = struct {
188
241
base : Node = .{ .tag = .array_init },
189
- values : []* Node ,
242
+ data : []* Node ,
190
243
};
191
244
192
245
pub const ContainerInit = struct {
193
246
base : Node = .{ .tag = .container_init },
194
- values : []Initializer ,
247
+ data : []Initializer ,
195
248
196
249
pub const Initializer = struct {
197
250
name : []const u8 ,
@@ -201,7 +254,14 @@ pub const Node = struct {
201
254
202
255
pub const Block = struct {
203
256
base : Node = .{ .tag = .block },
204
- label : ? []const u8 ,
205
- stmts : []* Node ,
257
+ data : struct {
258
+ label : ? []const u8 ,
259
+ stmts : []* Node ,
260
+ },
206
261
};
207
262
};
263
+
264
+ /// Converts the nodes into a Zig ast and then renders it.
265
+ pub fn render (allocator : * Allocator , nodes : []const Node ) ! void {
266
+ @panic ("TODO" );
267
+ }
0 commit comments