Skip to content

Commit f4a1e4c

Browse files
committed
translate-c: make Node more like Type
1 parent d63ac84 commit f4a1e4c

File tree

2 files changed

+147
-82
lines changed

2 files changed

+147
-82
lines changed

src/translate_c/ast.zig

Lines changed: 142 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,19 @@ const std = @import("std");
22
const Type = @import("../type.zig").Type;
33

44
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,
79

810
pub const Tag = enum {
911
null_literal,
1012
undefined_literal,
1113
opaque_literal,
12-
bool_literal,
14+
true_literal,
15+
false_literal,
16+
// After this, the tag requires a payload.
17+
1318
int,
1419
float,
1520
string,
@@ -39,12 +44,18 @@ pub const Node = struct {
3944
discard,
4045
block,
4146

47+
pub const last_no_payload_tag = Tag.false_literal;
48+
pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
49+
4250
pub fn Type(tag: Tag) ?type {
4351
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+
4859
.int,
4960
.float,
5061
.string,
@@ -54,144 +65,186 @@ pub const Node = struct {
5465
.field_access_arrow,
5566
.warning,
5667
.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,
6374
.array_access,
6475
.std_mem_zeroes,
6576
.@"return",
6677
.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,
76100
};
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;
77106
}
78107
};
108+
};
109+
110+
pub const Payload = struct {
111+
tag: Tag,
79112

80113
pub const Infix = struct {
81114
base: Node,
82-
lhs: *Node,
83-
rhs: *Node,
115+
data: struct {
116+
lhs: *Node,
117+
rhs: *Node,
118+
},
84119
};
85120

86121
pub const Value = struct {
87122
base: Node,
88-
val: []const u8,
123+
data: []const u8,
89124
};
90125

91126
pub const SingleArg = struct {
92127
base: Node,
93-
index: *Node,
128+
data: *Node,
94129
};
95130

96131
pub const If = struct {
97132
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+
},
101138
};
102139

103140
pub const While = struct {
104141
base: Node = .{ .tag = .@"while" },
105-
cond: *Node,
106-
body: *Node,
142+
data: struct {
143+
cond: *Node,
144+
body: *Node,
145+
},
107146
};
108147

109148
pub const Switch = struct {
110149
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,
114154

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+
},
120161
};
121162

122163
pub const Break = struct {
123164
base: Node = .{ .tag = .@"break" },
124-
label: ?[]const u8,
125-
rhs: ?*Node,
165+
data: struct {
166+
label: ?[]const u8,
167+
rhs: ?*Node,
168+
},
126169
};
127170

128171
pub const Call = struct {
129172
base: Node = .{.call},
130-
lhs: *Node,
131-
args: []*Node,
173+
data: struct {
174+
lhs: *Node,
175+
args: []*Node,
176+
},
132177
};
133178

134179
pub const VarDecl = struct {
135180
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+
},
143190
};
144191

145192
pub const Func = struct {
146193
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+
},
161210
};
162211

163212
pub const Enum = struct {
164213
base: Node = .{ .tag = .@"enum" },
165-
name: ?[]const u8,
166-
fields: []Field,
214+
data: struct {
215+
name: ?[]const u8,
216+
fields: []Field,
167217

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+
},
172223
};
173224

174225
pub const Record = struct {
175226
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,
179231

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+
},
185238
};
186239

187240
pub const ArrayInit = struct {
188241
base: Node = .{ .tag = .array_init },
189-
values: []*Node,
242+
data: []*Node,
190243
};
191244

192245
pub const ContainerInit = struct {
193246
base: Node = .{ .tag = .container_init },
194-
values: []Initializer,
247+
data: []Initializer,
195248

196249
pub const Initializer = struct {
197250
name: []const u8,
@@ -201,7 +254,14 @@ pub const Node = struct {
201254

202255
pub const Block = struct {
203256
base: Node = .{ .tag = .block },
204-
label: ?[]const u8,
205-
stmts: []*Node,
257+
data: struct {
258+
label: ?[]const u8,
259+
stmts: []*Node,
260+
},
206261
};
207262
};
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+
}

src/type.zig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3406,6 +3406,11 @@ pub const Type = extern union {
34063406
};
34073407
}
34083408

3409+
pub fn init(comptime t: Tag) Type {
3410+
comptime std.debug.assert(@enumToInt(t) < Tag.no_payload_count);
3411+
return .{ .tag_if_small_enough = @enumToInt(t) };
3412+
}
3413+
34093414
pub fn create(comptime t: Tag, ally: *Allocator, data: Data(t)) error{OutOfMemory}!Type {
34103415
const ptr = try ally.create(t.Type());
34113416
ptr.* = .{

0 commit comments

Comments
 (0)