feat: error message for unknown global variables
This commit is contained in:
parent
c940374f27
commit
47351cd6f9
6 changed files with 184 additions and 89 deletions
63
src/Sema.zig
63
src/Sema.zig
|
|
@ -1,19 +1,25 @@
|
|||
const std = @import("std");
|
||||
const Ast = @import("Ast.zig");
|
||||
const Ir = @import("Ir.zig");
|
||||
const Story = @import("Story.zig");
|
||||
const Compilation = @import("compile.zig").Compilation;
|
||||
const compile = @import("compile.zig");
|
||||
const Compilation = compile.Compilation;
|
||||
const assert = std.debug.assert;
|
||||
const Sema = @This();
|
||||
|
||||
gpa: std.mem.Allocator,
|
||||
ir: *const Ir,
|
||||
arena: std.mem.Allocator,
|
||||
tree: Ast,
|
||||
ir: Ir,
|
||||
constants: std.ArrayListUnmanaged(Compilation.Constant) = .empty,
|
||||
constant_map: std.AutoHashMapUnmanaged(Compilation.Constant, u32) = .empty,
|
||||
knots: std.ArrayListUnmanaged(Compilation.Knot) = .empty,
|
||||
globals: std.ArrayListUnmanaged(u32) = .empty,
|
||||
errors: *std.ArrayListUnmanaged(Compilation.Error),
|
||||
|
||||
const InnerError = error{
|
||||
OutOfMemory,
|
||||
AnalysisFail,
|
||||
TooManyConstants,
|
||||
InvalidJump,
|
||||
};
|
||||
|
|
@ -37,8 +43,26 @@ pub fn deinit(sema: *Sema) void {
|
|||
sema.* = undefined;
|
||||
}
|
||||
|
||||
fn fail(_: *Sema, message: []const u8) InnerError {
|
||||
@panic(message);
|
||||
pub const SrcLoc = struct {
|
||||
byte_offset: u32,
|
||||
};
|
||||
|
||||
fn fail(
|
||||
sema: *Sema,
|
||||
src: SrcLoc,
|
||||
comptime format: []const u8,
|
||||
args: anytype,
|
||||
) error{ OutOfMemory, AnalysisFail } {
|
||||
// TODO: Revisit this
|
||||
const message = try std.fmt.allocPrint(sema.arena, format, args);
|
||||
const loc = compile.findLineColumn(sema.tree.source, src.byte_offset);
|
||||
try sema.errors.append(sema.gpa, .{
|
||||
.line = loc.line,
|
||||
.column = loc.column,
|
||||
.snippet = loc.source_line,
|
||||
.message = message,
|
||||
});
|
||||
return error.AnalysisFail;
|
||||
}
|
||||
|
||||
fn getConstant(sema: *Sema, data: Compilation.Constant) !Ref {
|
||||
|
|
@ -61,23 +85,23 @@ fn addGlobal(sema: *Sema, name: Ir.NullTerminatedString) !Ref {
|
|||
return .{ .global = interned.constant };
|
||||
}
|
||||
|
||||
fn getGlobal(sema: *Sema, name: Ir.NullTerminatedString) !Ref {
|
||||
fn getGlobal(sema: *Sema, name: Ir.NullTerminatedString) !?Ref {
|
||||
const interned = try sema.getConstant(.{ .string = name });
|
||||
for (sema.ir.globals) |global| {
|
||||
if (global.name == name) {
|
||||
return .{ .global = interned.constant };
|
||||
}
|
||||
}
|
||||
return fail(sema, "unknown global variable");
|
||||
return null;
|
||||
}
|
||||
|
||||
fn irInteger(sema: *Sema, inst: Ir.Inst.Index) InnerError!Ref {
|
||||
const data = sema.ir.instructions[@intFromEnum(inst)].data.integer;
|
||||
return sema.getConstant(.{ .integer = data.value });
|
||||
const value = sema.ir.instructions[@intFromEnum(inst)].data.int;
|
||||
return sema.getConstant(.{ .integer = value });
|
||||
}
|
||||
|
||||
fn irString(sema: *Sema, inst: Ir.Inst.Index) InnerError!Ref {
|
||||
const data = sema.ir.instructions[@intFromEnum(inst)].data.string;
|
||||
const data = sema.ir.instructions[@intFromEnum(inst)].data.str;
|
||||
return sema.getConstant(.{ .string = data.start });
|
||||
}
|
||||
|
||||
|
|
@ -308,9 +332,20 @@ fn irImplicitRet(_: *Sema, chunk: *Chunk, _: Ir.Inst.Index) InnerError!Ref {
|
|||
return chunk.addByteOp(.exit);
|
||||
}
|
||||
|
||||
fn resolveGlobal(
|
||||
sema: *Sema,
|
||||
byte_offset: u32,
|
||||
global_name: Ir.NullTerminatedString,
|
||||
) !Ref {
|
||||
if (try sema.getGlobal(global_name)) |global| {
|
||||
return global;
|
||||
}
|
||||
return fail(sema, .{ .byte_offset = byte_offset }, "unknown global variable", .{});
|
||||
}
|
||||
|
||||
fn irDeclRef(sema: *Sema, _: *Chunk, inst: Ir.Inst.Index) InnerError!Ref {
|
||||
const data = sema.ir.instructions[@intFromEnum(inst)].data.string;
|
||||
return sema.getGlobal(data.start);
|
||||
const data = sema.ir.instructions[@intFromEnum(inst)].data.str_tok;
|
||||
return resolveGlobal(sema, data.src_offset, data.start);
|
||||
}
|
||||
|
||||
fn irDeclVar(
|
||||
|
|
@ -470,8 +505,8 @@ fn blockBodyInner(sema: *Sema, chunk: *Chunk, body: []const Ir.Inst.Index) Inner
|
|||
.cmp_gt => try irBinary(sema, chunk, inst, .cmp_gt),
|
||||
.cmp_gte => try irBinary(sema, chunk, inst, .cmp_gte),
|
||||
.decl_ref => try irDeclRef(sema, chunk, inst),
|
||||
.integer => try irInteger(sema, inst),
|
||||
.string => try irString(sema, inst),
|
||||
.int => try irInteger(sema, inst),
|
||||
.str => try irString(sema, inst),
|
||||
.condbr => try irCondBr(sema, chunk, inst),
|
||||
.@"break" => {
|
||||
try irBreak(sema, inst);
|
||||
|
|
@ -505,7 +540,7 @@ fn blockBodyInner(sema: *Sema, chunk: *Chunk, body: []const Ir.Inst.Index) Inner
|
|||
}
|
||||
}
|
||||
|
||||
pub fn analyzeFile(sema: *Sema, inst: Ir.Inst.Index) !void {
|
||||
pub fn analyzeFile(sema: *Sema, inst: Ir.Inst.Index) InnerError!void {
|
||||
const data = sema.ir.instructions[@intFromEnum(inst)].data.payload;
|
||||
const extra = sema.ir.extraData(Ir.Inst.Block, data.payload_index);
|
||||
const body = sema.ir.bodySlice(extra.end, extra.data.body_len);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue