Field access, function calls based on function value
This commit is contained in:
parent
779c3c0710
commit
da00751726
@ -13,14 +13,16 @@ const analysis = @import("analysis.zig");
|
|||||||
const DocumentStore = @import("DocumentStore.zig");
|
const DocumentStore = @import("DocumentStore.zig");
|
||||||
const ComptimeInterpreter = @This();
|
const ComptimeInterpreter = @This();
|
||||||
|
|
||||||
tree: Ast,
|
|
||||||
root_scope: *InterpreterScope = undefined,
|
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
|
document_store: *DocumentStore,
|
||||||
|
handle: *const DocumentStore.Handle,
|
||||||
|
root_scope: ?*InterpreterScope = null,
|
||||||
|
|
||||||
type_info: std.ArrayListUnmanaged(TypeInfo) = .{},
|
type_info: std.ArrayListUnmanaged(TypeInfo) = .{},
|
||||||
type_info_map: std.HashMapUnmanaged(TypeInfo, usize, TypeInfo.Context, std.hash_map.default_max_load_percentage) = .{},
|
type_info_map: std.HashMapUnmanaged(TypeInfo, usize, TypeInfo.Context, std.hash_map.default_max_load_percentage) = .{},
|
||||||
|
|
||||||
pub fn deinit(interpreter: *ComptimeInterpreter) void {
|
pub fn deinit(interpreter: *ComptimeInterpreter) void {
|
||||||
|
if (interpreter.root_scope) |rs| rs.deinit();
|
||||||
for (interpreter.type_info.items) |*ti| ti.deinit(interpreter.allocator);
|
for (interpreter.type_info.items) |*ti| ti.deinit(interpreter.allocator);
|
||||||
interpreter.type_info.deinit(interpreter.allocator);
|
interpreter.type_info.deinit(interpreter.allocator);
|
||||||
interpreter.type_info_map.deinit(interpreter.allocator);
|
interpreter.type_info_map.deinit(interpreter.allocator);
|
||||||
@ -83,6 +85,7 @@ pub const TypeInfo = union(enum) {
|
|||||||
|
|
||||||
@"struct": Struct,
|
@"struct": Struct,
|
||||||
pointer: Pointer,
|
pointer: Pointer,
|
||||||
|
@"fn": Fn,
|
||||||
|
|
||||||
int: Int,
|
int: Int,
|
||||||
@"comptime_int",
|
@"comptime_int",
|
||||||
@ -145,6 +148,13 @@ pub const TypeInfo = union(enum) {
|
|||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn getScopeOfType(ti: TypeInfo) ?*InterpreterScope {
|
||||||
|
return switch (ti) {
|
||||||
|
.@"struct" => |s| s.scope,
|
||||||
|
else => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Type = struct {
|
pub const Type = struct {
|
||||||
@ -180,6 +190,7 @@ pub const ValueData = union(enum) {
|
|||||||
signed_int: i64,
|
signed_int: i64,
|
||||||
float: f64,
|
float: f64,
|
||||||
|
|
||||||
|
@"fn",
|
||||||
runtime,
|
runtime,
|
||||||
comptime_undetermined,
|
comptime_undetermined,
|
||||||
|
|
||||||
@ -233,7 +244,7 @@ pub const Declaration = struct {
|
|||||||
.aligned_var_decl,
|
.aligned_var_decl,
|
||||||
.simple_var_decl,
|
.simple_var_decl,
|
||||||
=> {
|
=> {
|
||||||
return tree.tokenSlice(ast.varDecl(tree, declaration.node_idx).?.ast.mut_token).len == 3;
|
return tree.tokenSlice(ast.varDecl(tree, declaration.node_idx).?.ast.mut_token).len != 3;
|
||||||
},
|
},
|
||||||
else => false,
|
else => false,
|
||||||
};
|
};
|
||||||
@ -261,7 +272,7 @@ pub fn typeToTypeInfo(interpreter: ComptimeInterpreter, @"type": Type) TypeInfo
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub const TypeInfoFormatter = struct {
|
pub const TypeInfoFormatter = struct {
|
||||||
interpreter: *ComptimeInterpreter,
|
interpreter: *const ComptimeInterpreter,
|
||||||
ti: TypeInfo,
|
ti: TypeInfo,
|
||||||
|
|
||||||
pub fn format(value: TypeInfoFormatter, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
|
pub fn format(value: TypeInfoFormatter, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
|
||||||
@ -285,7 +296,7 @@ pub const TypeInfoFormatter = struct {
|
|||||||
var iterator = s.scope.declarations.iterator();
|
var iterator = s.scope.declarations.iterator();
|
||||||
while (iterator.next()) |di| {
|
while (iterator.next()) |di| {
|
||||||
const decl = di.value_ptr.*;
|
const decl = di.value_ptr.*;
|
||||||
if (decl.isConstant(value.interpreter.tree)) {
|
if (decl.isConstant(value.interpreter.handle.tree)) {
|
||||||
try writer.print("const {s}: {any} = TODO_PRINT_VALUES, ", .{ decl.name, value.interpreter.formatTypeInfo(value.interpreter.typeToTypeInfo(decl.@"type")) });
|
try writer.print("const {s}: {any} = TODO_PRINT_VALUES, ", .{ decl.name, value.interpreter.formatTypeInfo(value.interpreter.typeToTypeInfo(decl.@"type")) });
|
||||||
} else {
|
} else {
|
||||||
try writer.print("var {s}: {any}, ", .{ decl.name, value.interpreter.formatTypeInfo(value.interpreter.typeToTypeInfo(decl.@"type")) });
|
try writer.print("var {s}: {any}, ", .{ decl.name, value.interpreter.formatTypeInfo(value.interpreter.typeToTypeInfo(decl.@"type")) });
|
||||||
@ -298,7 +309,7 @@ pub const TypeInfoFormatter = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn formatTypeInfo(interpreter: *ComptimeInterpreter, ti: TypeInfo) TypeInfoFormatter {
|
pub fn formatTypeInfo(interpreter: *const ComptimeInterpreter, ti: TypeInfo) TypeInfoFormatter {
|
||||||
return TypeInfoFormatter{ .interpreter = interpreter, .ti = ti };
|
return TypeInfoFormatter{ .interpreter = interpreter, .ti = ti };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,11 +376,13 @@ pub const InterpreterScope = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(scope: *InterpreterScope) void {
|
pub fn deinit(scope: *InterpreterScope) void {
|
||||||
scope.declarations.deinit(scope.interpreter.allocator);
|
const allocator = scope.interpreter.allocator;
|
||||||
for (scope.child_scopes.items) |child| child.deinit();
|
|
||||||
scope.child_scopes.deinit(scope.interpreter.allocator);
|
|
||||||
|
|
||||||
scope.interpreter.allocator.destroy(scope);
|
scope.declarations.deinit(allocator);
|
||||||
|
for (scope.child_scopes.items) |child| child.deinit();
|
||||||
|
scope.child_scopes.deinit(allocator);
|
||||||
|
|
||||||
|
allocator.destroy(scope);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -431,7 +444,7 @@ pub fn interpret(
|
|||||||
// _ = node;
|
// _ = node;
|
||||||
// _ = observe_values;
|
// _ = observe_values;
|
||||||
|
|
||||||
const tree = interpreter.tree;
|
const tree = interpreter.handle.tree;
|
||||||
const tags = tree.nodes.items(.tag);
|
const tags = tree.nodes.items(.tag);
|
||||||
const data = tree.nodes.items(.data);
|
const data = tree.nodes.items(.data);
|
||||||
const main_tokens = tree.nodes.items(.main_token);
|
const main_tokens = tree.nodes.items(.main_token);
|
||||||
@ -445,12 +458,12 @@ pub fn interpret(
|
|||||||
.container_decl_arg_trailing,
|
.container_decl_arg_trailing,
|
||||||
.container_decl_two,
|
.container_decl_two,
|
||||||
.container_decl_two_trailing,
|
.container_decl_two_trailing,
|
||||||
.tagged_union,
|
// .tagged_union, // TODO: Fix these
|
||||||
.tagged_union_trailing,
|
// .tagged_union_trailing,
|
||||||
.tagged_union_two,
|
// .tagged_union_two,
|
||||||
.tagged_union_two_trailing,
|
// .tagged_union_two_trailing,
|
||||||
.tagged_union_enum_tag,
|
// .tagged_union_enum_tag,
|
||||||
.tagged_union_enum_tag_trailing,
|
// .tagged_union_enum_tag_trailing,
|
||||||
.root,
|
.root,
|
||||||
.error_set_decl,
|
.error_set_decl,
|
||||||
=> {
|
=> {
|
||||||
@ -631,6 +644,20 @@ pub fn interpret(
|
|||||||
std.log.err("Identifier not found: {s}", .{value});
|
std.log.err("Identifier not found: {s}", .{value});
|
||||||
return error.IdentifierNotFound;
|
return error.IdentifierNotFound;
|
||||||
},
|
},
|
||||||
|
.field_access => {
|
||||||
|
if (data[node_idx].rhs == 0) return error.CriticalAstFailure;
|
||||||
|
const rhs_str = ast.tokenSlice(tree, data[node_idx].rhs) catch return error.CriticalAstFailure;
|
||||||
|
|
||||||
|
var ir = try interpreter.interpret(data[node_idx].lhs, scope, options);
|
||||||
|
var irv = try ir.getValue();
|
||||||
|
|
||||||
|
var sub_scope = interpreter.typeToTypeInfo(irv.value_data.@"type").getScopeOfType() orelse return error.IdentifierNotFound;
|
||||||
|
var scope_sub_decl = sub_scope.declarations.get(rhs_str) orelse return error.IdentifierNotFound;
|
||||||
|
|
||||||
|
return InterpretResult{
|
||||||
|
.value = scope_sub_decl.value,
|
||||||
|
};
|
||||||
|
},
|
||||||
.grouped_expression => {
|
.grouped_expression => {
|
||||||
return try interpreter.interpret(data[node_idx].lhs, scope, options);
|
return try interpreter.interpret(data[node_idx].lhs, scope, options);
|
||||||
},
|
},
|
||||||
@ -796,12 +823,11 @@ pub fn interpret(
|
|||||||
|
|
||||||
// TODO: Add params
|
// TODO: Add params
|
||||||
|
|
||||||
// var type_info = TypeInfo{
|
var type_info = TypeInfo{
|
||||||
// .@"fn" = .{
|
.@"fn" = .{
|
||||||
// .definition_scope = scope.?,
|
.return_type = null,
|
||||||
// .node_idx = node_idx,
|
},
|
||||||
// },
|
};
|
||||||
// };
|
|
||||||
|
|
||||||
// var it = func.iterate(&tree);
|
// var it = func.iterate(&tree);
|
||||||
// while (ast.nextFnParam(&it)) |param| {
|
// while (ast.nextFnParam(&it)) |param| {
|
||||||
@ -827,20 +853,19 @@ pub fn interpret(
|
|||||||
// if ((try interpreter.interpret(func.ast.return_type, func_scope_idx, .{ .observe_values = true, .is_comptime = true })).maybeGetValue()) |value|
|
// if ((try interpreter.interpret(func.ast.return_type, func_scope_idx, .{ .observe_values = true, .is_comptime = true })).maybeGetValue()) |value|
|
||||||
// fnd.return_type = value.value_data.@"type";
|
// fnd.return_type = value.value_data.@"type";
|
||||||
|
|
||||||
// var value = Value{
|
var value = Value{
|
||||||
// .node_idx = node_idx,
|
.node_idx = node_idx,
|
||||||
// .@"type" = try interpreter.createType(node_idx, type_info),
|
.@"type" = try interpreter.createType(node_idx, type_info),
|
||||||
// .value_data = .{ .@"fn" = .{} },
|
.value_data = .{ .@"fn" = .{} },
|
||||||
// };
|
};
|
||||||
|
|
||||||
// const name = analysis.getDeclName(tree, node_idx).?;
|
const name = analysis.getDeclName(tree, node_idx).?;
|
||||||
// // TODO: DANGER DANGER DANGER
|
try scope.?.declarations.put(interpreter.allocator, name, .{
|
||||||
// try scope.?.declarations.put(interpreter.allocator, name, .{
|
.node_idx = node_idx,
|
||||||
// .node_idx = node_idx,
|
.name = name,
|
||||||
// .name = name,
|
.@"type" = value.@"type",
|
||||||
// .@"type" = undefined,
|
.@"value" = value,
|
||||||
// .@"value" = undefined,
|
});
|
||||||
// });
|
|
||||||
|
|
||||||
return InterpretResult{ .nothing = .{} };
|
return InterpretResult{ .nothing = .{} };
|
||||||
},
|
},
|
||||||
@ -863,13 +888,15 @@ pub fn interpret(
|
|||||||
try args.append(interpreter.allocator, try (try interpreter.interpret(param, scope, .{})).getValue());
|
try args.append(interpreter.allocator, try (try interpreter.interpret(param, scope, .{})).getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Make this actually resolve function; requires interpreting whole file
|
std.log.err("AEWEWEWE: {s}", .{tree.getNodeSource(call_full.ast.fn_expr)});
|
||||||
// const res = try interpreter.interpret(call_full.ast.fn_expr, scope, .{});
|
|
||||||
// const value = try res.getValue();
|
|
||||||
|
|
||||||
const call_res = try interpreter.call(tree.rootDecls()[0], args.items, options);
|
const func_id_result = try interpreter.interpret(call_full.ast.fn_expr, interpreter.root_scope, .{});
|
||||||
|
const func_id_val = try func_id_result.getValue();
|
||||||
|
|
||||||
|
const call_res = try interpreter.call(interpreter.root_scope, func_id_val.node_idx, args.items, options);
|
||||||
// defer call_res.scope.deinit();
|
// defer call_res.scope.deinit();
|
||||||
// TODO: Figure out call result memory model
|
// TODO: Figure out call result memory model; this is actually fine because newScope
|
||||||
|
// makes this a child of the decl scope which is freed on refresh... in theory
|
||||||
|
|
||||||
return switch (call_res.result) {
|
return switch (call_res.result) {
|
||||||
.value => |v| .{ .value = v },
|
.value => |v| .{ .value = v },
|
||||||
@ -905,6 +932,7 @@ pub const CallResult = struct {
|
|||||||
|
|
||||||
pub fn call(
|
pub fn call(
|
||||||
interpreter: *ComptimeInterpreter,
|
interpreter: *ComptimeInterpreter,
|
||||||
|
scope: ?*InterpreterScope,
|
||||||
func_node_idx: Ast.Node.Index,
|
func_node_idx: Ast.Node.Index,
|
||||||
arguments: []const Value,
|
arguments: []const Value,
|
||||||
options: InterpretOptions,
|
options: InterpretOptions,
|
||||||
@ -915,12 +943,12 @@ pub fn call(
|
|||||||
_ = options;
|
_ = options;
|
||||||
// _ = arguments;
|
// _ = arguments;
|
||||||
|
|
||||||
const tree = interpreter.tree;
|
const tree = interpreter.handle.tree;
|
||||||
const tags = tree.nodes.items(.tag);
|
const tags = tree.nodes.items(.tag);
|
||||||
|
|
||||||
std.debug.assert(tags[func_node_idx] == .fn_decl);
|
std.debug.assert(tags[func_node_idx] == .fn_decl);
|
||||||
|
|
||||||
var fn_scope = try interpreter.newScope(null, func_node_idx);
|
var fn_scope = try interpreter.newScope(scope, func_node_idx);
|
||||||
|
|
||||||
var buf: [1]Ast.Node.Index = undefined;
|
var buf: [1]Ast.Node.Index = undefined;
|
||||||
var proto = ast.fnProto(tree, func_node_idx, &buf).?;
|
var proto = ast.fnProto(tree, func_node_idx, &buf).?;
|
||||||
|
@ -12,6 +12,7 @@ const BuildConfig = @import("special/build_runner.zig").BuildConfig;
|
|||||||
const tracy = @import("tracy.zig");
|
const tracy = @import("tracy.zig");
|
||||||
const Config = @import("Config.zig");
|
const Config = @import("Config.zig");
|
||||||
const translate_c = @import("translate_c.zig");
|
const translate_c = @import("translate_c.zig");
|
||||||
|
const ComptimeInterpreter = @import("ComptimeInterpreter.zig");
|
||||||
|
|
||||||
const DocumentStore = @This();
|
const DocumentStore = @This();
|
||||||
|
|
||||||
@ -55,6 +56,8 @@ pub const Handle = struct {
|
|||||||
uri: Uri,
|
uri: Uri,
|
||||||
text: [:0]const u8,
|
text: [:0]const u8,
|
||||||
tree: Ast,
|
tree: Ast,
|
||||||
|
/// Not null if a ComptimeInterpreter is actually used
|
||||||
|
interpreter: ?*ComptimeInterpreter = null,
|
||||||
document_scope: analysis.DocumentScope,
|
document_scope: analysis.DocumentScope,
|
||||||
/// Contains one entry for every import in the document
|
/// Contains one entry for every import in the document
|
||||||
import_uris: std.ArrayListUnmanaged(Uri) = .{},
|
import_uris: std.ArrayListUnmanaged(Uri) = .{},
|
||||||
@ -189,6 +192,11 @@ pub fn refreshDocument(self: *DocumentStore, uri: Uri, new_text: [:0]const u8) !
|
|||||||
|
|
||||||
const handle = self.handles.get(uri) orelse unreachable;
|
const handle = self.handles.get(uri) orelse unreachable;
|
||||||
|
|
||||||
|
if (handle.interpreter) |int| {
|
||||||
|
int.deinit();
|
||||||
|
handle.interpreter = null;
|
||||||
|
}
|
||||||
|
|
||||||
self.allocator.free(handle.text);
|
self.allocator.free(handle.text);
|
||||||
handle.text = new_text;
|
handle.text = new_text;
|
||||||
|
|
||||||
@ -927,3 +935,18 @@ pub fn errorCompletionItems(self: DocumentStore, arena: std.mem.Allocator, handl
|
|||||||
pub fn enumCompletionItems(self: DocumentStore, arena: std.mem.Allocator, handle: Handle) ![]types.CompletionItem {
|
pub fn enumCompletionItems(self: DocumentStore, arena: std.mem.Allocator, handle: Handle) ![]types.CompletionItem {
|
||||||
return try self.tagStoreCompletionItems(arena, handle, "enum_completions");
|
return try self.tagStoreCompletionItems(arena, handle, "enum_completions");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ensureInterpreterExists(self: *DocumentStore, uri: Uri) !void {
|
||||||
|
var handle = self.handles.get(uri) orelse unreachable;
|
||||||
|
if (handle.interpreter == null) {
|
||||||
|
var int = try self.allocator.create(ComptimeInterpreter);
|
||||||
|
int.* = ComptimeInterpreter{
|
||||||
|
.allocator = self.allocator,
|
||||||
|
.document_store = self,
|
||||||
|
.handle = handle,
|
||||||
|
};
|
||||||
|
_ = try int.interpret(0, null, .{});
|
||||||
|
|
||||||
|
handle.interpreter = int;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -18,6 +18,7 @@ const Ast = std.zig.Ast;
|
|||||||
const tracy = @import("tracy.zig");
|
const tracy = @import("tracy.zig");
|
||||||
const uri_utils = @import("uri.zig");
|
const uri_utils = @import("uri.zig");
|
||||||
const diff = @import("diff.zig");
|
const diff = @import("diff.zig");
|
||||||
|
const ComptimeInterpreter = @import("ComptimeInterpreter.zig");
|
||||||
|
|
||||||
const data = @import("data/data.zig");
|
const data = @import("data/data.zig");
|
||||||
const snipped_data = @import("data/snippets.zig");
|
const snipped_data = @import("data/snippets.zig");
|
||||||
@ -492,7 +493,7 @@ fn typeToCompletion(
|
|||||||
while (it.next()) |entry| {
|
while (it.next()) |entry| {
|
||||||
try list.append(allocator, .{
|
try list.append(allocator, .{
|
||||||
.label = entry.key_ptr.*,
|
.label = entry.key_ptr.*,
|
||||||
.kind = if (entry.value_ptr.isConstant(co.interpreter.tree)) .Constant else .Variable,
|
.kind = if (entry.value_ptr.isConstant(co.interpreter.handle.tree)) .Constant else .Variable,
|
||||||
.insertText = entry.key_ptr.*,
|
.insertText = entry.key_ptr.*,
|
||||||
.insertTextFormat = .PlainText,
|
.insertTextFormat = .PlainText,
|
||||||
});
|
});
|
||||||
@ -819,7 +820,10 @@ fn hoverSymbol(server: *Server, decl_handle: analysis.DeclWithHandle) error{OutO
|
|||||||
const resolved_type = try decl_handle.resolveType(&server.document_store, &server.arena, &bound_type_params);
|
const resolved_type = try decl_handle.resolveType(&server.document_store, &server.arena, &bound_type_params);
|
||||||
|
|
||||||
const resolved_type_str = if (resolved_type) |rt|
|
const resolved_type_str = if (resolved_type) |rt|
|
||||||
if (rt.type.is_type_val) "type" else switch (rt.type.data) { // TODO: Investigate random weird numbers like 897 that cause index of bounds
|
if (rt.type.is_type_val) switch (rt.type.data) {
|
||||||
|
.@"comptime" => |*co| try std.fmt.allocPrint(server.arena.allocator(), "{ }", .{co.interpreter.formatTypeInfo(co.interpreter.typeToTypeInfo(co.type))}),
|
||||||
|
else => "type",
|
||||||
|
} else switch (rt.type.data) { // TODO: Investigate random weird numbers like 897 that cause index of bounds
|
||||||
.pointer,
|
.pointer,
|
||||||
.slice,
|
.slice,
|
||||||
.error_union,
|
.error_union,
|
||||||
|
@ -749,14 +749,32 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
|
|||||||
// TODO: Better case-by-case; we just use the ComptimeInterpreter when all else fails,
|
// TODO: Better case-by-case; we just use the ComptimeInterpreter when all else fails,
|
||||||
// probably better to use it more liberally
|
// probably better to use it more liberally
|
||||||
// TODO: Handle non-isolate args; e.g. `const T = u8; TypeFunc(T);`
|
// TODO: Handle non-isolate args; e.g. `const T = u8; TypeFunc(T);`
|
||||||
var interpreter = ComptimeInterpreter{ .tree = tree, .allocator = arena.allocator() };
|
// var interpreter = ComptimeInterpreter{ .tree = tree, .allocator = arena.allocator() };
|
||||||
|
|
||||||
const result = interpreter.interpret(node, null, .{}) catch |err| {
|
// var top_decl = try (try interpreter.interpret(0, null, .{})).getValue();
|
||||||
|
// var top_scope = interpreter.typeToTypeInfo(top_decl.@"type".info_idx).@"struct".scope;
|
||||||
|
|
||||||
|
// var fn_decl_scope = top_scope.getParentScopeFromNode(node);
|
||||||
|
|
||||||
|
store.ensureInterpreterExists(handle.uri) catch |err| {
|
||||||
std.log.err("Interpreter error: {s}", .{@errorName(err)});
|
std.log.err("Interpreter error: {s}", .{@errorName(err)});
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
var interpreter = handle.interpreter.?;
|
||||||
|
|
||||||
|
// TODO: Start from current/nearest-current scope
|
||||||
|
const result = interpreter.interpret(node, interpreter.root_scope, .{}) catch |err| {
|
||||||
|
std.log.err("Interpreter error: {s}", .{@errorName(err)});
|
||||||
|
if (@errorReturnTrace()) |trace| {
|
||||||
|
std.debug.dumpStackTrace(trace.*);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
const val = result.getValue() catch |err| {
|
const val = result.getValue() catch |err| {
|
||||||
std.log.err("Interpreter error: {s}", .{@errorName(err)});
|
std.log.err("Interpreter error: {s}", .{@errorName(err)});
|
||||||
|
if (@errorReturnTrace()) |trace| {
|
||||||
|
std.debug.dumpStackTrace(trace.*);
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -997,7 +1015,7 @@ pub const Type = struct {
|
|||||||
primitive: Ast.Node.Index,
|
primitive: Ast.Node.Index,
|
||||||
array_index,
|
array_index,
|
||||||
@"comptime": struct {
|
@"comptime": struct {
|
||||||
interpreter: ComptimeInterpreter,
|
interpreter: *ComptimeInterpreter,
|
||||||
type: ComptimeInterpreter.Type,
|
type: ComptimeInterpreter.Type,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user