so... jai :D
This commit is contained in:
110
src/core.zig
Normal file
110
src/core.zig
Normal file
@@ -0,0 +1,110 @@
|
||||
const std = @import("std");
|
||||
const ast = @import("ast.zig");
|
||||
const parser = @import("parser.zig");
|
||||
const imports = @import("imports.zig");
|
||||
const sema = @import("sema.zig");
|
||||
const codegen = @import("codegen.zig");
|
||||
const errors = @import("errors.zig");
|
||||
const Node = ast.Node;
|
||||
|
||||
pub const Compilation = struct {
|
||||
allocator: std.mem.Allocator,
|
||||
io: std.Io,
|
||||
file_path: []const u8,
|
||||
source: [:0]const u8,
|
||||
diagnostics: errors.DiagnosticList,
|
||||
|
||||
// Pipeline results
|
||||
root: ?*Node = null,
|
||||
resolved_root: ?*Node = null,
|
||||
import_sources: std.StringHashMap([:0]const u8),
|
||||
sema_result: ?sema.SemaResult = null,
|
||||
cg: ?codegen.CodeGen = null,
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator, io: std.Io, file_path: []const u8, source: [:0]const u8) Compilation {
|
||||
return .{
|
||||
.allocator = allocator,
|
||||
.io = io,
|
||||
.file_path = file_path,
|
||||
.source = source,
|
||||
.diagnostics = errors.DiagnosticList.init(allocator, source, file_path),
|
||||
.import_sources = std.StringHashMap([:0]const u8).init(allocator),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Compilation) void {
|
||||
if (self.cg) |*cg| cg.deinit();
|
||||
self.diagnostics.deinit();
|
||||
}
|
||||
|
||||
pub fn parse(self: *Compilation) !void {
|
||||
var p = parser.Parser.init(self.allocator, self.source);
|
||||
p.diagnostics = &self.diagnostics;
|
||||
self.root = p.parse() catch return error.CompileError;
|
||||
}
|
||||
|
||||
pub fn resolveImports(self: *Compilation) !void {
|
||||
const root = self.root orelse return error.CompileError;
|
||||
var chain = std.StringHashMap(void).init(self.allocator);
|
||||
var cache = imports.ModuleCache.init(self.allocator);
|
||||
const base_dir = imports.dirName(self.file_path);
|
||||
const mod = imports.resolveImports(
|
||||
self.allocator,
|
||||
self.io,
|
||||
root,
|
||||
base_dir,
|
||||
self.file_path,
|
||||
&chain,
|
||||
&cache,
|
||||
&self.import_sources,
|
||||
&self.diagnostics,
|
||||
) catch return error.CompileError;
|
||||
|
||||
// Build a root node from the resolved module's decls
|
||||
const new_root = try self.allocator.create(Node);
|
||||
new_root.* = .{
|
||||
.span = root.span,
|
||||
.data = .{ .root = .{ .decls = mod.decls } },
|
||||
};
|
||||
self.resolved_root = new_root;
|
||||
}
|
||||
|
||||
pub fn analyze(self: *Compilation) !void {
|
||||
const root = self.resolved_root orelse self.root orelse return error.CompileError;
|
||||
var analyzer = sema.Analyzer.init(self.allocator);
|
||||
self.sema_result = analyzer.analyze(root) catch return error.CompileError;
|
||||
// Merge sema diagnostics into our list
|
||||
if (self.sema_result) |sr| {
|
||||
for (sr.diagnostics) |d| {
|
||||
self.diagnostics.add(d.level, d.message, d.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generateCode(self: *Compilation) !void {
|
||||
const root = self.resolved_root orelse self.root orelse return error.CompileError;
|
||||
var cg = codegen.CodeGen.init(self.allocator, "sx_module");
|
||||
cg.diagnostics = &self.diagnostics;
|
||||
if (self.sema_result) |*sr| {
|
||||
cg.sema_result = sr;
|
||||
}
|
||||
cg.generate(root) catch return error.CompileError;
|
||||
self.cg = cg;
|
||||
}
|
||||
|
||||
pub fn renderErrors(self: *const Compilation) void {
|
||||
for (self.diagnostics.items.items) |d| {
|
||||
const level_str = switch (d.level) {
|
||||
.err => "error",
|
||||
.warn => "warning",
|
||||
.note => "note",
|
||||
};
|
||||
if (d.span) |span| {
|
||||
const loc = errors.SourceLoc.compute(self.source, span.start);
|
||||
std.debug.print("{s}:{d}:{d}: {s}: {s}\n", .{ self.file_path, loc.line, loc.col, level_str, d.message });
|
||||
} else {
|
||||
std.debug.print("{s}: {s}: {s}\n", .{ self.file_path, level_str, d.message });
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user