This commit is contained in:
agra
2026-02-21 02:25:21 +02:00
parent ff2b2a69ab
commit b02fe37a87
6 changed files with 96 additions and 12 deletions

View File

@@ -2338,6 +2338,9 @@ pub const CodeGen = struct {
const llvm_ty = self.typeToLLVM(target_ty);
switch (node.data) {
.int_literal => |lit| {
if (target_ty.isFloat()) {
return c.LLVMConstReal(llvm_ty, @floatFromInt(@as(i64, lit.value)));
}
return c.LLVMConstInt(llvm_ty, @bitCast(@as(i64, lit.value)), 0);
},
.float_literal => |lit| {
@@ -4773,6 +4776,15 @@ pub const CodeGen = struct {
return entry.ptr;
}
}
// Non-identifier expressions (e.g. field access, tuple element):
// generate value, store into temp alloca, return alloca pointer
if (node.data != .identifier) {
const val = try self.genExpr(node);
const llvm_ty = c.LLVMTypeOf(val);
const tmp = self.buildEntryBlockAlloca(llvm_ty, "implicit_addr");
_ = c.LLVMBuildStore(self.builder, val, tmp);
return tmp;
}
}
}

View File

@@ -164,7 +164,7 @@ pub const Server = struct {
const doc = self.documents.get(file_path) orelse {
return try self.sendResponse(id_json, "null");
};
const sema = doc.sema orelse {
const sema = doc.sema orelse doc.last_good_sema orelse {
return try self.sendResponse(id_json, "null");
};
@@ -420,7 +420,9 @@ pub const Server = struct {
}
// Regular completion: all in-scope symbols + keywords
const sema = doc.sema orelse {
// Fall back to last successful analysis when current parse/analysis fails
// (common while user is mid-typing)
const sema = doc.sema orelse doc.last_good_sema orelse {
return try self.sendResponse(id_json, "[]");
};
@@ -490,7 +492,7 @@ pub const Server = struct {
var items = std.ArrayList(lsp.CompletionItem).empty;
if (extractDotPrefix(doc.source, cursor_offset)) |prefix| {
if (doc.sema) |sema| {
if (doc.sema orelse doc.last_good_sema) |sema| {
// Check if prefix is a namespace — offer imported doc's declarations
if (self.findImportByNs(doc, prefix)) |imp| {
if (self.documents.get(imp.path)) |imp_doc| {

View File

@@ -539,7 +539,19 @@ pub const Analyzer = struct {
fn analyzeParams(self: *Analyzer, params: []const ast.Param) !void {
for (params) |param| {
const param_type = Type.fromTypeExpr(param.type_expr);
self.resolveTypeRef(param.type_expr);
const param_type = Type.fromTypeExpr(param.type_expr) orelse blk: {
if (param.type_expr.data == .type_expr) {
const name = param.type_expr.data.type_expr.name;
const resolved = self.type_aliases.get(name) orelse name;
if (self.symbol_index.get(resolved)) |indices| {
for (indices.items) |idx| {
if (self.symbols.items[idx].ty) |ty| break :blk ty;
}
}
}
break :blk null;
};
try self.addSymbol(param.name, .param, param_type, param.name_span);
}
}
@@ -884,14 +896,63 @@ pub const Analyzer = struct {
const resolved = self.type_aliases.get(name) orelse name;
if (self.symbol_index.get(resolved)) |indices| {
for (indices.items) |idx| {
if (self.symbols.items[idx].ty) |ty| return ty;
if (self.symbols.items[idx].ty) |ty| {
// Register a reference so go-to-definition works on type names
self.tryAddReference(resolved, tn.span);
return ty;
}
}
}
}
// For compound types (pointers, slices, arrays), resolve inner type refs
self.resolveTypeRef(tn);
}
return null;
}
/// Try to create a reference for a name without emitting diagnostics.
/// Used for type names where missing symbols are expected (primitives, builtins).
fn tryAddReference(self: *Analyzer, name: []const u8, span: Span) void {
if (self.symbol_index.get(name)) |indices| {
var j = indices.items.len;
while (j > 0) {
j -= 1;
const idx = indices.items[j];
const sym = self.symbols.items[idx];
if (sym.scope_depth <= self.scope_depth) {
self.references.append(self.allocator, .{
.span = span,
.symbol_index = idx,
}) catch {};
return;
}
}
}
}
/// Create references for type expression nodes so go-to-definition works on type names.
/// Only resolves compound types (pointer/slice/array element types).
fn resolveTypeRef(self: *Analyzer, node: *Node) void {
switch (node.data) {
.type_expr => |te| {
self.tryAddReference(te.name, node.span);
},
.pointer_type_expr => |pte| {
self.resolveTypeRef(pte.pointee_type);
},
.many_pointer_type_expr => |mpte| {
self.resolveTypeRef(mpte.element_type);
},
.slice_type_expr => |ste| {
self.resolveTypeRef(ste.element_type);
},
.array_type_expr => |ate| {
self.resolveTypeRef(ate.element_type);
},
else => {},
}
}
fn inferValueType(value: *Node) ?Type {
return switch (value.data) {
.int_literal => Type.s(64),