Merge pull request #126 from birth-software/polymorphic-type-sketch
First polymorphic type implementation
This commit is contained in:
commit
2343a1ff4e
@ -3222,6 +3222,7 @@ 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,
|
||||||
@ -3837,10 +3838,6 @@ pub const Struct = struct {
|
|||||||
|
|
||||||
pub const Kind = union(enum) {
|
pub const Kind = union(enum) {
|
||||||
@"struct": Struct.Descriptor,
|
@"struct": Struct.Descriptor,
|
||||||
@"union": struct {
|
|
||||||
scope: Debug.Scope.Global,
|
|
||||||
fields: UnpinnedArray(Struct.Field.Index) = .{},
|
|
||||||
},
|
|
||||||
error_union: struct {
|
error_union: struct {
|
||||||
@"error": Type.Index,
|
@"error": Type.Index,
|
||||||
type: Type.Index,
|
type: Type.Index,
|
||||||
@ -3864,11 +3861,21 @@ pub const Struct = struct {
|
|||||||
};
|
};
|
||||||
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,
|
||||||
@ -4509,7 +4516,7 @@ pub const Builder = struct {
|
|||||||
// TODO: depends? .right is not always the right choice
|
// TODO: depends? .right is not always the right choice
|
||||||
const v = try builder.resolveRuntimeValue(unit, context, Type.Expect.none, argument_node_index, .right);
|
const v = try builder.resolveRuntimeValue(unit, context, Type.Expect.none, argument_node_index, .right);
|
||||||
|
|
||||||
const cast_id: Instruction.Cast.Id = switch (type_expect) {
|
switch (type_expect) {
|
||||||
.type => |type_index| {
|
.type => |type_index| {
|
||||||
const cast_id = try builder.resolveCast(unit, context, type_index, v);
|
const cast_id = try builder.resolveCast(unit, context, type_index, v);
|
||||||
switch (cast_id) {
|
switch (cast_id) {
|
||||||
@ -4534,9 +4541,7 @@ pub const Builder = struct {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
}
|
||||||
_ = cast_id; // autofix
|
|
||||||
|
|
||||||
},
|
},
|
||||||
.size => {
|
.size => {
|
||||||
assert(argument_node_list.len == 1);
|
assert(argument_node_list.len == 1);
|
||||||
@ -6512,12 +6517,127 @@ pub const Builder = struct {
|
|||||||
break :blk unit.all_errors;
|
break :blk unit.all_errors;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// This is a data structures with parameters
|
||||||
|
.call => b: {
|
||||||
|
const parameterized_type_index = try builder.resolveType(unit, context, node.left);
|
||||||
|
const parameter_nodes = unit.getNodeList(node.right);
|
||||||
|
var parameter_types = UnpinnedArray(Type.Index){};
|
||||||
|
|
||||||
|
for (parameter_nodes) |parameter_node_index| {
|
||||||
|
const parameter_node = unit.getNode(parameter_node_index);
|
||||||
|
switch (parameter_node.id) {
|
||||||
|
.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);
|
||||||
|
break :b instantiated_type_index;
|
||||||
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
|
|
||||||
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);
|
||||||
@ -7502,11 +7622,39 @@ pub const Builder = struct {
|
|||||||
.@"struct" => b: {
|
.@"struct" => b: {
|
||||||
assert(container_node.id == .struct_type);
|
assert(container_node.id == .struct_type);
|
||||||
|
|
||||||
var struct_options = Struct.Options{};
|
const struct_index = try unit.structs.append(context.my_allocator, .{
|
||||||
|
.kind = .{
|
||||||
|
.@"struct" = .{
|
||||||
|
.scope = .{
|
||||||
|
.scope = .{
|
||||||
|
.kind = switch (builder.current_scope.kind) {
|
||||||
|
.file => .file_container,
|
||||||
|
else => .container,
|
||||||
|
},
|
||||||
|
.line = token_debug_info.line,
|
||||||
|
.column = token_debug_info.column,
|
||||||
|
.level = builder.current_scope.level + 1,
|
||||||
|
.local = false,
|
||||||
|
.file = builder.current_file,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.options = .{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const type_index = try unit.types.append(context.my_allocator, .{
|
||||||
|
.@"struct" = struct_index,
|
||||||
|
});
|
||||||
|
|
||||||
|
const struct_type = unit.structs.get(struct_index);
|
||||||
|
const struct_options = & struct_type.kind.@"struct".options;
|
||||||
|
|
||||||
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){};
|
||||||
|
|
||||||
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);
|
||||||
switch (struct_option_node.id) {
|
switch (struct_option_node.id) {
|
||||||
@ -7538,37 +7686,48 @@ pub const Builder = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
.comptime_expression => {
|
||||||
|
assert(struct_option_node.left != .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);
|
||||||
|
assert(left.id == .identifier);
|
||||||
|
const identifier = unit.getExpectedTokenBytes(left.token, .identifier);
|
||||||
|
const hash = try unit.processIdentifier(context, identifier);
|
||||||
|
const polymorphic_type_index = try unit.types.append(context.my_allocator, .{
|
||||||
|
.polymorphic = undefined,
|
||||||
|
});
|
||||||
|
const global_declaration_index = try unit.global_declarations.append(context.my_allocator, .{
|
||||||
|
.declaration = .{
|
||||||
|
.scope = &struct_type.kind.@"struct".scope.scope,
|
||||||
|
.name = hash,
|
||||||
|
.type = .type,
|
||||||
|
.line = declaration_token_debug_info.line,
|
||||||
|
.column = declaration_token_debug_info.column,
|
||||||
|
.mutability = .@"const",
|
||||||
|
.kind = .global,
|
||||||
|
},
|
||||||
|
.initial_value = .{
|
||||||
|
.type = polymorphic_type_index,
|
||||||
|
},
|
||||||
|
.type_node_index = .null,
|
||||||
|
.attributes = .{},
|
||||||
|
});
|
||||||
|
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);
|
||||||
|
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)),
|
else => |t| @panic(@tagName(t)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct_type.kind.@"struct".options.polymorphism_kind = .{
|
||||||
|
.declaration = parameter_types.slice(),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct_index = try unit.structs.append(context.my_allocator, .{
|
|
||||||
.kind = .{
|
|
||||||
.@"struct" = .{
|
|
||||||
.scope = .{
|
|
||||||
.scope = .{
|
|
||||||
.kind = switch (builder.current_scope.kind) {
|
|
||||||
.file => .file_container,
|
|
||||||
else => .container,
|
|
||||||
},
|
|
||||||
.line = token_debug_info.line,
|
|
||||||
.column = token_debug_info.column,
|
|
||||||
.level = builder.current_scope.level + 1,
|
|
||||||
.local = false,
|
|
||||||
.file = builder.current_file,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
.options = struct_options,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const struct_type = unit.structs.get(struct_index);
|
|
||||||
|
|
||||||
const type_index = try unit.types.append(context.my_allocator, .{
|
|
||||||
.@"struct" = struct_index,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Save file type
|
// Save file type
|
||||||
switch (builder.current_scope.kind) {
|
switch (builder.current_scope.kind) {
|
||||||
.file => {
|
.file => {
|
||||||
@ -8681,6 +8840,26 @@ pub const Builder = struct {
|
|||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
.cast => {
|
||||||
|
assert(argument_node_list.len == 1);
|
||||||
|
switch (type_expect) {
|
||||||
|
.type => |type_index| {
|
||||||
|
const value = try builder.resolveComptimeValue(unit, context, Type.Expect.none, .{}, argument_node_list[0], null, .right);
|
||||||
|
const ty = unit.types.get(type_index);
|
||||||
|
switch (ty.*) {
|
||||||
|
.pointer => |_| switch (value) {
|
||||||
|
.@"comptime_int" => |ct_int| switch (ct_int.value) {
|
||||||
|
0 => return .null_pointer,
|
||||||
|
else => unreachable,
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
}
|
||||||
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -10988,6 +11167,15 @@ pub const Builder = struct {
|
|||||||
else => unreachable,
|
else => unreachable,
|
||||||
}, unreachable),
|
}, unreachable),
|
||||||
},
|
},
|
||||||
|
.empty_container_literal_guess => {
|
||||||
|
assert(node.left != .null);
|
||||||
|
assert(node.right != .null);
|
||||||
|
const container_type = try builder.resolveType(unit, context, node.left);
|
||||||
|
const node_list = unit.getNodeList(node.right);
|
||||||
|
assert(node_list.len == 0);
|
||||||
|
const result = try builder.resolveContainerLiteral(unit, context, node_list, container_type);
|
||||||
|
return result;
|
||||||
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -15832,6 +16020,13 @@ 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 {
|
||||||
@ -15854,7 +16049,6 @@ pub const FixedKeyword = enum {
|
|||||||
@"else",
|
@"else",
|
||||||
@"struct",
|
@"struct",
|
||||||
@"enum",
|
@"enum",
|
||||||
@"union",
|
|
||||||
null,
|
null,
|
||||||
@"align",
|
@"align",
|
||||||
@"for",
|
@"for",
|
||||||
|
@ -196,6 +196,7 @@ pub const Node = struct {
|
|||||||
payload,
|
payload,
|
||||||
catch_payload,
|
catch_payload,
|
||||||
bitfield_type,
|
bitfield_type,
|
||||||
|
comptime_expression,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1210,6 +1211,7 @@ const Analyzer = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn primaryExpression(analyzer: *Analyzer) !Node.Index {
|
fn primaryExpression(analyzer: *Analyzer) !Node.Index {
|
||||||
|
const token = analyzer.token_i;
|
||||||
const result = switch (analyzer.peekToken()) {
|
const result = switch (analyzer.peekToken()) {
|
||||||
.identifier => switch (analyzer.peekTokenAhead(1)) {
|
.identifier => switch (analyzer.peekTokenAhead(1)) {
|
||||||
// TODO: tags
|
// TODO: tags
|
||||||
@ -1244,7 +1246,6 @@ const Analyzer = struct {
|
|||||||
.fixed_keyword_return => try analyzer.addNode(.{
|
.fixed_keyword_return => try analyzer.addNode(.{
|
||||||
.id = .@"return",
|
.id = .@"return",
|
||||||
.token = blk: {
|
.token = blk: {
|
||||||
const token = analyzer.token_i;
|
|
||||||
analyzer.consumeToken();
|
analyzer.consumeToken();
|
||||||
break :blk token;
|
break :blk token;
|
||||||
},
|
},
|
||||||
@ -1256,6 +1257,16 @@ const Analyzer = struct {
|
|||||||
.operator_left_brace => try analyzer.block(),
|
.operator_left_brace => try analyzer.block(),
|
||||||
.fixed_keyword_if => try analyzer.ifExpression(),
|
.fixed_keyword_if => try analyzer.ifExpression(),
|
||||||
.fixed_keyword_bitfield => try analyzer.processContainerType(.fixed_keyword_bitfield),
|
.fixed_keyword_bitfield => try analyzer.processContainerType(.fixed_keyword_bitfield),
|
||||||
|
.operator_dollar => blk: {
|
||||||
|
analyzer.consumeToken();
|
||||||
|
const t = try analyzer.typeExpression();
|
||||||
|
break :blk try analyzer.addNode(.{
|
||||||
|
.id = .comptime_expression,
|
||||||
|
.token = token,
|
||||||
|
.left = t,
|
||||||
|
.right = .null,
|
||||||
|
});
|
||||||
|
},
|
||||||
else => |id| @panic(@tagName(id)),
|
else => |id| @panic(@tagName(id)),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1653,7 +1664,7 @@ const Analyzer = struct {
|
|||||||
const initialization: InitializationType = current_initialization orelse switch (type_node) {
|
const initialization: InitializationType = current_initialization orelse switch (type_node) {
|
||||||
.null => .empty_literal,
|
.null => .empty_literal,
|
||||||
else => switch (analyzer.nodes.get(type_node).id) {
|
else => switch (analyzer.nodes.get(type_node).id) {
|
||||||
.identifier => .empty_container_literal_guess,
|
.identifier, .call => .empty_container_literal_guess,
|
||||||
.array_type => .empty_array_literal,
|
.array_type => .empty_array_literal,
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
},
|
},
|
||||||
|
1
lib/std/data_structures.nat
Normal file
1
lib/std/data_structures.nat
Normal file
@ -0,0 +1 @@
|
|||||||
|
const PinnedArray = #import("data_structures/pinned_array.nat").PinnedArray;
|
5
lib/std/data_structures/pinned_array.nat
Normal file
5
lib/std/data_structures/pinned_array.nat
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
const PinnedArray = struct(.{ .sliceable = true }, $T) {
|
||||||
|
pointer: [&]T = #cast(0),
|
||||||
|
length: u32 = 0,
|
||||||
|
capacity: u32 = 0,
|
||||||
|
};
|
@ -5,17 +5,22 @@ comptime {
|
|||||||
test {
|
test {
|
||||||
_ = build;
|
_ = build;
|
||||||
_ = builtin;
|
_ = builtin;
|
||||||
|
_ = data_structures;
|
||||||
_ = os;
|
_ = os;
|
||||||
_ = start;
|
_ = start;
|
||||||
}
|
}
|
||||||
|
|
||||||
const build = #import("build.nat");
|
const build = #import("build.nat");
|
||||||
const builtin = #import("builtin.nat");
|
const builtin = #import("builtin.nat");
|
||||||
const os = #import("os.nat");
|
|
||||||
const c = #import("c.nat");
|
|
||||||
const start = #import("start.nat");
|
|
||||||
const testing = #import("testing.nat");
|
const testing = #import("testing.nat");
|
||||||
|
|
||||||
|
const data_structures = #import("data_structures.nat");
|
||||||
|
|
||||||
|
const c = #import("c.nat");
|
||||||
|
const os = #import("os.nat");
|
||||||
|
|
||||||
|
const start = #import("start.nat");
|
||||||
|
|
||||||
const assert = fn(ok: bool) void {
|
const assert = fn(ok: bool) void {
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
unreachable;
|
unreachable;
|
||||||
|
6
test/standalone/pinned_array/main.nat
Normal file
6
test/standalone/pinned_array/main.nat
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
const std = #import("std");
|
||||||
|
const PinnedArray = std.data_structures.PinnedArray;
|
||||||
|
|
||||||
|
const main = fn () *!void {
|
||||||
|
var pinned_array = PinnedArray(u32){};
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user