do not intern Structs, Enums and Unions
This commit is contained in:
parent
9131285db1
commit
55364f2e2b
@ -23,7 +23,6 @@ allocator: std.mem.Allocator,
|
|||||||
ip: InternPool = .{},
|
ip: InternPool = .{},
|
||||||
document_store: *DocumentStore,
|
document_store: *DocumentStore,
|
||||||
uri: DocumentStore.Uri,
|
uri: DocumentStore.Uri,
|
||||||
decls: std.ArrayListUnmanaged(Decl) = .{},
|
|
||||||
namespaces: std.MultiArrayList(Namespace) = .{},
|
namespaces: std.MultiArrayList(Namespace) = .{},
|
||||||
|
|
||||||
/// Interpreter diagnostic errors
|
/// Interpreter diagnostic errors
|
||||||
@ -69,7 +68,6 @@ pub fn deinit(interpreter: *ComptimeInterpreter) void {
|
|||||||
interpreter.namespaces.items(.usingnamespaces)[i].deinit(interpreter.allocator);
|
interpreter.namespaces.items(.usingnamespaces)[i].deinit(interpreter.allocator);
|
||||||
}
|
}
|
||||||
interpreter.namespaces.deinit(interpreter.allocator);
|
interpreter.namespaces.deinit(interpreter.allocator);
|
||||||
interpreter.decls.deinit(interpreter.allocator);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const Type = struct {
|
pub const Type = struct {
|
||||||
@ -86,29 +84,18 @@ pub const Value = struct {
|
|||||||
ty: Index,
|
ty: Index,
|
||||||
val: Index,
|
val: Index,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Decl = struct {
|
|
||||||
name: []const u8,
|
|
||||||
ty: Index,
|
|
||||||
val: Index,
|
|
||||||
alignment: u16,
|
|
||||||
address_space: std.builtin.AddressSpace,
|
|
||||||
is_pub: bool,
|
|
||||||
is_exported: bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
// pub const Comptimeness = enum { @"comptime", runtime };
|
// pub const Comptimeness = enum { @"comptime", runtime };
|
||||||
|
|
||||||
pub const NamespaceIndex = InternPool.NamespaceIndex;
|
|
||||||
|
|
||||||
pub const Namespace = struct {
|
pub const Namespace = struct {
|
||||||
/// always points to Namespace or Index.none
|
/// always points to Namespace or Index.none
|
||||||
parent: NamespaceIndex,
|
parent: Namespace.Index,
|
||||||
node_idx: Ast.Node.Index,
|
node_idx: Ast.Node.Index,
|
||||||
/// Will be a struct, enum, union, opaque or .none
|
/// Will be a struct, enum, union, opaque or .none
|
||||||
ty: Index,
|
ty: InternPool.Index,
|
||||||
decls: std.StringArrayHashMapUnmanaged(Decl) = .{},
|
decls: std.StringArrayHashMapUnmanaged(InternPool.DeclIndex) = .{},
|
||||||
usingnamespaces: std.ArrayListUnmanaged(NamespaceIndex) = .{},
|
usingnamespaces: std.ArrayListUnmanaged(InternPool.DeclIndex) = .{},
|
||||||
|
|
||||||
|
pub const Index = InternPool.NamespaceIndex;
|
||||||
|
|
||||||
// TODO: Actually use this value
|
// TODO: Actually use this value
|
||||||
// comptimeness: Comptimeness,
|
// comptimeness: Comptimeness,
|
||||||
@ -161,15 +148,15 @@ pub const InterpretResult = union(enum) {
|
|||||||
|
|
||||||
pub fn huntItDown(
|
pub fn huntItDown(
|
||||||
interpreter: *ComptimeInterpreter,
|
interpreter: *ComptimeInterpreter,
|
||||||
namespace: NamespaceIndex,
|
namespace: Namespace.Index,
|
||||||
decl_name: []const u8,
|
decl_name: []const u8,
|
||||||
options: InterpretOptions,
|
options: InterpretOptions,
|
||||||
) ?Decl {
|
) ?InternPool.DeclIndex {
|
||||||
_ = options;
|
_ = options;
|
||||||
|
|
||||||
var current_namespace = namespace;
|
var current_namespace = namespace;
|
||||||
while (current_namespace != .none) {
|
while (current_namespace != .none) {
|
||||||
const decls: std.StringArrayHashMapUnmanaged(Decl) = interpreter.namespaces.items(.decls)[@enumToInt(current_namespace)];
|
const decls = interpreter.namespaces.items(.decls)[@enumToInt(current_namespace)];
|
||||||
defer current_namespace = interpreter.namespaces.items(.parent)[@enumToInt(current_namespace)];
|
defer current_namespace = interpreter.namespaces.items(.parent)[@enumToInt(current_namespace)];
|
||||||
|
|
||||||
if (decls.get(decl_name)) |decl| {
|
if (decls.get(decl_name)) |decl| {
|
||||||
@ -199,7 +186,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,
|
||||||
namespace: NamespaceIndex,
|
namespace: Namespace.Index,
|
||||||
options: InterpretOptions,
|
options: InterpretOptions,
|
||||||
) InterpretError!InterpretResult {
|
) InterpretError!InterpretResult {
|
||||||
const tree = interpreter.getHandle().tree;
|
const tree = interpreter.getHandle().tree;
|
||||||
@ -229,10 +216,16 @@ pub fn interpret(
|
|||||||
.node_idx = node_idx,
|
.node_idx = node_idx,
|
||||||
.ty = undefined,
|
.ty = undefined,
|
||||||
});
|
});
|
||||||
const container_namespace = @intToEnum(NamespaceIndex, interpreter.namespaces.len - 1);
|
const container_namespace = @intToEnum(Namespace.Index, interpreter.namespaces.len - 1);
|
||||||
|
|
||||||
var fields = std.ArrayListUnmanaged(InternPool.Struct.Field){};
|
const struct_index = try interpreter.ip.createStruct(interpreter.allocator, .{
|
||||||
defer fields.deinit(interpreter.allocator);
|
.fields = .{},
|
||||||
|
.namespace = container_namespace,
|
||||||
|
.layout = .Auto, // TODO
|
||||||
|
.backing_int_ty = .none, // TODO
|
||||||
|
.status = .none, // TODO
|
||||||
|
});
|
||||||
|
var struct_info = interpreter.ip.getStruct(struct_index);
|
||||||
|
|
||||||
var buffer: [2]Ast.Node.Index = undefined;
|
var buffer: [2]Ast.Node.Index = undefined;
|
||||||
|
|
||||||
@ -259,28 +252,18 @@ pub fn interpret(
|
|||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const field_name = try interpreter.ip.get(interpreter.allocator, .{
|
|
||||||
.bytes = tree.tokenSlice(container_field.ast.main_token),
|
const field_name = tree.tokenSlice(container_field.ast.main_token);
|
||||||
});
|
|
||||||
const field: InternPool.Struct.Field = .{
|
try struct_info.fields.put(interpreter.allocator, field_name, .{
|
||||||
.name = field_name,
|
|
||||||
.ty = init_type_value.val,
|
.ty = init_type_value.val,
|
||||||
.default_value = default_value,
|
.default_value = default_value,
|
||||||
.alignment = 0, // TODO,
|
.alignment = 0, // TODO,
|
||||||
.is_comptime = false, // TODO
|
.is_comptime = false, // TODO
|
||||||
};
|
});
|
||||||
|
|
||||||
try fields.append(interpreter.allocator, field);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct_type = try interpreter.ip.get(interpreter.allocator, Key{
|
const struct_type = try interpreter.ip.get(interpreter.allocator, Key{ .struct_type = struct_index }); // TODO potential double free on struct_info.field
|
||||||
.struct_type = .{
|
|
||||||
.fields = fields.items,
|
|
||||||
.namespace = namespace,
|
|
||||||
.layout = .Auto, // TODO
|
|
||||||
.backing_int_ty = .none, // TODO
|
|
||||||
},
|
|
||||||
});
|
|
||||||
interpreter.namespaces.items(.ty)[@enumToInt(container_namespace)] = struct_type;
|
interpreter.namespaces.items(.ty)[@enumToInt(container_namespace)] = struct_type;
|
||||||
|
|
||||||
return InterpretResult{ .value = Value{
|
return InterpretResult{ .value = Value{
|
||||||
@ -317,7 +300,7 @@ pub fn interpret(
|
|||||||
if (v.ty != type_type) return InterpretResult{ .nothing = {} };
|
if (v.ty != type_type) return InterpretResult{ .nothing = {} };
|
||||||
}
|
}
|
||||||
|
|
||||||
try decls.putNoClobber(interpreter.allocator, name, .{
|
const decl_index = try interpreter.ip.createDecl(interpreter.allocator, .{
|
||||||
.name = name,
|
.name = name,
|
||||||
.ty = if (type_value) |v| v.val else init_value.?.ty,
|
.ty = if (type_value) |v| v.val else init_value.?.ty,
|
||||||
.val = if (init_value) |init| init.val else .none,
|
.val = if (init_value) |init| init.val else .none,
|
||||||
@ -326,6 +309,7 @@ pub fn interpret(
|
|||||||
.is_pub = true, // TODO
|
.is_pub = true, // TODO
|
||||||
.is_exported = false, // TODO
|
.is_exported = false, // TODO
|
||||||
});
|
});
|
||||||
|
try decls.putNoClobber(interpreter.allocator, name, decl_index);
|
||||||
|
|
||||||
// TODO: Am I a dumbo shrimp? (e.g. is this tree shaking correct? works on my machine so like...)
|
// TODO: Am I a dumbo shrimp? (e.g. is this tree shaking correct? works on my machine so like...)
|
||||||
|
|
||||||
@ -345,7 +329,7 @@ pub fn interpret(
|
|||||||
.node_idx = node_idx,
|
.node_idx = node_idx,
|
||||||
.ty = .none,
|
.ty = .none,
|
||||||
});
|
});
|
||||||
const block_namespace = @intToEnum(NamespaceIndex, interpreter.namespaces.len - 1);
|
const block_namespace = @intToEnum(Namespace.Index, interpreter.namespaces.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).?;
|
||||||
@ -442,7 +426,8 @@ pub fn interpret(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Logic to find identifiers in accessible scopes
|
// Logic to find identifiers in accessible scopes
|
||||||
if (interpreter.huntItDown(namespace, identifier, options)) |decl| {
|
if (interpreter.huntItDown(namespace, identifier, options)) |decl_index| {
|
||||||
|
const decl = interpreter.ip.getDecl(decl_index);
|
||||||
return InterpretResult{ .value = Value{
|
return InterpretResult{ .value = Value{
|
||||||
.interpreter = interpreter,
|
.interpreter = interpreter,
|
||||||
.node_idx = node_idx,
|
.node_idx = node_idx,
|
||||||
@ -478,7 +463,8 @@ pub fn interpret(
|
|||||||
if (irv.val == .none) break :blk true;
|
if (irv.val == .none) break :blk true;
|
||||||
|
|
||||||
const ty_key = interpreter.ip.indexToKey(irv.val);
|
const ty_key = interpreter.ip.indexToKey(irv.val);
|
||||||
if (interpreter.huntItDown(ty_key.getNamespace(), field_name, options)) |decl| {
|
if (interpreter.huntItDown(ty_key.getNamespace(interpreter.ip), field_name, options)) |decl_index| {
|
||||||
|
const decl = interpreter.ip.getDecl(decl_index);
|
||||||
return InterpretResult{ .value = Value{
|
return InterpretResult{ .value = Value{
|
||||||
.interpreter = interpreter,
|
.interpreter = interpreter,
|
||||||
.node_idx = node_idx,
|
.node_idx = node_idx,
|
||||||
@ -492,10 +478,10 @@ pub fn interpret(
|
|||||||
_ = error_set_info;
|
_ = error_set_info;
|
||||||
},
|
},
|
||||||
.union_type => {}, // TODO
|
.union_type => {}, // TODO
|
||||||
.enum_type => |enum_info| { // TODO
|
.enum_type => |enum_index| { // TODO
|
||||||
if (interpreter.ip.contains(Key{ .bytes = field_name })) |field_name_index| {
|
const enum_info = interpreter.ip.getEnum(enum_index);
|
||||||
for (enum_info.fields) |field| {
|
if (enum_info.fields.get(field_name)) |field| {
|
||||||
if (field.name != field_name_index) continue;
|
_ = field;
|
||||||
return InterpretResult{
|
return InterpretResult{
|
||||||
.value = Value{
|
.value = Value{
|
||||||
.interpreter = interpreter,
|
.interpreter = interpreter,
|
||||||
@ -505,7 +491,6 @@ pub fn interpret(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
else => break :blk false,
|
else => break :blk false,
|
||||||
}
|
}
|
||||||
@ -583,17 +568,15 @@ pub fn interpret(
|
|||||||
} };
|
} };
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.struct_type => |struct_info| blk: {
|
.struct_type => |struct_index| blk: {
|
||||||
// if the intern pool does not contain the field name, it is impossible that there is a field with the given name
|
const struct_info = interpreter.ip.getStruct(struct_index);
|
||||||
const field_name_index = interpreter.ip.contains(Key{ .bytes = field_name }) orelse break :blk true;
|
if (struct_info.fields.getIndex(field_name)) |field_index| {
|
||||||
|
const field = struct_info.fields.values()[field_index];
|
||||||
for (struct_info.fields) |field, i| {
|
|
||||||
if (field.name != field_name_index) continue;
|
|
||||||
const val = found_val: {
|
const val = found_val: {
|
||||||
if (irv.val == .none) break :found_val .none;
|
if (irv.val == .none) break :found_val .none;
|
||||||
const val_key = interpreter.ip.indexToKey(irv.val);
|
const val_key = interpreter.ip.indexToKey(irv.val);
|
||||||
if (val_key != .aggregate) break :found_val .none;
|
if (val_key != .aggregate) break :found_val .none;
|
||||||
break :found_val val_key.aggregate[i];
|
break :found_val val_key.aggregate[field_index];
|
||||||
};
|
};
|
||||||
|
|
||||||
return InterpretResult{ .value = Value{
|
return InterpretResult{ .value = Value{
|
||||||
@ -813,15 +796,17 @@ pub fn interpret(
|
|||||||
|
|
||||||
// TODO: Implement root support
|
// TODO: Implement root support
|
||||||
if (std.mem.eql(u8, import_str[1 .. import_str.len - 1], "root")) {
|
if (std.mem.eql(u8, import_str[1 .. import_str.len - 1], "root")) {
|
||||||
return InterpretResult{ .value = Value{
|
const struct_index = try interpreter.ip.createStruct(interpreter.allocator, .{
|
||||||
.interpreter = interpreter,
|
.fields = .{},
|
||||||
.node_idx = node_idx,
|
|
||||||
.ty = try interpreter.ip.get(interpreter.allocator, Key{ .struct_type = .{
|
|
||||||
.fields = &.{},
|
|
||||||
.namespace = .none,
|
.namespace = .none,
|
||||||
.layout = .Auto,
|
.layout = .Auto,
|
||||||
.backing_int_ty = .none,
|
.backing_int_ty = .none,
|
||||||
} }),
|
.status = .none,
|
||||||
|
});
|
||||||
|
return InterpretResult{ .value = Value{
|
||||||
|
.interpreter = interpreter,
|
||||||
|
.node_idx = node_idx,
|
||||||
|
.ty = try interpreter.ip.get(interpreter.allocator, Key{ .struct_type = struct_index }),
|
||||||
.val = try interpreter.ip.get(interpreter.allocator, Key{ .simple = .undefined_value }),
|
.val = try interpreter.ip.get(interpreter.allocator, Key{ .simple = .undefined_value }),
|
||||||
} };
|
} };
|
||||||
}
|
}
|
||||||
@ -865,7 +850,7 @@ pub fn interpret(
|
|||||||
if (value.ty != type_type) return error.InvalidBuiltin;
|
if (value.ty != type_type) return error.InvalidBuiltin;
|
||||||
if (interpreter.ip.indexToKey(field_name.ty) != .pointer_type) return error.InvalidBuiltin; // Check if it's a []const u8
|
if (interpreter.ip.indexToKey(field_name.ty) != .pointer_type) return error.InvalidBuiltin; // Check if it's a []const u8
|
||||||
|
|
||||||
const value_namespace = interpreter.ip.indexToKey(value.val).getNamespace();
|
const value_namespace = interpreter.ip.indexToKey(value.val).getNamespace(interpreter.ip);
|
||||||
if (value_namespace == .none) return error.InvalidBuiltin;
|
if (value_namespace == .none) return error.InvalidBuiltin;
|
||||||
|
|
||||||
const name = interpreter.ip.indexToKey(field_name.val).bytes; // TODO add checks
|
const name = interpreter.ip.indexToKey(field_name.val).bytes; // TODO add checks
|
||||||
@ -986,7 +971,8 @@ pub fn interpret(
|
|||||||
|
|
||||||
if (namespace != .none) {
|
if (namespace != .none) {
|
||||||
const decls = &interpreter.namespaces.items(.decls)[@enumToInt(namespace)];
|
const decls = &interpreter.namespaces.items(.decls)[@enumToInt(namespace)];
|
||||||
try decls.put(interpreter.allocator, name, .{
|
|
||||||
|
const decl_index = try interpreter.ip.createDecl(interpreter.allocator, .{
|
||||||
.name = name,
|
.name = name,
|
||||||
.ty = type_type,
|
.ty = type_type,
|
||||||
.val = function_type,
|
.val = function_type,
|
||||||
@ -995,6 +981,7 @@ pub fn interpret(
|
|||||||
.is_pub = false, // TODO
|
.is_pub = false, // TODO
|
||||||
.is_exported = false, // TODO
|
.is_exported = false, // TODO
|
||||||
});
|
});
|
||||||
|
try decls.putNoClobber(interpreter.allocator, name, decl_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
return InterpretResult{ .nothing = {} };
|
return InterpretResult{ .nothing = {} };
|
||||||
@ -1107,7 +1094,7 @@ pub fn interpret(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub const CallResult = struct {
|
pub const CallResult = struct {
|
||||||
namespace: NamespaceIndex,
|
namespace: Namespace.Index,
|
||||||
result: union(enum) {
|
result: union(enum) {
|
||||||
value: Value,
|
value: Value,
|
||||||
nothing,
|
nothing,
|
||||||
@ -1116,7 +1103,7 @@ pub const CallResult = struct {
|
|||||||
|
|
||||||
pub fn call(
|
pub fn call(
|
||||||
interpreter: *ComptimeInterpreter,
|
interpreter: *ComptimeInterpreter,
|
||||||
namespace: NamespaceIndex,
|
namespace: Namespace.Index,
|
||||||
func_node_idx: Ast.Node.Index,
|
func_node_idx: Ast.Node.Index,
|
||||||
arguments: []const Value,
|
arguments: []const Value,
|
||||||
options: InterpretOptions,
|
options: InterpretOptions,
|
||||||
@ -1136,7 +1123,7 @@ pub fn call(
|
|||||||
.node_idx = func_node_idx,
|
.node_idx = func_node_idx,
|
||||||
.ty = .none,
|
.ty = .none,
|
||||||
});
|
});
|
||||||
const fn_namespace = @intToEnum(NamespaceIndex, interpreter.namespaces.len - 1);
|
const fn_namespace = @intToEnum(Namespace.Index, interpreter.namespaces.len - 1);
|
||||||
|
|
||||||
const type_type = try interpreter.ip.get(interpreter.allocator, Key{ .simple = .type });
|
const type_type = try interpreter.ip.get(interpreter.allocator, Key{ .simple = .type });
|
||||||
|
|
||||||
@ -1157,7 +1144,8 @@ pub fn call(
|
|||||||
if (param.name_token) |name_token| {
|
if (param.name_token) |name_token| {
|
||||||
const name = offsets.tokenToSlice(tree, name_token);
|
const name = offsets.tokenToSlice(tree, name_token);
|
||||||
|
|
||||||
try interpreter.namespaces.items(.decls)[@enumToInt(fn_namespace)].put(interpreter.allocator, name, .{
|
const decls = &interpreter.namespaces.items(.decls)[@enumToInt(fn_namespace)];
|
||||||
|
const decl_index = try interpreter.ip.createDecl(interpreter.allocator, .{
|
||||||
.name = name,
|
.name = name,
|
||||||
.ty = tex.val,
|
.ty = tex.val,
|
||||||
.val = arguments[arg_index].val,
|
.val = arguments[arg_index].val,
|
||||||
@ -1166,6 +1154,7 @@ pub fn call(
|
|||||||
.is_pub = true, // TODO
|
.is_pub = true, // TODO
|
||||||
.is_exported = false, // TODO
|
.is_exported = false, // TODO
|
||||||
});
|
});
|
||||||
|
try decls.putNoClobber(interpreter.allocator, name, decl_index);
|
||||||
arg_index += 1;
|
arg_index += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,11 @@ map: std.AutoArrayHashMapUnmanaged(void, void) = .{},
|
|||||||
items: std.MultiArrayList(Item) = .{},
|
items: std.MultiArrayList(Item) = .{},
|
||||||
extra: std.ArrayListUnmanaged(u8) = .{},
|
extra: std.ArrayListUnmanaged(u8) = .{},
|
||||||
|
|
||||||
|
decls: std.ArrayListUnmanaged(InternPool.Decl) = .{},
|
||||||
|
structs: std.ArrayListUnmanaged(InternPool.Struct) = .{},
|
||||||
|
enums: std.ArrayListUnmanaged(InternPool.Enum) = .{},
|
||||||
|
unions: std.ArrayListUnmanaged(InternPool.Union) = .{},
|
||||||
|
|
||||||
const InternPool = @This();
|
const InternPool = @This();
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
@ -36,15 +41,26 @@ pub const Array = packed struct {
|
|||||||
sentinel: Index = .none,
|
sentinel: Index = .none,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const FieldStatus = enum {
|
||||||
|
none,
|
||||||
|
field_types_wip,
|
||||||
|
have_field_types,
|
||||||
|
layout_wip,
|
||||||
|
have_layout,
|
||||||
|
fully_resolved_wip,
|
||||||
|
fully_resolved,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const StructIndex = enum(u32) { _ };
|
||||||
|
|
||||||
pub const Struct = struct {
|
pub const Struct = struct {
|
||||||
fields: []const Field,
|
fields: std.StringArrayHashMapUnmanaged(Field),
|
||||||
namespace: NamespaceIndex,
|
namespace: NamespaceIndex,
|
||||||
layout: std.builtin.Type.ContainerLayout = .Auto,
|
layout: std.builtin.Type.ContainerLayout = .Auto,
|
||||||
backing_int_ty: Index,
|
backing_int_ty: Index,
|
||||||
|
status: FieldStatus,
|
||||||
|
|
||||||
pub const Field = packed struct {
|
pub const Field = packed struct {
|
||||||
/// guaranteed to be .bytes
|
|
||||||
name: Index,
|
|
||||||
ty: Index,
|
ty: Index,
|
||||||
default_value: Index = .none,
|
default_value: Index = .none,
|
||||||
alignment: u16 = 0,
|
alignment: u16 = 0,
|
||||||
@ -66,17 +82,14 @@ pub const ErrorSet = struct {
|
|||||||
names: []const Index,
|
names: []const Index,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const EnumIndex = enum(u32) { _ };
|
||||||
|
|
||||||
pub const Enum = struct {
|
pub const Enum = struct {
|
||||||
tag_type: Index,
|
tag_type: Index,
|
||||||
fields: []const Field,
|
fields: std.StringArrayHashMapUnmanaged(void),
|
||||||
|
values: std.AutoArrayHashMapUnmanaged(Index, void),
|
||||||
namespace: NamespaceIndex,
|
namespace: NamespaceIndex,
|
||||||
tag_type_infered: bool,
|
tag_type_infered: bool,
|
||||||
|
|
||||||
pub const Field = packed struct {
|
|
||||||
/// guaranteed to be .bytes
|
|
||||||
name: Index,
|
|
||||||
val: Index,
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Function = struct {
|
pub const Function = struct {
|
||||||
@ -94,15 +107,16 @@ pub const Function = struct {
|
|||||||
is_var_args: bool = false,
|
is_var_args: bool = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const UnionIndex = enum(u32) { _ };
|
||||||
|
|
||||||
pub const Union = struct {
|
pub const Union = struct {
|
||||||
tag_type: Index,
|
tag_type: Index,
|
||||||
fields: []const Field,
|
fields: std.StringArrayHashMapUnmanaged(Field),
|
||||||
namespace: NamespaceIndex,
|
namespace: NamespaceIndex,
|
||||||
layout: std.builtin.Type.ContainerLayout = .Auto,
|
layout: std.builtin.Type.ContainerLayout = .Auto,
|
||||||
|
status: FieldStatus,
|
||||||
|
|
||||||
pub const Field = packed struct {
|
pub const Field = packed struct {
|
||||||
/// guaranteed to be .bytes
|
|
||||||
name: Index,
|
|
||||||
ty: Index,
|
ty: Index,
|
||||||
alignment: u16,
|
alignment: u16,
|
||||||
};
|
};
|
||||||
@ -134,19 +148,34 @@ pub const UnionValue = packed struct {
|
|||||||
val: Index,
|
val: Index,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const DeclIndex = enum(u32) { _ };
|
||||||
|
|
||||||
|
pub const Decl = struct {
|
||||||
|
name: []const u8,
|
||||||
|
ty: Index,
|
||||||
|
val: Index,
|
||||||
|
alignment: u16,
|
||||||
|
address_space: std.builtin.AddressSpace,
|
||||||
|
is_pub: bool,
|
||||||
|
is_exported: bool,
|
||||||
|
};
|
||||||
|
|
||||||
pub const Key = union(enum) {
|
pub const Key = union(enum) {
|
||||||
simple: Simple,
|
simple: Simple,
|
||||||
|
|
||||||
int_type: Int,
|
int_type: Int,
|
||||||
pointer_type: Pointer,
|
pointer_type: Pointer,
|
||||||
array_type: Array,
|
array_type: Array,
|
||||||
struct_type: Struct,
|
/// TODO consider *Struct instead of StructIndex
|
||||||
|
struct_type: StructIndex,
|
||||||
optional_type: Optional,
|
optional_type: Optional,
|
||||||
error_union_type: ErrorUnion,
|
error_union_type: ErrorUnion,
|
||||||
error_set_type: ErrorSet,
|
error_set_type: ErrorSet,
|
||||||
enum_type: Enum,
|
/// TODO consider *Enum instead of EnumIndex
|
||||||
|
enum_type: EnumIndex,
|
||||||
function_type: Function,
|
function_type: Function,
|
||||||
union_type: Union,
|
/// TODO consider *Union instead of UnionIndex
|
||||||
|
union_type: UnionIndex,
|
||||||
tuple_type: Tuple,
|
tuple_type: Tuple,
|
||||||
vector_type: Vector,
|
vector_type: Vector,
|
||||||
anyframe_type: AnyFrame,
|
anyframe_type: AnyFrame,
|
||||||
@ -396,7 +425,8 @@ pub const Key = union(enum) {
|
|||||||
},
|
},
|
||||||
.int_type => |int_info| return int_info,
|
.int_type => |int_info| return int_info,
|
||||||
.enum_type => return panicOrElse("TODO", .{ .signedness = .unsigned, .bits = 0 }),
|
.enum_type => return panicOrElse("TODO", .{ .signedness = .unsigned, .bits = 0 }),
|
||||||
.struct_type => |struct_info| {
|
.struct_type => |struct_index| {
|
||||||
|
const struct_info = ip.getStruct(struct_index);
|
||||||
assert(struct_info.layout == .Packed);
|
assert(struct_info.layout == .Packed);
|
||||||
key = ip.indexToKey(struct_info.backing_int_ty);
|
key = ip.indexToKey(struct_info.backing_int_ty);
|
||||||
},
|
},
|
||||||
@ -485,11 +515,11 @@ pub const Key = union(enum) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getNamespace(ty: Key) NamespaceIndex {
|
pub fn getNamespace(ty: Key, ip: InternPool) NamespaceIndex {
|
||||||
return switch (ty) {
|
return switch (ty) {
|
||||||
.struct_type => |struct_info| struct_info.namespace,
|
.struct_type => |struct_index| ip.getStruct(struct_index).namespace,
|
||||||
.enum_type => |enum_info| enum_info.namespace,
|
.enum_type => |enum_index| ip.getEnum(enum_index).namespace,
|
||||||
.union_type => |union_info| union_info.namespace,
|
.union_type => |union_index| ip.getUnion(union_index).namespace,
|
||||||
else => .none,
|
else => .none,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -555,10 +585,12 @@ pub const Key = union(enum) {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
.struct_type => |struct_info| {
|
.struct_type => |struct_index| {
|
||||||
for (struct_info.fields) |field| {
|
const struct_info = ip.getStruct(struct_index);
|
||||||
if (field.is_comptime) continue;
|
var field_it = struct_info.fields.iterator();
|
||||||
if (ip.indexToKey(field.ty).onePossibleValue(ip) != null) continue;
|
while (field_it.next()) |entry| {
|
||||||
|
if (entry.value_ptr.is_comptime) continue;
|
||||||
|
if (ip.indexToKey(entry.value_ptr.ty).onePossibleValue(ip) != null) continue;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return panicOrElse("TODO return empty struct value", null);
|
return panicOrElse("TODO return empty struct value", null);
|
||||||
@ -572,10 +604,11 @@ pub const Key = union(enum) {
|
|||||||
},
|
},
|
||||||
.error_union_type => return null,
|
.error_union_type => return null,
|
||||||
.error_set_type => return null,
|
.error_set_type => return null,
|
||||||
.enum_type => |enum_info| {
|
.enum_type => |enum_index| {
|
||||||
switch (enum_info.fields.len) {
|
const enum_info = ip.getEnum(enum_index);
|
||||||
|
switch (enum_info.fields.count()) {
|
||||||
0 => return Key{ .simple = .unreachable_value },
|
0 => return Key{ .simple = .unreachable_value },
|
||||||
1 => return ip.indexToKey(enum_info.fields[0].val),
|
1 => return ip.indexToKey(enum_info.values.keys()[0]),
|
||||||
else => return null,
|
else => return null,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -623,11 +656,7 @@ pub const Key = union(enum) {
|
|||||||
ip: InternPool,
|
ip: InternPool,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO implement options
|
pub const FormatOptions = struct {};
|
||||||
pub const FormatOptions = struct {
|
|
||||||
include_fields: bool = true,
|
|
||||||
include_declarations: bool = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
fn formatType(
|
fn formatType(
|
||||||
ctx: TypeFormatContext,
|
ctx: TypeFormatContext,
|
||||||
@ -925,27 +954,27 @@ pub const Key = union(enum) {
|
|||||||
|
|
||||||
.bytes => |bytes| try writer.print("\"{}\"", .{std.zig.fmtEscapes(bytes)}),
|
.bytes => |bytes| try writer.print("\"{}\"", .{std.zig.fmtEscapes(bytes)}),
|
||||||
.aggregate => |aggregate| {
|
.aggregate => |aggregate| {
|
||||||
const struct_info = ip.indexToKey(ty).struct_type;
|
const struct_info = ip.getStruct(ip.indexToKey(ty).struct_type);
|
||||||
assert(aggregate.len == struct_info.fields.len);
|
assert(aggregate.len == struct_info.fields.count());
|
||||||
|
|
||||||
try writer.writeAll(".{");
|
try writer.writeAll(".{");
|
||||||
var i: u32 = 0;
|
var i: u32 = 0;
|
||||||
while (i < aggregate.len) : (i += 1) {
|
while (i < aggregate.len) : (i += 1) {
|
||||||
if (i != 0) try writer.writeAll(", ");
|
if (i != 0) try writer.writeAll(", ");
|
||||||
|
|
||||||
const field_name = ip.indexToKey(struct_info.fields[i].name).bytes;
|
const field_name = struct_info.fields.keys()[i];
|
||||||
try writer.print(".{s} = ", .{field_name});
|
try writer.print(".{s} = ", .{field_name});
|
||||||
try printValue(ip.indexToKey(aggregate[i]), struct_info.fields[i].ty, ip, writer);
|
try printValue(ip.indexToKey(aggregate[i]), struct_info.fields.values()[i].ty, ip, writer);
|
||||||
}
|
}
|
||||||
try writer.writeByte('}');
|
try writer.writeByte('}');
|
||||||
},
|
},
|
||||||
.union_value => |union_value| {
|
.union_value => |union_value| {
|
||||||
const union_info = ip.indexToKey(ty).union_type;
|
const union_info = ip.getUnion(ip.indexToKey(ty).union_type);
|
||||||
|
|
||||||
const name = ip.indexToKey(union_info.fields[union_value.field_index].name).bytes;
|
const name = union_info.fields.keys()[union_value.field_index];
|
||||||
try writer.print(".{{ .{} = {} }}", .{
|
try writer.print(".{{ .{} = {} }}", .{
|
||||||
std.zig.fmtId(name),
|
std.zig.fmtId(name),
|
||||||
union_value.val.fmtValue(union_info.fields[union_value.field_index].ty, ip),
|
union_value.val.fmtValue(union_info.fields.values()[union_value.field_index].ty, ip),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -978,6 +1007,7 @@ pub const Item = struct {
|
|||||||
/// Two values which have the same type can be equality compared simply
|
/// Two values which have the same type can be equality compared simply
|
||||||
/// by checking if their indexes are equal, provided they are both in
|
/// by checking if their indexes are equal, provided they are both in
|
||||||
/// the same `InternPool`.
|
/// the same `InternPool`.
|
||||||
|
/// TODO split this into an Optional and non-Optional Index
|
||||||
pub const Index = enum(u32) {
|
pub const Index = enum(u32) {
|
||||||
none = std.math.maxInt(u32),
|
none = std.math.maxInt(u32),
|
||||||
_,
|
_,
|
||||||
@ -1181,6 +1211,21 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {
|
|||||||
ip.map.deinit(gpa);
|
ip.map.deinit(gpa);
|
||||||
ip.items.deinit(gpa);
|
ip.items.deinit(gpa);
|
||||||
ip.extra.deinit(gpa);
|
ip.extra.deinit(gpa);
|
||||||
|
|
||||||
|
for (ip.structs.items) |*item| {
|
||||||
|
item.fields.deinit(gpa);
|
||||||
|
}
|
||||||
|
for (ip.enums.items) |*item| {
|
||||||
|
item.fields.deinit(gpa);
|
||||||
|
item.values.deinit(gpa);
|
||||||
|
}
|
||||||
|
for (ip.unions.items) |*item| {
|
||||||
|
item.fields.deinit(gpa);
|
||||||
|
}
|
||||||
|
ip.decls.deinit(gpa);
|
||||||
|
ip.structs.deinit(gpa);
|
||||||
|
ip.enums.deinit(gpa);
|
||||||
|
ip.unions.deinit(gpa);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn indexToKey(ip: InternPool, index: Index) Key {
|
pub fn indexToKey(ip: InternPool, index: Index) Key {
|
||||||
@ -1199,17 +1244,18 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
|
|||||||
} },
|
} },
|
||||||
.type_pointer => .{ .pointer_type = ip.extraData(Pointer, data) },
|
.type_pointer => .{ .pointer_type = ip.extraData(Pointer, data) },
|
||||||
.type_array => .{ .array_type = ip.extraData(Array, data) },
|
.type_array => .{ .array_type = ip.extraData(Array, data) },
|
||||||
.type_struct => .{ .struct_type = ip.extraData(Struct, data) },
|
|
||||||
.type_optional => .{ .optional_type = .{ .payload_type = @intToEnum(Index, data) } },
|
.type_optional => .{ .optional_type = .{ .payload_type = @intToEnum(Index, data) } },
|
||||||
.type_anyframe => .{ .anyframe_type = .{ .child = @intToEnum(Index, data) } },
|
.type_anyframe => .{ .anyframe_type = .{ .child = @intToEnum(Index, data) } },
|
||||||
.type_error_union => .{ .error_union_type = ip.extraData(ErrorUnion, data) },
|
.type_error_union => .{ .error_union_type = ip.extraData(ErrorUnion, data) },
|
||||||
.type_error_set => .{ .error_set_type = ip.extraData(ErrorSet, data) },
|
.type_error_set => .{ .error_set_type = ip.extraData(ErrorSet, data) },
|
||||||
.type_enum => .{ .enum_type = ip.extraData(Enum, data) },
|
|
||||||
.type_function => .{ .function_type = ip.extraData(Function, data) },
|
.type_function => .{ .function_type = ip.extraData(Function, data) },
|
||||||
.type_union => .{ .union_type = ip.extraData(Union, data) },
|
|
||||||
.type_tuple => .{ .tuple_type = ip.extraData(Tuple, data) },
|
.type_tuple => .{ .tuple_type = ip.extraData(Tuple, data) },
|
||||||
.type_vector => .{ .vector_type = ip.extraData(Vector, data) },
|
.type_vector => .{ .vector_type = ip.extraData(Vector, data) },
|
||||||
|
|
||||||
|
.type_struct => .{ .struct_type = @intToEnum(StructIndex, data) },
|
||||||
|
.type_enum => .{ .enum_type = @intToEnum(EnumIndex, data) },
|
||||||
|
.type_union => .{ .union_type = @intToEnum(UnionIndex, data) },
|
||||||
|
|
||||||
.int_u32 => .{ .int_u64_value = @intCast(u32, data) },
|
.int_u32 => .{ .int_u64_value = @intCast(u32, data) },
|
||||||
.int_i32 => .{ .int_i64_value = @bitCast(i32, data) },
|
.int_i32 => .{ .int_i64_value = @bitCast(i32, data) },
|
||||||
.int_u64 => .{ .int_u64_value = ip.extraData(u64, data) },
|
.int_u64 => .{ .int_u64_value = ip.extraData(u64, data) },
|
||||||
@ -1248,6 +1294,10 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
|
|||||||
.optional_type => |optional_ty| @enumToInt(optional_ty.payload_type),
|
.optional_type => |optional_ty| @enumToInt(optional_ty.payload_type),
|
||||||
.anyframe_type => |anyframe_ty| @enumToInt(anyframe_ty.child),
|
.anyframe_type => |anyframe_ty| @enumToInt(anyframe_ty.child),
|
||||||
|
|
||||||
|
.struct_type => |struct_index| @enumToInt(struct_index),
|
||||||
|
.enum_type => |enum_index| @enumToInt(enum_index),
|
||||||
|
.union_type => |union_index| @enumToInt(union_index),
|
||||||
|
|
||||||
.int_u64_value => |int_val| if (tag == .int_u32) @intCast(u32, int_val) else try ip.addExtra(gpa, int_val),
|
.int_u64_value => |int_val| if (tag == .int_u32) @intCast(u32, int_val) else try ip.addExtra(gpa, int_val),
|
||||||
.int_i64_value => |int_val| if (tag == .int_i32) @bitCast(u32, @intCast(u32, int_val)) else try ip.addExtra(gpa, int_val),
|
.int_i64_value => |int_val| if (tag == .int_i32) @bitCast(u32, @intCast(u32, int_val)) else try ip.addExtra(gpa, int_val),
|
||||||
.int_big_value => |big_int_val| try ip.addExtra(gpa, big_int_val.limbs),
|
.int_big_value => |big_int_val| try ip.addExtra(gpa, big_int_val.limbs),
|
||||||
@ -1270,6 +1320,36 @@ pub fn contains(ip: InternPool, key: Key) ?Index {
|
|||||||
return @intToEnum(Index, index);
|
return @intToEnum(Index, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn getDecl(ip: *InternPool, index: InternPool.DeclIndex) *InternPool.Decl {
|
||||||
|
return &ip.decls.items[@enumToInt(index)];
|
||||||
|
}
|
||||||
|
pub fn getStruct(ip: InternPool, index: InternPool.StructIndex) *InternPool.Struct {
|
||||||
|
return &ip.structs.items[@enumToInt(index)];
|
||||||
|
}
|
||||||
|
pub fn getEnum(ip: InternPool, index: InternPool.EnumIndex) *InternPool.Enum {
|
||||||
|
return &ip.enums.items[@enumToInt(index)];
|
||||||
|
}
|
||||||
|
pub fn getUnion(ip: InternPool, index: InternPool.UnionIndex) *InternPool.Union {
|
||||||
|
return &ip.unions.items[@enumToInt(index)];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn createDecl(ip: *InternPool, gpa: Allocator, decl: InternPool.Decl) error{OutOfMemory}!InternPool.DeclIndex {
|
||||||
|
try ip.decls.append(gpa, decl);
|
||||||
|
return @intToEnum(InternPool.DeclIndex, ip.decls.items.len - 1);
|
||||||
|
}
|
||||||
|
pub fn createStruct(ip: *InternPool, gpa: Allocator, struct_info: InternPool.Struct) error{OutOfMemory}!InternPool.StructIndex {
|
||||||
|
try ip.structs.append(gpa, struct_info);
|
||||||
|
return @intToEnum(InternPool.StructIndex, ip.structs.items.len - 1);
|
||||||
|
}
|
||||||
|
pub fn createEnum(ip: *InternPool, gpa: Allocator, enum_info: InternPool.Enum) error{OutOfMemory}!InternPool.EnumIndex {
|
||||||
|
try ip.enums.append(gpa, enum_info);
|
||||||
|
return @intToEnum(InternPool.EnumIndex, ip.enums.items.len - 1);
|
||||||
|
}
|
||||||
|
pub fn createUnion(ip: *InternPool, gpa: Allocator, union_info: InternPool.Union) error{OutOfMemory}!InternPool.UnionIndex {
|
||||||
|
try ip.unions.append(gpa, union_info);
|
||||||
|
return @intToEnum(InternPool.UnionIndex, ip.unions.items.len - 1);
|
||||||
|
}
|
||||||
|
|
||||||
fn addExtra(ip: *InternPool, gpa: Allocator, extra: anytype) Allocator.Error!u32 {
|
fn addExtra(ip: *InternPool, gpa: Allocator, extra: anytype) Allocator.Error!u32 {
|
||||||
const T = @TypeOf(extra);
|
const T = @TypeOf(extra);
|
||||||
comptime if (@sizeOf(T) <= 4) {
|
comptime if (@sizeOf(T) <= 4) {
|
||||||
@ -2997,41 +3077,6 @@ test "array type" {
|
|||||||
try testExpectFmtType(ip, u32_0_0_array_type, "[3:0]u32");
|
try testExpectFmtType(ip, u32_0_0_array_type, "[3:0]u32");
|
||||||
}
|
}
|
||||||
|
|
||||||
test "struct type" {
|
|
||||||
const gpa = std.testing.allocator;
|
|
||||||
|
|
||||||
var ip: InternPool = .{};
|
|
||||||
defer ip.deinit(gpa);
|
|
||||||
|
|
||||||
const i32_type = try ip.get(gpa, .{ .int_type = .{ .signedness = .signed, .bits = 32 } });
|
|
||||||
const u64_type = try ip.get(gpa, .{ .int_type = .{ .signedness = .unsigned, .bits = 64 } });
|
|
||||||
const bool_type = try ip.get(gpa, .{ .simple = .bool });
|
|
||||||
|
|
||||||
const foo_name = try ip.get(gpa, .{ .bytes = "foo" });
|
|
||||||
const bar_name = try ip.get(gpa, .{ .bytes = "bar" });
|
|
||||||
const baz_name = try ip.get(gpa, .{ .bytes = "baz" });
|
|
||||||
|
|
||||||
const field1 = Struct.Field{ .name = foo_name, .ty = u64_type };
|
|
||||||
const field2 = Struct.Field{ .name = bar_name, .ty = i32_type };
|
|
||||||
const field3 = Struct.Field{ .name = baz_name, .ty = bool_type };
|
|
||||||
|
|
||||||
const struct_type_0 = try ip.get(gpa, .{ .struct_type = .{
|
|
||||||
.fields = &.{ field1, field2, field3 },
|
|
||||||
.namespace = .none,
|
|
||||||
.layout = .Auto,
|
|
||||||
.backing_int_ty = .none,
|
|
||||||
} });
|
|
||||||
|
|
||||||
const struct_type_1 = try ip.get(gpa, .{ .struct_type = .{
|
|
||||||
.fields = &.{ field1, field2, field3 },
|
|
||||||
.namespace = .none,
|
|
||||||
.layout = .Auto,
|
|
||||||
.backing_int_ty = .none,
|
|
||||||
} });
|
|
||||||
|
|
||||||
try std.testing.expect(struct_type_0 == struct_type_1);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "struct value" {
|
test "struct value" {
|
||||||
const gpa = std.testing.allocator;
|
const gpa = std.testing.allocator;
|
||||||
|
|
||||||
@ -3041,18 +3086,17 @@ test "struct value" {
|
|||||||
const i32_type = try ip.get(gpa, .{ .int_type = .{ .signedness = .signed, .bits = 32 } });
|
const i32_type = try ip.get(gpa, .{ .int_type = .{ .signedness = .signed, .bits = 32 } });
|
||||||
const bool_type = try ip.get(gpa, .{ .simple = .bool });
|
const bool_type = try ip.get(gpa, .{ .simple = .bool });
|
||||||
|
|
||||||
const foo_name = try ip.get(gpa, .{ .bytes = "foo" });
|
const struct_index = try ip.createStruct(gpa, .{
|
||||||
const bar_name = try ip.get(gpa, .{ .bytes = "bar" });
|
.fields = .{},
|
||||||
|
|
||||||
const field1 = Struct.Field{ .name = foo_name, .ty = i32_type };
|
|
||||||
const field2 = Struct.Field{ .name = bar_name, .ty = bool_type };
|
|
||||||
|
|
||||||
const struct_type = try ip.get(gpa, .{ .struct_type = .{
|
|
||||||
.fields = &.{ field1, field2 },
|
|
||||||
.namespace = .none,
|
.namespace = .none,
|
||||||
.layout = .Auto,
|
.layout = .Auto,
|
||||||
.backing_int_ty = .none,
|
.backing_int_ty = .none,
|
||||||
} });
|
.status = .none,
|
||||||
|
});
|
||||||
|
const struct_type = try ip.get(gpa, .{ .struct_type = struct_index });
|
||||||
|
const struct_info = ip.getStruct(struct_index);
|
||||||
|
try struct_info.fields.put(gpa, "foo", .{ .ty = i32_type });
|
||||||
|
try struct_info.fields.put(gpa, "bar", .{ .ty = bool_type });
|
||||||
|
|
||||||
const one_value = try ip.get(gpa, .{ .int_i64_value = 1 });
|
const one_value = try ip.get(gpa, .{ .int_i64_value = 1 });
|
||||||
const true_value = try ip.get(gpa, .{ .simple = .bool_true });
|
const true_value = try ip.get(gpa, .{ .simple = .bool_true });
|
||||||
@ -3062,50 +3106,6 @@ test "struct value" {
|
|||||||
try ip.testExpectFmtValue(aggregate_value, struct_type, ".{.foo = 1, .bar = true}");
|
try ip.testExpectFmtValue(aggregate_value, struct_type, ".{.foo = 1, .bar = true}");
|
||||||
}
|
}
|
||||||
|
|
||||||
test "enum type" {
|
|
||||||
const gpa = std.testing.allocator;
|
|
||||||
|
|
||||||
var ip: InternPool = .{};
|
|
||||||
defer ip.deinit(gpa);
|
|
||||||
|
|
||||||
const zig_name = try ip.get(gpa, .{ .bytes = "zig" });
|
|
||||||
const cpp_name = try ip.get(gpa, .{ .bytes = "cpp" });
|
|
||||||
|
|
||||||
const empty_enum1 = try ip.get(gpa, .{ .enum_type = .{
|
|
||||||
.tag_type = .none,
|
|
||||||
.fields = &.{},
|
|
||||||
.namespace = .none,
|
|
||||||
.tag_type_infered = true,
|
|
||||||
} });
|
|
||||||
|
|
||||||
const empty_enum2 = try ip.get(gpa, .{ .enum_type = .{
|
|
||||||
.tag_type = .none,
|
|
||||||
.fields = &.{},
|
|
||||||
.namespace = .none,
|
|
||||||
.tag_type_infered = true,
|
|
||||||
} });
|
|
||||||
|
|
||||||
const field1 = Enum.Field{ .name = zig_name, .val = .none };
|
|
||||||
const field2 = Enum.Field{ .name = cpp_name, .val = .none };
|
|
||||||
|
|
||||||
const enum1 = try ip.get(gpa, .{ .enum_type = .{
|
|
||||||
.tag_type = .none,
|
|
||||||
.fields = &.{ field1, field2 },
|
|
||||||
.namespace = .none,
|
|
||||||
.tag_type_infered = true,
|
|
||||||
} });
|
|
||||||
const enum2 = try ip.get(gpa, .{ .enum_type = .{
|
|
||||||
.tag_type = .none,
|
|
||||||
.fields = &.{ field2, field1 },
|
|
||||||
.namespace = .none,
|
|
||||||
.tag_type_infered = true,
|
|
||||||
} });
|
|
||||||
|
|
||||||
try std.testing.expect(empty_enum1 == empty_enum2);
|
|
||||||
try std.testing.expect(empty_enum2 != enum1);
|
|
||||||
try std.testing.expect(enum1 != enum2);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "function type" {
|
test "function type" {
|
||||||
const gpa = std.testing.allocator;
|
const gpa = std.testing.allocator;
|
||||||
|
|
||||||
@ -3152,40 +3152,6 @@ test "function type" {
|
|||||||
try testExpectFmtType(ip, @"fn() align(4) callconv(.C) type", "fn() align(4) callconv(.C) type");
|
try testExpectFmtType(ip, @"fn() align(4) callconv(.C) type", "fn() align(4) callconv(.C) type");
|
||||||
}
|
}
|
||||||
|
|
||||||
test "union type" {
|
|
||||||
const gpa = std.testing.allocator;
|
|
||||||
|
|
||||||
var ip: InternPool = .{};
|
|
||||||
defer ip.deinit(gpa);
|
|
||||||
|
|
||||||
const u32_type = try ip.get(gpa, .{ .int_type = .{ .signedness = .unsigned, .bits = 32 } });
|
|
||||||
const void_type = try ip.get(gpa, .{ .simple = .void });
|
|
||||||
|
|
||||||
const ok_name = try ip.get(gpa, .{ .bytes = "Ok" });
|
|
||||||
const err_name = try ip.get(gpa, .{ .bytes = "Err" });
|
|
||||||
|
|
||||||
var field1 = Union.Field{ .name = ok_name, .ty = u32_type, .alignment = 0 };
|
|
||||||
var field2 = Union.Field{ .name = err_name, .ty = void_type, .alignment = 0 };
|
|
||||||
|
|
||||||
const union_type1 = try ip.get(gpa, .{
|
|
||||||
.union_type = .{
|
|
||||||
.tag_type = .none,
|
|
||||||
.fields = &.{ field1, field2 },
|
|
||||||
.namespace = .none,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const union_type2 = try ip.get(gpa, .{
|
|
||||||
.union_type = .{
|
|
||||||
.tag_type = .none,
|
|
||||||
.fields = &.{ field2, field1 },
|
|
||||||
.namespace = .none,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
try std.testing.expect(union_type1 != union_type2);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "union value" {
|
test "union value" {
|
||||||
const gpa = std.testing.allocator;
|
const gpa = std.testing.allocator;
|
||||||
|
|
||||||
@ -3198,19 +3164,17 @@ test "union value" {
|
|||||||
const int_value = try ip.get(gpa, .{ .int_u64_value = 1 });
|
const int_value = try ip.get(gpa, .{ .int_u64_value = 1 });
|
||||||
const f16_value = try ip.get(gpa, .{ .float_16_value = 0.25 });
|
const f16_value = try ip.get(gpa, .{ .float_16_value = 0.25 });
|
||||||
|
|
||||||
const int_name = try ip.get(gpa, .{ .bytes = "int" });
|
const union_index = try ip.createUnion(gpa, .{
|
||||||
const float_name = try ip.get(gpa, .{ .bytes = "float" });
|
|
||||||
|
|
||||||
var field1 = Union.Field{ .name = int_name, .ty = u32_type, .alignment = 0 };
|
|
||||||
var field2 = Union.Field{ .name = float_name, .ty = f16_type, .alignment = 0 };
|
|
||||||
|
|
||||||
const union_type = try ip.get(gpa, .{
|
|
||||||
.union_type = .{
|
|
||||||
.tag_type = .none,
|
.tag_type = .none,
|
||||||
.fields = &.{ field1, field2 },
|
.fields = .{},
|
||||||
.namespace = .none,
|
.namespace = .none,
|
||||||
},
|
.layout = .Auto,
|
||||||
|
.status = .none,
|
||||||
});
|
});
|
||||||
|
const union_type = try ip.get(gpa, .{ .union_type = union_index });
|
||||||
|
const union_info = ip.getUnion(union_index);
|
||||||
|
try union_info.fields.put(gpa, "int", .{ .ty = u32_type, .alignment = 0 });
|
||||||
|
try union_info.fields.put(gpa, "float", .{ .ty = f16_type, .alignment = 0 });
|
||||||
|
|
||||||
const union_value1 = try ip.get(gpa, .{ .union_value = .{
|
const union_value1 = try ip.get(gpa, .{ .union_value = .{
|
||||||
.field_index = 0,
|
.field_index = 0,
|
||||||
|
@ -24,7 +24,7 @@ pub fn dotCompletions(
|
|||||||
.simple => |simple| switch (simple) {
|
.simple => |simple| switch (simple) {
|
||||||
.type => {
|
.type => {
|
||||||
const ty_key = ip.indexToKey(val);
|
const ty_key = ip.indexToKey(val);
|
||||||
const namespace = ty_key.getNamespace();
|
const namespace = ty_key.getNamespace(ip.*);
|
||||||
if (namespace != .none) {
|
if (namespace != .none) {
|
||||||
// TODO lookup in namespace
|
// TODO lookup in namespace
|
||||||
}
|
}
|
||||||
@ -40,11 +40,12 @@ pub fn dotCompletions(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
.union_type => {}, // TODO
|
.union_type => {}, // TODO
|
||||||
.enum_type => |enum_info| {
|
.enum_type => |enum_index| {
|
||||||
for (enum_info.fields) |field| {
|
const enum_info = ip.getEnum(enum_index);
|
||||||
const field_name = ip.indexToKey(field.name).bytes;
|
var field_it = enum_info.fields.iterator();
|
||||||
|
while (field_it.next()) |entry| {
|
||||||
try completions.append(arena, .{
|
try completions.append(arena, .{
|
||||||
.label = field_name,
|
.label = entry.key_ptr.*,
|
||||||
.kind = .Constant,
|
.kind = .Constant,
|
||||||
// include field.val?
|
// include field.val?
|
||||||
});
|
});
|
||||||
@ -85,14 +86,15 @@ pub fn dotCompletions(
|
|||||||
.detail = try std.fmt.allocPrint(arena, "usize ({d})", .{array_info.len}), // TODO how should this be displayed
|
.detail = try std.fmt.allocPrint(arena, "usize ({d})", .{array_info.len}), // TODO how should this be displayed
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.struct_type => |struct_info| {
|
.struct_type => |struct_index| {
|
||||||
for (struct_info.fields) |field| {
|
const struct_info = ip.getStruct(struct_index);
|
||||||
const field_name = ip.indexToKey(field.name).bytes;
|
var field_it = struct_info.fields.iterator();
|
||||||
|
while (field_it.next()) |entry| {
|
||||||
try completions.append(arena, types.CompletionItem{
|
try completions.append(arena, types.CompletionItem{
|
||||||
.label = field_name,
|
.label = entry.key_ptr.*,
|
||||||
.kind = .Field,
|
.kind = .Field,
|
||||||
// TODO include alignment and comptime
|
// TODO include alignment and comptime
|
||||||
.detail = try std.fmt.allocPrint(arena, "{}", .{field.ty.fmtType(ip.*)}),
|
.detail = try std.fmt.allocPrint(arena, "{}", .{entry.value_ptr.ty.fmtType(ip.*)}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -103,26 +105,28 @@ pub fn dotCompletions(
|
|||||||
.detail = try std.fmt.allocPrint(arena, "{}", .{optional_info.payload_type.fmtType(ip.*)}),
|
.detail = try std.fmt.allocPrint(arena, "{}", .{optional_info.payload_type.fmtType(ip.*)}),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.enum_type => |enum_info| {
|
.enum_type => |enum_index| {
|
||||||
for (enum_info.fields) |field| {
|
const enum_info = ip.getEnum(enum_index);
|
||||||
const field_name = ip.indexToKey(field.name).bytes;
|
for (enum_info.fields.keys()) |field_name, i| {
|
||||||
|
const field_val = enum_info.values.keys()[i];
|
||||||
try completions.append(arena, .{
|
try completions.append(arena, .{
|
||||||
.label = field_name,
|
.label = field_name,
|
||||||
.kind = .Field,
|
.kind = .Field,
|
||||||
.detail = try std.fmt.allocPrint(arena, "{}", .{field.val.fmtValue(enum_info.tag_type, ip.*)}),
|
.detail = try std.fmt.allocPrint(arena, "{}", .{field_val.fmtValue(enum_info.tag_type, ip.*)}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.union_type => |union_info| {
|
.union_type => |union_index| {
|
||||||
for (union_info.fields) |field| {
|
const union_info = ip.getUnion(union_index);
|
||||||
const field_name = ip.indexToKey(field.name).bytes;
|
var field_it = union_info.fields.iterator();
|
||||||
|
while (field_it.next()) |entry| {
|
||||||
try completions.append(arena, .{
|
try completions.append(arena, .{
|
||||||
.label = field_name,
|
.label = entry.key_ptr.*,
|
||||||
.kind = .Field,
|
.kind = .Field,
|
||||||
.detail = if (field.alignment != 0)
|
.detail = if (entry.value_ptr.alignment != 0)
|
||||||
try std.fmt.allocPrint(arena, "align({d}) {}", .{ field.alignment, field.ty.fmtType(ip.*) })
|
try std.fmt.allocPrint(arena, "align({d}) {}", .{ entry.value_ptr.alignment, entry.value_ptr.ty.fmtType(ip.*) })
|
||||||
else
|
else
|
||||||
try std.fmt.allocPrint(arena, "{}", .{field.ty.fmtType(ip.*)}),
|
try std.fmt.allocPrint(arena, "{}", .{entry.value_ptr.ty.fmtType(ip.*)}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -772,7 +772,7 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
|
|||||||
};
|
};
|
||||||
var interpreter: *ComptimeInterpreter = handle.interpreter.?;
|
var interpreter: *ComptimeInterpreter = handle.interpreter.?;
|
||||||
|
|
||||||
const root_namespace = @intToEnum(ComptimeInterpreter.NamespaceIndex, 0);
|
const root_namespace = @intToEnum(ComptimeInterpreter.Namespace.Index, 0);
|
||||||
|
|
||||||
// TODO: Start from current/nearest-current scope
|
// TODO: Start from current/nearest-current scope
|
||||||
const result = interpreter.interpret(node, root_namespace, .{}) catch |err| {
|
const result = interpreter.interpret(node, root_namespace, .{}) catch |err| {
|
||||||
|
@ -169,16 +169,15 @@ test "ComptimeInterpreter - call return struct" {
|
|||||||
|
|
||||||
try std.testing.expect(result.ty == .simple);
|
try std.testing.expect(result.ty == .simple);
|
||||||
try std.testing.expect(result.ty.simple == .type);
|
try std.testing.expect(result.ty.simple == .type);
|
||||||
const struct_info = result.val.?.struct_type;
|
const struct_info = context.interpreter.ip.getStruct(result.val.?.struct_type);
|
||||||
try std.testing.expectEqual(Index.none, struct_info.backing_int_ty);
|
try std.testing.expectEqual(Index.none, struct_info.backing_int_ty);
|
||||||
try std.testing.expectEqual(std.builtin.Type.ContainerLayout.Auto, struct_info.layout);
|
try std.testing.expectEqual(std.builtin.Type.ContainerLayout.Auto, struct_info.layout);
|
||||||
|
|
||||||
const field_name = context.interpreter.ip.indexToKey(struct_info.fields[0].name).bytes;
|
|
||||||
const bool_type = try context.interpreter.ip.get(allocator, .{ .simple = .bool });
|
const bool_type = try context.interpreter.ip.get(allocator, .{ .simple = .bool });
|
||||||
|
|
||||||
try std.testing.expectEqual(@as(usize, 1), struct_info.fields.len);
|
try std.testing.expectEqual(@as(usize, 1), struct_info.fields.count());
|
||||||
try std.testing.expectEqualStrings("slay", field_name);
|
try std.testing.expectEqualStrings("slay", struct_info.fields.keys()[0]);
|
||||||
try std.testing.expect(struct_info.fields[0].ty == bool_type);
|
try std.testing.expect(struct_info.fields.values()[0].ty == bool_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "ComptimeInterpreter - call comptime argument" {
|
test "ComptimeInterpreter - call comptime argument" {
|
||||||
@ -284,7 +283,7 @@ const Context = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const namespace = @intToEnum(ComptimeInterpreter.NamespaceIndex, 0); // root namespace
|
const namespace = @intToEnum(ComptimeInterpreter.Namespace.Index, 0); // root namespace
|
||||||
const result = (try self.interpreter.call(namespace, func_node, args, .{})).result;
|
const result = (try self.interpreter.call(namespace, func_node, args, .{})).result;
|
||||||
|
|
||||||
try std.testing.expect(result == .value);
|
try std.testing.expect(result == .value);
|
||||||
@ -297,7 +296,7 @@ const Context = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn interpret(self: *Context, node: Ast.Node.Index) !KV {
|
pub fn interpret(self: *Context, node: Ast.Node.Index) !KV {
|
||||||
const namespace = @intToEnum(ComptimeInterpreter.NamespaceIndex, 0); // root namespace
|
const namespace = @intToEnum(ComptimeInterpreter.Namespace.Index, 0); // root namespace
|
||||||
const result = try (try self.interpreter.interpret(node, namespace, .{})).getValue();
|
const result = try (try self.interpreter.interpret(node, namespace, .{})).getValue();
|
||||||
|
|
||||||
try std.testing.expect(result.ty != .none);
|
try std.testing.expect(result.ty != .none);
|
||||||
|
Loading…
Reference in New Issue
Block a user