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 {...@@ -66,7 +66,9 @@ pub const Inst = struct {
66 pub const Deref = struct {66 pub const Deref = struct {
67 base: Inst = Inst{ .tag = .deref },67 base: Inst = Inst{ .tag = .deref },
6868
69 positionals: struct {},69 positionals: struct {
70 ptr: *Inst,
71 },
70 kw_args: struct {},72 kw_args: struct {},
71 };73 };
7274
...@@ -151,7 +153,7 @@ pub fn parseRoot(ctx: *ParseContext) !void {...@@ -151,7 +153,7 @@ pub fn parseRoot(ctx: *ParseContext) !void {
151 ctx.i += 1;153 ctx.i += 1;
152 const ident = try skipToAndOver(ctx, ' ');154 const ident = try skipToAndOver(ctx, ' ');
153 const opt_type = try parseOptionalType(ctx);155 const opt_type = try parseOptionalType(ctx);
154 const inst = try parseInstruction(ctx, opt_type);156 const inst = try parseInstruction(ctx, opt_type, null);
155 const ident_index = ctx.decls.items.len;157 const ident_index = ctx.decls.items.len;
156 if (try ctx.global_name_map.put(ident, ident_index)) |_| {158 if (try ctx.global_name_map.put(ident, ident_index)) |_| {
157 return parseError(ctx, "redefinition of identifier '{}'", .{ident});159 return parseError(ctx, "redefinition of identifier '{}'", .{ident});
...@@ -224,7 +226,11 @@ fn parseOptionalType(ctx: *ParseContext) !?Type {...@@ -224,7 +226,11 @@ fn parseOptionalType(ctx: *ParseContext) !?Type {
224 }226 }
225}227}
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 {
228 switch (ctx.source[ctx.i]) {234 switch (ctx.source[ctx.i]) {
229 '"' => return parseStringLiteralConst(ctx, opt_type),235 '"' => return parseStringLiteralConst(ctx, opt_type),
230 '0'...'9' => return parseIntegerLiteralConst(ctx, opt_type),236 '0'...'9' => return parseIntegerLiteralConst(ctx, opt_type),
...@@ -234,7 +240,7 @@ fn parseInstruction(ctx: *ParseContext, opt_type: ?Type) error{ OutOfMemory, Par...@@ -234,7 +240,7 @@ fn parseInstruction(ctx: *ParseContext, opt_type: ?Type) error{ OutOfMemory, Par
234 inline for (@typeInfo(Inst.Tag).Enum.fields) |field| {240 inline for (@typeInfo(Inst.Tag).Enum.fields) |field| {
235 if (mem.eql(u8, field.name, fn_name)) {241 if (mem.eql(u8, field.name, fn_name)) {
236 const tag = @field(Inst.Tag, field.name);242 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);
238 }244 }
239 }245 }
240 return parseError(ctx, "unknown instruction '{}'", .{fn_name});246 return parseError(ctx, "unknown instruction '{}'", .{fn_name});
...@@ -245,6 +251,7 @@ fn parseInstructionGeneric(...@@ -245,6 +251,7 @@ fn parseInstructionGeneric(
245 comptime fn_name: []const u8,251 comptime fn_name: []const u8,
246 comptime InstType: type,252 comptime InstType: type,
247 opt_type: ?Type,253 opt_type: ?Type,
254 body_ctx: ?*BodyContext,
248) !*Inst {255) !*Inst {
249 const inst_specific = try ctx.allocator.create(InstType);256 const inst_specific = try ctx.allocator.create(InstType);
250257
...@@ -262,7 +269,11 @@ fn parseInstructionGeneric(...@@ -262,7 +269,11 @@ fn parseInstructionGeneric(
262 } else if (ctx.source[ctx.i] == ')') {269 } else if (ctx.source[ctx.i] == ')') {
263 return parseError(ctx, "expected positional parameter '{}'", .{arg_field.name});270 return parseError(ctx, "expected positional parameter '{}'", .{arg_field.name});
264 }271 }
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 );
266 skipSpace(ctx);277 skipSpace(ctx);
267 }278 }
268279
...@@ -274,7 +285,11 @@ fn parseInstructionGeneric(...@@ -274,7 +285,11 @@ fn parseInstructionGeneric(
274 const name = try skipToAndOver(ctx, '=');285 const name = try skipToAndOver(ctx, '=');
275 inline for (@typeInfo(KW_Args).Struct.fields) |arg_field| {286 inline for (@typeInfo(KW_Args).Struct.fields) |arg_field| {
276 if (mem.eql(u8, name, arg_field.name)) {287 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 );
278 break;293 break;
279 }294 }
280 }295 }
...@@ -285,7 +300,7 @@ fn parseInstructionGeneric(...@@ -285,7 +300,7 @@ fn parseInstructionGeneric(
285 return &inst_specific.base;300 return &inst_specific.base;
286}301}
287302
288fn parseParameterGeneric(ctx: *ParseContext, comptime T: type) !T {303fn parseParameterGeneric(ctx: *ParseContext, comptime T: type, body_ctx: ?*BodyContext) !T {
289 if (@typeInfo(T) == .Enum) {304 if (@typeInfo(T) == .Enum) {
290 const start = ctx.i;305 const start = ctx.i;
291 while (ctx.i < ctx.source.len) : (ctx.i += 1) switch (ctx.source[ctx.i]) {306 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 {...@@ -303,12 +318,20 @@ fn parseParameterGeneric(ctx: *ParseContext, comptime T: type) !T {
303 switch (T) {318 switch (T) {
304 Inst.Fn.Body => return parseBody(ctx),319 Inst.Fn.Body => return parseBody(ctx),
305 *Inst => {320 *Inst => {
306 const map = switch (ctx.source[ctx.i]) {321 const local_ref = switch (ctx.source[ctx.i]) {
307 '@' => ctx.global_name_map,322 '@' => false,
308 '%' => return parseError(ctx, "TODO implement parsing % parameter", .{}),323 '%' => true,
309 '"' => return parseStringLiteralConst(ctx, null),324 '"' => return parseStringLiteralConst(ctx, null),
310 else => |byte| return parseError(ctx, "unexpected byte: '{c}'", .{byte}),325 else => |byte| return parseError(ctx, "unexpected byte: '{c}'", .{byte}),
311 };326 };
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
312 ctx.i += 1;335 ctx.i += 1;
313 const name_start = ctx.i;336 const name_start = ctx.i;
314 while (ctx.i < ctx.source.len) : (ctx.i += 1) switch (ctx.source[ctx.i]) {337 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 {...@@ -321,7 +344,11 @@ fn parseParameterGeneric(ctx: *ParseContext, comptime T: type) !T {
321 ctx.i = name_start - 1;344 ctx.i = name_start - 1;
322 return parseError(ctx, "unrecognized identifier: {}", .{bad_name});345 return parseError(ctx, "unrecognized identifier: {}", .{bad_name});
323 };346 };
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 }
325 },352 },
326 Value => return parseError(ctx, "TODO implement parseParameterGeneric for type Value", .{}),353 Value => return parseError(ctx, "TODO implement parseParameterGeneric for type Value", .{}),
327 else => @compileError("Unimplemented: ir parseParameterGeneric for type " ++ @typeName(T)),354 else => @compileError("Unimplemented: ir parseParameterGeneric for type " ++ @typeName(T)),
...@@ -329,12 +356,18 @@ fn parseParameterGeneric(ctx: *ParseContext, comptime T: type) !T {...@@ -329,12 +356,18 @@ fn parseParameterGeneric(ctx: *ParseContext, comptime T: type) !T {
329 return parseError(ctx, "TODO parse parameter {}", .{@typeName(T)});356 return parseError(ctx, "TODO parse parameter {}", .{@typeName(T)});
330}357}
331358
332fn parseBody(ctx: *ParseContext) !Inst.Fn.Body {359const BodyContext = struct {
333 var instructions = std.ArrayList(*Inst).init(ctx.allocator);360 instructions: std.ArrayList(*Inst),
334 defer instructions.deinit();361 name_map: std.StringHashMap(usize),
362};
335363
336 var name_map = std.StringHashMap(usize).init(ctx.allocator);364fn parseBody(ctx: *ParseContext) !Inst.Fn.Body {
337 defer name_map.deinit();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
339 try requireEatBytes(ctx, "{");372 try requireEatBytes(ctx, "{");
340 skipSpace(ctx);373 skipSpace(ctx);
...@@ -345,12 +378,12 @@ fn parseBody(ctx: *ParseContext) !Inst.Fn.Body {...@@ -345,12 +378,12 @@ fn parseBody(ctx: *ParseContext) !Inst.Fn.Body {
345 ctx.i += 1;378 ctx.i += 1;
346 const ident = try skipToAndOver(ctx, ' ');379 const ident = try skipToAndOver(ctx, ' ');
347 const opt_type = try parseOptionalType(ctx);380 const opt_type = try parseOptionalType(ctx);
348 const inst = try parseInstruction(ctx, opt_type);381 const inst = try parseInstruction(ctx, opt_type, &body_context);
349 const ident_index = instructions.items.len;382 const ident_index = body_context.instructions.items.len;
350 if (try name_map.put(ident, ident_index)) |_| {383 if (try body_context.name_map.put(ident, ident_index)) |_| {
351 return parseError(ctx, "redefinition of identifier '{}'", .{ident});384 return parseError(ctx, "redefinition of identifier '{}'", .{ident});
352 }385 }
353 try instructions.append(inst);386 try body_context.instructions.append(inst);
354 continue;387 continue;
355 },388 },
356 ' ', '\n' => continue,389 ' ', '\n' => continue,
...@@ -358,7 +391,7 @@ fn parseBody(ctx: *ParseContext) !Inst.Fn.Body {...@@ -358,7 +391,7 @@ fn parseBody(ctx: *ParseContext) !Inst.Fn.Body {
358 };391 };
359392
360 return Inst.Fn.Body{393 return Inst.Fn.Body{
361 .instructions = instructions.toOwnedSlice(),394 .instructions = body_context.instructions.toOwnedSlice(),
362 };395 };
363}396}
364397