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
|
||||
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
|
||||
//
|
||||
@ -57,7 +46,6 @@ pub fn build(b: *std.Build) void {
|
||||
.optimize = optimize,
|
||||
});
|
||||
lexic_module.addImport("config", options_module);
|
||||
lexic_module.addImport("errors", error_module);
|
||||
lexic_module.addImport("context", context_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("lexic", lexic_module);
|
||||
syntax_module.addImport("errors", error_module);
|
||||
syntax_module.addImport("context", context_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("lexic", lexic_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);
|
||||
|
||||
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{
|
||||
"src/01_lexic/root.zig",
|
||||
"src/02_syntax/root.zig",
|
||||
"src/errors/root.zig",
|
||||
"src/context/root.zig",
|
||||
};
|
||||
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("lexic", lexic_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);
|
||||
|
||||
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 lexic = @import("lexic");
|
||||
const syntax = @import("syntax");
|
||||
const errors = @import("errors");
|
||||
const context = @import("context");
|
||||
|
||||
const cli = @import("cli.zig");
|
||||
@ -77,13 +76,6 @@ fn repl() !void {
|
||||
//
|
||||
// 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) {
|
||||
error.OutOfMemory => {
|
||||
try stdout.print("FATAL ERROR: System Out of Memory!", .{});
|
||||
|
Loading…
Reference in New Issue
Block a user