fix remaining compiler errors

This commit is contained in:
Techatrix 2022-12-27 03:02:07 +01:00
parent 03e50066a1
commit 6118686d00
4 changed files with 232 additions and 263 deletions

View File

@ -77,93 +77,6 @@ pub const Value = struct {
val: IPIndex, val: IPIndex,
}; };
pub const FieldDefinition = struct {
node_idx: Ast.Node.Index,
/// Store name so tree doesn't need to be used to access field name
/// When the field is a tuple field, `name` will be an empty slice
name: []const u8,
ty: Type,
default_value: ?Value,
};
pub const Declaration = struct {
scope: u32,
node_idx: Ast.Node.Index,
/// Store name so tree doesn't need to be used to access declaration name
name: []const u8,
/// If value is null, declaration has not been interpreted yet
value: ?Value = null,
// TODO: figure this out
// pub const DeclarationKind = enum{variable, function};
// pub fn declarationKind(declaration: Declaration, tree: Ast) DeclarationKind {
// return switch(tree.nodes.items(.tag)[declaration.node_idx]) {
// .fn_proto,
// .fn_proto_one,
// .fn_proto_simple,
// .fn_proto_multi,
// .fn_decl
// }
// }
pub fn getValue(decl: *Declaration) InterpretError!Value {
var interpreter = decl.scope.interpreter;
const tree = decl.scope.interpreter.getHandle().tree;
const tags = tree.nodes.items(.tag);
if (decl.value == null) {
switch (tags[decl.node_idx]) {
.global_var_decl,
.local_var_decl,
.aligned_var_decl,
.simple_var_decl,
=> {
const var_decl = ast.varDecl(tree, decl.node_idx).?;
if (var_decl.ast.init_node == 0)
return error.CriticalAstFailure;
var value = try (try interpreter.interpret(var_decl.ast.init_node, decl.scope, .{})).getValue();
if (var_decl.ast.type_node != 0) {
var type_val = try (try interpreter.interpret(var_decl.ast.type_node, decl.scope, .{})).getValue();
const type_type = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = .type });
if (type_val.ty != type_type) {
try interpreter.recordError(
decl.node_idx,
"expected_type",
std.fmt.allocPrint(interpreter.allocator, "expected type 'type', found '{}'", .{type_val.ty.fmtType(&interpreter.ip)}) catch return error.CriticalAstFailure,
);
return error.InvalidCast;
}
value = try interpreter.cast(var_decl.ast.type_node, type_val.value_data.type, value);
}
decl.value = value;
},
else => @panic("No other case supported for lazy declaration evaluation"),
}
}
return decl.value.?;
}
pub fn isConstant(declaration: Declaration) bool {
const tree = declaration.scope.interpreter.getHandle().tree;
return switch (tree.nodes.items(.tag)[declaration.node_idx]) {
.global_var_decl,
.local_var_decl,
.aligned_var_decl,
.simple_var_decl,
=> {
return tree.tokenSlice(ast.varDecl(tree, declaration.node_idx).?.ast.mut_token).len != 3;
},
else => false,
};
}
};
// pub const Comptimeness = enum { @"comptime", runtime }; // pub const Comptimeness = enum { @"comptime", runtime };
pub const Scope = struct { pub const Scope = struct {
@ -217,21 +130,6 @@ pub const Scope = struct {
} }
}; };
pub fn newScope(
interpreter: *ComptimeInterpreter,
maybe_parent: ?Scope,
node_idx: Ast.Node.Index,
) std.mem.Allocator.Error!*Scope {
var ls = try interpreter.allocator.create(Scope);
if (maybe_parent) |parent| try parent.child_scopes.append(interpreter.allocator, ls);
ls.* = .{
.interpreter = interpreter,
.parent = maybe_parent,
.node_idx = node_idx,
};
return ls;
}
pub const InterpretResult = union(enum) { pub const InterpretResult = union(enum) {
@"break": ?[]const u8, @"break": ?[]const u8,
break_with_value: struct { break_with_value: struct {
@ -332,7 +230,7 @@ pub const InterpretError = std.mem.Allocator.Error || std.fmt.ParseIntError || s
pub fn interpret( pub fn interpret(
interpreter: *ComptimeInterpreter, interpreter: *ComptimeInterpreter,
node_idx: Ast.Node.Index, node_idx: Ast.Node.Index,
scope: ?Scope, scope: u32,
options: InterpretOptions, options: InterpretOptions,
) InterpretError!InterpretResult { ) InterpretError!InterpretResult {
const tree = interpreter.getHandle().tree; const tree = interpreter.getHandle().tree;
@ -358,12 +256,13 @@ pub fn interpret(
=> { => {
const type_type = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = .type }); const type_type = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = .type });
var container_scope = Scope{ try interpreter.scopes.append(interpreter.allocator, .{
.interpreter = interpreter, .interpreter = interpreter,
.parent = if (scope) |sc| sc.parent else 0, .parent = scope,
.node_idx = node_idx, .node_idx = node_idx,
.namespace = IPIndex.none, // declarations have not been resolved yet .namespace = IPIndex.none, // declarations have not been resolved yet
}; });
const container_scope = @intCast(u32, interpreter.scopes.len - 1);
var fields = std.StringArrayHashMapUnmanaged(InternPool.Struct.Field){}; var fields = std.StringArrayHashMapUnmanaged(InternPool.Struct.Field){};
defer fields.deinit(interpreter.allocator); defer fields.deinit(interpreter.allocator);
@ -469,12 +368,13 @@ pub fn interpret(
.block_two, .block_two,
.block_two_semicolon, .block_two_semicolon,
=> { => {
var block_scope = Scope{ try interpreter.scopes.append(interpreter.allocator, .{
.interpreter = interpreter, .interpreter = interpreter,
.parent = if (scope) |sc| sc.parent else 0, .parent = scope,
.node_idx = node_idx, .node_idx = node_idx,
.namespace = IPIndex.none, .namespace = IPIndex.none,
}; });
const block_scope = @intCast(u32, interpreter.scopes.len - 1);
var buffer: [2]Ast.Node.Index = undefined; var buffer: [2]Ast.Node.Index = undefined;
const statements = ast.blockStatements(tree, node_idx, &buffer).?; const statements = ast.blockStatements(tree, node_idx, &buffer).?;
@ -483,7 +383,7 @@ pub fn interpret(
const ret = try interpreter.interpret(idx, block_scope, options); const ret = try interpreter.interpret(idx, block_scope, options);
switch (ret) { switch (ret) {
.@"break" => |lllll| { .@"break" => |lllll| {
const maybe_block_label_string = if (scope.?.getLabel()) |i| tree.tokenSlice(i) else null; const maybe_block_label_string = if (interpreter.scopes.get(scope).getLabel()) |i| tree.tokenSlice(i) else null;
if (lllll) |l| { if (lllll) |l| {
if (maybe_block_label_string) |ls| { if (maybe_block_label_string) |ls| {
if (std.mem.eql(u8, l, ls)) { if (std.mem.eql(u8, l, ls)) {
@ -495,7 +395,7 @@ pub fn interpret(
} }
}, },
.break_with_value => |bwv| { .break_with_value => |bwv| {
const maybe_block_label_string = if (scope.?.getLabel()) |i| tree.tokenSlice(i) else null; const maybe_block_label_string = if (interpreter.scopes.get(scope).getLabel()) |i| tree.tokenSlice(i) else null;
if (bwv.label) |l| { if (bwv.label) |l| {
if (maybe_block_label_string) |ls| { if (maybe_block_label_string) |ls| {
@ -569,7 +469,8 @@ pub fn interpret(
// TODO: Floats // TODO: Floats
// Logic to find identifiers in accessible scopes // Logic to find identifiers in accessible scopes
const decl = interpreter.huntItDown(scope.?.namespace, value, options) catch |err| { const namespace = interpreter.scopes.items(.namespace)[scope];
const decl = interpreter.huntItDown(namespace, value, options) catch |err| {
if (err == error.IdentifierNotFound) try interpreter.recordError( if (err == error.IdentifierNotFound) try interpreter.recordError(
node_idx, node_idx,
"undeclared_identifier", "undeclared_identifier",
@ -710,13 +611,13 @@ pub fn interpret(
// TODO: Actually consider operators // TODO: Actually consider operators
if (std.mem.eql(u8, tree.getNodeSource(data[node_idx].lhs), "_")) { if (std.mem.eql(u8, tree.getNodeSource(data[node_idx].lhs), "_")) {
_ = try interpreter.interpret(data[node_idx].rhs, scope.?, options); _ = try interpreter.interpret(data[node_idx].rhs, scope, options);
return InterpretResult{ .nothing = {} }; return InterpretResult{ .nothing = {} };
} }
var ir = try interpreter.interpret(data[node_idx].lhs, scope, options); var ir = try interpreter.interpret(data[node_idx].lhs, scope, options);
var to_value = try ir.getValue(); var to_value = try ir.getValue();
var from_value = (try (try interpreter.interpret(data[node_idx].rhs, scope.?, options)).getValue()); var from_value = (try (try interpreter.interpret(data[node_idx].rhs, scope, options)).getValue());
_ = try interpreter.cast(undefined, to_value.ty, from_value.ty); _ = try interpreter.cast(undefined, to_value.ty, from_value.ty);
@ -756,7 +657,7 @@ pub fn interpret(
try writer.writeAll("indeterminate"); try writer.writeAll("indeterminate");
continue; continue;
}; };
try writer.print("@as({s}, {s})", .{ value.ty.fmtType(&interpreter.ip), value.val.fmtValue(value.ty, &interpreter.ip) }); try writer.print("@as({}, {})", .{ value.ty.fmtType(&interpreter.ip), value.val.fmtValue(value.ty, &interpreter.ip) });
if (index != params.len - 1) if (index != params.len - 1)
try writer.writeAll(", "); try writer.writeAll(", ");
} }
@ -801,12 +702,14 @@ pub fn interpret(
var handle = interpreter.document_store.getOrLoadHandle(import_uri) orelse return error.ImportFailure; var handle = interpreter.document_store.getOrLoadHandle(import_uri) orelse return error.ImportFailure;
try interpreter.document_store.ensureInterpreterExists(handle.uri); try interpreter.document_store.ensureInterpreterExists(handle.uri);
return InterpretResult{ .value = Value{ return InterpretResult{
.interpreter = interpreter, .value = Value{
.node_idx = node_idx, .interpreter = interpreter,
.ty = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = .type }), .node_idx = node_idx,
.val = try interpreter.ip.get(interpreter.allocator, IPKey{ .type_value = undefined }), // TODO .ty = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = .type }),
} }; .val = try interpreter.ip.get(interpreter.allocator, IPKey{ .type_value = undefined }), // TODO
},
};
} }
if (std.mem.eql(u8, call_name, "@TypeOf")) { if (std.mem.eql(u8, call_name, "@TypeOf")) {
@ -837,9 +740,9 @@ pub fn interpret(
const name = interpreter.ip.indexToKey(field_name.val).bytes.data; // TODO add checks const name = interpreter.ip.indexToKey(field_name.val).bytes.data; // TODO add checks
const has_decl = for (namespace.decls) |decl|{ const has_decl = for (namespace.decls) |decl| {
const decl_name = interpreter.ip.indexToKey(decl).declaration.name; const decl_name = interpreter.ip.indexToKey(decl).declaration.name;
if(std.mem.eql(u8, decl_name, name)) break true; if (std.mem.eql(u8, decl_name, name)) break true;
} else false; } else false;
return InterpretResult{ .value = Value{ return InterpretResult{ .value = Value{
@ -989,10 +892,10 @@ 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());
} }
const func_id_result = try interpreter.interpret(call_full.ast.fn_expr, interpreter.root_type.?.getTypeInfo().getScopeOfType().?, .{}); const func_id_result = try interpreter.interpret(call_full.ast.fn_expr, scope, .{});
const func_id_val = try func_id_result.getValue(); const func_id_val = try func_id_result.getValue();
const call_res = try interpreter.call(interpreter.root_type.?.getTypeInfo().getScopeOfType().?, func_id_val.node_idx, args.items, options); const call_res = try interpreter.call(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; this is actually fine because newScope // 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 // makes this a child of the decl scope which is freed on refresh... in theory
@ -1077,7 +980,7 @@ pub fn interpret(
} }
pub const CallResult = struct { pub const CallResult = struct {
scope: *Scope, scope: u32,
result: union(enum) { result: union(enum) {
value: Value, value: Value,
nothing, nothing,
@ -1086,7 +989,7 @@ pub const CallResult = struct {
pub fn call( pub fn call(
interpreter: *ComptimeInterpreter, interpreter: *ComptimeInterpreter,
scope: ?Scope, scope: u32,
func_node_idx: Ast.Node.Index, func_node_idx: Ast.Node.Index,
arguments: []const Value, arguments: []const Value,
options: InterpretOptions, options: InterpretOptions,
@ -1101,9 +1004,15 @@ pub fn call(
if (tags[func_node_idx] != .fn_decl) return error.CriticalAstFailure; if (tags[func_node_idx] != .fn_decl) return error.CriticalAstFailure;
// TODO: Make argument scope to evaluate arguments in // TODO: Make argument scope to evaluate arguments in
var fn_scope = try interpreter.newScope(scope, func_node_idx); try interpreter.scopes.append(interpreter.allocator, Scope{
.interpreter = interpreter,
const type_type = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = .type }); .parent = scope,
.node_idx = func_node_idx,
.namespace = IPIndex.none,
});
const fn_scope = @intCast(u32, interpreter.scopes.len - 1);
const type_type = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = .type });
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).?;
@ -1122,13 +1031,18 @@ pub fn call(
return error.InvalidCast; return error.InvalidCast;
} }
if (param.name_token) |nt| { if (param.name_token) |nt| {
const decl = Declaration{ _ = nt;
.scope = fn_scope, // const decl = InternPool.Decl{
.node_idx = param.type_expr, // .name = tree.tokenSlice(nt),
.name = tree.tokenSlice(nt), // .ty = tex.val,
.value = try interpreter.cast(arguments[arg_index].node_idx, tex.val, arguments[arg_index]), // .val = try interpreter.cast(arguments[arg_index].node_idx, tex.val, arguments[arg_index].val),
}; // .alignment = 0, // TODO
try fn_scope.declarations.put(interpreter.allocator, tree.tokenSlice(nt), decl); // .address_space = .generic, // TODO
// .is_pub = true, // TODO
// .is_exported = false, // TODO
// };
// TODO
// try fn_scope.declarations.put(interpreter.allocator, tree.tokenSlice(nt), decl);
arg_index += 1; arg_index += 1;
} }
} }

View File

@ -949,6 +949,6 @@ pub fn ensureInterpreterExists(self: *DocumentStore, uri: Uri) !void {
.uri = uri, .uri = uri,
}; };
handle.interpreter = int; handle.interpreter = int;
_ = try int.interpret(0, null, .{}); _ = try int.interpret(0, 0, .{});
} }
} }

View File

@ -255,6 +255,8 @@ pub const Key = union(enum) {
.float_64_value => |f| std.hash.autoHash(&hasher, @bitCast(u64, f)), .float_64_value => |f| std.hash.autoHash(&hasher, @bitCast(u64, f)),
.float_80_value => |f| std.hash.autoHash(&hasher, @bitCast(u80, f)), .float_80_value => |f| std.hash.autoHash(&hasher, @bitCast(u80, f)),
.float_128_value => |f| std.hash.autoHash(&hasher, @bitCast(u128, f)), .float_128_value => |f| std.hash.autoHash(&hasher, @bitCast(u128, f)),
.bytes => |bytes| hasher.update(bytes.data),
inline else => |info| std.hash.autoHash(&hasher, info), // TODO sad stage1 noises :( inline else => |info| std.hash.autoHash(&hasher, info), // TODO sad stage1 noises :(
} }
return @truncate(u32, hasher.final()); return @truncate(u32, hasher.final());
@ -303,9 +305,9 @@ pub const Key = union(enum) {
return true; return true;
}, },
.union_type => |union_info| { .union_type => |union_info| {
if (union_info.tag_type != b.union_info.tag_type) return false; if (union_info.tag_type != b.union_type.tag_type) return false;
if (union_info.layout != b.union_info.layout) return false; if (union_info.layout != b.union_type.layout) return false;
if (union_info.fields.count() != b.union_info.fields.count()) return false; if (union_info.fields.count() != b.union_type.fields.count()) return false;
@panic("TODO: implement union equality"); @panic("TODO: implement union equality");
}, },
.tuple_type => |tuple_info| { .tuple_type => |tuple_info| {
@ -331,17 +333,16 @@ pub const Key = union(enum) {
return true; return true;
}, },
.namespace => |namespace_info| { .namespace => |namespace_info| {
if (!std.meta.eql(namespace_info.parent, b.namespace.parent)) return false; if (namespace_info.parent != b.namespace.parent) return false;
if (namespace_info.ty != b.namespace.ty) return false;
if (namespace_info.decls.len != b.namespace.decls.len) return false; if (namespace_info.decls.len != b.namespace.decls.len) return false;
if (namespace_info.usingnamespaces.len != b.namespace.usingnamespaces.len) return false; if (namespace_info.usingnamespaces.len != b.namespace.usingnamespaces.len) return false;
for (namespace_info.decls) |decl, i| { for (namespace_info.decls) |decl, i| {
if (!decl != b.namespace.decls[i]) return false; if (decl != b.namespace.decls[i]) return false;
} }
for (namespace_info.usingnamespaces) |namespace, i| { for (namespace_info.usingnamespaces) |namespace, i| {
if (!namespace != b.namespace.usingnamespaces[i]) return false; if (namespace != b.namespace.usingnamespaces[i]) return false;
} }
return false; return false;
}, },
@ -431,37 +432,71 @@ pub const Key = union(enum) {
.bool_false, .bool_false,
=> unreachable, => unreachable,
}, },
.int_type => .Int,
.pointer_type => .Pointer,
.array_type => .Array,
.struct_type => .Struct,
.optional_type => .Optional,
.error_union_type => .ErrorUnion,
.error_set_type => .ErrorSet,
.enum_type => .Enum,
.function_type => .Fn,
.union_type => .Union,
.tuple_type => .Struct, // TODO this correct?
.vector_type => .Vector,
.declaration,
.namespace,
=> unreachable,
.int_u64_value,
.int_i64_value,
.int_big_value,
.float_16_value,
.float_32_value,
.float_64_value,
.float_80_value,
.float_128_value,
.type_value,
=> unreachable,
.bytes,
.one_pointer,
=> unreachable,
}; };
} }
/// Asserts the type is an integer, enum, error set, packed struct, or vector of one of them. /// Asserts the type is an integer, enum, error set, packed struct, or vector of one of them.
pub fn intInfo(ty: Key, target: std.Target, ip: InternPool) Int { pub fn intInfo(ty: Key, target: std.Target, ip: *const InternPool) Int {
var key: Key = ty; var key: Key = ty;
while (true) switch (key) { while (true) switch (key) {
.simple => |simple| switch (simple) { .simple => |simple| switch (simple) {
.usize => return .{ .signdness = .signed, .bits = target.cpu.arch.ptrBitWidth() }, .usize => return .{ .signedness = .signed, .bits = target.cpu.arch.ptrBitWidth() },
.isize => return .{ .signdness = .unsigned, .bits = target.cpu.arch.ptrBitWidth() }, .isize => return .{ .signedness = .unsigned, .bits = target.cpu.arch.ptrBitWidth() },
// TODO correctly resolve size based on `target` // TODO correctly resolve size based on `target`
.c_short => return .{ .signdness = .signed, .bits = @bitSizeOf(c_short) }, .c_short => return .{ .signedness = .signed, .bits = @bitSizeOf(c_short) },
.c_ushort => return .{ .signdness = .unsigned, .bits = @bitSizeOf(c_ushort) }, .c_ushort => return .{ .signedness = .unsigned, .bits = @bitSizeOf(c_ushort) },
.c_int => return .{ .signdness = .signed, .bits = @bitSizeOf(c_int) }, .c_int => return .{ .signedness = .signed, .bits = @bitSizeOf(c_int) },
.c_uint => return .{ .signdness = .unsigned, .bits = @bitSizeOf(c_uint) }, .c_uint => return .{ .signedness = .unsigned, .bits = @bitSizeOf(c_uint) },
.c_long => return .{ .signdness = .signed, .bits = @bitSizeOf(c_long) }, .c_long => return .{ .signedness = .signed, .bits = @bitSizeOf(c_long) },
.c_ulong => return .{ .signdness = .unsigned, .bits = @bitSizeOf(c_ulong) }, .c_ulong => return .{ .signedness = .unsigned, .bits = @bitSizeOf(c_ulong) },
.c_longlong => return .{ .signdness = .signed, .bits = @bitSizeOf(c_longlong) }, .c_longlong => return .{ .signedness = .signed, .bits = @bitSizeOf(c_longlong) },
.c_ulonglong => return .{ .signdness = .unsigned, .bits = @bitSizeOf(c_ulonglong) }, .c_ulonglong => return .{ .signedness = .unsigned, .bits = @bitSizeOf(c_ulonglong) },
.c_longdouble => return .{ .signdness = .signed, .bits = @bitSizeOf(c_longdouble) }, .c_longdouble => return .{ .signedness = .signed, .bits = @bitSizeOf(c_longdouble) },
// TODO revisit this when error sets support custom int types (comment taken from zig codebase) // TODO revisit this when error sets support custom int types (comment taken from zig codebase)
.anyerror => return .{ .signedness = .unsigned, .bits = 16 }, .anyerror => return .{ .signedness = .unsigned, .bits = 16 },
else => unreachable,
}, },
.int_type => |int_info| return int_info, .int_type => |int_info| return int_info,
.enum_type => @panic("TODO"), .enum_type => @panic("TODO"),
.struct_type => |struct_info| { .struct_type => |struct_info| {
std.debug.assert(struct_info.layout == .Packed); std.debug.assert(struct_info.layout == .Packed);
key = struct_info.backing_int_ty; key = ip.indexToKey(struct_info.backing_int_ty);
}, },
// TODO revisit this when error sets support custom int types (comment taken from zig codebase) // TODO revisit this when error sets support custom int types (comment taken from zig codebase)
.error_set_type => return .{ .signedness = .unsigned, .bits = 16 }, .error_set_type => return .{ .signedness = .unsigned, .bits = 16 },
@ -469,7 +504,6 @@ pub const Key = union(enum) {
std.debug.assert(vector_info.len == 1); std.debug.assert(vector_info.len == 1);
key = ip.indexToKey(vector_info.child); key = ip.indexToKey(vector_info.child);
}, },
else => unreachable, else => unreachable,
}; };
} }
@ -511,13 +545,20 @@ pub const Key = union(enum) {
}; };
} }
pub fn isConstPtr(ty: Key) bool {
return switch (ty) {
.pointer_type => |pointer_info| pointer_info.is_const,
else => false,
};
}
pub fn isSlice(ty: Key) bool { pub fn isSlice(ty: Key) bool {
return switch (ty) { return switch (ty) {
.pointer_type => |pointer_info| pointer_info.size == .Slice, .pointer_type => |pointer_info| pointer_info.size == .Slice,
else => false, else => false,
}; };
} }
pub fn getNamespace(ty: Key) ?Index { pub fn getNamespace(ty: Key) ?Index {
return switch (ty) { return switch (ty) {
.struct_type => |struct_info| struct_info.namespace, .struct_type => |struct_info| struct_info.namespace,
@ -1030,7 +1071,7 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
.type => .{ .type_value = @intToEnum(Index, data) }, .type => .{ .type_value = @intToEnum(Index, data) },
.bytes => unreachable, // TODO .bytes => unreachable, // TODO
.one_pointer => .{.one_pointer = @intToEnum(Index, data)}, .one_pointer => .{ .one_pointer = @intToEnum(Index, data) },
else => @panic("TODO"), else => @panic("TODO"),
}; };
} }
@ -1068,7 +1109,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
.float_32_value => |float_val| .{ .tag = .float_f32, .data = @bitCast(u32, float_val) }, .float_32_value => |float_val| .{ .tag = .float_f32, .data = @bitCast(u32, float_val) },
.type_value => |ty| .{ .tag = .type, .data = @enumToInt(ty) }, .type_value => |ty| .{ .tag = .type, .data = @enumToInt(ty) },
.bytes => unreachable, // TODO .bytes => unreachable, // TODO
.one_pointer => |val| .{.tag = .one_pointer, .data = @enumToInt(val)}, .one_pointer => |val| .{ .tag = .one_pointer, .data = @enumToInt(val) },
inline else => |data| .{ .tag = key.tag(), .data = try ip.addExtra(gpa, data) }, // TODO sad stage1 noises :( inline else => |data| .{ .tag = key.tag(), .data = try ip.addExtra(gpa, data) }, // TODO sad stage1 noises :(
}; };
try ip.items.append(gpa, item); try ip.items.append(gpa, item);
@ -1095,26 +1136,31 @@ fn extraData(ip: InternPool, comptime T: type, index: usize) T {
// --------------------------------------------- // ---------------------------------------------
pub fn cast(ip: *InternPool, gpa: Allocator, destination_ty: Index, source_ty: Index, target: std.Target) Allocator.Error!Index { pub fn cast(ip: *InternPool, gpa: Allocator, destination_ty: Index, source_ty: Index, target: std.Target) Allocator.Error!Index {
return resolvePeerTypes(ip, gpa, &.{destination_ty, source_ty}, target); return resolvePeerTypes(ip, gpa, &.{ destination_ty, source_ty }, target);
} }
pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, target: std.Target) Allocator.Error!Index { pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, target: std.Target) Allocator.Error!Index {
switch (types.len) { switch (types.len) {
0 => return Key{ .simple = .noreturn }, 0 => return try ip.get(gpa, .{ .simple = .noreturn }),
1 => types[0], 1 => return types[0],
else => {},
} }
var arena_allocator = std.heap.ArenaAllocator.init(gpa);
defer arena_allocator.deinit();
var arena = arena_allocator.allocator();
var chosen = types[0]; var chosen = types[0];
var any_are_null = false; var any_are_null = false;
var seen_const = false; var seen_const = false;
var convert_to_slice = false; var convert_to_slice = false;
var chosen_i: usize = 0; var chosen_i: usize = 0;
for (types[1..]) |candidate, candidate_i| { for (types[1..]) |candidate, candidate_i| {
if (candidate == chosen) continue;
const candidate_key: Key = ip.indexToKey(candidate); const candidate_key: Key = ip.indexToKey(candidate);
const chosen_key = ip.indexToKey(chosen); const chosen_key = ip.indexToKey(chosen);
if (candidate_key == chosen_key) continue;
switch (candidate_key) { switch (candidate_key) {
.simple => |candidate_simple| switch (candidate_simple) { .simple => |candidate_simple| switch (candidate_simple) {
// TODO usize, isize // TODO usize, isize
@ -1133,6 +1179,7 @@ pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, t
}, },
else => {}, else => {},
}, },
else => {},
}, },
.noreturn, .undefined_type => continue, .noreturn, .undefined_type => continue,
@ -1148,6 +1195,7 @@ pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, t
.usize, .isize => continue, .usize, .isize => continue,
.comptime_int => unreachable, .comptime_int => unreachable,
.comptime_float => continue, .comptime_float => continue,
else => {},
}, },
.int_type => continue, .int_type => continue,
.pointer_type => |chosen_info| if (chosen_info.size == .C) continue, .pointer_type => |chosen_info| if (chosen_info.size == .C) continue,
@ -1161,6 +1209,7 @@ pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, t
chosen_i = candidate_i + 1; chosen_i = candidate_i + 1;
continue; continue;
}, },
else => {},
}, },
else => {}, else => {},
}, },
@ -1242,13 +1291,13 @@ pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, t
const chosen_elem_ty = chosen_elem_info.array_type.child; const chosen_elem_ty = chosen_elem_info.array_type.child;
const cand_elem_ty = candidate_elem_info.array_type.child; const cand_elem_ty = candidate_elem_info.array_type.child;
const chosen_ok = .ok == try ip.coerceInMemoryAllowed(gpa, chosen_elem_ty, cand_elem_ty, chosen_info.mutable, target); const chosen_ok = .ok == try ip.coerceInMemoryAllowed(gpa, chosen_elem_ty, cand_elem_ty, !chosen_info.is_const, target);
if (chosen_ok) { if (chosen_ok) {
convert_to_slice = true; convert_to_slice = true;
continue; continue;
} }
const cand_ok = .ok == try ip.coerceInMemoryAllowed(gpa, cand_elem_ty, chosen_elem_ty, candidate_info.mutable, target); const cand_ok = .ok == try ip.coerceInMemoryAllowed(gpa, cand_elem_ty, chosen_elem_ty, !candidate_info.is_const, target);
if (cand_ok) { if (cand_ok) {
convert_to_slice = true; convert_to_slice = true;
chosen = candidate; chosen = candidate;
@ -1268,8 +1317,8 @@ pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, t
// the one we will keep. If they're both OK then we keep the // the one we will keep. If they're both OK then we keep the
// C pointer since it matches both single and many pointers. // C pointer since it matches both single and many pointers.
if (candidate_info.size == .C or chosen_info.size == .C) { if (candidate_info.size == .C or chosen_info.size == .C) {
const cand_ok = .ok == try ip.coerceInMemoryAllowed(candidate_info.elem_type, chosen_info.elem_type, candidate_info.mutable, target); const cand_ok = .ok == try ip.coerceInMemoryAllowed(arena, candidate_info.elem_type, chosen_info.elem_type, !candidate_info.is_const, target);
const chosen_ok = .ok == try ip.coerceInMemoryAllowed(chosen_info.elem_type, candidate_info.elem_type, chosen_info.mutable, target); const chosen_ok = .ok == try ip.coerceInMemoryAllowed(arena, chosen_info.elem_type, candidate_info.elem_type, !chosen_info.is_const, target);
if (cand_ok) { if (cand_ok) {
if (!chosen_ok or chosen_info.size != .C) { if (!chosen_ok or chosen_info.size != .C) {
@ -1327,14 +1376,16 @@ pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, t
} }
} }
}, },
.function_type => { .function_type => |chosen_info| {
if (candidate_info.is_const and if (candidate_info.is_const) {
ip.indexToKey(candidate_info.elem_type) == .function_type and const candidate_elem_key = ip.indexToKey(candidate_info.elem_type);
.ok == try ip.coerceInMemoryAllowedFns(chosen, candidate_info.pointee_type, target)) if (candidate_elem_key == .function_type and
{ .ok == try ip.coerceInMemoryAllowedFns(arena, chosen_info, candidate_elem_key.function_type, target))
chosen = candidate; {
chosen_i = candidate_i + 1; chosen = candidate;
continue; chosen_i = candidate_i + 1;
continue;
}
} }
}, },
else => {}, else => {},
@ -1349,8 +1400,8 @@ pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, t
else => false, else => false,
}; };
if ((try ip.coerceInMemoryAllowed(chosen, candidate_info.payload_type, false, target)) == .ok) { if ((try ip.coerceInMemoryAllowed(arena, chosen, candidate_info.payload_type, false, target)) == .ok) {
seen_const = seen_const or candidate_info.payload_type.isConstPtr(); seen_const = seen_const or ip.indexToKey(candidate_info.payload_type).isConstPtr();
any_are_null = true; any_are_null = true;
continue; continue;
} }
@ -1374,44 +1425,42 @@ pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, t
switch (chosen_key) { switch (chosen_key) {
.simple => |simple| switch (simple) { .simple => |simple| switch (simple) {
.noreturn, .undefined_type => { .noreturn,
.undefined_type,
=> {
chosen = candidate; chosen = candidate;
chosen_i = candidate_i + 1; chosen_i = candidate_i + 1;
continue; continue;
}, },
} .null_type => {
.NoReturn, any_are_null = true;
.Undefined => { chosen = candidate;
chosen = candidate; chosen_i = candidate_i + 1;
chosen_i = candidate_i + 1; continue;
continue; },
else => {},
}, },
.Null => { .optional_type => |chosen_info| {
any_are_null = true; if ((try ip.coerceInMemoryAllowed(arena, chosen_info.payload_type, candidate, false, target)) == .ok) {
chosen = candidate;
chosen_i = candidate_i + 1;
continue;
},
.Optional => {
if ((try ip.coerceInMemoryAllowed(chosen_key.optional_type.payload_type, candidate, false, target)) == .ok) {
continue; continue;
} }
if ((try ip.coerceInMemoryAllowed(candidate, chosen_key.optional_type.payload_type, false, target)) == .ok) { if ((try ip.coerceInMemoryAllowed(arena, candidate, chosen_info.payload_type, false, target)) == .ok) {
any_are_null = true; any_are_null = true;
chosen = candidate; chosen = candidate;
chosen_i = candidate_i + 1; chosen_i = candidate_i + 1;
continue; continue;
} }
}, },
.ErrorUnion => { .error_union_type => |chosen_info| {
const payload_ty = chosen_key.error_union_type.payload_type; if ((try ip.coerceInMemoryAllowed(arena, chosen_info.payload_type, candidate, false, target)) == .ok) {
if ((try ip.coerceInMemoryAllowed(payload_ty, candidate, false, target)) == .ok) {
continue; continue;
} }
}, },
else => {}, else => {},
} }
} }
@panic("TODO");
} }
const InMemoryCoercionResult = union(enum) { const InMemoryCoercionResult = union(enum) {
@ -1542,7 +1591,7 @@ fn coerceInMemoryAllowed(
src_ty: Index, src_ty: Index,
dest_is_mut: bool, dest_is_mut: bool,
target: std.Target, target: std.Target,
) !InMemoryCoercionResult { ) error{OutOfMemory}!InMemoryCoercionResult {
if (dest_ty == src_ty) return .ok; if (dest_ty == src_ty) return .ok;
const dest_key = ip.indexToKey(dest_ty); const dest_key = ip.indexToKey(dest_ty);
@ -1576,7 +1625,7 @@ fn coerceInMemoryAllowed(
if (dest_tag == .Float and src_tag == .Float and if (dest_tag == .Float and src_tag == .Float and
// this is an optimization because only a long double can have the same size as a other Float // this is an optimization because only a long double can have the same size as a other Float
// SAFETY: every Float is a Simple // SAFETY: every Float is a Simple
dest_key.simple == .c_longdouble or src_tag.simple == .c_longdouble) dest_key.simple == .c_longdouble or src_key.simple == .c_longdouble)
{ {
const dest_bits = dest_key.floatBits(target); const dest_bits = dest_key.floatBits(target);
const src_bits = src_key.floatBits(target); const src_bits = src_key.floatBits(target);
@ -1587,24 +1636,26 @@ fn coerceInMemoryAllowed(
const maybe_dest_ptr_ty = try ip.typePtrOrOptionalPtrTy(dest_ty); const maybe_dest_ptr_ty = try ip.typePtrOrOptionalPtrTy(dest_ty);
const maybe_src_ptr_ty = try ip.typePtrOrOptionalPtrTy(src_ty); const maybe_src_ptr_ty = try ip.typePtrOrOptionalPtrTy(src_ty);
if (maybe_dest_ptr_ty != Index.none and maybe_src_ptr_ty != Index.none) { if (maybe_dest_ptr_ty != Index.none and maybe_src_ptr_ty != Index.none) {
return try ip.coerceInMemoryAllowedPtrs(dest_ty, src_ty, maybe_dest_ptr_ty, maybe_src_ptr_ty, dest_is_mut, target); @panic("TODO: implement coerceInMemoryAllowedPtrs");
// return try ip.coerceInMemoryAllowedPtrs(dest_ty, src_ty, maybe_dest_ptr_ty, maybe_src_ptr_ty, dest_is_mut, target);
} }
// Slices // Slices
if (dest_key.isSlice() and src_key.isSlice()) { if (dest_key.isSlice() and src_key.isSlice()) {
return try ip.coerceInMemoryAllowedPtrs(dest_ty, src_ty, dest_ty, src_ty, dest_is_mut, target); @panic("TODO: implement coerceInMemoryAllowedPtrs");
// return try ip.coerceInMemoryAllowedPtrs(dest_ty, src_ty, dest_ty, src_ty, dest_is_mut, target);
} }
// Functions // Functions
if (dest_tag == .Fn and src_tag == .Fn) { if (dest_tag == .Fn and src_tag == .Fn) {
return try ip.coerceInMemoryAllowedFns(dest_ty, src_ty, target); return try ip.coerceInMemoryAllowedFns(arena, dest_key.function_type, src_key.function_type, target);
} }
// Error Unions // Error Unions
if (dest_tag == .ErrorUnion and src_tag == .ErrorUnion) { if (dest_tag == .ErrorUnion and src_tag == .ErrorUnion) {
const dest_payload = dest_key.error_union_type.payload_type; const dest_payload = dest_key.error_union_type.payload_type;
const src_payload = src_key.error_union_type.payload_type; const src_payload = src_key.error_union_type.payload_type;
const child = try ip.coerceInMemoryAllowed(dest_payload, src_payload, dest_is_mut, target); const child = try ip.coerceInMemoryAllowed(arena, dest_payload, src_payload, dest_is_mut, target);
if (child != .ok) { if (child != .ok) {
return InMemoryCoercionResult{ .error_union_payload = .{ return InMemoryCoercionResult{ .error_union_payload = .{
.child = try child.dupe(arena), .child = try child.dupe(arena),
@ -1612,7 +1663,9 @@ fn coerceInMemoryAllowed(
.wanted = dest_payload, .wanted = dest_payload,
} }; } };
} }
return try ip.coerceInMemoryAllowed(dest_ty.errorUnionSet(), src_ty.errorUnionSet(), dest_is_mut, target); const dest_set = dest_key.error_union_type.error_set_type;
const src_set = src_key.error_union_type.error_set_type;
return try ip.coerceInMemoryAllowed(arena, dest_set, src_set, dest_is_mut, target);
} }
// Error Sets // Error Sets
@ -1623,8 +1676,8 @@ fn coerceInMemoryAllowed(
// Arrays // Arrays
if (dest_tag == .Array and src_tag == .Array) { if (dest_tag == .Array and src_tag == .Array) {
const dest_info = dest_key.array_type.len; const dest_info = dest_key.array_type;
const src_info = src_key.array_type.len; const src_info = src_key.array_type;
if (dest_info.len != src_info.len) { if (dest_info.len != src_info.len) {
return InMemoryCoercionResult{ .array_len = .{ return InMemoryCoercionResult{ .array_len = .{
.actual = src_info.len, .actual = src_info.len,
@ -1632,24 +1685,24 @@ fn coerceInMemoryAllowed(
} }; } };
} }
const child = try ip.coerceInMemoryAllowed(dest_key.array_type.child, src_key.array_type.child, dest_is_mut, target); const child = try ip.coerceInMemoryAllowed(arena, dest_info.child, src_info.child, dest_is_mut, target);
if (child != .ok) { if (child != .ok) {
return InMemoryCoercionResult{ .array_elem = .{ return InMemoryCoercionResult{ .array_elem = .{
.child = try child.dupe(arena), .child = try child.dupe(arena),
.actual = src_key.array_type.child, .actual = src_info.child,
.wanted = dest_key.array_type.child, .wanted = dest_info.child,
} }; } };
} }
const ok_sent = dest_key.array_type.sentinel == Index.none or const ok_sent = dest_info.sentinel == Index.none or
(src_key.array_type.sentinel != Index.none and (src_info.sentinel != Index.none and
dest_key.array_type.sentinel == src_key.array_type.sentinel // is this enough for a value equality check? dest_info.sentinel == src_info.sentinel // is this enough for a value equality check?
); );
if (!ok_sent) { if (!ok_sent) {
return InMemoryCoercionResult{ .array_sentinel = .{ return InMemoryCoercionResult{ .array_sentinel = .{
.actual = src_info.sentinel, .actual = src_info.sentinel,
.wanted = dest_info.sentinel, .wanted = dest_info.sentinel,
.ty = dest_key.array_type.child, .ty = dest_info.child,
} }; } };
} }
return .ok; return .ok;
@ -1669,7 +1722,7 @@ fn coerceInMemoryAllowed(
const dest_elem_ty = dest_key.vector_type.child; const dest_elem_ty = dest_key.vector_type.child;
const src_elem_ty = src_key.vector_type.child; const src_elem_ty = src_key.vector_type.child;
const child = try ip.coerceInMemoryAllowed(dest_elem_ty, src_elem_ty, dest_is_mut, target); const child = try ip.coerceInMemoryAllowed(arena, dest_elem_ty, src_elem_ty, dest_is_mut, target);
if (child != .ok) { if (child != .ok) {
return InMemoryCoercionResult{ .vector_elem = .{ return InMemoryCoercionResult{ .vector_elem = .{
.child = try child.dupe(arena), .child = try child.dupe(arena),
@ -1693,7 +1746,7 @@ fn coerceInMemoryAllowed(
const dest_child_type = dest_key.optional_type.payload_type; const dest_child_type = dest_key.optional_type.payload_type;
const src_child_type = src_key.optional_type.payload_type; const src_child_type = src_key.optional_type.payload_type;
const child = try ip.coerceInMemoryAllowed(dest_child_type, src_child_type, dest_is_mut, target); const child = try ip.coerceInMemoryAllowed(arena, dest_child_type, src_child_type, dest_is_mut, target);
if (child != .ok) { if (child != .ok) {
return InMemoryCoercionResult{ .optional_child = .{ return InMemoryCoercionResult{ .optional_child = .{
.child = try child.dupe(arena), .child = try child.dupe(arena),
@ -1865,13 +1918,10 @@ fn coerceInMemoryAllowed(
fn coerceInMemoryAllowedFns( fn coerceInMemoryAllowedFns(
ip: *InternPool, ip: *InternPool,
arena: std.mem.Allocator, arena: std.mem.Allocator,
dest_ty: Index, dest_info: Fn,
src_ty: Index, src_info: Fn,
target: std.Target, target: std.Target,
) !InMemoryCoercionResult { ) !InMemoryCoercionResult {
const dest_info = dest_ty.fnInfo();
const src_info = src_ty.fnInfo();
if (dest_info.is_var_args != src_info.is_var_args) { if (dest_info.is_var_args != src_info.is_var_args) {
return InMemoryCoercionResult{ .fn_var_args = dest_info.is_var_args }; return InMemoryCoercionResult{ .fn_var_args = dest_info.is_var_args };
} }
@ -1880,15 +1930,18 @@ fn coerceInMemoryAllowedFns(
return InMemoryCoercionResult{ .fn_generic = dest_info.is_generic }; return InMemoryCoercionResult{ .fn_generic = dest_info.is_generic };
} }
if (dest_info.cc != src_info.cc) { if (dest_info.calling_convention != src_info.calling_convention) {
return InMemoryCoercionResult{ .fn_cc = .{ return InMemoryCoercionResult{ .fn_cc = .{
.actual = src_info.cc, .actual = src_info.calling_convention,
.wanted = dest_info.cc, .wanted = dest_info.calling_convention,
} }; } };
} }
if (!src_info.return_type.isNoReturn()) { const return_type_key = ip.indexToKey(src_info.return_type);
const rt = try ip.coerceInMemoryAllowed(dest_info.return_type, src_info.return_type, false, target); const is_noreturn = return_type_key == .simple and return_type_key.simple == .noreturn;
if (!is_noreturn) {
const rt = try ip.coerceInMemoryAllowed(arena, dest_info.return_type, src_info.return_type, false, target);
if (rt != .ok) { if (rt != .ok) {
return InMemoryCoercionResult{ .fn_return_type = .{ return InMemoryCoercionResult{ .fn_return_type = .{
.child = try rt.dupe(arena), .child = try rt.dupe(arena),
@ -1898,41 +1951,43 @@ fn coerceInMemoryAllowedFns(
} }
} }
if (dest_info.param_types.len != src_info.param_types.len) { if (dest_info.args.len != src_info.args.len) {
return InMemoryCoercionResult{ .fn_param_count = .{ return InMemoryCoercionResult{ .fn_param_count = .{
.actual = src_info.param_types.len, .actual = src_info.args.len,
.wanted = dest_info.param_types.len, .wanted = dest_info.args.len,
} }; } };
} }
if (dest_info.noalias_bits != src_info.noalias_bits) { // TODO
return InMemoryCoercionResult{ .fn_param_noalias = .{
.actual = src_info.noalias_bits,
.wanted = dest_info.noalias_bits,
} };
}
for (dest_info.param_types) |dest_param_ty, i| { // if (dest_info.noalias_bits != src_info.noalias_bits) {
const src_param_ty = src_info.param_types[i]; // return InMemoryCoercionResult{ .fn_param_noalias = .{
// .actual = src_info.noalias_bits,
// .wanted = dest_info.noalias_bits,
// } };
// }
if (dest_info.comptime_params[i] != src_info.comptime_params[i]) { // for (dest_info.param_types) |dest_param_ty, i| {
return InMemoryCoercionResult{ .fn_param_comptime = .{ // const src_param_ty = src_info.param_types[i];
.index = i,
.wanted = dest_info.comptime_params[i],
} };
}
// Note: Cast direction is reversed here. // if (dest_info.comptime_params[i] != src_info.comptime_params[i]) {
const param = try ip.coerceInMemoryAllowed(src_param_ty, dest_param_ty, false, target); // return InMemoryCoercionResult{ .fn_param_comptime = .{
if (param != .ok) { // .index = i,
return InMemoryCoercionResult{ .fn_param = .{ // .wanted = dest_info.comptime_params[i],
.child = try param.dupe(arena), // } };
.actual = src_param_ty, // }
.wanted = dest_param_ty,
.index = i, // // Note: Cast direction is reversed here.
} }; // const param = try ip.coerceInMemoryAllowed(src_param_ty, dest_param_ty, false, target);
} // if (param != .ok) {
} // return InMemoryCoercionResult{ .fn_param = .{
// .child = try param.dupe(arena),
// .actual = src_param_ty,
// .wanted = dest_param_ty,
// .index = i,
// } };
// }
// }
return .ok; return .ok;
} }
@ -1943,8 +1998,8 @@ fn coerceInMemoryAllowedFns(
/// a type has zero bits, which can cause a "foo depends on itself" compile error. /// a type has zero bits, which can cause a "foo depends on itself" compile error.
/// This logic must be kept in sync with `Type.isPtrLikeOptional`. /// This logic must be kept in sync with `Type.isPtrLikeOptional`.
fn typePtrOrOptionalPtrTy( fn typePtrOrOptionalPtrTy(
ty: Index,
ip: InternPool, ip: InternPool,
ty: Index,
) !Index { ) !Index {
const key = ip.indexToKey(ty); const key = ip.indexToKey(ty);
switch (key) { switch (key) {
@ -1960,7 +2015,7 @@ fn typePtrOrOptionalPtrTy(
if (child_key != .pointer_type) return Index.none; if (child_key != .pointer_type) return Index.none;
const child_ptr_key = child_key.pointer_type; const child_ptr_key = child_key.pointer_type;
switch (child_ptr_key) { switch (child_ptr_key.size) {
.Slice, .C => return Index.none, .Slice, .C => return Index.none,
.Many, .One => { .Many, .One => {
if (child_ptr_key.is_allowzero) return Index.none; if (child_ptr_key.is_allowzero) return Index.none;

View File

@ -769,15 +769,15 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
}; };
var interpreter = handle.interpreter.?; var interpreter = handle.interpreter.?;
var root_scope = ComptimeInterpreter.Scope{ try interpreter.scopes.append(interpreter.allocator, .{
.interpreter = interpreter, .interpreter = interpreter,
.parent = 0, .parent = 0,
.node_idx = 0, .node_idx = 0,
.namespace = ComptimeInterpreter.IPIndex.none, .namespace = .none,
}; });
// TODO: Start from current/nearest-current scope // TODO: Start from current/nearest-current scope
const result = interpreter.interpret(node, root_scope, .{}) catch |err| { const result = interpreter.interpret(node, 0, .{}) catch |err| {
log.err("Interpreter error: {s}", .{@errorName(err)}); log.err("Interpreter error: {s}", .{@errorName(err)});
if (@errorReturnTrace()) |trace| { if (@errorReturnTrace()) |trace| {
std.debug.dumpStackTrace(trace.*); std.debug.dumpStackTrace(trace.*);
@ -794,7 +794,7 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
const type_type = try interpreter.ip.get(interpreter.allocator, ComptimeInterpreter.IPKey{ .simple = .type }); const type_type = try interpreter.ip.get(interpreter.allocator, ComptimeInterpreter.IPKey{ .simple = .type });
if (val.ty != type_type) { if (val.ty != type_type) {
log.err("Not a type: { }", .{val.ty.fmtType(&interpreter.ip)}); log.err("Not a type: {}", .{val.ty.fmtType(&interpreter.ip)});
return null; return null;
} }