Merge branch 'flow/sx-plan-arch/A8.1' into arch-refactor
This commit is contained in:
14
src/core.zig
14
src/core.zig
@@ -2,7 +2,6 @@ const std = @import("std");
|
|||||||
const ast = @import("ast.zig");
|
const ast = @import("ast.zig");
|
||||||
const parser = @import("parser.zig");
|
const parser = @import("parser.zig");
|
||||||
const imports = @import("imports.zig");
|
const imports = @import("imports.zig");
|
||||||
const sema = @import("sema.zig");
|
|
||||||
const errors = @import("errors.zig");
|
const errors = @import("errors.zig");
|
||||||
const c_import = @import("c_import.zig");
|
const c_import = @import("c_import.zig");
|
||||||
const ir = @import("ir/ir.zig");
|
const ir = @import("ir/ir.zig");
|
||||||
@@ -27,7 +26,6 @@ pub const Compilation = struct {
|
|||||||
import_sources: std.StringHashMap([:0]const u8),
|
import_sources: std.StringHashMap([:0]const u8),
|
||||||
module_scopes: std.StringHashMap(std.StringHashMap(void)),
|
module_scopes: std.StringHashMap(std.StringHashMap(void)),
|
||||||
import_graph: std.StringHashMap(std.StringHashMap(void)),
|
import_graph: std.StringHashMap(std.StringHashMap(void)),
|
||||||
sema_result: ?sema.SemaResult = null,
|
|
||||||
ir_emitter: ?ir.LLVMEmitter = null,
|
ir_emitter: ?ir.LLVMEmitter = null,
|
||||||
/// Lowered IR module, kept alive past `generateCode` so post-link
|
/// Lowered IR module, kept alive past `generateCode` so post-link
|
||||||
/// callbacks can re-enter the interpreter to invoke sx functions
|
/// callbacks can re-enter the interpreter to invoke sx functions
|
||||||
@@ -128,18 +126,6 @@ pub const Compilation = struct {
|
|||||||
self.resolved_root = new_root;
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generate code via the IR pipeline: lower AST → IR → LLVM.
|
/// Generate code via the IR pipeline: lower AST → IR → LLVM.
|
||||||
pub fn generateCode(self: *Compilation) !void {
|
pub fn generateCode(self: *Compilation) !void {
|
||||||
// Heap-allocate the IR module so its address is stable during emit
|
// Heap-allocate the IR module so its address is stable during emit
|
||||||
|
|||||||
@@ -23,7 +23,9 @@ pub const Document = struct {
|
|||||||
version: i64,
|
version: i64,
|
||||||
/// AST root for this file only (not merged).
|
/// AST root for this file only (not merged).
|
||||||
root: ?*sx.ast.Node,
|
root: ?*sx.ast.Node,
|
||||||
/// Sema results for this file (references are relative to this source).
|
/// Editor index for this file — symbols/references/types for navigation,
|
||||||
|
/// completion, and hover (references are relative to this source). Not a
|
||||||
|
/// diagnostic source; see `sema.zig` module doc.
|
||||||
sema: ?sx.sema.SemaResult,
|
sema: ?sx.sema.SemaResult,
|
||||||
/// Last successful sema (preserved across parse failures for completions).
|
/// Last successful sema (preserved across parse failures for completions).
|
||||||
last_good_sema: ?sx.sema.SemaResult = null,
|
last_good_sema: ?sx.sema.SemaResult = null,
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ pub const Server = struct {
|
|||||||
const text = jsonStr(jsonGet(td, "text") orelse return) orelse return;
|
const text = jsonStr(jsonGet(td, "text") orelse return) orelse return;
|
||||||
const version = jsonInt(jsonGet(td, "version") orelse return) orelse return;
|
const version = jsonInt(jsonGet(td, "version") orelse return) orelse return;
|
||||||
|
|
||||||
try self.analyzeAndPublish(uri, text, version);
|
try self.refreshEditorIndex(uri, text, version);
|
||||||
self.runProjectCheck();
|
self.runProjectCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,7 +173,7 @@ pub const Server = struct {
|
|||||||
const last = changes_arr[changes_arr.len - 1];
|
const last = changes_arr[changes_arr.len - 1];
|
||||||
const text = jsonStr(jsonGet(last, "text") orelse return) orelse return;
|
const text = jsonStr(jsonGet(last, "text") orelse return) orelse return;
|
||||||
|
|
||||||
try self.analyzeAndPublish(uri, text, version);
|
try self.refreshEditorIndex(uri, text, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handleDidClose(_: *Server, params: std.json.Value) void {
|
fn handleDidClose(_: *Server, params: std.json.Value) void {
|
||||||
@@ -1919,41 +1919,16 @@ pub const Server = struct {
|
|||||||
|
|
||||||
// ---- Core analysis pipeline ----
|
// ---- Core analysis pipeline ----
|
||||||
|
|
||||||
fn analyzeAndPublish(self: *Server, uri: []const u8, text: []const u8, version: i64) !void {
|
/// Refresh the editor index for a document (symbols/references/types that
|
||||||
|
/// power navigation, completion, hover, and token classification). Publishes
|
||||||
|
/// no diagnostics — authoritative diagnostics come only from the canonical
|
||||||
|
/// compiler pipeline in `runProjectCheck`.
|
||||||
|
fn refreshEditorIndex(self: *Server, uri: []const u8, text: []const u8, version: i64) !void {
|
||||||
const file_path = uriToFilePath(uri) orelse "";
|
const file_path = uriToFilePath(uri) orelse "";
|
||||||
const source = try self.allocator.dupeZ(u8, text);
|
const source = try self.allocator.dupeZ(u8, text);
|
||||||
|
|
||||||
const doc = try self.documents.openOrUpdate(file_path, source, version);
|
const doc = try self.documents.openOrUpdate(file_path, source, version);
|
||||||
self.documents.analyzeDocument(doc) catch {};
|
self.documents.analyzeDocument(doc) catch {};
|
||||||
|
|
||||||
// Publish diagnostics from sema
|
|
||||||
if (doc.sema) |sema| {
|
|
||||||
try self.sendDiagnostics(uri, semaToLspDiags(self.allocator, doc.source, sema.diagnostics));
|
|
||||||
} else {
|
|
||||||
try self.sendDiagnostics(uri, &.{});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn semaToLspDiags(allocator: std.mem.Allocator, source: [:0]const u8, diags: []const sx.errors.Diagnostic) []const lsp.Diagnostic {
|
|
||||||
var result = std.ArrayList(lsp.Diagnostic).empty;
|
|
||||||
for (diags) |d| {
|
|
||||||
const range = if (d.span) |span| spanToRange(source, span) else lsp.Range{
|
|
||||||
.start = .{ .line = 0, .character = 0 },
|
|
||||||
.end = .{ .line = 0, .character = 1 },
|
|
||||||
};
|
|
||||||
const severity: u32 = switch (d.level) {
|
|
||||||
.err => 1,
|
|
||||||
.warn => 2,
|
|
||||||
.note => 3,
|
|
||||||
.help => 4,
|
|
||||||
};
|
|
||||||
result.append(allocator, .{
|
|
||||||
.range = range,
|
|
||||||
.severity = severity,
|
|
||||||
.message = d.message,
|
|
||||||
}) catch continue;
|
|
||||||
}
|
|
||||||
return result.items;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sendDiagnostics(self: *Server, uri: []const u8, diagnostics: []const lsp.Diagnostic) !void {
|
fn sendDiagnostics(self: *Server, uri: []const u8, diagnostics: []const lsp.Diagnostic) !void {
|
||||||
@@ -2012,8 +1987,8 @@ pub const Server = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Drive the whole-program check from the workspace entry point and publish
|
/// Drive the whole-program check from the workspace entry point and publish
|
||||||
/// the real compiler's diagnostics per file (runs on save; the sema layer
|
/// the real compiler's diagnostics per file. Runs on open and save; this is
|
||||||
/// keeps live per-keystroke feedback).
|
/// the sole source of LSP diagnostics (the editor index publishes none).
|
||||||
fn runProjectCheck(self: *Server) void {
|
fn runProjectCheck(self: *Server) void {
|
||||||
if (self.root_path.len == 0) return;
|
if (self.root_path.len == 0) return;
|
||||||
const entry_path = std.fmt.allocPrint(self.allocator, "{s}/main.sx", .{self.root_path}) catch return;
|
const entry_path = std.fmt.allocPrint(self.allocator, "{s}/main.sx", .{self.root_path}) catch return;
|
||||||
|
|||||||
Reference in New Issue
Block a user