refactor: remove error module
This commit is contained in:
parent
2aa81dd39f
commit
d0feb04b55
16
build.zig
16
build.zig
@ -26,17 +26,6 @@ pub fn build(b: *std.Build) void {
|
|||||||
// Add options to executable
|
// Add options to executable
|
||||||
exe.root_module.addImport("config", options_module);
|
exe.root_module.addImport("config", options_module);
|
||||||
|
|
||||||
//
|
|
||||||
// Error handling module
|
|
||||||
//
|
|
||||||
const error_module = b.addModule("errors", .{
|
|
||||||
.root_source_file = b.path("src/errors/root.zig"),
|
|
||||||
.target = target,
|
|
||||||
.optimize = optimize,
|
|
||||||
});
|
|
||||||
error_module.addImport("config", options_module);
|
|
||||||
exe.root_module.addImport("errors", error_module);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Context module
|
// Context module
|
||||||
//
|
//
|
||||||
@ -57,7 +46,6 @@ pub fn build(b: *std.Build) void {
|
|||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
lexic_module.addImport("config", options_module);
|
lexic_module.addImport("config", options_module);
|
||||||
lexic_module.addImport("errors", error_module);
|
|
||||||
lexic_module.addImport("context", context_module);
|
lexic_module.addImport("context", context_module);
|
||||||
exe.root_module.addImport("lexic", lexic_module);
|
exe.root_module.addImport("lexic", lexic_module);
|
||||||
|
|
||||||
@ -71,7 +59,6 @@ pub fn build(b: *std.Build) void {
|
|||||||
});
|
});
|
||||||
syntax_module.addImport("config", options_module);
|
syntax_module.addImport("config", options_module);
|
||||||
syntax_module.addImport("lexic", lexic_module);
|
syntax_module.addImport("lexic", lexic_module);
|
||||||
syntax_module.addImport("errors", error_module);
|
|
||||||
syntax_module.addImport("context", context_module);
|
syntax_module.addImport("context", context_module);
|
||||||
exe.root_module.addImport("syntax", syntax_module);
|
exe.root_module.addImport("syntax", syntax_module);
|
||||||
|
|
||||||
@ -100,7 +87,6 @@ pub fn build(b: *std.Build) void {
|
|||||||
exe_unit_tests.root_module.addImport("config", options_module);
|
exe_unit_tests.root_module.addImport("config", options_module);
|
||||||
exe_unit_tests.root_module.addImport("lexic", lexic_module);
|
exe_unit_tests.root_module.addImport("lexic", lexic_module);
|
||||||
exe_unit_tests.root_module.addImport("syntax", syntax_module);
|
exe_unit_tests.root_module.addImport("syntax", syntax_module);
|
||||||
exe_unit_tests.root_module.addImport("errors", error_module);
|
|
||||||
exe_unit_tests.root_module.addImport("context", context_module);
|
exe_unit_tests.root_module.addImport("context", context_module);
|
||||||
|
|
||||||
const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);
|
const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);
|
||||||
@ -112,7 +98,6 @@ pub fn build(b: *std.Build) void {
|
|||||||
const files = [_][]const u8{
|
const files = [_][]const u8{
|
||||||
"src/01_lexic/root.zig",
|
"src/01_lexic/root.zig",
|
||||||
"src/02_syntax/root.zig",
|
"src/02_syntax/root.zig",
|
||||||
"src/errors/root.zig",
|
|
||||||
"src/context/root.zig",
|
"src/context/root.zig",
|
||||||
};
|
};
|
||||||
for (files) |file| {
|
for (files) |file| {
|
||||||
@ -124,7 +109,6 @@ pub fn build(b: *std.Build) void {
|
|||||||
file_unit_test.root_module.addImport("config", options_module);
|
file_unit_test.root_module.addImport("config", options_module);
|
||||||
file_unit_test.root_module.addImport("lexic", lexic_module);
|
file_unit_test.root_module.addImport("lexic", lexic_module);
|
||||||
file_unit_test.root_module.addImport("syntax", syntax_module);
|
file_unit_test.root_module.addImport("syntax", syntax_module);
|
||||||
file_unit_test.root_module.addImport("errors", error_module);
|
|
||||||
file_unit_test.root_module.addImport("context", context_module);
|
file_unit_test.root_module.addImport("context", context_module);
|
||||||
|
|
||||||
var test_artifact = b.addRunArtifact(file_unit_test);
|
var test_artifact = b.addRunArtifact(file_unit_test);
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
|
|
||||||
pub const ErrorLabel = struct {
|
|
||||||
message: []const u8,
|
|
||||||
start: usize,
|
|
||||||
end: usize,
|
|
||||||
};
|
|
@ -1,222 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
pub const ErrorLabel = @import("./error_label.zig").ErrorLabel;
|
|
||||||
|
|
||||||
/// Holds information about errors generated during the compilation,
|
|
||||||
/// and pretty prints them.
|
|
||||||
pub const ErrorData = struct {
|
|
||||||
reason: []const u8,
|
|
||||||
help: ?[]const u8,
|
|
||||||
start_position: usize,
|
|
||||||
end_position: usize,
|
|
||||||
labels: std.ArrayList(ErrorLabel),
|
|
||||||
alloc: std.mem.Allocator,
|
|
||||||
|
|
||||||
pub fn init(
|
|
||||||
target: *@This(),
|
|
||||||
reason: []const u8,
|
|
||||||
start_position: usize,
|
|
||||||
end_position: usize,
|
|
||||||
alloc: std.mem.Allocator,
|
|
||||||
) !void {
|
|
||||||
target.* = .{
|
|
||||||
.reason = reason,
|
|
||||||
.start_position = start_position,
|
|
||||||
.end_position = end_position,
|
|
||||||
.labels = std.ArrayList(ErrorLabel).init(alloc),
|
|
||||||
.help = null,
|
|
||||||
.alloc = alloc,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_label(self: *@This(), message: []const u8, start: usize, end: usize) !void {
|
|
||||||
try self.labels.append(.{
|
|
||||||
.message = message,
|
|
||||||
.start = start,
|
|
||||||
.end = end,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets the help message of this error.
|
|
||||||
pub fn set_help(self: *@This(), help: []const u8) void {
|
|
||||||
self.help = help;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generates an error string. `alloc` is used to create the string,
|
|
||||||
/// the caller should call `free` on the returning slice.
|
|
||||||
pub fn get_error_str(self: *@This(), source_code: []const u8, filename: []const u8, alloc: std.mem.Allocator) ![]u8 {
|
|
||||||
const faulty_line = get_line(source_code, self.start_position);
|
|
||||||
|
|
||||||
var error_message = try std.fmt.allocPrint(alloc,
|
|
||||||
\\Error: {s}
|
|
||||||
\\[{s}:{d}:{d}]
|
|
||||||
, .{
|
|
||||||
self.reason,
|
|
||||||
filename,
|
|
||||||
faulty_line.line_number,
|
|
||||||
faulty_line.column_number,
|
|
||||||
});
|
|
||||||
errdefer alloc.free(error_message);
|
|
||||||
|
|
||||||
// generate errors for each label, and concat
|
|
||||||
for (self.labels.items) |label| {
|
|
||||||
const label_line = get_line(source_code, label.start);
|
|
||||||
|
|
||||||
// Build the error position indicator
|
|
||||||
const column_number_len_str = try std.fmt.allocPrint(
|
|
||||||
alloc,
|
|
||||||
"{d}",
|
|
||||||
.{label_line.line_number},
|
|
||||||
);
|
|
||||||
const column_number_len = column_number_len_str.len;
|
|
||||||
alloc.free(column_number_len_str);
|
|
||||||
|
|
||||||
// position up to where the error starts
|
|
||||||
const error_start_len = column_number_len + 4 + label_line.column_number - 1;
|
|
||||||
const error_len = label.end - label.start;
|
|
||||||
|
|
||||||
// chars for the error
|
|
||||||
const empty_space_before_indicator = try alloc.alloc(u8, error_start_len);
|
|
||||||
defer alloc.free(empty_space_before_indicator);
|
|
||||||
@memset(empty_space_before_indicator, ' ');
|
|
||||||
|
|
||||||
// top error indicator: unicode box drawing characters in the range U+250x-U+257x (3 bytes)
|
|
||||||
const error_indicator = try alloc.alloc(u8, error_len * 3);
|
|
||||||
defer alloc.free(error_indicator);
|
|
||||||
|
|
||||||
// the first char is always '╭', the rest are lines
|
|
||||||
error_indicator[0] = '\xe2';
|
|
||||||
error_indicator[1] = '\x95';
|
|
||||||
error_indicator[2] = '\xad';
|
|
||||||
|
|
||||||
// set bytes of the rest
|
|
||||||
var i: usize = 1;
|
|
||||||
while (i < error_len) : (i += 1) {
|
|
||||||
// set bytes
|
|
||||||
error_indicator[i * 3 + 0] = '\xe2';
|
|
||||||
error_indicator[i * 3 + 1] = '\x94';
|
|
||||||
error_indicator[i * 3 + 2] = '\x80';
|
|
||||||
}
|
|
||||||
|
|
||||||
// bottom error indicator: always ╰─
|
|
||||||
const bottom_error_indicator = "╰─";
|
|
||||||
|
|
||||||
const help_message: []u8 = msg: {
|
|
||||||
if (self.help) |help_text| {
|
|
||||||
// this will be manually freed later
|
|
||||||
break :msg try std.fmt.allocPrint(alloc, "\n Help: {s}", .{help_text});
|
|
||||||
} else {
|
|
||||||
break :msg "";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
defer if (help_message.len > 0) {
|
|
||||||
alloc.free(help_message);
|
|
||||||
};
|
|
||||||
|
|
||||||
const label_error = try std.fmt.allocPrint(alloc,
|
|
||||||
\\
|
|
||||||
\\
|
|
||||||
\\ {d} | {s}
|
|
||||||
\\{s}{s}
|
|
||||||
\\{s}{s} {s}
|
|
||||||
\\{s}
|
|
||||||
, .{
|
|
||||||
label_line.line_number,
|
|
||||||
label_line.line,
|
|
||||||
empty_space_before_indicator,
|
|
||||||
error_indicator,
|
|
||||||
empty_space_before_indicator,
|
|
||||||
bottom_error_indicator,
|
|
||||||
label.message,
|
|
||||||
help_message,
|
|
||||||
});
|
|
||||||
errdefer alloc.free(label_error);
|
|
||||||
|
|
||||||
// append the previous bytes to the current ones,
|
|
||||||
// in a temp variable
|
|
||||||
const new_bytes = try std.mem.concat(alloc, u8, &[_][]const u8{ error_message, label_error });
|
|
||||||
|
|
||||||
// free the previous bytes
|
|
||||||
alloc.free(label_error);
|
|
||||||
alloc.free(error_message);
|
|
||||||
|
|
||||||
// reference the new bytes
|
|
||||||
error_message = new_bytes;
|
|
||||||
|
|
||||||
// continue
|
|
||||||
}
|
|
||||||
|
|
||||||
return error_message;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO:
|
|
||||||
// - transform absolute position into line:column
|
|
||||||
// - Get previous, current and next line
|
|
||||||
// - Display message
|
|
||||||
|
|
||||||
/// Writes this error as a JSON to the writer
|
|
||||||
pub fn write_json(self: ErrorData, alloc: std.mem.Allocator, writer: anytype) !void {
|
|
||||||
// get this as JSON
|
|
||||||
const json_str = try std.json.stringifyAlloc(alloc, .{
|
|
||||||
.reason = self.reason,
|
|
||||||
.help = self.help,
|
|
||||||
.start_position = self.start_position,
|
|
||||||
.end_position = self.end_position,
|
|
||||||
.labels = self.labels.items,
|
|
||||||
}, .{});
|
|
||||||
defer alloc.free(json_str);
|
|
||||||
|
|
||||||
// write the JSON to the writer
|
|
||||||
try writer.writeAll(json_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deinit(self: *@This()) void {
|
|
||||||
self.labels.deinit();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const LineInfo = struct {
|
|
||||||
line: []const u8,
|
|
||||||
/// 1 based
|
|
||||||
line_number: usize,
|
|
||||||
/// 1 based
|
|
||||||
column_number: usize,
|
|
||||||
};
|
|
||||||
|
|
||||||
fn get_line(input: []const u8, at: usize) LineInfo {
|
|
||||||
var line_number: usize = 1;
|
|
||||||
var line_start: usize = 0;
|
|
||||||
var line_end: usize = 0;
|
|
||||||
var current_pos: usize = 0;
|
|
||||||
const cap = input.len;
|
|
||||||
|
|
||||||
// search the start pos of the line
|
|
||||||
while (current_pos < cap and current_pos < at) : (current_pos += 1) {
|
|
||||||
if (input[current_pos] == '\n' and current_pos + 1 < cap) {
|
|
||||||
line_start = current_pos + 1;
|
|
||||||
line_number += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// compute the column number
|
|
||||||
const column_number: usize = current_pos - line_start + 1;
|
|
||||||
|
|
||||||
// search the end pos of the line
|
|
||||||
while (current_pos < cap) : (current_pos += 1) {
|
|
||||||
// EOF is EOL
|
|
||||||
if (current_pos + 1 == cap) {
|
|
||||||
line_end = current_pos + 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (input[current_pos] == '\n') {
|
|
||||||
// dont count the newline as part of the... line
|
|
||||||
line_end = current_pos;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return .{
|
|
||||||
.line = input[line_start..line_end],
|
|
||||||
.line_number = line_number,
|
|
||||||
.column_number = column_number,
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,7 +1,6 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const lexic = @import("lexic");
|
const lexic = @import("lexic");
|
||||||
const syntax = @import("syntax");
|
const syntax = @import("syntax");
|
||||||
const errors = @import("errors");
|
|
||||||
const context = @import("context");
|
const context = @import("context");
|
||||||
|
|
||||||
const cli = @import("cli.zig");
|
const cli = @import("cli.zig");
|
||||||
@ -77,13 +76,6 @@ fn repl() !void {
|
|||||||
//
|
//
|
||||||
// Tokenize
|
// Tokenize
|
||||||
//
|
//
|
||||||
var error_array = std.ArrayList(errors.ErrorData).init(alloc);
|
|
||||||
defer error_array.deinit();
|
|
||||||
defer for (error_array.items) |item| {
|
|
||||||
var i = item;
|
|
||||||
i.deinit();
|
|
||||||
};
|
|
||||||
|
|
||||||
const tokens = lexic.tokenize(line, &ctx) catch |e| switch (e) {
|
const tokens = lexic.tokenize(line, &ctx) catch |e| switch (e) {
|
||||||
error.OutOfMemory => {
|
error.OutOfMemory => {
|
||||||
try stdout.print("FATAL ERROR: System Out of Memory!", .{});
|
try stdout.print("FATAL ERROR: System Out of Memory!", .{});
|
||||||
|
Loading…
Reference in New Issue
Block a user