Skip to content

Commit

Permalink
feat: better error messaging for unsupported features
Browse files Browse the repository at this point in the history
  • Loading branch information
sno2 committed Oct 30, 2024
1 parent 5e2a82a commit ba71242
Showing 1 changed file with 44 additions and 18 deletions.
62 changes: 44 additions & 18 deletions src/CodeGen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,19 @@ pub const ErrorInfo = struct {
invalid_function_call,
invalid_define,
invalid_number,
unsupported,
unsupported: Feature,

pub const Feature = enum {
bool,
define,
variable,
conditional,
comparison,
lambda,
call,
list_pair,
reference,
};
};
};

Expand All @@ -135,6 +147,10 @@ fn fail(cg: *CodeGen, error_info: ErrorInfo) !noreturn {
return error.InvalidSyntax;
}

fn failUnsupported(cg: *CodeGen, feature: ErrorInfo.Data.Feature) !noreturn {
try cg.fail(.{ .data = .{ .unsupported = feature }, .source_range = cg.tokenizer.tokenRange() });
}

pub fn formatError(cg: *CodeGen, config: std.io.tty.Config, writer: anytype) !void {
const error_info = cg.error_info.?;
try config.setColor(writer, .bold);
Expand All @@ -148,13 +164,23 @@ pub fn formatError(cg: *CodeGen, config: std.io.tty.Config, writer: anytype) !vo
.invalid_function_call => try writer.writeAll("invalid function call"),
.invalid_define => try writer.writeAll("define must be top-level"),
.invalid_number => try writer.writeAll("failed to parse number literal"),
.unsupported => try writer.print("syntax is not supported in {s}", .{switch (cg.flavor) {
.unsupported => |feature| try writer.print("{s} are not supported in {s}", .{ switch (feature) {
.bool => "boolean literals",
.define => "defines",
.variable => "variables",
.conditional => "conditionals",
.comparison => "comparisons",
.lambda => "lambdas",
.call => "calls",
.list_pair => "lists and pairs",
.reference => "references",
}, switch (cg.flavor) {
.arithlang => "ArithLang",
.varlang => "VarLang",
.definelang => "DefineLang",
.funclang => "FuncLang",
.reflang => "RefLang",
}}),
} }),
}
try config.setColor(writer, .reset);
}
Expand Down Expand Up @@ -219,7 +245,7 @@ fn genExpression(cg: *CodeGen, exe: *Executable, is_tail: bool) !void {
switch (cg.tokenizer.token) {
inline .@"#f", .@"#t" => |tag| {
if (cg.flavor.isBefore(.funclang)) {
try cg.fail(.{ .data = .unsupported, .source_range = cg.tokenizer.tokenRange() });
try cg.failUnsupported(.bool);
}
try exe.emitConstant(Value.from(tag == .@"#t"), null);
cg.tokenizer.next();
Expand Down Expand Up @@ -252,7 +278,7 @@ fn genExpression(cg: *CodeGen, exe: *Executable, is_tail: bool) !void {
},
.identifier => {
if (cg.flavor.isBefore(.varlang)) {
try cg.fail(.{ .data = .unsupported, .source_range = cg.tokenizer.tokenRange() });
try cg.failUnsupported(.variable);
}
try cg.genIdentifier(exe, cg.tokenizer.tokenSource());
cg.tokenizer.next();
Expand All @@ -269,7 +295,7 @@ fn genExpression(cg: *CodeGen, exe: *Executable, is_tail: bool) !void {
},
.let => {
if (cg.flavor.isBefore(.varlang)) {
try cg.fail(.{ .data = .unsupported, .source_range = cg.tokenizer.tokenRange() });
try cg.failUnsupported(.variable);
}
cg.tokenizer.next();

Expand Down Expand Up @@ -317,7 +343,7 @@ fn genExpression(cg: *CodeGen, exe: *Executable, is_tail: bool) !void {
},
.@"if" => {
if (cg.flavor.isBefore(.funclang)) {
try cg.fail(.{ .data = .unsupported, .source_range = cg.tokenizer.tokenRange() });
try cg.failUnsupported(.conditional);
}
const hint = cg.tokenizer.start;
cg.tokenizer.next();
Expand All @@ -336,7 +362,7 @@ fn genExpression(cg: *CodeGen, exe: *Executable, is_tail: bool) !void {
switch (tag) {
.@"<", .@">", .@"=" => {
if (cg.flavor.isBefore(.funclang)) {
try cg.fail(.{ .data = .unsupported, .source_range = cg.tokenizer.tokenRange() });
try cg.failUnsupported(.comparison);
}
},
else => {},
Expand Down Expand Up @@ -373,7 +399,7 @@ fn genExpression(cg: *CodeGen, exe: *Executable, is_tail: bool) !void {
},
.lambda => {
if (cg.flavor.isBefore(.funclang)) {
try cg.fail(.{ .data = .unsupported, .source_range = cg.tokenizer.tokenRange() });
try cg.failUnsupported(.lambda);
}
cg.tokenizer.next();

Expand Down Expand Up @@ -404,7 +430,7 @@ fn genExpression(cg: *CodeGen, exe: *Executable, is_tail: bool) !void {
},
.identifier, .@"(" => {
if (cg.flavor.isBefore(.funclang)) {
try cg.fail(.{ .data = .unsupported, .source_range = cg.tokenizer.tokenRange() });
try cg.failUnsupported(.call);
}
const hint = cg.tokenizer.start;
try cg.genExpression(exe, false);
Expand All @@ -423,7 +449,7 @@ fn genExpression(cg: *CodeGen, exe: *Executable, is_tail: bool) !void {
},
.list => {
if (cg.flavor.isBefore(.funclang)) {
try cg.fail(.{ .data = .unsupported, .source_range = cg.tokenizer.tokenRange() });
try cg.failUnsupported(.list_pair);
}
cg.tokenizer.next();
var item_count: u16 = 0;
Expand All @@ -435,7 +461,7 @@ fn genExpression(cg: *CodeGen, exe: *Executable, is_tail: bool) !void {
},
.cons => {
if (cg.flavor.isBefore(.funclang)) {
try cg.fail(.{ .data = .unsupported, .source_range = cg.tokenizer.tokenRange() });
try cg.failUnsupported(.list_pair);
}
const hint = cg.tokenizer.start;
cg.tokenizer.next();
Expand All @@ -446,7 +472,7 @@ fn genExpression(cg: *CodeGen, exe: *Executable, is_tail: bool) !void {
},
.car => {
if (cg.flavor.isBefore(.funclang)) {
try cg.fail(.{ .data = .unsupported, .source_range = cg.tokenizer.tokenRange() });
try cg.failUnsupported(.list_pair);
}
const hint = cg.tokenizer.start;
cg.tokenizer.next();
Expand All @@ -456,7 +482,7 @@ fn genExpression(cg: *CodeGen, exe: *Executable, is_tail: bool) !void {
},
.cdr => {
if (cg.flavor.isBefore(.funclang)) {
try cg.fail(.{ .data = .unsupported, .source_range = cg.tokenizer.tokenRange() });
try cg.failUnsupported(.list_pair);
}
const hint = cg.tokenizer.start;
cg.tokenizer.next();
Expand All @@ -466,7 +492,7 @@ fn genExpression(cg: *CodeGen, exe: *Executable, is_tail: bool) !void {
},
.@"null?" => {
if (cg.flavor.isBefore(.funclang)) {
try cg.fail(.{ .data = .unsupported, .source_range = cg.tokenizer.tokenRange() });
try cg.failUnsupported(.list_pair);
}
const hint = cg.tokenizer.start;
cg.tokenizer.next();
Expand All @@ -476,7 +502,7 @@ fn genExpression(cg: *CodeGen, exe: *Executable, is_tail: bool) !void {
},
inline .ref, .free, .deref => |tag| {
if (cg.flavor.isBefore(.reflang)) {
try cg.fail(.{ .data = .unsupported, .source_range = cg.tokenizer.tokenRange() });
try cg.failUnsupported(.reference);
}
const hint = cg.tokenizer.start;
cg.tokenizer.next();
Expand All @@ -491,7 +517,7 @@ fn genExpression(cg: *CodeGen, exe: *Executable, is_tail: bool) !void {
},
.@"set!" => {
if (cg.flavor.isBefore(.reflang)) {
try cg.fail(.{ .data = .unsupported, .source_range = cg.tokenizer.tokenRange() });
try cg.failUnsupported(.reference);
}
// rhs is evaluated before lhs
const hint = cg.tokenizer.start;
Expand Down Expand Up @@ -565,7 +591,7 @@ pub fn genProgram(cg: *CodeGen, mode: Mode) Error!Executable {
break :define;
}
if (cg.flavor.isBefore(.definelang)) {
try cg.fail(.{ .data = .unsupported, .source_range = cg.tokenizer.tokenRange() });
try cg.failUnsupported(.define);
}
cg.tokenizer.next();

Expand Down

0 comments on commit ba71242

Please sign in to comment.