authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-04-19 01:29:01-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-04-19 19:31:50-04:00
log82e294cf09cab1610f948430f4c05150f3913806
tree3ccd56a0d82d48e4c25e63fb4bbbf7ad442ddba3
parent730dd887e49e8cde90af1dc76238c0c07d6c3c36

ir: parse deref instruction


1 files changed, 54 insertions(+), 21 deletions(-)

src-self-hosted/ir.zig+54-21
......@@ -66,7 +66,9 @@ pub const Inst = struct {
6666 pub const Deref = struct {
6767 base: Inst = Inst{ .tag = .deref },
6868
69 positionals: struct {},
69 positionals: struct {
70 ptr: *Inst,
71 },
7072 kw_args: struct {},
7173 };
7274
......@@ -151,7 +153,7 @@ pub fn parseRoot(ctx: *ParseContext) !void {
151153 ctx.i += 1;
152154 const ident = try skipToAndOver(ctx, ' ');
153155 const opt_type = try parseOptionalType(ctx);
154 const inst = try parseInstruction(ctx, opt_type);
156 const inst = try parseInstruction(ctx, opt_type, null);
155157 const ident_index = ctx.decls.items.len;
156158 if (try ctx.global_name_map.put(ident, ident_index)) |_| {
157159 return parseError(ctx, "redefinition of identifier '{}'", .{ident});
......@@ -224,7 +226,11 @@ fn parseOptionalType(ctx: *ParseContext) !?Type {
224226 }
225227}
226228
227fn parseInstruction(ctx: *ParseContext, opt_type: ?Type) error{ OutOfMemory, ParseFailure }!*Inst {
229fn parseInstruction(
230 ctx: *ParseContext,
231 opt_type: ?Type,
232 body_ctx: ?*BodyContext,
233) error{ OutOfMemory, ParseFailure }!*Inst {
228234 switch (ctx.source[ctx.i]) {
229235 '"' => return parseStringLiteralConst(ctx, opt_type),
230236 '0'...'9' => return parseIntegerLiteralConst(ctx, opt_type),
......@@ -234,7 +240,7 @@ fn parseInstruction(ctx: *ParseContext, opt_type: ?Type) error{ OutOfMemory, Par
234240 inline for (@typeInfo(Inst.Tag).Enum.fields) |field| {
235241 if (mem.eql(u8, field.name, fn_name)) {
236242 const tag = @field(Inst.Tag, field.name);
237 return parseInstructionGeneric(ctx, field.name, Inst.TagToType(tag), opt_type);
243 return parseInstructionGeneric(ctx, field.name, Inst.TagToType(tag), opt_type, body_ctx);
238244 }
239245 }
240246 return parseError(ctx, "unknown instruction '{}'", .{fn_name});
......@@ -245,6 +251,7 @@ fn parseInstructionGeneric(
245251 comptime fn_name: []const u8,
246252 comptime InstType: type,
247253 opt_type: ?Type,
254 body_ctx: ?*BodyContext,
248255) !*Inst {
249256 const inst_specific = try ctx.allocator.create(InstType);
250257
......@@ -262,7 +269,11 @@ fn parseInstructionGeneric(
262269 } else if (ctx.source[ctx.i] == ')') {
263270 return parseError(ctx, "expected positional parameter '{}'", .{arg_field.name});
264271 }
265 @field(inst_specific.positionals, arg_field.name) = try parseParameterGeneric(ctx, arg_field.field_type);
272 @field(inst_specific.positionals, arg_field.name) = try parseParameterGeneric(
273 ctx,
274 arg_field.field_type,
275 body_ctx,
276 );
266277 skipSpace(ctx);
267278 }
268279
......@@ -274,7 +285,11 @@ fn parseInstructionGeneric(
274285 const name = try skipToAndOver(ctx, '=');
275286 inline for (@typeInfo(KW_Args).Struct.fields) |arg_field| {
276287 if (mem.eql(u8, name, arg_field.name)) {
277 @field(inst_specific.kw_args, arg_field.name) = try parseParameterGeneric(ctx, arg_field.field_type);
288 @field(inst_specific.kw_args, arg_field.name) = try parseParameterGeneric(
289 ctx,
290 arg_field.field_type,
291 body_ctx,
292 );
278293 break;
279294 }
280295 }
......@@ -285,7 +300,7 @@ fn parseInstructionGeneric(
285300 return &inst_specific.base;
286301}
287302
288fn parseParameterGeneric(ctx: *ParseContext, comptime T: type) !T {
303fn parseParameterGeneric(ctx: *ParseContext, comptime T: type, body_ctx: ?*BodyContext) !T {
289304 if (@typeInfo(T) == .Enum) {
290305 const start = ctx.i;
291306 while (ctx.i < ctx.source.len) : (ctx.i += 1) switch (ctx.source[ctx.i]) {
......@@ -303,12 +318,20 @@ fn parseParameterGeneric(ctx: *ParseContext, comptime T: type) !T {
303318 switch (T) {
304319 Inst.Fn.Body => return parseBody(ctx),
305320 *Inst => {
306 const map = switch (ctx.source[ctx.i]) {
307 '@' => ctx.global_name_map,
308 '%' => return parseError(ctx, "TODO implement parsing % parameter", .{}),
321 const local_ref = switch (ctx.source[ctx.i]) {
322 '@' => false,
323 '%' => true,
309324 '"' => return parseStringLiteralConst(ctx, null),
310325 else => |byte| return parseError(ctx, "unexpected byte: '{c}'", .{byte}),
311326 };
327 const map = if (local_ref)
328 if (body_ctx) |bc|
329 &bc.name_map
330 else
331 return parseError(ctx, "referencing a % instruction in global scope", .{})
332 else
333 ctx.global_name_map;
334
312335 ctx.i += 1;
313336 const name_start = ctx.i;
314337 while (ctx.i < ctx.source.len) : (ctx.i += 1) switch (ctx.source[ctx.i]) {
......@@ -321,7 +344,11 @@ fn parseParameterGeneric(ctx: *ParseContext, comptime T: type) !T {
321344 ctx.i = name_start - 1;
322345 return parseError(ctx, "unrecognized identifier: {}", .{bad_name});
323346 };
324 return ctx.decls.items[kv.value];
347 if (local_ref) {
348 return body_ctx.?.instructions.items[kv.value];
349 } else {
350 return ctx.decls.items[kv.value];
351 }
325352 },
326353 Value => return parseError(ctx, "TODO implement parseParameterGeneric for type Value", .{}),
327354 else => @compileError("Unimplemented: ir parseParameterGeneric for type " ++ @typeName(T)),
......@@ -329,12 +356,18 @@ fn parseParameterGeneric(ctx: *ParseContext, comptime T: type) !T {
329356 return parseError(ctx, "TODO parse parameter {}", .{@typeName(T)});
330357}
331358
332fn parseBody(ctx: *ParseContext) !Inst.Fn.Body {
333 var instructions = std.ArrayList(*Inst).init(ctx.allocator);
334 defer instructions.deinit();
359const BodyContext = struct {
360 instructions: std.ArrayList(*Inst),
361 name_map: std.StringHashMap(usize),
362};
335363
336 var name_map = std.StringHashMap(usize).init(ctx.allocator);
337 defer name_map.deinit();
364fn parseBody(ctx: *ParseContext) !Inst.Fn.Body {
365 var body_context = BodyContext{
366 .instructions = std.ArrayList(*Inst).init(ctx.allocator),
367 .name_map = std.StringHashMap(usize).init(ctx.allocator),
368 };
369 defer body_context.instructions.deinit();
370 defer body_context.name_map.deinit();
338371
339372 try requireEatBytes(ctx, "{");
340373 skipSpace(ctx);
......@@ -345,12 +378,12 @@ fn parseBody(ctx: *ParseContext) !Inst.Fn.Body {
345378 ctx.i += 1;
346379 const ident = try skipToAndOver(ctx, ' ');
347380 const opt_type = try parseOptionalType(ctx);
348 const inst = try parseInstruction(ctx, opt_type);
349 const ident_index = instructions.items.len;
350 if (try name_map.put(ident, ident_index)) |_| {
381 const inst = try parseInstruction(ctx, opt_type, &body_context);
382 const ident_index = body_context.instructions.items.len;
383 if (try body_context.name_map.put(ident, ident_index)) |_| {
351384 return parseError(ctx, "redefinition of identifier '{}'", .{ident});
352385 }
353 try instructions.append(inst);
386 try body_context.instructions.append(inst);
354387 continue;
355388 },
356389 ' ', '\n' => continue,
......@@ -358,7 +391,7 @@ fn parseBody(ctx: *ParseContext) !Inst.Fn.Body {
358391 };
359392
360393 return Inst.Fn.Body{
361 .instructions = instructions.toOwnedSlice(),
394 .instructions = body_context.instructions.toOwnedSlice(),
362395 };
363396}
364397