Rework polymorphism

This commit is contained in:
David Gonzalez Martin 2024-04-07 13:09:32 -06:00
parent 149aa360f2
commit 80a4b656f9
2 changed files with 238 additions and 284 deletions

View File

@ -3222,13 +3222,94 @@ pub const Type = union(enum) {
void, void,
noreturn, noreturn,
type, type,
polymorphic: *Debug.Declaration.Global,
@"struct": Struct.Index, @"struct": Struct.Index,
function: Function.Prototype.Index, function: Function.Prototype.Index,
integer: Type.Integer, integer: Type.Integer,
pointer: Type.Pointer, pointer: Type.Pointer,
slice: Type.Slice, slice: Type.Slice,
array: Type.Array, array: Type.Array,
polymorphic: Type.Polymorphic,
pub const Polymorphic = struct{
parameters: []const Token.Index,
instantiations: MyHashMap(u32, *Debug.Declaration.Global) = .{},
node: Node.Index,
pub fn get_instantiation(polymorphic: *Polymorphic, types: []const V.Comptime) ?*Debug.Declaration.Global {
const parameter_hash = hash(types);
const result = polymorphic.instantiations.get(parameter_hash);
return result;
}
pub fn add_instantiation(polymorphic: *Polymorphic, unit: *Unit, context: *const Context, types: []const V.Comptime, original_declaration: *Debug.Declaration.Global, type_index: Type.Index) !void {
var name = UnpinnedArray(u8){};
const original_name = unit.getIdentifier( original_declaration.declaration.name);
try name.append_slice(context.my_allocator, original_name);
try name.append(context.my_allocator, '(');
if (types.len > 0) {
for (types) |parameter| {
switch (parameter) {
.type => |parameter_type_index| if (unit.type_declarations.get(parameter_type_index)) |foo| {
_ = foo; // autofix
unreachable;
} else switch (unit.types.get(parameter_type_index).*) {
.integer => |integer| switch (integer.kind) {
.materialized_int => {
const char: u8 = switch (integer.signedness) {
.signed => 's',
.unsigned => 'u',
};
try name.append(context.my_allocator, char);
var bit_buffer: [32]u8 = undefined;
const formatted_int = format_int(&bit_buffer, integer.bit_count, 10, false);
try name.append_slice(context.my_allocator, formatted_int);
},
else => |t| @panic(@tagName(t)),
},
else => |t| @panic(@tagName(t)),
},
else => |t| @panic(@tagName(t)),
}
try name.append(context.my_allocator, ',');
try name.append(context.my_allocator, ' ');
}
name.length -= 2;
name.pointer[name.length] = ')';
name.length += 1;
}
const name_hash = try unit.processIdentifier(context, name.slice());
const new_declaration_index = try unit.global_declarations.append(context.my_allocator, .{
.declaration = .{
.scope = original_declaration.declaration.scope,
.type = .type,
.name = name_hash,
.line = original_declaration.declaration.line,
.column = original_declaration.declaration.column,
.mutability = original_declaration.declaration.mutability,
.kind = original_declaration.declaration.kind,
},
.initial_value = .{
.type = type_index,
},
.type_node_index = original_declaration.type_node_index,
.attributes = original_declaration.attributes,
});
const new_declaration = unit.global_declarations.get(new_declaration_index);
const parameter_hash = hash(types);
try polymorphic.instantiations.put_no_clobber(context.my_allocator, parameter_hash, new_declaration);
}
fn hash(types: []const V.Comptime) u32 {
const result = data_structures.my_hash(std.mem.sliceAsBytes(types));
return result;
}
};
pub fn getBitSize(ty: *Type, unit: *Unit) u32 { pub fn getBitSize(ty: *Type, unit: *Unit) u32 {
return getTypeBitSize(ty, unit); return getTypeBitSize(ty, unit);
@ -3859,23 +3940,14 @@ pub const Struct = struct {
fields: UnpinnedArray(Struct.Field.Index) = .{}, fields: UnpinnedArray(Struct.Field.Index) = .{},
options: Options, options: Options,
}; };
pub const Options = struct { pub const Options = struct {
sliceable: ?Sliceable = null, sliceable: ?Sliceable = null,
polymorphism_kind: PolymorphismKind = .none,
pub const Id = enum { pub const Id = enum {
sliceable, sliceable,
}; };
}; };
pub const PolymorphismKind = union(enum) {
none,
declaration: []const Type.Index,
implementation: struct {
types: []const Type.Index,
original: Type.Index,
},
};
pub const Sliceable = struct { pub const Sliceable = struct {
pointer: u32, pointer: u32,
length: u32, length: u32,
@ -4548,7 +4620,7 @@ pub const Builder = struct {
}, },
.size => { .size => {
assert(argument_node_list.len == 1); assert(argument_node_list.len == 1);
const argument_type_index = try builder.resolveType(unit, context, argument_node_list[0]); const argument_type_index = try builder.resolveType(unit, context, argument_node_list[0], &.{});
const argument_type = unit.types.get(argument_type_index); const argument_type = unit.types.get(argument_type_index);
const argument_size = argument_type.getByteSize(unit); const argument_size = argument_type.getByteSize(unit);
@ -4667,7 +4739,7 @@ pub const Builder = struct {
}, },
.@"export" => { .@"export" => {
assert(argument_node_list.len == 1); assert(argument_node_list.len == 1);
const expression = try builder.resolveComptimeValue(unit, context, Type.Expect.none, Debug.Declaration.Global.Attributes.initMany(&.{.@"export"}), argument_node_list[0], null, .left); const expression = try builder.resolveComptimeValue(unit, context, Type.Expect.none, Debug.Declaration.Global.Attributes.initMany(&.{.@"export"}), argument_node_list[0], null, .left, &.{});
switch (expression) { switch (expression) {
.global => {}, .global => {},
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
@ -4911,7 +4983,7 @@ pub const Builder = struct {
const main_node_index = file.parser.main_node_index; const main_node_index = file.parser.main_node_index;
// File type already assigned // File type already assigned
_ = try builder.resolveContainerType(unit, context, main_node_index, .@"struct", null); _ = try builder.resolveContainerType(unit, context, main_node_index, .@"struct", null, &.{});
file.status = .analyzed; file.status = .analyzed;
assert(file.scope.type != .null); assert(file.scope.type != .null);
} }
@ -5020,7 +5092,7 @@ pub const Builder = struct {
}; };
}; };
fn referenceGlobalDeclaration(builder: *Builder, unit: *Unit, context: *const Context, scope: *Debug.Scope, declaration: *Debug.Declaration, global_attribute_override: Debug.Declaration.Global.Attributes) !*Debug.Declaration.Global { fn referenceGlobalDeclaration(builder: *Builder, unit: *Unit, context: *const Context, scope: *Debug.Scope, declaration: *Debug.Declaration, global_attribute_override: Debug.Declaration.Global.Attributes, new_parameters: []const V.Comptime) !*Debug.Declaration.Global {
// TODO: implement this // TODO: implement this
assert(declaration.kind == .global); assert(declaration.kind == .global);
const old_context = builder.startContextSwitch(.{ const old_context = builder.startContextSwitch(.{
@ -5028,6 +5100,7 @@ pub const Builder = struct {
.file = scope.file, .file = scope.file,
.basic_block = .null, .basic_block = .null,
}); });
defer builder.endContextSwitch(old_context);
const global_declaration: *Debug.Declaration.Global = @fieldParentPtr("declaration", declaration); const global_declaration: *Debug.Declaration.Global = @fieldParentPtr("declaration", declaration);
switch (global_declaration.initial_value) { switch (global_declaration.initial_value) {
@ -5036,7 +5109,7 @@ pub const Builder = struct {
switch (global_declaration.type_node_index) { switch (global_declaration.type_node_index) {
.null => {}, .null => {},
else => |type_node_index| { else => |type_node_index| {
declaration.type = try builder.resolveType(unit, context, type_node_index); declaration.type = try builder.resolveType(unit, context, type_node_index, &.{});
}, },
} }
@ -5054,7 +5127,7 @@ pub const Builder = struct {
} }
} }
global_declaration.initial_value = try builder.resolveComptimeValue(unit, context, type_expect, global_declaration.attributes, declaration_node_index, global_declaration, .right); global_declaration.initial_value = try builder.resolveComptimeValue(unit, context, type_expect, global_declaration.attributes, declaration_node_index, global_declaration, .right, new_parameters);
switch (declaration.type) { switch (declaration.type) {
.null => { .null => {
@ -5094,9 +5167,15 @@ pub const Builder = struct {
}, },
.type => |type_index| { .type => |type_index| {
assert(declaration.type == .type); assert(declaration.type == .type);
unit.type_declarations.put(context.my_allocator, type_index, global_declaration) catch { switch (unit.types.get(type_index).*) {
.polymorphic => |*poly| if (new_parameters.len > 0) {
const result = poly.get_instantiation(new_parameters) orelse unreachable;
return result;
},
else => unit.type_declarations.put(context.my_allocator, type_index, global_declaration) catch {
assert(unit.type_declarations.get(type_index).? == global_declaration); assert(unit.type_declarations.get(type_index).? == global_declaration);
}; },
}
}, },
else => { else => {
if (global_declaration.attributes.contains(.@"export") or declaration.mutability == .@"var") { if (global_declaration.attributes.contains(.@"export") or declaration.mutability == .@"var") {
@ -5115,8 +5194,6 @@ pub const Builder = struct {
} }
} }
builder.endContextSwitch(old_context);
return global_declaration; return global_declaration;
} }
@ -5496,7 +5573,7 @@ pub const Builder = struct {
right, right,
}; };
fn resolveIdentifier(builder: *Builder, unit: *Unit, context: *const Context, type_expect: Type.Expect, identifier: []const u8, global_attributes: Debug.Declaration.Global.Attributes, side: Side) !V { fn resolveIdentifier(builder: *Builder, unit: *Unit, context: *const Context, type_expect: Type.Expect, identifier: []const u8, global_attributes: Debug.Declaration.Global.Attributes, side: Side, new_parameters: []const V.Comptime) !V {
const hash = try unit.processIdentifier(context, identifier); const hash = try unit.processIdentifier(context, identifier);
const look_in_parent_scopes = true; const look_in_parent_scopes = true;
@ -5508,7 +5585,7 @@ pub const Builder = struct {
.file, .file,
.struct_type, .struct_type,
=> b: { => b: {
const global = try builder.referenceGlobalDeclaration(unit, context, lookup.scope, lookup.declaration, global_attributes); const global = try builder.referenceGlobalDeclaration(unit, context, lookup.scope, lookup.declaration, global_attributes, new_parameters);
const pointer_to_global = try unit.getPointerType(context, .{ const pointer_to_global = try unit.getPointerType(context, .{
.type = global.declaration.type, .type = global.declaration.type,
.termination = switch (type_expect) { .termination = switch (type_expect) {
@ -6291,7 +6368,7 @@ pub const Builder = struct {
var termination = Type.Termination.none; var termination = Type.Termination.none;
const len_node = unit.getNode(attribute_node_list[0]); const len_node = unit.getNode(attribute_node_list[0]);
const len = switch (len_node.id) { const len = switch (len_node.id) {
else => switch (try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = .usize }, .{}, attribute_node_list[0], null, .right)) { else => switch (try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = .usize }, .{}, attribute_node_list[0], null, .right, &.{})) {
.comptime_int => |ct_int| ct_int.value, .comptime_int => |ct_int| ct_int.value,
.constant_int => |constant_int| constant_int.value, .constant_int => |constant_int| constant_int.value,
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
@ -6314,7 +6391,7 @@ pub const Builder = struct {
} }
const element_type_index = @as(usize, 1) + @intFromBool(attribute_node_list.len == 3); const element_type_index = @as(usize, 1) + @intFromBool(attribute_node_list.len == 3);
const element_type = try builder.resolveType(unit, context, attribute_node_list[element_type_index]); const element_type = try builder.resolveType(unit, context, attribute_node_list[element_type_index], &.{});
const array_type = try unit.getArrayType(context, .{ const array_type = try unit.getArrayType(context, .{
.count = len, .count = len,
.type = element_type, .type = element_type,
@ -6323,7 +6400,7 @@ pub const Builder = struct {
return array_type; return array_type;
} }
fn resolveType(builder: *Builder, unit: *Unit, context: *const Context, node_index: Node.Index) anyerror!Type.Index { fn resolveType(builder: *Builder, unit: *Unit, context: *const Context, node_index: Node.Index, new_parameters: []const V.Comptime) anyerror!Type.Index {
const node = unit.getNode(node_index); const node = unit.getNode(node_index);
const result: Type.Index = switch (node.id) { const result: Type.Index = switch (node.id) {
@ -6331,7 +6408,7 @@ pub const Builder = struct {
.usize_type => .usize, .usize_type => .usize,
.void_type => .void, .void_type => .void,
.identifier, .field_access => { .identifier, .field_access => {
const resolved_type_value = try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = .type }, .{}, node_index, null, .right); const resolved_type_value = try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = .type }, .{}, node_index, null, .right, new_parameters);
return resolved_type_value.type; return resolved_type_value.type;
}, },
.bool_type => .bool, .bool_type => .bool,
@ -6365,7 +6442,7 @@ pub const Builder = struct {
unreachable; unreachable;
} }
element_type_index = try builder.resolveType(unit, context, element_node_index); element_type_index = try builder.resolveType(unit, context, element_node_index, &.{});
}, },
.const_expression => mutability = .@"const", .const_expression => mutability = .@"const",
.many_pointer_expression => many = true, .many_pointer_expression => many = true,
@ -6418,7 +6495,7 @@ pub const Builder = struct {
unreachable; unreachable;
} }
element_type_index = try builder.resolveType(unit, context, element_node_index); element_type_index = try builder.resolveType(unit, context, element_node_index, &.{});
}, },
.const_expression => mutability = .@"const", .const_expression => mutability = .@"const",
.zero_terminated => { .zero_terminated => {
@ -6454,7 +6531,7 @@ pub const Builder = struct {
}, },
.array_type => try builder.resolveArrayType(unit, context, node_index, null), .array_type => try builder.resolveArrayType(unit, context, node_index, null),
.optional_type => blk: { .optional_type => blk: {
const element_type_index = try builder.resolveType(unit, context, node.left); const element_type_index = try builder.resolveType(unit, context, node.left, &.{});
const element_type = unit.types.get(element_type_index); const element_type = unit.types.get(element_type_index);
const r = switch (element_type.*) { const r = switch (element_type.*) {
.pointer => |pointer| b: { .pointer => |pointer| b: {
@ -6481,8 +6558,8 @@ pub const Builder = struct {
assert(node.left != .null); assert(node.left != .null);
assert(node.right != .null); assert(node.right != .null);
const err = try builder.resolveType(unit, context, node.left); const err = try builder.resolveType(unit, context, node.left, &.{});
const ty = try builder.resolveType(unit, context, node.right); const ty = try builder.resolveType(unit, context, node.right, &.{});
const error_union = try builder.getErrorUnionType(unit, context, .{ const error_union = try builder.getErrorUnionType(unit, context, .{
.@"error" = err, .@"error" = err,
@ -6522,21 +6599,21 @@ pub const Builder = struct {
} }
}, },
// This is a data structures with parameters // This is a data structures with parameters
.call => b: { .call => {
const parameterized_type_index = try builder.resolveType(unit, context, node.left); // const parameterized_type_index = try builder.resolveType(unit, context, node.left);
const parameter_nodes = unit.getNodeList(node.right); const parameter_nodes = unit.getNodeList(node.right);
var parameter_types = UnpinnedArray(Type.Index){}; var parameters = UnpinnedArray(V.Comptime){};
for (parameter_nodes) |parameter_node_index| { for (parameter_nodes) |parameter_node_index| {
const parameter_node = unit.getNode(parameter_node_index); const parameter = try builder.resolveComptimeValue(unit, context, Type.Expect.none, .{}, parameter_node_index, null, .right, &.{});
switch (parameter_node.id) { try parameters.append(context.my_allocator, parameter);
.unsigned_integer_type => try parameter_types.append(context.my_allocator, try builder.resolveType(unit, context, parameter_node_index)),
else => |t| @panic(@tagName(t)),
}
} }
const instantiated_type_index = try builder.instantiate_polymorphic_type(unit, context, parameterized_type_index, parameter_types.slice(), parameterized_type_index); const instantiated_type = try builder.resolveType(unit, context, node.left, parameters.slice());
break :b instantiated_type_index; const instantiated_ty = unit.types.get(instantiated_type);
assert(instantiated_ty.* != .polymorphic);
return instantiated_type;
}, },
.self => { .self => {
var scope = builder.current_scope; var scope = builder.current_scope;
@ -6557,104 +6634,6 @@ pub const Builder = struct {
return result; return result;
} }
fn instantiate_polymorphic_type(builder: *Builder, unit: *Unit, context: *const Context, type_index: Type.Index, parameter_types: []const Type.Index, original_type_index: Type.Index) !Type.Index {
const parameterized_type = unit.types.get(type_index);
const original_type = unit.types.get(original_type_index);
switch (parameterized_type.*) {
.@"struct" => |struct_index| switch (unit.structs.get(struct_index).kind) {
.@"struct" => |*struct_type| {
switch (struct_type.options.polymorphism_kind) {
.declaration => |declaration_types| {
if (declaration_types.len != parameter_types.len) @panic("Argument count mismatch");
// var s = struct_type.*;
var fields = try UnpinnedArray(Struct.Field.Index).initialize_with_capacity(context.my_allocator, struct_type.fields.length);
var is_polymorphic = false;
for (struct_type.fields.slice()) |field_index| {
const field = unit.struct_fields.get(field_index);
const new_type_index = try builder.instantiate_polymorphic_type(unit, context, field.type, parameter_types, original_type_index);
is_polymorphic = is_polymorphic or new_type_index == field.type;
if (field.type != new_type_index) {
var f = field.*;
f.type = new_type_index;
const new_field_index = try unit.struct_fields.append(context.my_allocator, f);
fields.append_with_capacity(new_field_index);
} else {
fields.append_with_capacity(field_index);
}
}
if (is_polymorphic) {
var s = struct_type.*;
s.fields = fields;
s.options.polymorphism_kind = .{
.implementation = .{
.types = parameter_types,
.original = type_index,
},
};
const si = try unit.structs.append(context.my_allocator, .{
.kind = .{
.@"struct" = s,
},
});
const sti = try unit.types.append(context.my_allocator, .{
.@"struct" = si,
});
return sti;
} else {
unreachable;
}
},
else => |t| @panic(@tagName(t)),
}
},
else => |t| @panic(@tagName(t)),
},
.pointer => |pointer| {
const new_type_index = try builder.instantiate_polymorphic_type(unit, context, pointer.type, parameter_types, original_type_index);
if (new_type_index != pointer.type) {
var p = pointer;
p.type = new_type_index;
return try unit.getPointerType(context, p);
} else {
unreachable;
}
},
.polymorphic => |polymorphic_declaration| {
assert(polymorphic_declaration.initial_value.type == type_index);
const name_hash = polymorphic_declaration.declaration.name;
switch (original_type.*) {
.@"struct" => |struct_index| switch (unit.structs.get(struct_index).kind) {
.@"struct" => |*struct_type| {
switch (struct_type.options.polymorphism_kind) {
.declaration => |declaration_types| {
for (declaration_types, parameter_types) |declaration_type_index, parameter_type_index| {
if (declaration_type_index == type_index) {
return parameter_type_index;
}
}
unreachable;
},
else => |t| @panic(@tagName(t)),
}
unreachable;
},
else => |t| @panic(@tagName(t)),
},
else => |t| @panic(@tagName(t)),
}
_ = name_hash; // autofix
unreachable;
},
.integer => return type_index,
else => |t| @panic(@tagName(t)),
}
}
fn get_builtin_declaration(builder: *Builder, unit: *Unit, context: *const Context, name: []const u8) !*Debug.Declaration.Global { fn get_builtin_declaration(builder: *Builder, unit: *Unit, context: *const Context, name: []const u8) !*Debug.Declaration.Global {
const std_file_index = try builder.resolveImportStringLiteral(unit, context, Type.Expect{ .type = .type }, "std"); const std_file_index = try builder.resolveImportStringLiteral(unit, context, Type.Expect{ .type = .type }, "std");
const std_file = unit.files.get(std_file_index); const std_file = unit.files.get(std_file_index);
@ -6664,14 +6643,14 @@ pub const Builder = struct {
const look_in_parent_scopes = false; const look_in_parent_scopes = false;
if (std_file_struct.kind.@"struct".scope.scope.lookupDeclaration(builtin_hash, look_in_parent_scopes)) |lookup| { if (std_file_struct.kind.@"struct".scope.scope.lookupDeclaration(builtin_hash, look_in_parent_scopes)) |lookup| {
const builtin_declaration = try builder.referenceGlobalDeclaration(unit, context, &std_file_struct.kind.@"struct".scope.scope, lookup.declaration, .{}); const builtin_declaration = try builder.referenceGlobalDeclaration(unit, context, &std_file_struct.kind.@"struct".scope.scope, lookup.declaration, .{}, &.{});
switch (builtin_declaration.initial_value) { switch (builtin_declaration.initial_value) {
.type => |builtin_type_index| { .type => |builtin_type_index| {
const builtin_type_struct_index = unit.types.get(builtin_type_index).@"struct"; const builtin_type_struct_index = unit.types.get(builtin_type_index).@"struct";
const builtin_type_struct = &unit.structs.get(builtin_type_struct_index).kind.@"struct"; const builtin_type_struct = &unit.structs.get(builtin_type_struct_index).kind.@"struct";
const hash = try unit.processIdentifier(context, name); const hash = try unit.processIdentifier(context, name);
if (builtin_type_struct.scope.scope.lookupDeclaration(hash, look_in_parent_scopes)) |declaration_lookup| { if (builtin_type_struct.scope.scope.lookupDeclaration(hash, look_in_parent_scopes)) |declaration_lookup| {
const declaration_global = try builder.referenceGlobalDeclaration(unit, context, declaration_lookup.scope, declaration_lookup.declaration, .{}); const declaration_global = try builder.referenceGlobalDeclaration(unit, context, declaration_lookup.scope, declaration_lookup.declaration, .{}, &.{});
return declaration_global; return declaration_global;
} else { } else {
unreachable; unreachable;
@ -6709,7 +6688,7 @@ pub const Builder = struct {
} }
assert(unit.cc_type != .null); assert(unit.cc_type != .null);
const cc = try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = unit.cc_type }, .{}, attribute_node.left, null, .right); const cc = try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = unit.cc_type }, .{}, attribute_node.left, null, .right, &.{});
switch (cc) { switch (cc) {
.enum_value => |enum_field_index| { .enum_value => |enum_field_index| {
const enum_field = unit.enum_fields.get(enum_field_index); const enum_field = unit.enum_fields.get(enum_field_index);
@ -6742,14 +6721,14 @@ pub const Builder = struct {
const argument_node = unit.getNode(argument_node_index); const argument_node = unit.getNode(argument_node_index);
assert(argument_node.id == .argument_declaration); assert(argument_node.id == .argument_declaration);
const argument_type_index = try builder.resolveType(unit, context, argument_node.left); const argument_type_index = try builder.resolveType(unit, context, argument_node.left, &.{});
argument_types.append_with_capacity(argument_type_index); argument_types.append_with_capacity(argument_type_index);
} }
function_prototype.argument_types = argument_types.slice(); function_prototype.argument_types = argument_types.slice();
} }
function_prototype.return_type = try builder.resolveType(unit, context, return_type_node_index); function_prototype.return_type = try builder.resolveType(unit, context, return_type_node_index, &.{});
try builder.resolveFunctionPrototypeAbi(unit, context, function_prototype); try builder.resolveFunctionPrototypeAbi(unit, context, function_prototype);
@ -7020,13 +6999,6 @@ pub const Builder = struct {
.direct_pair => |direct_pair| try unit.getTwoStruct(context, direct_pair), .direct_pair => |direct_pair| try unit.getTwoStruct(context, direct_pair),
.direct => function_prototype.return_type, .direct => function_prototype.return_type,
.indirect => |indirect| b: { .indirect => |indirect| b: {
// const pointer_type = try unit.getPointerType(context, .{
// .type = indirect.type,
// .termination = .none,
// .mutability = .@"var",
// .many = false,
// .nullable = false,
// });
try abi_parameter_types.append(context.my_allocator, indirect.pointer); try abi_parameter_types.append(context.my_allocator, indirect.pointer);
break :b .void; break :b .void;
}, },
@ -7039,20 +7011,11 @@ pub const Builder = struct {
switch (parameter_abi.kind) { switch (parameter_abi.kind) {
.direct => try abi_parameter_types.append(context.my_allocator, parameter_type_index), .direct => try abi_parameter_types.append(context.my_allocator, parameter_type_index),
.direct_coerce => |coerced_type| try abi_parameter_types.append(context.my_allocator, coerced_type), .direct_coerce => |coerced_type| try abi_parameter_types.append(context.my_allocator, coerced_type),
.indirect => |indirect| try abi_parameter_types.append(context.my_allocator, indirect.pointer),
.direct_pair => |direct_pair| { .direct_pair => |direct_pair| {
try abi_parameter_types.append(context.my_allocator, direct_pair[0]); try abi_parameter_types.append(context.my_allocator, direct_pair[0]);
try abi_parameter_types.append(context.my_allocator, direct_pair[1]); try abi_parameter_types.append(context.my_allocator, direct_pair[1]);
}, },
.indirect => |indirect| {
// const pointer_type = try unit.getPointerType(context, .{
// .type = indirect.type,
// .termination = .none,
// .mutability = .@"var",
// .many = false,
// .nullable = false,
// });
try abi_parameter_types.append(context.my_allocator, indirect.pointer);
},
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
} }
@ -7621,7 +7584,7 @@ pub const Builder = struct {
} }
} }
fn resolveContainerType(builder: *Builder, unit: *Unit, context: *const Context, container_node_index: Node.Index, container_type: ContainerType, maybe_global: ?*Debug.Declaration.Global) !Type.Index { fn resolveContainerType(builder: *Builder, unit: *Unit, context: *const Context, container_node_index: Node.Index, container_type: ContainerType, maybe_global: ?*Debug.Declaration.Global, new_parameters: []const V.Comptime) !Type.Index {
const current_basic_block = builder.current_basic_block; const current_basic_block = builder.current_basic_block;
defer builder.current_basic_block = current_basic_block; defer builder.current_basic_block = current_basic_block;
builder.current_basic_block = .null; builder.current_basic_block = .null;
@ -7631,7 +7594,8 @@ pub const Builder = struct {
const Data = struct { const Data = struct {
scope: *Debug.Scope.Global, scope: *Debug.Scope.Global,
type: Type.Index, plain: Type.Index,
polymorphic: Type.Index,
}; };
const token_debug_info = builder.getTokenDebugInfo(unit, container_node.token); const token_debug_info = builder.getTokenDebugInfo(unit, container_node.token);
@ -7660,17 +7624,15 @@ pub const Builder = struct {
}, },
}); });
const type_index = try unit.types.append(context.my_allocator, .{
.@"struct" = struct_index,
});
const struct_type = unit.structs.get(struct_index); const struct_type = unit.structs.get(struct_index);
const struct_options = & struct_type.kind.@"struct".options; const struct_options = & struct_type.kind.@"struct".options;
var parameter_types = UnpinnedArray(Token.Index){};
if (container_node.right != .null) { if (container_node.right != .null) {
const struct_option_nodes = unit.getNodeList(container_node.right); const struct_option_nodes = unit.getNodeList(container_node.right);
var struct_options_value = false; var struct_options_value = false;
var parameter_types = UnpinnedArray(Type.Index){}; _ = &parameter_types;
for (struct_option_nodes) |struct_option_node_index| { for (struct_option_nodes) |struct_option_node_index| {
const struct_option_node = unit.getNode(struct_option_node_index); const struct_option_node = unit.getNode(struct_option_node_index);
@ -7706,14 +7668,29 @@ pub const Builder = struct {
.comptime_expression => { .comptime_expression => {
assert(struct_option_node.left != .null); assert(struct_option_node.left != .null);
assert(struct_option_node.right == .null); assert(struct_option_node.right == .null);
const declaration_token_debug_info = builder.getTokenDebugInfo(unit, struct_option_node.token);
const left = unit.getNode(struct_option_node.left); const left = unit.getNode(struct_option_node.left);
assert(left.id == .identifier); assert(left.id == .identifier);
const identifier = unit.getExpectedTokenBytes(left.token, .identifier); try parameter_types.append(context.my_allocator, left.token);
const hash = try unit.processIdentifier(context, identifier); },
const polymorphic_type_index = try unit.types.append(context.my_allocator, .{ else => |t| @panic(@tagName(t)),
.polymorphic = undefined, }
}
}
const plain_type_index = try unit.types.append(context.my_allocator, .{
.@"struct" = struct_index,
}); });
assert(new_parameters.len == parameter_types.length);
for (parameter_types.slice(), new_parameters) |parameter_type_token, parameter_value| {
const parameter_type = switch (parameter_value) {
.type => |type_index| type_index,
else => |t| @panic(@tagName(t)),
};
const declaration_token_debug_info = builder.getTokenDebugInfo(unit, parameter_type_token);
const identifier = unit.getExpectedTokenBytes(parameter_type_token, .identifier);
const hash = try unit.processIdentifier(context, identifier);
const global_declaration_index = try unit.global_declarations.append(context.my_allocator, .{ const global_declaration_index = try unit.global_declarations.append(context.my_allocator, .{
.declaration = .{ .declaration = .{
.scope = &struct_type.kind.@"struct".scope.scope, .scope = &struct_type.kind.@"struct".scope.scope,
@ -7725,32 +7702,36 @@ pub const Builder = struct {
.kind = .global, .kind = .global,
}, },
.initial_value = .{ .initial_value = .{
.type = polymorphic_type_index, .type = parameter_type,
}, },
.type_node_index = .null, .type_node_index = .null,
.attributes = .{}, .attributes = .{},
}); });
const global_declaration = unit.global_declarations.get(global_declaration_index); const global_declaration = unit.global_declarations.get(global_declaration_index);
try struct_type.kind.@"struct".scope.scope.declarations.put_no_clobber(context.my_allocator, hash, &global_declaration.declaration); try struct_type.kind.@"struct".scope.scope.declarations.put_no_clobber(context.my_allocator, hash, &global_declaration.declaration);
const polymorphic_type = unit.types.get(polymorphic_type_index);
polymorphic_type.polymorphic = global_declaration;
try parameter_types.append(context.my_allocator, polymorphic_type_index);
},
else => |t| @panic(@tagName(t)),
}
} }
struct_type.kind.@"struct".options.polymorphism_kind = .{ const polymorphic_type_index = switch (parameter_types.length > 0) {
.declaration = parameter_types.slice(), true => blk: {
const polymorphic_type_index = try unit.types.append(context.my_allocator, .{
.polymorphic = .{
.parameters = parameter_types.slice(),
.node = container_node_index,
},
});
const polymorphic_type = &unit.types.get(polymorphic_type_index).polymorphic;
try polymorphic_type.add_instantiation(unit, context, new_parameters, maybe_global.?, plain_type_index);
break :blk polymorphic_type_index;
},
false => .null,
}; };
}
// Assign the struct type to the upper file scope // Assign the struct type to the upper file scope
switch (builder.current_scope.kind) { switch (builder.current_scope.kind) {
.file => { .file => {
const global_scope: *Debug.Scope.Global = @fieldParentPtr("scope", builder.current_scope); const global_scope: *Debug.Scope.Global = @fieldParentPtr("scope", builder.current_scope);
const file: *Debug.File = @fieldParentPtr("scope", global_scope); const file: *Debug.File = @fieldParentPtr("scope", global_scope);
file.scope.type = type_index; file.scope.type = plain_type_index;
}, },
.file_container => {}, .file_container => {},
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
@ -7758,7 +7739,8 @@ pub const Builder = struct {
break :b .{ break :b .{
.scope = &struct_type.kind.@"struct".scope, .scope = &struct_type.kind.@"struct".scope,
.type = type_index, .plain = plain_type_index,
.polymorphic = polymorphic_type_index,
}; };
}, },
.@"enum" => b: { .@"enum" => b: {
@ -7772,7 +7754,7 @@ pub const Builder = struct {
else => e: { else => e: {
const node_list = unit.getNodeList(container_node.right); const node_list = unit.getNodeList(container_node.right);
assert(node_list.len == 1); assert(node_list.len == 1);
const backing_type_index = try builder.resolveType(unit, context, node_list[0]); const backing_type_index = try builder.resolveType(unit, context, node_list[0], &.{});
const backing_type = unit.types.get(backing_type_index); const backing_type = unit.types.get(backing_type_index);
break :e switch (backing_type.*) { break :e switch (backing_type.*) {
.integer => |integer| switch (integer.kind) { .integer => |integer| switch (integer.kind) {
@ -7807,7 +7789,8 @@ pub const Builder = struct {
const e_type = unit.types.get(type_index); const e_type = unit.types.get(type_index);
break :b .{ break :b .{
.scope = &e_type.integer.kind.@"enum".scope, .scope = &e_type.integer.kind.@"enum".scope,
.type = type_index, .plain = type_index,
.polymorphic = .null,
}; };
}, },
.bitfield => b: { .bitfield => b: {
@ -7817,7 +7800,7 @@ pub const Builder = struct {
else => e: { else => e: {
const argument_nodes = unit.getNodeList(container_node.right); const argument_nodes = unit.getNodeList(container_node.right);
assert(argument_nodes.len == 1); assert(argument_nodes.len == 1);
const backing_type_index = try builder.resolveType(unit, context, argument_nodes[0]); const backing_type_index = try builder.resolveType(unit, context, argument_nodes[0], &.{});
const backing_type = unit.types.get(backing_type_index); const backing_type = unit.types.get(backing_type_index);
break :e switch (backing_type.*) { break :e switch (backing_type.*) {
.integer => |integer| switch (integer.kind) { .integer => |integer| switch (integer.kind) {
@ -7851,22 +7834,23 @@ pub const Builder = struct {
}); });
break :b .{ break :b .{
.type = bitfield_type_index, .plain = bitfield_type_index,
.polymorphic = .null,
.scope = &unit.types.get(bitfield_type_index).integer.kind.bitfield.scope, .scope = &unit.types.get(bitfield_type_index).integer.kind.bitfield.scope,
}; };
}, },
}; };
const scope = data.scope; const scope = data.scope;
const type_index = data.type; scope.type = data.plain;
scope.type = type_index;
if (maybe_global) |global| { if (maybe_global) |global| {
global.declaration.type = .type; global.declaration.type = .type;
global.initial_value = .{ global.initial_value = .{
.type = type_index, .type = if (data.polymorphic != .null) data.polymorphic else data.plain,
}; };
} }
try builder.pushScope(unit, context, &scope.scope); try builder.pushScope(unit, context, &scope.scope);
defer builder.popScope(unit, context) catch unreachable; defer builder.popScope(unit, context) catch unreachable;
@ -8008,7 +7992,7 @@ pub const Builder = struct {
} }
if (count.fields > 0) { if (count.fields > 0) {
const ty = unit.types.get(type_index); const ty = unit.types.get(data.plain);
const field_count = field_nodes.length; const field_count = field_nodes.length;
switch (container_type) { switch (container_type) {
.@"enum" => { .@"enum" => {
@ -8053,7 +8037,7 @@ pub const Builder = struct {
else => b: { else => b: {
const enum_value = try builder.resolveComptimeValue(unit, context, Type.Expect{ const enum_value = try builder.resolveComptimeValue(unit, context, Type.Expect{
.type = integer_type, .type = integer_type,
}, .{}, field_node.left, null, .right); }, .{}, field_node.left, null, .right, &.{});
assert(enum_value.comptime_int.signedness == .unsigned); assert(enum_value.comptime_int.signedness == .unsigned);
break :b enum_value.comptime_int.value; break :b enum_value.comptime_int.value;
}, },
@ -8062,7 +8046,7 @@ pub const Builder = struct {
const enum_field_index = try unit.enum_fields.append(context.my_allocator, .{ const enum_field_index = try unit.enum_fields.append(context.my_allocator, .{
.name = hash, .name = hash,
.value = enum_value, .value = enum_value,
.parent = type_index, .parent = data.plain,
}); });
ty.integer.kind.@"enum".fields.append_with_capacity(enum_field_index); ty.integer.kind.@"enum".fields.append_with_capacity(enum_field_index);
}, },
@ -8086,10 +8070,10 @@ pub const Builder = struct {
} }
} }
} }
const field_type = try builder.resolveType(unit, context, field_node.left); const field_type = try builder.resolveType(unit, context, field_node.left, &.{});
const field_default_value: ?V.Comptime = switch (field_node.right) { const field_default_value: ?V.Comptime = switch (field_node.right) {
.null => null, .null => null,
else => |default_value_node_index| try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = field_type }, .{}, default_value_node_index, null, .right), else => |default_value_node_index| try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = field_type }, .{}, default_value_node_index, null, .right, &.{}),
}; };
const struct_field = try unit.struct_fields.append(context.my_allocator, .{ const struct_field = try unit.struct_fields.append(context.my_allocator, .{
@ -8104,10 +8088,10 @@ pub const Builder = struct {
const bitfield = &ty.integer.kind.bitfield; const bitfield = &ty.integer.kind.bitfield;
const field_name = unit.getExpectedTokenBytes(field_node.token, .identifier); const field_name = unit.getExpectedTokenBytes(field_node.token, .identifier);
const field_name_hash = try unit.processIdentifier(context, field_name); const field_name_hash = try unit.processIdentifier(context, field_name);
const field_type = try builder.resolveType(unit, context, field_node.left); const field_type = try builder.resolveType(unit, context, field_node.left, &.{});
const field_default_value: ?V.Comptime = switch (field_node.right) { const field_default_value: ?V.Comptime = switch (field_node.right) {
.null => null, .null => null,
else => |default_value_node_index| try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = field_type }, .{}, default_value_node_index, null, .right), else => |default_value_node_index| try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = field_type }, .{}, default_value_node_index, null, .right, &.{}),
}; };
const struct_field = try unit.struct_fields.append(context.my_allocator, .{ const struct_field = try unit.struct_fields.append(context.my_allocator, .{
@ -8233,12 +8217,12 @@ pub const Builder = struct {
const name = unit.getIdentifier(export_declaration.declaration.name); const name = unit.getIdentifier(export_declaration.declaration.name);
_ = name; _ = name;
//if (byte_equal(name, "nat_big_struct_both")) @breakpoint(); //if (byte_equal(name, "nat_big_struct_both")) @breakpoint();
const result = try builder.referenceGlobalDeclaration(unit, context, &scope.scope, &export_declaration.declaration, .{}); const result = try builder.referenceGlobalDeclaration(unit, context, &scope.scope, &export_declaration.declaration, .{}, &.{});
assert(result == export_declaration); assert(result == export_declaration);
} }
} }
return type_index; return if (data.polymorphic != .null) data.polymorphic else data.plain;
} }
fn emitMemcpy(builder: *Builder, unit: *Unit, context: *const Context, arguments: Instruction.Memcpy) !void { fn emitMemcpy(builder: *Builder, unit: *Unit, context: *const Context, arguments: Instruction.Memcpy) !void {
@ -8478,15 +8462,6 @@ pub const Builder = struct {
assert(high_offset + sizes[1] <= argument_type.getAbiSize(unit)); assert(high_offset + sizes[1] <= argument_type.getAbiSize(unit));
const stack = try builder.createStackVariable(unit, context, argument_type_index, null); const stack = try builder.createStackVariable(unit, context, argument_type_index, null);
// const pointer_type = try unit.getPointerType(context, .{
// .type = argument_type_index,
// .termination = .none,
// .mutability = .@"var",
// .many = false,
// .nullable = false,
// });
// _ = pointer_type; // autofix
const pointer_types = [2]Type.Index{ const pointer_types = [2]Type.Index{
try unit.getPointerType(context, .{ try unit.getPointerType(context, .{
.type = pair[0], .type = pair[0],
@ -8823,7 +8798,7 @@ pub const Builder = struct {
} }
/// Last value is used to cache types being analyzed so we dont hit stack overflow /// Last value is used to cache types being analyzed so we dont hit stack overflow
fn resolveComptimeValue(builder: *Builder, unit: *Unit, context: *const Context, type_expect: Type.Expect, global_attributes: Debug.Declaration.Global.Attributes, node_index: Node.Index, maybe_global: ?*Debug.Declaration.Global, side: Side) anyerror!V.Comptime { fn resolveComptimeValue(builder: *Builder, unit: *Unit, context: *const Context, type_expect: Type.Expect, global_attributes: Debug.Declaration.Global.Attributes, node_index: Node.Index, maybe_global: ?*Debug.Declaration.Global, side: Side, new_parameters: []const V.Comptime) anyerror!V.Comptime {
const node = unit.getNode(node_index); const node = unit.getNode(node_index);
switch (node.id) { switch (node.id) {
.intrinsic => { .intrinsic => {
@ -8857,7 +8832,7 @@ pub const Builder = struct {
assert(argument_node_list.len == 1); assert(argument_node_list.len == 1);
switch (type_expect) { switch (type_expect) {
.type => |type_index| { .type => |type_index| {
const value = try builder.resolveComptimeValue(unit, context, Type.Expect.none, .{}, argument_node_list[0], null, .right); const value = try builder.resolveComptimeValue(unit, context, Type.Expect.none, .{}, argument_node_list[0], null, .right, &.{});
const ty = unit.types.get(type_index); const ty = unit.types.get(type_index);
switch (ty.*) { switch (ty.*) {
.pointer => |_| switch (value) { .pointer => |_| switch (value) {
@ -8877,7 +8852,7 @@ pub const Builder = struct {
} }
}, },
.field_access => { .field_access => {
const result = try builder.resolveFieldAccess(unit, context, type_expect, node_index, .right); const result = try builder.resolveFieldAccess(unit, context, type_expect, node_index, .right, new_parameters);
return switch (result.value) { return switch (result.value) {
.@"comptime" => |ct| ct, .@"comptime" => |ct| ct,
else => @panic("Expected comptime value, found runtime value"), else => @panic("Expected comptime value, found runtime value"),
@ -8923,23 +8898,18 @@ pub const Builder = struct {
.struct_type => .@"struct", .struct_type => .@"struct",
.bitfield_type => .bitfield, .bitfield_type => .bitfield,
else => unreachable, else => unreachable,
}, maybe_global); }, maybe_global, new_parameters);
return .{ return .{
.type = type_index, .type = type_index,
}; };
}, },
.unsigned_integer_type => return .{
.type = try builder.resolveType(unit, context, node_index, new_parameters),
},
.@"switch" => return try builder.resolveComptimeSwitch(unit, context, type_expect, global_attributes, node_index, maybe_global), .@"switch" => return try builder.resolveComptimeSwitch(unit, context, type_expect, global_attributes, node_index, maybe_global),
.identifier => { .identifier => {
const identifier = unit.getExpectedTokenBytes(node.token, .identifier); const identifier = unit.getExpectedTokenBytes(node.token, .identifier);
// const side: Side = switch (type_expect) { const resolved_value = try builder.resolveIdentifier(unit, context, type_expect, identifier, global_attributes, side, new_parameters);
// .none => .left,
// .type => |type_index| switch (unit.types.get(type_index).*) {
// .type => .right,
// else => |t| @panic(@tagName(t)),
// },
// else => unreachable,
// };
const resolved_value = try builder.resolveIdentifier(unit, context, type_expect, identifier, global_attributes, side);
return switch (resolved_value.value) { return switch (resolved_value.value) {
.@"comptime" => |ct| ct, .@"comptime" => |ct| ct,
.runtime => return error.cannot_evaluate, .runtime => return error.cannot_evaluate,
@ -8952,17 +8922,10 @@ pub const Builder = struct {
.type = result, .type = result,
}; };
}, },
.compare_greater_equal => {
const left = try builder.resolveComptimeValue(unit, context, Type.Expect.none, .{}, node.left, null, .right);
const left_type = left.getType(unit);
const right = try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = left_type }, .{}, node.right, null, .right);
_ = right; // autofix
unreachable;
},
.add => { .add => {
const left = try builder.resolveComptimeValue(unit, context, Type.Expect.none, .{}, node.left, null, .right); const left = try builder.resolveComptimeValue(unit, context, Type.Expect.none, .{}, node.left, null, .right, &.{});
const left_type = left.getType(unit); const left_type = left.getType(unit);
const right = try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = left_type }, .{}, node.right, null, .right); const right = try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = left_type }, .{}, node.right, null, .right, &.{});
switch (left) { switch (left) {
.comptime_int => |left_ct_int| { .comptime_int => |left_ct_int| {
assert(left_ct_int.signedness == .unsigned); assert(left_ct_int.signedness == .unsigned);
@ -8988,7 +8951,7 @@ pub const Builder = struct {
.empty_container_literal_guess => { .empty_container_literal_guess => {
assert(node.left != .null); assert(node.left != .null);
assert(node.right != .null); assert(node.right != .null);
const container_type = try builder.resolveType(unit, context, node.left); const container_type = try builder.resolveType(unit, context, node.left, &.{});
const node_list = unit.getNodeList(node.right); const node_list = unit.getNodeList(node.right);
assert(node_list.len == 0); assert(node_list.len == 0);
const result = try builder.resolveContainerLiteral(unit, context, node_list, container_type); const result = try builder.resolveContainerLiteral(unit, context, node_list, container_type);
@ -9159,7 +9122,7 @@ pub const Builder = struct {
const v: V = switch (node.id) { const v: V = switch (node.id) {
.identifier => block: { .identifier => block: {
const identifier = unit.getExpectedTokenBytes(node.token, .identifier); const identifier = unit.getExpectedTokenBytes(node.token, .identifier);
const result = try builder.resolveIdentifier(unit, context, type_expect, identifier, .{}, side); const result = try builder.resolveIdentifier(unit, context, type_expect, identifier, .{}, side, &.{});
break :block result; break :block result;
}, },
.intrinsic => try builder.resolveIntrinsic(unit, context, type_expect, node_index), .intrinsic => try builder.resolveIntrinsic(unit, context, type_expect, node_index),
@ -9579,7 +9542,7 @@ pub const Builder = struct {
} }
}, },
.call => try builder.resolveCall(unit, context, node_index), .call => try builder.resolveCall(unit, context, node_index),
.field_access => try builder.resolveFieldAccess(unit, context, type_expect, node_index, side), .field_access => try builder.resolveFieldAccess(unit, context, type_expect, node_index, side, &.{}),
.number_literal => switch (std.zig.parseNumberLiteral(unit.getExpectedTokenBytes(node.token, .number_literal))) { .number_literal => switch (std.zig.parseNumberLiteral(unit.getExpectedTokenBytes(node.token, .number_literal))) {
.int => |integer_value| switch (type_expect) { .int => |integer_value| switch (type_expect) {
.type => |type_index| switch (unit.types.get(type_index).*) { .type => |type_index| switch (unit.types.get(type_index).*) {
@ -9636,7 +9599,7 @@ pub const Builder = struct {
assert(node.left != .null); assert(node.left != .null);
assert(node.right != .null); assert(node.right != .null);
const initialization_nodes = unit.getNodeList(node.right); const initialization_nodes = unit.getNodeList(node.right);
const container_type_index = try builder.resolveType(unit, context, node.left); const container_type_index = try builder.resolveType(unit, context, node.left, &.{});
const result = try builder.resolveContainerLiteral(unit, context, initialization_nodes, container_type_index); const result = try builder.resolveContainerLiteral(unit, context, initialization_nodes, container_type_index);
break :block result; break :block result;
@ -11178,12 +11141,12 @@ pub const Builder = struct {
.struct_type => .@"struct", .struct_type => .@"struct",
.bitfield_type => .bitfield, .bitfield_type => .bitfield,
else => unreachable, else => unreachable,
}, unreachable), }, unreachable, &.{}),
}, },
.empty_container_literal_guess => { .empty_container_literal_guess => {
assert(node.left != .null); assert(node.left != .null);
assert(node.right != .null); assert(node.right != .null);
const container_type = try builder.resolveType(unit, context, node.left); const container_type = try builder.resolveType(unit, context, node.left, &.{});
const node_list = unit.getNodeList(node.right); const node_list = unit.getNodeList(node.right);
assert(node_list.len == 0); assert(node_list.len == 0);
const result = try builder.resolveContainerLiteral(unit, context, node_list, container_type); const result = try builder.resolveContainerLiteral(unit, context, node_list, container_type);
@ -11954,7 +11917,7 @@ pub const Builder = struct {
const look_in_parent_scopes = false; const look_in_parent_scopes = false;
if (container_scope.lookupDeclaration(right_identifier_hash, look_in_parent_scopes)) |lookup| { if (container_scope.lookupDeclaration(right_identifier_hash, look_in_parent_scopes)) |lookup| {
const global = try builder.referenceGlobalDeclaration(unit, context, lookup.scope, lookup.declaration, .{}); const global = try builder.referenceGlobalDeclaration(unit, context, lookup.scope, lookup.declaration, .{}, &.{});
switch (global.initial_value) { switch (global.initial_value) {
.function_definition, .function_declaration => { .function_definition, .function_declaration => {
const value = V{ const value = V{
@ -11986,7 +11949,7 @@ pub const Builder = struct {
} else { } else {
const look_in_parent_scopes = false; const look_in_parent_scopes = false;
if (struct_type.scope.scope.lookupDeclaration(right_identifier_hash, look_in_parent_scopes)) |lookup| { if (struct_type.scope.scope.lookupDeclaration(right_identifier_hash, look_in_parent_scopes)) |lookup| {
const right_symbol = try builder.referenceGlobalDeclaration(unit, context, lookup.scope, lookup.declaration, .{}); const right_symbol = try builder.referenceGlobalDeclaration(unit, context, lookup.scope, lookup.declaration, .{}, &.{});
switch (right_symbol.initial_value) { switch (right_symbol.initial_value) {
.function_definition => { .function_definition => {
const function_type_index = right_symbol.declaration.type; const function_type_index = right_symbol.declaration.type;
@ -12094,7 +12057,7 @@ pub const Builder = struct {
} else { } else {
const look_in_parent_scopes = false; const look_in_parent_scopes = false;
if (struct_type.scope.scope.lookupDeclaration(right_identifier_hash, look_in_parent_scopes)) |lookup| { if (struct_type.scope.scope.lookupDeclaration(right_identifier_hash, look_in_parent_scopes)) |lookup| {
const right_symbol = try builder.referenceGlobalDeclaration(unit, context, lookup.scope, lookup.declaration, .{}); const right_symbol = try builder.referenceGlobalDeclaration(unit, context, lookup.scope, lookup.declaration, .{}, &.{});
switch (right_symbol.initial_value) { switch (right_symbol.initial_value) {
.function_definition => { .function_definition => {
const function_type_index = right_symbol.declaration.type; const function_type_index = right_symbol.declaration.type;
@ -12254,7 +12217,7 @@ pub const Builder = struct {
}, },
.identifier => blk: { .identifier => blk: {
const identifier = unit.getExpectedTokenBytes(left_node.token, .identifier); const identifier = unit.getExpectedTokenBytes(left_node.token, .identifier);
const result = try builder.resolveIdentifier(unit, context, Type.Expect.none, identifier, .{}, .left); const result = try builder.resolveIdentifier(unit, context, Type.Expect.none, identifier, .{}, .left, &.{});
break :blk switch (result.value) { break :blk switch (result.value) {
.@"comptime" => |ct| switch (ct) { .@"comptime" => |ct| switch (ct) {
.global => |global| switch (global.initial_value) { .global => |global| switch (global.initial_value) {
@ -12909,7 +12872,7 @@ pub const Builder = struct {
const type_node_index = metadata_node.left; const type_node_index = metadata_node.left;
assert(metadata_node.right == .null); assert(metadata_node.right == .null);
const type_expect = Type.Expect{ const type_expect = Type.Expect{
.type = try builder.resolveType(unit, context, type_node_index), .type = try builder.resolveType(unit, context, type_node_index, &.{}),
}; };
break :b type_expect; break :b type_expect;
}, },
@ -13732,7 +13695,7 @@ pub const Builder = struct {
fn resolveComptimeSwitch(builder: *Builder, unit: *Unit, context: *const Context, type_expect: Type.Expect, global_attributes: Debug.Declaration.Global.Attributes, node_index: Node.Index, maybe_global: ?*Debug.Declaration.Global) !V.Comptime { fn resolveComptimeSwitch(builder: *Builder, unit: *Unit, context: *const Context, type_expect: Type.Expect, global_attributes: Debug.Declaration.Global.Attributes, node_index: Node.Index, maybe_global: ?*Debug.Declaration.Global) !V.Comptime {
const node = unit.getNode(node_index); const node = unit.getNode(node_index);
assert(node.id == .@"switch"); assert(node.id == .@"switch");
const expression_to_switch_on = try builder.resolveComptimeValue(unit, context, Type.Expect.none, .{}, node.left, null, .right); const expression_to_switch_on = try builder.resolveComptimeValue(unit, context, Type.Expect.none, .{}, node.left, null, .right, &.{});
const case_nodes = unit.getNodeList(node.right); const case_nodes = unit.getNodeList(node.right);
switch (expression_to_switch_on) { switch (expression_to_switch_on) {
.enum_value => |enum_field_index| { .enum_value => |enum_field_index| {
@ -13750,7 +13713,7 @@ pub const Builder = struct {
}; };
} else typecheck_enum_result.else_switch_case_group_index orelse unreachable; } else typecheck_enum_result.else_switch_case_group_index orelse unreachable;
const true_switch_case_node = unit.getNode(case_nodes[group_index]); const true_switch_case_node = unit.getNode(case_nodes[group_index]);
return try builder.resolveComptimeValue(unit, context, type_expect, global_attributes, true_switch_case_node.right, maybe_global, .right); return try builder.resolveComptimeValue(unit, context, type_expect, global_attributes, true_switch_case_node.right, maybe_global, .right, &.{});
}, },
.bool => |boolean| { .bool => |boolean| {
assert(case_nodes.len == 2); assert(case_nodes.len == 2);
@ -13758,11 +13721,11 @@ pub const Builder = struct {
const case_node = unit.getNode(case_node_index); const case_node = unit.getNode(case_node_index);
assert(case_node.left != .null); assert(case_node.left != .null);
assert(case_node.right != .null); assert(case_node.right != .null);
const boolean_value = try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = .bool }, .{}, case_node.left, null, .right); const boolean_value = try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = .bool }, .{}, case_node.left, null, .right, &.{});
switch (boolean_value) { switch (boolean_value) {
.bool => |case_boolean| { .bool => |case_boolean| {
if (case_boolean == boolean) { if (case_boolean == boolean) {
return try builder.resolveComptimeValue(unit, context, type_expect, global_attributes, case_node.right, maybe_global, .right); return try builder.resolveComptimeValue(unit, context, type_expect, global_attributes, case_node.right, maybe_global, .right, &.{});
} }
}, },
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
@ -13807,7 +13770,7 @@ pub const Builder = struct {
const case_node = unit.getNode(case_node_index); const case_node = unit.getNode(case_node_index);
assert(case_node.left != .null); assert(case_node.left != .null);
assert(case_node.right != .null); assert(case_node.right != .null);
const boolean_value = try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = .bool }, .{}, case_node.left, null, .right); const boolean_value = try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = .bool }, .{}, case_node.left, null, .right, &.{});
switch (boolean_value) { switch (boolean_value) {
.bool => |case_boolean| { .bool => |case_boolean| {
if (case_boolean == boolean) { if (case_boolean == boolean) {
@ -13866,12 +13829,12 @@ pub const Builder = struct {
const condition_nodes = unit.getNodeListFromNode(condition_node); const condition_nodes = unit.getNodeListFromNode(condition_node);
try conditions.ensure_capacity(context.my_allocator, @intCast(condition_nodes.len)); try conditions.ensure_capacity(context.my_allocator, @intCast(condition_nodes.len));
for (condition_nodes) |condition_node_index| { for (condition_nodes) |condition_node_index| {
const condition = try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = condition_type }, .{}, condition_node_index, null, .right); const condition = try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = condition_type }, .{}, condition_node_index, null, .right, &.{});
conditions.append_with_capacity(condition); conditions.append_with_capacity(condition);
} }
}, },
else => { else => {
const v = try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = condition_type }, .{}, case_node.left, null, .right); const v = try builder.resolveComptimeValue(unit, context, Type.Expect{ .type = condition_type }, .{}, case_node.left, null, .right, &.{});
try conditions.ensure_capacity(context.my_allocator, 1); try conditions.ensure_capacity(context.my_allocator, 1);
conditions.append_with_capacity(v); conditions.append_with_capacity(v);
}, },
@ -13927,7 +13890,7 @@ pub const Builder = struct {
} }
} }
fn resolveFieldAccess(builder: *Builder, unit: *Unit, context: *const Context, type_expect: Type.Expect, node_index: Node.Index, side: Side) !V { fn resolveFieldAccess(builder: *Builder, unit: *Unit, context: *const Context, type_expect: Type.Expect, node_index: Node.Index, side: Side, new_parameters: []const V.Comptime) !V {
const node = unit.getNode(node_index); const node = unit.getNode(node_index);
const right_node = unit.getNode(node.right); const right_node = unit.getNode(node.right);
assert(right_node.id == .identifier); assert(right_node.id == .identifier);
@ -13945,7 +13908,7 @@ pub const Builder = struct {
const look_in_parent_scopes = false; const look_in_parent_scopes = false;
const result: V = if (scope.lookupDeclaration(identifier_hash, look_in_parent_scopes)) |lookup| blk: { const result: V = if (scope.lookupDeclaration(identifier_hash, look_in_parent_scopes)) |lookup| blk: {
const global = try builder.referenceGlobalDeclaration(unit, context, lookup.scope, lookup.declaration, .{}); const global = try builder.referenceGlobalDeclaration(unit, context, lookup.scope, lookup.declaration, .{}, new_parameters);
const pointer_type = try unit.getPointerType(context, .{ const pointer_type = try unit.getPointerType(context, .{
.type = global.declaration.type, .type = global.declaration.type,
.termination = .none, .termination = .none,
@ -14739,11 +14702,6 @@ pub const Builder = struct {
const function_definition = unit.function_definitions.get(builder.current_function); const function_definition = unit.function_definitions.get(builder.current_function);
const function_prototype_index = unit.types.get(function_definition.type).function; const function_prototype_index = unit.types.get(function_definition.type).function;
const function_prototype = unit.function_prototypes.get(function_prototype_index); const function_prototype = unit.function_prototypes.get(function_prototype_index);
// const LowerKind = union(enum){
// direct,
// direct_pair: [2]Type.Index,
// };
// _ = LowerKind; // autofix
const abi_value = switch (function_prototype.abi.return_type_abi.kind) { const abi_value = switch (function_prototype.abi.return_type_abi.kind) {
.direct, .ignore => value, .direct, .ignore => value,
.direct_pair => |pair| b: { .direct_pair => |pair| b: {
@ -16031,13 +15989,6 @@ pub const Unit = struct {
return type_index; return type_index;
} }
} }
fn getPolymorphicTypes(unit: *Unit, type_index: Type.Index) []const Type.Index {
const ty = unit.types.get(type_index);
return switch (ty.*) {
else => |t| @panic(@tagName(t)),
};
}
}; };
pub const FixedKeyword = enum { pub const FixedKeyword = enum {

View File

@ -23,11 +23,14 @@ pub fn build(b: *std.Build) !void {
const self_hosted_ci = b.option(bool, "self_hosted_ci", "This option enables the self-hosted CI behavior") orelse false; const self_hosted_ci = b.option(bool, "self_hosted_ci", "This option enables the self-hosted CI behavior") orelse false;
const third_party_ci = b.option(bool, "third_party_ci", "This option enables the third-party CI behavior") orelse false; const third_party_ci = b.option(bool, "third_party_ci", "This option enables the third-party CI behavior") orelse false;
const is_ci = self_hosted_ci or third_party_ci; const is_ci = self_hosted_ci or third_party_ci;
const print_stack_trace = b.option(bool, "print_stack_trace", "This option enables printing stack traces inside the compiler") orelse is_ci or os == .macos; const print_stack_trace = b.option(bool, "print_stack_trace", "This option enables printing stack traces inside the compiler") orelse is_ci; //or os == .macos;
const native_target = b.resolveTargetQuery(.{}); const native_target = b.resolveTargetQuery(.{});
const optimization = b.standardOptimizeOption(.{}); const optimization = b.standardOptimizeOption(.{});
const use_debug = b.option(bool, "use_debug", "This option enables the LLVM debug build in the development PC") orelse false; const use_debug = b.option(bool, "use_debug", "This option enables the LLVM debug build in the development PC") orelse false;
const static = b.option(bool, "static", "This option enables the compiler to be built statically") orelse use_debug; const static = b.option(bool, "static", "This option enables the compiler to be built statically") orelse switch (@import("builtin").os.tag) {
else => use_debug,
.macos => true,
};
const compiler_options = b.addOptions(); const compiler_options = b.addOptions();
compiler_options.addOption(bool, "print_stack_trace", print_stack_trace); compiler_options.addOption(bool, "print_stack_trace", print_stack_trace);