diff --git a/build.zig b/build.zig index 98577c4..6835b5a 100644 --- a/build.zig +++ b/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); diff --git a/src/errors/error_label.zig b/src/errors/error_label.zig deleted file mode 100644 index 257eec6..0000000 --- a/src/errors/error_label.zig +++ /dev/null @@ -1,7 +0,0 @@ -const std = @import("std"); - -pub const ErrorLabel = struct { - message: []const u8, - start: usize, - end: usize, -}; diff --git a/src/errors/root.zig b/src/errors/root.zig deleted file mode 100644 index a25110a..0000000 --- a/src/errors/root.zig +++ /dev/null @@ -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, - }; -} diff --git a/src/main.zig b/src/main.zig index d6becc3..2c569cc 100644 --- a/src/main.zig +++ b/src/main.zig @@ -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!", .{});