fix: error reporting for global variables
This commit is contained in:
parent
2dfa6cd842
commit
9ca2200448
5 changed files with 80 additions and 55 deletions
92
src/Sema.zig
92
src/Sema.zig
|
|
@ -12,6 +12,7 @@ gpa: std.mem.Allocator,
|
|||
arena: std.mem.Allocator,
|
||||
module: *compile.Module,
|
||||
ir: Ir,
|
||||
inst_map: std.AutoHashMapUnmanaged(Ir.Inst.Index, Ref) = .empty,
|
||||
errors: *std.ArrayListUnmanaged(Module.Error),
|
||||
|
||||
const InnerError = error{
|
||||
|
|
@ -75,14 +76,16 @@ pub fn lookupIdentifier(
|
|||
sema: *Sema,
|
||||
chunk: *Chunk,
|
||||
ident: InternPool.Constant.Index,
|
||||
src: SrcLoc,
|
||||
) !Ref {
|
||||
return sema.lookupInNamespace(chunk.namespace, ident);
|
||||
return sema.lookupInNamespace(chunk.namespace, ident, src);
|
||||
}
|
||||
|
||||
pub fn lookupInNamespace(
|
||||
sema: *Sema,
|
||||
namespace: *Module.Namespace,
|
||||
ident: InternPool.Constant.Index,
|
||||
src: SrcLoc,
|
||||
) !Ref {
|
||||
var scope: ?*Module.Namespace = namespace;
|
||||
while (scope) |s| : (scope = s.parent) {
|
||||
|
|
@ -95,10 +98,11 @@ pub fn lookupInNamespace(
|
|||
};
|
||||
}
|
||||
// FIXME: This is temporary
|
||||
return sema.fail(.{ .src_offset = 0 }, "unknown identifier", .{});
|
||||
return sema.fail(src, "unknown identifier", .{});
|
||||
}
|
||||
|
||||
pub fn deinit(sema: *Sema) void {
|
||||
sema.inst_map.deinit(sema.gpa);
|
||||
sema.* = undefined;
|
||||
}
|
||||
|
||||
|
|
@ -106,7 +110,6 @@ pub const Chunk = struct {
|
|||
sema: *Sema,
|
||||
namespace: *Module.Namespace,
|
||||
code: *Module.CodeChunk,
|
||||
inst_map: std.AutoHashMapUnmanaged(Ir.Inst.Index, Ref) = .empty,
|
||||
constants_map: std.AutoHashMapUnmanaged(InternPool.Constant.Index, u8) = .empty,
|
||||
labels: std.ArrayListUnmanaged(Label) = .empty,
|
||||
fixups: std.ArrayListUnmanaged(Fixup) = .empty,
|
||||
|
|
@ -127,7 +130,6 @@ pub const Chunk = struct {
|
|||
const dummy_address = 0xffffffff;
|
||||
|
||||
pub fn deinit(chunk: *Chunk, gpa: std.mem.Allocator) void {
|
||||
chunk.inst_map.deinit(gpa);
|
||||
chunk.constants_map.deinit(gpa);
|
||||
chunk.labels.deinit(gpa);
|
||||
chunk.fixups.deinit(gpa);
|
||||
|
|
@ -223,7 +225,7 @@ pub const Chunk = struct {
|
|||
|
||||
fn resolveInst(chunk: *Chunk, ref: Ir.Inst.Ref) Ref {
|
||||
if (ref.toIndex()) |index| {
|
||||
return chunk.inst_map.get(index).?;
|
||||
return chunk.sema.inst_map.get(index).?;
|
||||
}
|
||||
switch (ref) {
|
||||
.bool_true => return .bool_true,
|
||||
|
|
@ -511,8 +513,9 @@ fn irImplicitRet(_: *Sema, chunk: *Chunk, _: Ir.Inst.Index) InnerError!Ref {
|
|||
|
||||
fn irDeclRef(sema: *Sema, chunk: *Chunk, inst: Ir.Inst.Index) InnerError!Ref {
|
||||
const data = sema.ir.instructions[@intFromEnum(inst)].data.str_tok;
|
||||
const src_loc: SrcLoc = .{ .src_offset = data.src_offset };
|
||||
const decl_name = try sema.getOrPutStr(data.start);
|
||||
return sema.lookupIdentifier(chunk, decl_name.constant);
|
||||
return sema.lookupIdentifier(chunk, decl_name.constant, src_loc);
|
||||
}
|
||||
|
||||
fn irCall(_: *Sema, _: *Chunk, _: Ir.Inst.Index) !Ref {
|
||||
|
|
@ -532,19 +535,22 @@ fn irDivert(
|
|||
const data = sema.ir.instructions[@intFromEnum(inst)].data.payload;
|
||||
const extra = sema.ir.extraData(ExtraType, data.extra_index);
|
||||
const body = sema.ir.extra[extra.end..];
|
||||
const callee_src: SrcLoc = .{ .src_offset = data.src_offset };
|
||||
switch (kind) {
|
||||
.direct => {
|
||||
const callee = chunk.resolveInst(extra.data.callee);
|
||||
const callee_src: SrcLoc = .{ .src_offset = data.src_offset };
|
||||
_ = try analyzeDivertTarget(sema, chunk, callee_src, callee);
|
||||
},
|
||||
.field => {
|
||||
const callee = chunk.resolveInst(extra.data.obj_ptr);
|
||||
const callee_src: SrcLoc = .{ .src_offset = data.src_offset };
|
||||
const field_name = try sema.getOrPutStr(extra.data.field_name_start);
|
||||
|
||||
_ = try analyzeDivertTarget(sema, chunk, callee_src, callee);
|
||||
const e = try sema.lookupInNamespace(callee.knot.namespace, field_name.constant);
|
||||
const e = try sema.lookupInNamespace(
|
||||
callee.knot.namespace,
|
||||
field_name.constant,
|
||||
callee_src,
|
||||
);
|
||||
switch (e) {
|
||||
.knot => |knot| {
|
||||
const local_index = try chunk.getOrPutConstantIndex(knot.const_index);
|
||||
|
|
@ -682,7 +688,7 @@ fn analyzeBodyInner(sema: *Sema, chunk: *Chunk, body: []const Ir.Inst.Index) Inn
|
|||
.field_ptr => try irFieldPtr(sema, chunk, inst),
|
||||
.param => try irParam(sema, chunk, inst),
|
||||
};
|
||||
try chunk.inst_map.put(sema.gpa, inst, ref);
|
||||
try sema.inst_map.put(sema.gpa, inst, ref);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -738,6 +744,21 @@ fn analyzeNestedDecl(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn analyzeGlobalBlockInner(sema: *Sema, chunk: *Chunk, inst: Ir.Inst.Index) !void {
|
||||
const data = sema.ir.instructions[@intFromEnum(inst)].data.payload;
|
||||
const extra = sema.ir.extraData(Ir.Inst.Var, data.payload.extra_index);
|
||||
const body = sema.ir.bodySlice(extra.end, extra.data.body_len);
|
||||
try analyzeBodyInner(sema, chunk, body);
|
||||
// FIXME: hack
|
||||
{
|
||||
const last_inst = body[body.len - 1].toRef();
|
||||
const val = chunk.resolveInst(last_inst);
|
||||
_ = try chunk.doLoad(val);
|
||||
}
|
||||
_ = try chunk.addConstOp(.store_global, @intCast(@intFromEnum(0)));
|
||||
_ = try chunk.addByteOp(.pop);
|
||||
}
|
||||
|
||||
pub fn analyzeTopLevelDecl(
|
||||
sema: *Sema,
|
||||
namespace: *Module.Namespace,
|
||||
|
|
@ -747,42 +768,41 @@ pub fn analyzeTopLevelDecl(
|
|||
const extra = sema.ir.extraData(Ir.Inst.Declaration, data.extra_index).data;
|
||||
const decl_inst = sema.ir.instructions[@intFromEnum(extra.value)];
|
||||
const decl_name = try sema.module.intern_pool.getOrPutStr(sema.gpa, extra.name);
|
||||
const src_loc: SrcLoc = .{ .src_offset = data.src_offset };
|
||||
|
||||
switch (decl_inst.tag) {
|
||||
.decl_var => {
|
||||
const decl_extra = sema.ir.extraData(Ir.Inst.Var, decl_inst.data.payload.extra_index);
|
||||
const body = sema.ir.bodySlice(decl_extra.end, decl_extra.data.body_len);
|
||||
|
||||
try namespace.decls.put(sema.gpa, decl_name, .{
|
||||
.tag = .variable,
|
||||
.namespace = null,
|
||||
.decl_inst = extra.value,
|
||||
.args_count = 0,
|
||||
});
|
||||
|
||||
// FIXME: Broken
|
||||
var chunk: *Chunk = undefined;
|
||||
try analyzeBodyInner(sema, chunk, body);
|
||||
// FIXME: hack
|
||||
{
|
||||
const last_inst = body[body.len - 1].toRef();
|
||||
const val = chunk.resolveInst(last_inst);
|
||||
_ = try chunk.doLoad(val);
|
||||
const gop = try namespace.decls.getOrPut(sema.arena, decl_name);
|
||||
if (gop.found_existing) {
|
||||
return sema.fail(src_loc, "duplicate identifier", .{});
|
||||
} else {
|
||||
gop.value_ptr.* = .{
|
||||
.tag = .variable,
|
||||
.namespace = null,
|
||||
.decl_inst = extra.value,
|
||||
.args_count = 0,
|
||||
};
|
||||
}
|
||||
_ = try chunk.addConstOp(.store_global, @intCast(@intFromEnum(decl_name)));
|
||||
_ = try chunk.addByteOp(.pop);
|
||||
},
|
||||
.decl_knot => {
|
||||
const _data = sema.ir.instructions[@intFromEnum(extra.value)].data.payload;
|
||||
const _extra = sema.ir.extraData(Ir.Inst.Knot, _data.extra_index);
|
||||
const _body = sema.ir.bodySlice(_extra.end, _extra.data.body_len);
|
||||
const _stitches = sema.ir.bodySlice(_extra.end + _body.len, _extra.data.stitches_len);
|
||||
|
||||
const child_namespace = try sema.module.createNamespace(namespace);
|
||||
try namespace.decls.put(sema.arena, decl_name, .{
|
||||
.tag = .knot,
|
||||
.decl_inst = extra.value,
|
||||
.args_count = 0,
|
||||
.namespace = child_namespace,
|
||||
});
|
||||
const gop = try namespace.decls.getOrPut(sema.arena, decl_name);
|
||||
if (gop.found_existing) {
|
||||
return sema.fail(src_loc, "duplicate identifier", .{});
|
||||
} else {
|
||||
gop.value_ptr.* = .{
|
||||
.tag = .knot,
|
||||
.decl_inst = extra.value,
|
||||
.args_count = 0,
|
||||
.namespace = child_namespace,
|
||||
};
|
||||
}
|
||||
|
||||
try sema.module.queueWorkItem(.{
|
||||
.tag = .knot,
|
||||
.decl_name = decl_name,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue