cleanup
This commit is contained in:
512
src/codegen.zig
512
src/codegen.zig
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const types = @import("types.zig");
|
const types = @import("types.zig");
|
||||||
const Type = types.Type;
|
const Type = types.Type;
|
||||||
|
const unescape = @import("unescape.zig");
|
||||||
|
|
||||||
/// Runtime value for comptime evaluation.
|
/// Runtime value for comptime evaluation.
|
||||||
/// Replaces codegen's JitResult with richer type support.
|
/// Replaces codegen's JitResult with richer type support.
|
||||||
@@ -351,34 +352,6 @@ pub const Compiler = struct {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Process escape sequences in a raw string literal.
|
|
||||||
fn unescapeString(allocator: std.mem.Allocator, raw: []const u8) ![]u8 {
|
|
||||||
var result = try allocator.alloc(u8, raw.len);
|
|
||||||
var i: usize = 0;
|
|
||||||
var j: usize = 0;
|
|
||||||
while (i < raw.len) {
|
|
||||||
if (raw[i] == '\\' and i + 1 < raw.len) {
|
|
||||||
i += 1;
|
|
||||||
switch (raw[i]) {
|
|
||||||
'n' => result[j] = '\n',
|
|
||||||
't' => result[j] = '\t',
|
|
||||||
'r' => result[j] = '\r',
|
|
||||||
'\\' => result[j] = '\\',
|
|
||||||
'"' => result[j] = '"',
|
|
||||||
'0' => result[j] = 0,
|
|
||||||
else => result[j] = raw[i],
|
|
||||||
}
|
|
||||||
j += 1;
|
|
||||||
i += 1;
|
|
||||||
} else {
|
|
||||||
result[j] = raw[i];
|
|
||||||
j += 1;
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result[0..j];
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Compile a string literal with escape sequences and interpolation support.
|
/// Compile a string literal with escape sequences and interpolation support.
|
||||||
/// Handles `{expr}` patterns by parsing and compiling the inner expressions,
|
/// Handles `{expr}` patterns by parsing and compiling the inner expressions,
|
||||||
/// then concatenating all segments together.
|
/// then concatenating all segments together.
|
||||||
@@ -389,7 +362,7 @@ pub const Compiler = struct {
|
|||||||
fn compileStringLiteral(self: *Compiler, raw: []const u8) !void {
|
fn compileStringLiteral(self: *Compiler, raw: []const u8) !void {
|
||||||
// String literals are plain text — {} is NOT interpolated here.
|
// String literals are plain text — {} is NOT interpolated here.
|
||||||
// String interpolation is handled by print() at the call site.
|
// String interpolation is handled by print() at the call site.
|
||||||
const unescaped = try unescapeString(self.allocator, raw);
|
const unescaped = try unescape.unescapeString(self.allocator, raw);
|
||||||
const idx = try self.addString(unescaped);
|
const idx = try self.addString(unescaped);
|
||||||
try self.emit(.{ .push_string = idx });
|
try self.emit(.{ .push_string = idx });
|
||||||
}
|
}
|
||||||
|
|||||||
45
src/sema.zig
45
src/sema.zig
@@ -455,10 +455,7 @@ pub const Analyzer = struct {
|
|||||||
switch (node.data) {
|
switch (node.data) {
|
||||||
.fn_decl => |fd| {
|
.fn_decl => |fd| {
|
||||||
try self.pushScope();
|
try self.pushScope();
|
||||||
for (fd.params) |param| {
|
try self.analyzeParams(fd.params);
|
||||||
const param_type = Type.fromTypeExpr(param.type_expr);
|
|
||||||
try self.addSymbol(param.name, .param, param_type, param.name_span);
|
|
||||||
}
|
|
||||||
try self.analyzeNode(fd.body);
|
try self.analyzeNode(fd.body);
|
||||||
self.popScope();
|
self.popScope();
|
||||||
},
|
},
|
||||||
@@ -499,6 +496,13 @@ pub const Analyzer = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn analyzeParams(self: *Analyzer, params: []const ast.Param) !void {
|
||||||
|
for (params) |param| {
|
||||||
|
const param_type = Type.fromTypeExpr(param.type_expr);
|
||||||
|
try self.addSymbol(param.name, .param, param_type, param.name_span);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn addSymbol(self: *Analyzer, name: []const u8, kind: SymbolKind, ty: ?Type, span: Span) !void {
|
fn addSymbol(self: *Analyzer, name: []const u8, kind: SymbolKind, ty: ?Type, span: Span) !void {
|
||||||
// Check for duplicate only within the current scope window.
|
// Check for duplicate only within the current scope window.
|
||||||
const scope_start: usize = if (self.scope_starts.items.len > 0)
|
const scope_start: usize = if (self.scope_starts.items.len > 0)
|
||||||
@@ -563,11 +567,7 @@ pub const Analyzer = struct {
|
|||||||
.fn_decl => |fd| {
|
.fn_decl => |fd| {
|
||||||
try self.addSymbol(fd.name, .function, resolveReturnType(fd), node.span);
|
try self.addSymbol(fd.name, .function, resolveReturnType(fd), node.span);
|
||||||
try self.pushScope();
|
try self.pushScope();
|
||||||
// Add params as symbols
|
try self.analyzeParams(fd.params);
|
||||||
for (fd.params) |param| {
|
|
||||||
const param_type = Type.fromTypeExpr(param.type_expr);
|
|
||||||
try self.addSymbol(param.name, .param, param_type, param.name_span);
|
|
||||||
}
|
|
||||||
try self.analyzeNode(fd.body);
|
try self.analyzeNode(fd.body);
|
||||||
self.popScope();
|
self.popScope();
|
||||||
},
|
},
|
||||||
@@ -675,10 +675,7 @@ pub const Analyzer = struct {
|
|||||||
},
|
},
|
||||||
.lambda => |lam| {
|
.lambda => |lam| {
|
||||||
try self.pushScope();
|
try self.pushScope();
|
||||||
for (lam.params) |param| {
|
try self.analyzeParams(lam.params);
|
||||||
const param_type = Type.fromTypeExpr(param.type_expr);
|
|
||||||
try self.addSymbol(param.name, .param, param_type, param.name_span);
|
|
||||||
}
|
|
||||||
try self.analyzeNode(lam.body);
|
try self.analyzeNode(lam.body);
|
||||||
self.popScope();
|
self.popScope();
|
||||||
},
|
},
|
||||||
@@ -824,24 +821,22 @@ pub fn analyzeSource(allocator: std.mem.Allocator, root: *Node) !SemaResult {
|
|||||||
return analyzer.analyze(root);
|
return analyzer.analyze(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find the symbol whose definition span contains the given byte offset.
|
fn findSpanAtOffset(comptime T: type, items: []const T, offset: u32, comptime span_field: []const u8) ?usize {
|
||||||
pub fn findSymbolAtOffset(symbols: []const Symbol, offset: u32) ?usize {
|
for (items, 0..) |item, i| {
|
||||||
for (symbols, 0..) |sym, i| {
|
const span = @field(item, span_field);
|
||||||
if (offset >= sym.def_span.start and offset < sym.def_span.end) {
|
if (offset >= span.start and offset < span.end) return i;
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Find the symbol whose definition span contains the given byte offset.
|
||||||
|
pub fn findSymbolAtOffset(symbols: []const Symbol, offset: u32) ?usize {
|
||||||
|
return findSpanAtOffset(Symbol, symbols, offset, "def_span");
|
||||||
|
}
|
||||||
|
|
||||||
/// Find the reference at the given byte offset.
|
/// Find the reference at the given byte offset.
|
||||||
pub fn findReferenceAtOffset(references: []const Reference, offset: u32) ?usize {
|
pub fn findReferenceAtOffset(references: []const Reference, offset: u32) ?usize {
|
||||||
for (references, 0..) |ref_, i| {
|
return findSpanAtOffset(Reference, references, offset, "span");
|
||||||
if (offset >= ref_.span.start and offset < ref_.span.end) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Walk the AST to find the innermost node whose span contains the offset.
|
/// Walk the AST to find the innermost node whose span contains the offset.
|
||||||
|
|||||||
46
src/unescape.zig
Normal file
46
src/unescape.zig
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
/// Process escape sequences in a raw string literal.
|
||||||
|
pub fn unescapeString(allocator: std.mem.Allocator, raw: []const u8) ![]u8 {
|
||||||
|
var result = try allocator.alloc(u8, raw.len);
|
||||||
|
var i: usize = 0;
|
||||||
|
var j: usize = 0;
|
||||||
|
while (i < raw.len) {
|
||||||
|
if (raw[i] == '\\' and i + 1 < raw.len) {
|
||||||
|
i += 1;
|
||||||
|
switch (raw[i]) {
|
||||||
|
'n' => {
|
||||||
|
result[j] = '\n';
|
||||||
|
},
|
||||||
|
't' => {
|
||||||
|
result[j] = '\t';
|
||||||
|
},
|
||||||
|
'r' => {
|
||||||
|
result[j] = '\r';
|
||||||
|
},
|
||||||
|
'\\' => {
|
||||||
|
result[j] = '\\';
|
||||||
|
},
|
||||||
|
'"' => {
|
||||||
|
result[j] = '"';
|
||||||
|
},
|
||||||
|
'0' => {
|
||||||
|
result[j] = 0;
|
||||||
|
},
|
||||||
|
'`' => {
|
||||||
|
result[j] = '`';
|
||||||
|
},
|
||||||
|
else => {
|
||||||
|
result[j] = raw[i];
|
||||||
|
},
|
||||||
|
}
|
||||||
|
j += 1;
|
||||||
|
i += 1;
|
||||||
|
} else {
|
||||||
|
result[j] = raw[i];
|
||||||
|
j += 1;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result[0..j];
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user