analysis: create err ctx buffer on init()

- do better error message for resolveGlobalType
This commit is contained in:
Luna 2019-09-27 10:47:34 -03:00
parent c3d3486163
commit 76d888bde8
3 changed files with 39 additions and 25 deletions

View File

@ -8,7 +8,7 @@ fn f() i32 {
} }
fn f2() i32 { fn f2() i32 {
return f() + 2; return f.awoo;
} }
enum B { enum B {

View File

@ -16,8 +16,13 @@ pub const TypeSolver = struct {
err_tok: ?Token = null, err_tok: ?Token = null,
hadError: bool = false, hadError: bool = false,
pub fn init(allocator: *std.mem.Allocator) TypeSolver { err_ctx_buffer: []u8,
return TypeSolver{ .allocator = allocator };
pub fn init(allocator: *std.mem.Allocator) !TypeSolver {
return TypeSolver{
.allocator = allocator,
.err_ctx_buffer = try allocator.alloc(u8, 512),
};
} }
fn setErrContext(self: *@This(), comptime fmt: ?[]const u8, args: ...) void { fn setErrContext(self: *@This(), comptime fmt: ?[]const u8, args: ...) void {
@ -26,9 +31,11 @@ pub const TypeSolver = struct {
return; return;
} }
// TODO allocate buffer on init() and use it self.err_ctx = std.fmt.bufPrint(
var buf = self.allocator.alloc(u8, 256) catch unreachable; self.err_ctx_buffer,
self.err_ctx = std.fmt.bufPrint(buf, fmt.?, args) catch unreachable; fmt.?,
args,
) catch unreachable;
} }
fn setErrToken(self: *@This(), tok: ?Token) void { fn setErrToken(self: *@This(), tok: ?Token) void {
@ -38,7 +45,7 @@ pub const TypeSolver = struct {
fn doError(self: *@This(), comptime fmt: []const u8, args: ...) void { fn doError(self: *@This(), comptime fmt: []const u8, args: ...) void {
self.hadError = true; self.hadError = true;
std.debug.warn("type error"); std.debug.warn("analysis error");
if (self.err_tok) |tok| { if (self.err_tok) |tok| {
std.debug.warn(" at line {}", tok.line); std.debug.warn(" at line {}", tok.line);
} }
@ -53,35 +60,41 @@ pub const TypeSolver = struct {
} }
/// Resolve a type in global scope /// Resolve a type in global scope
/// Properly resolves composite (currently opaque) types to structs/enums.
fn resolveGlobalType( fn resolveGlobalType(
self: *@This(), self: *@This(),
ctx: *comp.CompilationContext, ctx: *comp.CompilationContext,
identifier: []const u8, identifier: []const u8,
) ?SymbolUnderlyingType { ) ?SymbolUnderlyingType {
// assume the identifier references a builtin // first, we assume the identifier is for a simple type
// if we fail (and this always returns OpaqueType as a fallback),
// we take it and find something in global scope
var typ = ctx.solveType(identifier); var typ = ctx.solveType(identifier);
switch (typ) { switch (typ) {
.OpaqueType => |val| { .OpaqueType => |val| {
// solve for opaque so it isnt opaque
var sym = ctx.symbol_table.get(val); var sym = ctx.symbol_table.get(val);
if (sym != null)
return switch (sym.?.value) {
.Struct => SymbolUnderlyingType{ .Struct = val },
.Enum => SymbolUnderlyingType{ .Enum = val },
else => blk: { if (sym == null) {
self.doError( self.doError("Unknown type: '{}'", val);
"expected struct or enum for type '{}', got {}", return null;
val, }
sym,
);
break :blk null;
},
};
self.doError("Unknown type: '{}'", val); return switch (sym.?.value) {
return null; .Struct => SymbolUnderlyingType{ .Struct = val },
.Enum => SymbolUnderlyingType{ .Enum = val },
// TODO name resolution
else => blk: {
self.doError(
"expected struct or enum for '{}', got {}",
val,
@tagName(comp.SymbolType(sym.?.value)),
);
break :blk null;
},
};
}, },
else => return typ, else => return typ,
@ -102,6 +115,7 @@ pub const TypeSolver = struct {
} }
} }
/// Compare if the given type names are equal.
fn compositeIdentifierEqual( fn compositeIdentifierEqual(
self: *@This(), self: *@This(),
typ_enum: comp.SymbolUnderlyingTypeEnum, typ_enum: comp.SymbolUnderlyingTypeEnum,

View File

@ -50,7 +50,7 @@ pub fn run(allocator: *std.mem.Allocator, slice: []const u8) !Result {
std.debug.warn("parse tree\n"); std.debug.warn("parse tree\n");
printer.printNode(root, 0); printer.printNode(root, 0);
var solver = analysis.TypeSolver.init(allocator); var solver = try analysis.TypeSolver.init(allocator);
var ctx = try solver.pass(root); var ctx = try solver.pass(root);
std.debug.warn("symbol table\n"); std.debug.warn("symbol table\n");