fix remaining compiler errors
This commit is contained in:
parent
03e50066a1
commit
6118686d00
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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, .{});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user