Introduce file writer
This commit is contained in:
parent
a18564c8e3
commit
3074411608
@ -214,12 +214,12 @@ pub const ContainerInitialization = struct {
|
|||||||
pub const Enum = struct {
|
pub const Enum = struct {
|
||||||
scope: Scope.Index,
|
scope: Scope.Index,
|
||||||
fields: ArrayList(Enum.Field.Index) = .{},
|
fields: ArrayList(Enum.Field.Index) = .{},
|
||||||
type: Type.Index,
|
backing_type: Type.Index,
|
||||||
|
|
||||||
pub const Field = struct {
|
pub const Field = struct {
|
||||||
name: u32,
|
name: u32,
|
||||||
value: Value.Index,
|
value: Value.Index,
|
||||||
parent: Enum.Index,
|
parent: Type.Index,
|
||||||
|
|
||||||
pub const List = BlockList(@This());
|
pub const List = BlockList(@This());
|
||||||
pub const Index = Enum.Field.List.Index;
|
pub const Index = Enum.Field.List.Index;
|
||||||
@ -816,7 +816,7 @@ pub const Value = union(enum) {
|
|||||||
.declaration_reference => |declaration_reference| declaration_reference.type,
|
.declaration_reference => |declaration_reference| declaration_reference.type,
|
||||||
.string_literal => |string_literal| string_literal.type,
|
.string_literal => |string_literal| string_literal.type,
|
||||||
.type => Type.type,
|
.type => Type.type,
|
||||||
.enum_field => |enum_field_index| module.types.enums.get(module.types.enum_fields.get(enum_field_index).parent).type,
|
.enum_field => |enum_field_index| module.types.enum_fields.get(enum_field_index).parent,
|
||||||
.function_definition => |function_index| module.types.function_definitions.get(function_index).prototype,
|
.function_definition => |function_index| module.types.function_definitions.get(function_index).prototype,
|
||||||
.function_declaration => |function_index| module.types.function_declarations.get(function_index).prototype,
|
.function_declaration => |function_index| module.types.function_declarations.get(function_index).prototype,
|
||||||
.binary_operation => |binary_operation| module.values.binary_operations.get(binary_operation).type,
|
.binary_operation => |binary_operation| module.values.binary_operations.get(binary_operation).type,
|
||||||
@ -1237,7 +1237,10 @@ pub fn compileModule(compilation: *Compilation, descriptor: Module.Descriptor) !
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generateAST() !void {}
|
pub const ContainerType = enum {
|
||||||
|
@"struct",
|
||||||
|
@"enum",
|
||||||
|
};
|
||||||
|
|
||||||
pub const Directory = struct {
|
pub const Directory = struct {
|
||||||
handle: std.fs.Dir,
|
handle: std.fs.Dir,
|
||||||
|
@ -35,6 +35,7 @@ pub const TranslationUnit = struct {
|
|||||||
function_set: AutoArrayHashMap(Compilation.Function.Index, []const u8) = .{},
|
function_set: AutoArrayHashMap(Compilation.Function.Index, []const u8) = .{},
|
||||||
slice_type_set: AutoArrayHashMap(Compilation.Type.Index, []const u8) = .{},
|
slice_type_set: AutoArrayHashMap(Compilation.Type.Index, []const u8) = .{},
|
||||||
array_type_set: AutoArrayHashMap(Compilation.Type.Index, []const u8) = .{},
|
array_type_set: AutoArrayHashMap(Compilation.Type.Index, []const u8) = .{},
|
||||||
|
enum_type_set: AutoArrayHashMap(Compilation.Type.Index, []const u8) = .{},
|
||||||
declaration_set: AutoArrayHashMap(Compilation.Declaration.Index, []const u8) = .{},
|
declaration_set: AutoArrayHashMap(Compilation.Declaration.Index, []const u8) = .{},
|
||||||
|
|
||||||
const SyscallBitset = std.StaticBitSet(6);
|
const SyscallBitset = std.StaticBitSet(6);
|
||||||
@ -76,15 +77,15 @@ pub const TranslationUnit = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn writeFunctionDefinition(unit: *TranslationUnit, module: *Module, allocator: Allocator, function_definition_index: Compilation.Function.Index) ![]const u8 {
|
fn writeFunctionDefinition(unit: *TranslationUnit, module: *Module, allocator: Allocator, function_definition_index: Compilation.Function.Index) ![]const u8 {
|
||||||
const gop = try unit.function_set.getOrPut(allocator, function_definition_index);
|
if (unit.function_set.getIndex(function_definition_index)) |index| {
|
||||||
|
return unit.function_set.values()[index];
|
||||||
if (!gop.found_existing) {
|
} else {
|
||||||
const function_definition = module.types.function_definitions.get(function_definition_index);
|
const function_definition = module.types.function_definitions.get(function_definition_index);
|
||||||
const function_prototype_type = function_definition.prototype;
|
const function_prototype_type = function_definition.prototype;
|
||||||
const function_prototype = module.types.function_prototypes.get(module.types.array.get(function_prototype_type).function);
|
const function_prototype = module.types.function_prototypes.get(module.types.array.get(function_prototype_type).function);
|
||||||
|
|
||||||
const function_name = try unit.writeFunctionHeader(module, &unit.function_declarations, allocator, function_definition_index);
|
const function_name = try unit.writeFunctionHeader(module, &unit.function_declarations, allocator, function_definition_index);
|
||||||
gop.value_ptr.* = function_name;
|
try unit.function_set.putNoClobber(allocator, function_definition_index, function_name);
|
||||||
|
|
||||||
_ = try unit.writeFunctionHeader(module, &unit.function_definitions, allocator, function_definition_index);
|
_ = try unit.writeFunctionHeader(module, &unit.function_definitions, allocator, function_definition_index);
|
||||||
try unit.function_declarations.appendSlice(allocator, ";\n\n");
|
try unit.function_declarations.appendSlice(allocator, ";\n\n");
|
||||||
@ -92,9 +93,9 @@ pub const TranslationUnit = struct {
|
|||||||
try unit.function_definitions.append(allocator, ' ');
|
try unit.function_definitions.append(allocator, ' ');
|
||||||
try unit.writeBlock(module, &unit.function_definitions, allocator, function_definition.body, function_prototype.return_type, 0);
|
try unit.writeBlock(module, &unit.function_definitions, allocator, function_definition.body, function_prototype.return_type, 0);
|
||||||
try unit.function_definitions.append(allocator, '\n');
|
try unit.function_definitions.append(allocator, '\n');
|
||||||
}
|
|
||||||
|
|
||||||
return gop.value_ptr.*;
|
return function_name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writeDeclaration(unit: *TranslationUnit, module: *Module, list: *ArrayList(u8), allocator: Allocator, declaration_index: Compilation.Declaration.Index, indentation: usize) !void {
|
fn writeDeclaration(unit: *TranslationUnit, module: *Module, list: *ArrayList(u8), allocator: Allocator, declaration_index: Compilation.Declaration.Index, indentation: usize) !void {
|
||||||
@ -324,9 +325,9 @@ pub const TranslationUnit = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn renderDeclarationName(unit: *TranslationUnit, module: *Module, allocator: Allocator, declaration_index: Compilation.Declaration.Index, mangle: bool) anyerror![]const u8 {
|
fn renderDeclarationName(unit: *TranslationUnit, module: *Module, allocator: Allocator, declaration_index: Compilation.Declaration.Index, mangle: bool) anyerror![]const u8 {
|
||||||
const gop = try unit.declaration_set.getOrPut(allocator, declaration_index);
|
if (unit.declaration_set.getIndex(declaration_index)) |index| {
|
||||||
|
return unit.declaration_set.values()[index];
|
||||||
if (!gop.found_existing) {
|
} else {
|
||||||
const declaration = module.values.declarations.get(declaration_index);
|
const declaration = module.values.declarations.get(declaration_index);
|
||||||
const base_declaration_name = module.getName(declaration.name).?;
|
const base_declaration_name = module.getName(declaration.name).?;
|
||||||
var list = ArrayList(u8){};
|
var list = ArrayList(u8){};
|
||||||
@ -362,7 +363,7 @@ pub const TranslationUnit = struct {
|
|||||||
|
|
||||||
// TODO: enhance declaration name rendering with file scope name
|
// TODO: enhance declaration name rendering with file scope name
|
||||||
// const scope = declaration.scope;
|
// const scope = declaration.scope;
|
||||||
gop.value_ptr.* = list.items;
|
try unit.declaration_set.putNoClobber(allocator, declaration_index, list.items);
|
||||||
|
|
||||||
switch (declaration.scope_type) {
|
switch (declaration.scope_type) {
|
||||||
.global => switch (module.types.array.get(declaration.type).*) {
|
.global => switch (module.types.array.get(declaration.type).*) {
|
||||||
@ -378,12 +379,9 @@ pub const TranslationUnit = struct {
|
|||||||
},
|
},
|
||||||
.local => {},
|
.local => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return list.items;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(@intFromPtr(gop.value_ptr.*.ptr) != 0xaaaa_aaaa_aaaa_aaaa);
|
|
||||||
logln(.c, .g, "Rendering name: {s}", .{gop.value_ptr.*});
|
|
||||||
|
|
||||||
return gop.value_ptr.*;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writeFunctionPrototype(unit: *TranslationUnit, module: *Module, list: *ArrayList(u8), allocator: Allocator, function_prototype_index: Compilation.Function.Prototype.Index, name: []const u8) !void {
|
fn writeFunctionPrototype(unit: *TranslationUnit, module: *Module, list: *ArrayList(u8), allocator: Allocator, function_prototype_index: Compilation.Function.Prototype.Index, name: []const u8) !void {
|
||||||
@ -472,6 +470,10 @@ pub const TranslationUnit = struct {
|
|||||||
try list.appendSlice(allocator, name);
|
try list.appendSlice(allocator, name);
|
||||||
},
|
},
|
||||||
.any => @panic("Internal compiler error: 'any' made it to the backend"),
|
.any => @panic("Internal compiler error: 'any' made it to the backend"),
|
||||||
|
.@"enum" => {
|
||||||
|
const name = try unit.cacheEnumType(module, allocator, type_index);
|
||||||
|
try list.appendSlice(allocator, name);
|
||||||
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -557,56 +559,110 @@ pub const TranslationUnit = struct {
|
|||||||
fn cacheStructType(unit: *TranslationUnit, module: *Module, allocator: Allocator, type_index: Compilation.Type.Index) ![]const u8 {
|
fn cacheStructType(unit: *TranslationUnit, module: *Module, allocator: Allocator, type_index: Compilation.Type.Index) ![]const u8 {
|
||||||
const t = module.types.array.get(type_index);
|
const t = module.types.array.get(type_index);
|
||||||
assert(t.* == .@"struct");
|
assert(t.* == .@"struct");
|
||||||
const gop = try unit.struct_type_set.getOrPut(allocator, type_index);
|
if (unit.struct_type_set.getIndex(type_index)) |index| {
|
||||||
|
return unit.struct_type_set.values()[index];
|
||||||
if (!gop.found_existing) {
|
} else {
|
||||||
const struct_type = module.types.structs.get(t.@"struct");
|
|
||||||
const type_name = try unit.renderTypeName(module, allocator, type_index);
|
const type_name = try unit.renderTypeName(module, allocator, type_index);
|
||||||
gop.value_ptr.* = type_name;
|
logln(.c, .g, "Registering struct {s}: #{}", .{ type_name, type_index.uniqueInteger() });
|
||||||
// Forward declare the struct
|
try unit.struct_type_set.putNoClobber(allocator, type_index, type_name);
|
||||||
{
|
|
||||||
try unit.type_forward_declarations.appendSlice(allocator, "typedef struct ");
|
|
||||||
try unit.type_forward_declarations.appendSlice(allocator, type_name);
|
|
||||||
try unit.type_forward_declarations.append(allocator, ' ');
|
|
||||||
try unit.type_forward_declarations.appendSlice(allocator, type_name);
|
|
||||||
try unit.type_forward_declarations.appendSlice(allocator, ";\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
try unit.forwardDeclareContainerType(allocator, .@"struct", type_name);
|
||||||
|
|
||||||
|
const struct_type = module.types.structs.get(t.@"struct");
|
||||||
// Actually declare the struct
|
// Actually declare the struct
|
||||||
{
|
{
|
||||||
try unit.type_declarations.appendSlice(allocator, "typedef struct ");
|
var list = ArrayList(u8){};
|
||||||
try unit.type_declarations.appendSlice(allocator, type_name);
|
try list.appendSlice(allocator, "typedef struct ");
|
||||||
try unit.type_declarations.appendSlice(allocator, " {\n");
|
try list.appendSlice(allocator, type_name);
|
||||||
|
try list.appendSlice(allocator, " {\n");
|
||||||
|
|
||||||
for (struct_type.fields.items) |struct_field_index| {
|
for (struct_type.fields.items) |struct_field_index| {
|
||||||
try unit.type_declarations.appendNTimes(allocator, ' ', margin_width);
|
try list.appendNTimes(allocator, ' ', margin_width);
|
||||||
|
|
||||||
const struct_field = module.types.container_fields.get(struct_field_index);
|
const struct_field = module.types.container_fields.get(struct_field_index);
|
||||||
const struct_field_name = module.getName(struct_field.name).?;
|
const struct_field_name = module.getName(struct_field.name).?;
|
||||||
|
|
||||||
switch (struct_type.backing_type.invalid) {
|
switch (struct_type.backing_type.invalid) {
|
||||||
false => {
|
false => {
|
||||||
try unit.writeType(module, &unit.type_declarations, allocator, struct_type.backing_type);
|
try unit.writeType(module, &list, allocator, struct_type.backing_type);
|
||||||
try unit.type_declarations.append(allocator, ' ');
|
try list.append(allocator, ' ');
|
||||||
try unit.type_declarations.appendSlice(allocator, struct_field_name);
|
try list.appendSlice(allocator, struct_field_name);
|
||||||
try unit.type_declarations.appendSlice(allocator, " : ");
|
try list.appendSlice(allocator, " : ");
|
||||||
try unit.type_declarations.writer(allocator).print("{}", .{module.types.array.get(struct_field.type).getBitSize()});
|
try list.writer(allocator).print("{}", .{module.types.array.get(struct_field.type).getBitSize()});
|
||||||
},
|
},
|
||||||
true => try unit.writeCDeclaration(module, &unit.type_declarations, allocator, struct_field_name, struct_field.type),
|
true => try unit.writeCDeclaration(module, &list, allocator, struct_field_name, struct_field.type),
|
||||||
}
|
}
|
||||||
|
|
||||||
try unit.type_declarations.appendSlice(allocator, ";\n");
|
try list.appendSlice(allocator, ";\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
try unit.type_declarations.appendSlice(allocator, "} ");
|
try list.appendSlice(allocator, "} ");
|
||||||
try unit.type_declarations.appendSlice(allocator, type_name);
|
try list.appendSlice(allocator, type_name);
|
||||||
try unit.type_declarations.appendSlice(allocator, ";\n\n");
|
try list.appendSlice(allocator, ";\n\n");
|
||||||
|
|
||||||
|
try unit.type_declarations.appendSlice(allocator, list.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
return type_name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(@intFromPtr(gop.value_ptr.*.ptr) != 0xaaaa_aaaa_aaaa_aaaa);
|
fn forwardDeclareContainerType(unit: *TranslationUnit, allocator: Allocator, container_type: Compilation.ContainerType, type_name: []const u8) !void {
|
||||||
|
try unit.type_forward_declarations.appendSlice(allocator, "typedef ");
|
||||||
|
try unit.type_forward_declarations.appendSlice(allocator, @tagName(container_type));
|
||||||
|
try unit.type_forward_declarations.append(allocator, ' ');
|
||||||
|
try unit.type_forward_declarations.appendSlice(allocator, type_name);
|
||||||
|
try unit.type_forward_declarations.append(allocator, ' ');
|
||||||
|
try unit.type_forward_declarations.appendSlice(allocator, type_name);
|
||||||
|
try unit.type_forward_declarations.appendSlice(allocator, ";\n");
|
||||||
|
}
|
||||||
|
|
||||||
return gop.value_ptr.*;
|
fn cacheEnumType(unit: *TranslationUnit, module: *Module, allocator: Allocator, type_index: Compilation.Type.Index) ![]const u8 {
|
||||||
|
if (unit.array_type_set.getIndex(type_index)) |index| {
|
||||||
|
return unit.array_type_set.values()[index];
|
||||||
|
} else {
|
||||||
|
const type_name = try unit.renderTypeName(module, allocator, type_index);
|
||||||
|
logln(.c, .g, "Registering enum {s}: #{}", .{ type_name, type_index.uniqueInteger() });
|
||||||
|
try unit.array_type_set.putNoClobber(allocator, type_index, type_name);
|
||||||
|
|
||||||
|
try unit.forwardDeclareContainerType(allocator, .@"enum", type_name);
|
||||||
|
|
||||||
|
const t = module.types.array.get(type_index);
|
||||||
|
const enum_type = module.types.enums.get(t.@"enum");
|
||||||
|
|
||||||
|
var list = ArrayList(u8){};
|
||||||
|
|
||||||
|
try list.appendSlice(allocator, "typedef enum ");
|
||||||
|
try list.appendSlice(allocator, type_name);
|
||||||
|
try list.appendSlice(allocator, " {\n");
|
||||||
|
|
||||||
|
for (enum_type.fields.items) |enum_field_index| {
|
||||||
|
try list.appendNTimes(allocator, ' ', margin_width);
|
||||||
|
|
||||||
|
const enum_field = module.types.enum_fields.get(enum_field_index);
|
||||||
|
const enum_field_name = module.getName(enum_field.name).?;
|
||||||
|
try list.appendSlice(allocator, type_name);
|
||||||
|
try list.append(allocator, '_');
|
||||||
|
try list.appendSlice(allocator, enum_field_name);
|
||||||
|
|
||||||
|
try list.appendSlice(allocator, " = ");
|
||||||
|
|
||||||
|
try unit.writeValue(module, &list, allocator, Compilation.Type.Index.invalid, 0, .{
|
||||||
|
.value_index = enum_field.value,
|
||||||
|
.type_index = Compilation.Type.usize,
|
||||||
|
});
|
||||||
|
|
||||||
|
try list.appendSlice(allocator, ",\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
try list.appendSlice(allocator, "} ");
|
||||||
|
try list.appendSlice(allocator, type_name);
|
||||||
|
try list.appendSlice(allocator, ";\n\n");
|
||||||
|
|
||||||
|
try unit.type_declarations.appendSlice(allocator, list.items);
|
||||||
|
|
||||||
|
return type_name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cacheOptionalType(unit: *TranslationUnit, module: *Module, allocator: Allocator, type_index: Compilation.Type.Index) ![]const u8 {
|
fn cacheOptionalType(unit: *TranslationUnit, module: *Module, allocator: Allocator, type_index: Compilation.Type.Index) ![]const u8 {
|
||||||
@ -614,121 +670,125 @@ pub const TranslationUnit = struct {
|
|||||||
assert(optional_type.* == .optional);
|
assert(optional_type.* == .optional);
|
||||||
const optional = optional_type.optional;
|
const optional = optional_type.optional;
|
||||||
|
|
||||||
const gop = try unit.optional_type_set.getOrPut(allocator, optional.element_type);
|
if (unit.optional_type_set.getIndex(optional.element_type)) |index| {
|
||||||
|
return unit.optional_type_set.values()[index];
|
||||||
if (!gop.found_existing) {
|
} else {
|
||||||
var type_name = ArrayList(u8){};
|
|
||||||
const optional_element_type = module.types.array.get(optional.element_type);
|
const optional_element_type = module.types.array.get(optional.element_type);
|
||||||
|
|
||||||
switch (optional_element_type.*) {
|
switch (optional_element_type.*) {
|
||||||
.pointer => {
|
.pointer => {
|
||||||
|
var type_name = ArrayList(u8){};
|
||||||
try unit.writeType(module, &type_name, allocator, optional.element_type);
|
try unit.writeType(module, &type_name, allocator, optional.element_type);
|
||||||
|
try unit.optional_type_set.putNoClobber(allocator, optional.element_type, type_name.items);
|
||||||
|
return type_name.items;
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
|
var type_name = ArrayList(u8){};
|
||||||
try type_name.appendSlice(allocator, "Optional_");
|
try type_name.appendSlice(allocator, "Optional_");
|
||||||
try unit.writeType(module, &type_name, allocator, optional.element_type);
|
try unit.writeType(module, &type_name, allocator, optional.element_type);
|
||||||
|
logln(.c, .g, "Registering optional {s}: #{}", .{ type_name.items, type_index.uniqueInteger() });
|
||||||
|
try unit.optional_type_set.putNoClobber(allocator, optional.element_type, type_name.items);
|
||||||
|
|
||||||
if (!gop.found_existing) {
|
try unit.forwardDeclareContainerType(allocator, .@"struct", type_name.items);
|
||||||
try unit.type_forward_declarations.appendSlice(allocator, "typedef struct ");
|
|
||||||
try unit.type_forward_declarations.appendSlice(allocator, type_name.items);
|
|
||||||
try unit.type_forward_declarations.append(allocator, ' ');
|
|
||||||
try unit.type_forward_declarations.appendSlice(allocator, type_name.items);
|
|
||||||
try unit.type_forward_declarations.appendSlice(allocator, ";\n");
|
|
||||||
|
|
||||||
try unit.type_declarations.appendSlice(allocator, "typedef struct ");
|
var list = ArrayList(u8){};
|
||||||
try unit.type_declarations.appendSlice(allocator, type_name.items);
|
|
||||||
try unit.type_declarations.appendSlice(allocator, " {\n");
|
|
||||||
|
|
||||||
try unit.type_declarations.appendNTimes(allocator, ' ', margin_width);
|
try list.appendSlice(allocator, "typedef struct ");
|
||||||
try unit.writeCDeclaration(module, &unit.type_declarations, allocator, "value", optional.element_type);
|
try list.appendSlice(allocator, type_name.items);
|
||||||
try unit.type_declarations.appendSlice(allocator, ";\n");
|
try list.appendSlice(allocator, " {\n");
|
||||||
|
|
||||||
try unit.type_declarations.appendNTimes(allocator, ' ', margin_width);
|
try list.appendNTimes(allocator, ' ', margin_width);
|
||||||
try unit.writeCDeclaration(module, &unit.type_declarations, allocator, "is_null", Compilation.Type.boolean);
|
try unit.writeCDeclaration(module, &list, allocator, "value", optional.element_type);
|
||||||
try unit.type_declarations.appendSlice(allocator, ";\n");
|
try list.appendSlice(allocator, ";\n");
|
||||||
|
|
||||||
try unit.type_declarations.appendSlice(allocator, "} ");
|
try list.appendNTimes(allocator, ' ', margin_width);
|
||||||
try unit.type_declarations.appendSlice(allocator, type_name.items);
|
try unit.writeCDeclaration(module, &list, allocator, "is_null", Compilation.Type.boolean);
|
||||||
try unit.type_declarations.appendSlice(allocator, ";\n\n");
|
try list.appendSlice(allocator, ";\n");
|
||||||
}
|
|
||||||
|
try list.appendSlice(allocator, "} ");
|
||||||
|
try list.appendSlice(allocator, type_name.items);
|
||||||
|
try list.appendSlice(allocator, ";\n\n");
|
||||||
|
|
||||||
|
try unit.type_declarations.appendSlice(allocator, list.items);
|
||||||
|
|
||||||
|
return type_name.items;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
gop.value_ptr.* = type_name.items;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return gop.value_ptr.*;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cacheSliceType(unit: *TranslationUnit, module: *Module, allocator: Allocator, type_index: Compilation.Type.Index) ![]const u8 {
|
fn cacheSliceType(unit: *TranslationUnit, module: *Module, allocator: Allocator, type_index: Compilation.Type.Index) ![]const u8 {
|
||||||
const slice = module.types.array.get(type_index).slice;
|
const slice = module.types.array.get(type_index).slice;
|
||||||
|
|
||||||
const gop = try unit.slice_type_set.getOrPut(allocator, slice.element_type);
|
if (unit.slice_type_set.getIndex(slice.element_type)) |index| {
|
||||||
|
return unit.slice_type_set.values()[index];
|
||||||
if (!gop.found_existing) {
|
} else {
|
||||||
var type_name = ArrayList(u8){};
|
var type_name = ArrayList(u8){};
|
||||||
try type_name.appendSlice(allocator, "Slice_");
|
try type_name.appendSlice(allocator, "Slice_");
|
||||||
try unit.writeType(module, &type_name, allocator, slice.element_type);
|
try unit.writeType(module, &type_name, allocator, slice.element_type);
|
||||||
gop.value_ptr.* = type_name.items;
|
logln(.c, .g, "Registering slice {s}: #{}", .{ type_name.items, type_index.uniqueInteger() });
|
||||||
|
try unit.slice_type_set.putNoClobber(allocator, slice.element_type, type_name.items);
|
||||||
|
|
||||||
try unit.type_forward_declarations.appendSlice(allocator, "typedef struct ");
|
try unit.forwardDeclareContainerType(allocator, .@"struct", type_name.items);
|
||||||
try unit.type_forward_declarations.appendSlice(allocator, type_name.items);
|
|
||||||
try unit.type_forward_declarations.append(allocator, ' ');
|
|
||||||
try unit.type_forward_declarations.appendSlice(allocator, type_name.items);
|
|
||||||
try unit.type_forward_declarations.appendSlice(allocator, ";\n");
|
|
||||||
|
|
||||||
try unit.type_declarations.appendSlice(allocator, "typedef struct ");
|
var list = ArrayList(u8){};
|
||||||
try unit.type_declarations.appendSlice(allocator, type_name.items);
|
|
||||||
try unit.type_declarations.appendSlice(allocator, " {\n");
|
|
||||||
|
|
||||||
try unit.type_declarations.appendNTimes(allocator, ' ', margin_width);
|
try list.appendSlice(allocator, "typedef struct ");
|
||||||
try unit.writeType(module, &unit.type_declarations, allocator, slice.element_type);
|
try list.appendSlice(allocator, type_name.items);
|
||||||
try unit.type_declarations.appendSlice(allocator, "* ptr;\n");
|
try list.appendSlice(allocator, " {\n");
|
||||||
|
|
||||||
try unit.type_declarations.appendNTimes(allocator, ' ', margin_width);
|
try list.appendNTimes(allocator, ' ', margin_width);
|
||||||
try unit.type_declarations.appendSlice(allocator, "usize len;\n");
|
try unit.writeType(module, &list, allocator, slice.element_type);
|
||||||
|
try list.appendSlice(allocator, "* ptr;\n");
|
||||||
|
|
||||||
try unit.type_declarations.appendSlice(allocator, "} ");
|
try list.appendNTimes(allocator, ' ', margin_width);
|
||||||
try unit.type_declarations.appendSlice(allocator, type_name.items);
|
try list.appendSlice(allocator, "usize len;\n");
|
||||||
try unit.type_declarations.appendSlice(allocator, ";\n\n");
|
|
||||||
|
try list.appendSlice(allocator, "} ");
|
||||||
|
try list.appendSlice(allocator, type_name.items);
|
||||||
|
try list.appendSlice(allocator, ";\n\n");
|
||||||
|
|
||||||
|
try unit.type_declarations.appendSlice(allocator, list.items);
|
||||||
|
|
||||||
|
return type_name.items;
|
||||||
}
|
}
|
||||||
|
|
||||||
return gop.value_ptr.*;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cacheArrayType(unit: *TranslationUnit, module: *Module, allocator: Allocator, type_index: Compilation.Type.Index) ![]const u8 {
|
fn cacheArrayType(unit: *TranslationUnit, module: *Module, allocator: Allocator, type_index: Compilation.Type.Index) ![]const u8 {
|
||||||
const array = module.types.array.get(type_index).array;
|
const array = module.types.array.get(type_index).array;
|
||||||
|
|
||||||
const gop = try unit.array_type_set.getOrPut(allocator, array.element_type);
|
if (unit.array_type_set.getIndex(array.element_type)) |index| {
|
||||||
|
return unit.array_type_set.values()[index];
|
||||||
if (!gop.found_existing) {
|
} else {
|
||||||
var type_name = ArrayList(u8){};
|
var type_name = ArrayList(u8){};
|
||||||
try type_name.appendSlice(allocator, "Array_");
|
try type_name.appendSlice(allocator, "Array_");
|
||||||
try unit.writeType(module, &type_name, allocator, array.element_type);
|
try unit.writeType(module, &type_name, allocator, array.element_type);
|
||||||
try type_name.writer(allocator).print("_{}", .{array.element_count});
|
try type_name.writer(allocator).print("_{}", .{array.element_count});
|
||||||
gop.value_ptr.* = type_name.items;
|
logln(.c, .g, "Registering array {s}: #{}", .{ type_name.items, type_index.uniqueInteger() });
|
||||||
|
try unit.array_type_set.putNoClobber(allocator, array.element_type, type_name.items);
|
||||||
|
|
||||||
try unit.type_forward_declarations.appendSlice(allocator, "typedef struct ");
|
try unit.forwardDeclareContainerType(allocator, .@"struct", type_name.items);
|
||||||
try unit.type_forward_declarations.appendSlice(allocator, type_name.items);
|
|
||||||
try unit.type_forward_declarations.append(allocator, ' ');
|
|
||||||
try unit.type_forward_declarations.appendSlice(allocator, type_name.items);
|
|
||||||
try unit.type_forward_declarations.appendSlice(allocator, ";\n");
|
|
||||||
|
|
||||||
try unit.type_declarations.appendSlice(allocator, "typedef struct ");
|
var list = ArrayList(u8){};
|
||||||
try unit.type_declarations.appendSlice(allocator, type_name.items);
|
|
||||||
try unit.type_declarations.appendSlice(allocator, " {\n");
|
|
||||||
|
|
||||||
try unit.type_declarations.appendNTimes(allocator, ' ', margin_width);
|
try list.appendSlice(allocator, "typedef struct ");
|
||||||
try unit.writeType(module, &unit.type_declarations, allocator, array.element_type);
|
try list.appendSlice(allocator, type_name.items);
|
||||||
try unit.type_declarations.appendSlice(allocator, " value\n");
|
try list.appendSlice(allocator, " {\n");
|
||||||
|
|
||||||
try unit.type_declarations.writer(allocator).print("[{}];\n", .{array.element_count});
|
try list.appendNTimes(allocator, ' ', margin_width);
|
||||||
|
try unit.writeType(module, &list, allocator, array.element_type);
|
||||||
|
try list.appendSlice(allocator, " value\n");
|
||||||
|
|
||||||
try unit.type_declarations.appendSlice(allocator, "} ");
|
try list.writer(allocator).print("[{}];\n", .{array.element_count});
|
||||||
try unit.type_declarations.appendSlice(allocator, type_name.items);
|
|
||||||
try unit.type_declarations.appendSlice(allocator, ";\n\n");
|
try list.appendSlice(allocator, "} ");
|
||||||
|
try list.appendSlice(allocator, type_name.items);
|
||||||
|
try list.appendSlice(allocator, ";\n\n");
|
||||||
|
|
||||||
|
try unit.type_declarations.appendSlice(allocator, list.items);
|
||||||
|
|
||||||
|
return type_name.items;
|
||||||
}
|
}
|
||||||
|
|
||||||
return gop.value_ptr.*;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writeSyscall(unit: *TranslationUnit, module: *Module, list: *ArrayList(u8), allocator: Allocator, syscall_index: Compilation.Syscall.Index, function_return_type: Compilation.Type.Index, indentation: usize) !void {
|
fn writeSyscall(unit: *TranslationUnit, module: *Module, list: *ArrayList(u8), allocator: Allocator, syscall_index: Compilation.Syscall.Index, function_return_type: Compilation.Type.Index, indentation: usize) !void {
|
||||||
@ -883,6 +943,7 @@ pub const TranslationUnit = struct {
|
|||||||
const type_index = arguments.type_index;
|
const type_index = arguments.type_index;
|
||||||
_ = type_index;
|
_ = type_index;
|
||||||
const value = module.values.array.get(value_index);
|
const value = module.values.array.get(value_index);
|
||||||
|
logln(.c, .g, "Generating C code for {s}", .{@tagName(value.*)});
|
||||||
switch (value.*) {
|
switch (value.*) {
|
||||||
.declaration => |declaration_index| {
|
.declaration => |declaration_index| {
|
||||||
try unit.writeDeclaration(module, list, allocator, declaration_index, indentation);
|
try unit.writeDeclaration(module, list, allocator, declaration_index, indentation);
|
||||||
@ -1135,13 +1196,29 @@ pub const TranslationUnit = struct {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
.slice => {
|
.slice => {
|
||||||
|
try list.append(allocator, '(');
|
||||||
switch (slice.range.end.invalid) {
|
switch (slice.range.end.invalid) {
|
||||||
false => {
|
false => {
|
||||||
try list.append(allocator, '(');
|
|
||||||
try unit.writeValue(module, list, allocator, function_return_type, indentation + 1, .{
|
try unit.writeValue(module, list, allocator, function_return_type, indentation + 1, .{
|
||||||
.value_index = slice.range.end,
|
.value_index = slice.range.end,
|
||||||
.type_index = Compilation.Type.Index.invalid,
|
.type_index = Compilation.Type.Index.invalid,
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
true => {
|
||||||
|
switch (sliceable_type.*) {
|
||||||
|
.slice => {
|
||||||
|
try list.append(allocator, '(');
|
||||||
|
try unit.writeValue(module, list, allocator, function_return_type, indentation + 1, .{
|
||||||
|
.value_index = slice.sliceable,
|
||||||
|
.type_index = Compilation.Type.Index.invalid,
|
||||||
|
});
|
||||||
|
try list.appendSlice(allocator, ").len");
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
try list.appendSlice(allocator, ") - (");
|
try list.appendSlice(allocator, ") - (");
|
||||||
try unit.writeValue(module, list, allocator, function_return_type, indentation + 1, .{
|
try unit.writeValue(module, list, allocator, function_return_type, indentation + 1, .{
|
||||||
.value_index = slice.range.start,
|
.value_index = slice.range.start,
|
||||||
@ -1149,11 +1226,6 @@ pub const TranslationUnit = struct {
|
|||||||
});
|
});
|
||||||
try list.appendSlice(allocator, ")\n");
|
try list.appendSlice(allocator, ")\n");
|
||||||
},
|
},
|
||||||
true => {
|
|
||||||
unreachable;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1288,18 +1360,33 @@ pub const TranslationUnit = struct {
|
|||||||
.value_index = array_coerce_to_slice.value,
|
.value_index = array_coerce_to_slice.value,
|
||||||
.type_index = Compilation.Type.Index.invalid,
|
.type_index = Compilation.Type.Index.invalid,
|
||||||
});
|
});
|
||||||
try list.appendSlice(allocator, ".value,\n");
|
switch (module.values.array.get(array_coerce_to_slice.value).*) {
|
||||||
|
.string_literal => {},
|
||||||
|
else => try list.appendSlice(allocator, ".value"),
|
||||||
|
}
|
||||||
|
try list.appendSlice(allocator, ",\n");
|
||||||
try list.appendNTimes(allocator, ' ', indentation * margin_width);
|
try list.appendNTimes(allocator, ' ', indentation * margin_width);
|
||||||
const array_value = module.values.array.get(array_coerce_to_slice.value);
|
const array_value = module.values.array.get(array_coerce_to_slice.value);
|
||||||
const array_type = module.types.array.get(array_value.getType(module));
|
const array_type = module.types.array.get(array_value.getType(module));
|
||||||
const array_length = switch (array_type.*) {
|
const array_length = switch (array_type.*) {
|
||||||
.array => |array| array.element_count,
|
.array => |array| array.element_count,
|
||||||
|
.pointer => |pointer| switch (module.types.array.get(pointer.element_type).*) {
|
||||||
|
.array => |array| array.element_count,
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
try list.writer(allocator).print(".len = {},\n", .{array_length});
|
try list.writer(allocator).print(".len = {},\n", .{array_length});
|
||||||
try list.appendNTimes(allocator, ' ', indentation * margin_width);
|
try list.appendNTimes(allocator, ' ', indentation * margin_width);
|
||||||
try list.append(allocator, '}');
|
try list.append(allocator, '}');
|
||||||
},
|
},
|
||||||
|
.enum_field => |enum_field_index| {
|
||||||
|
const enum_field = module.types.enum_fields.get(enum_field_index);
|
||||||
|
try unit.writeType(module, list, allocator, enum_field.parent);
|
||||||
|
try list.append(allocator, '_');
|
||||||
|
const enum_field_name = module.getName(enum_field.name).?;
|
||||||
|
try list.appendSlice(allocator, enum_field_name);
|
||||||
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ pub const Logger = enum {
|
|||||||
address_of,
|
address_of,
|
||||||
|
|
||||||
pub var bitset = std.EnumSet(Logger).initMany(&.{
|
pub var bitset = std.EnumSet(Logger).initMany(&.{
|
||||||
// .type,
|
.type,
|
||||||
.identifier,
|
.identifier,
|
||||||
// .symbol_declaration,
|
// .symbol_declaration,
|
||||||
// .scope_node,
|
// .scope_node,
|
||||||
@ -196,6 +196,8 @@ const Analyzer = struct {
|
|||||||
.token = block_node.token,
|
.token = block_node.token,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
logln(.sema, .type, "Creating block scope #{}. Parent: #{}", .{ scope_index.uniqueInteger(), parent_scope_index.uniqueInteger() });
|
||||||
|
|
||||||
const block_index = try analyzer.module.values.blocks.append(analyzer.allocator, .{
|
const block_index = try analyzer.module.values.blocks.append(analyzer.allocator, .{
|
||||||
.statements = ArrayList(Value.Index){},
|
.statements = ArrayList(Value.Index){},
|
||||||
.reaches_end = true,
|
.reaches_end = true,
|
||||||
@ -356,6 +358,13 @@ const Analyzer = struct {
|
|||||||
});
|
});
|
||||||
break :blk value_index;
|
break :blk value_index;
|
||||||
},
|
},
|
||||||
|
.simple_while => blk: {
|
||||||
|
const loop_index = try analyzer.whileLoop(scope_index, expect_type, statement_node_index);
|
||||||
|
const value_index = try analyzer.module.values.array.append(analyzer.allocator, .{
|
||||||
|
.loop = loop_index,
|
||||||
|
});
|
||||||
|
break :blk value_index;
|
||||||
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -474,7 +483,20 @@ const Analyzer = struct {
|
|||||||
break :blk address_of_index;
|
break :blk address_of_index;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
else => switch (analyzer.module.types.array.get(method_object_type).*) {
|
||||||
|
.pointer => blk: {
|
||||||
|
const unary_index = try analyzer.module.values.unary_operations.append(analyzer.allocator, .{
|
||||||
|
.id = .pointer_dereference,
|
||||||
|
.value = method_object,
|
||||||
|
.type = first_argument_type,
|
||||||
|
});
|
||||||
|
const pointer_dereference_index = try analyzer.module.values.array.append(analyzer.allocator, .{
|
||||||
|
.unary_operation = unary_index,
|
||||||
|
});
|
||||||
|
break :blk pointer_dereference_index;
|
||||||
|
},
|
||||||
else => method_object,
|
else => method_object,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
argument_array.appendAssumeCapacity(method_object_argument);
|
argument_array.appendAssumeCapacity(method_object_argument);
|
||||||
@ -533,9 +555,21 @@ const Analyzer = struct {
|
|||||||
const result = try analyzer.typeCheck(ExpectType{
|
const result = try analyzer.typeCheck(ExpectType{
|
||||||
.type_index = argument_declaration.type,
|
.type_index = argument_declaration.type,
|
||||||
}, call_site_type);
|
}, call_site_type);
|
||||||
assert(result == .success);
|
|
||||||
|
|
||||||
argument_array.appendAssumeCapacity(call_argument_value_index);
|
argument_array.appendAssumeCapacity(switch (result) {
|
||||||
|
.array_coerce_to_slice => blk: {
|
||||||
|
const array_coerce_to_slice = try analyzer.module.values.casts.append(analyzer.allocator, .{
|
||||||
|
.value = call_argument_value_index,
|
||||||
|
.type = argument_declaration.type,
|
||||||
|
});
|
||||||
|
const coertion_value = try analyzer.module.values.array.append(analyzer.allocator, .{
|
||||||
|
.array_coerce_to_slice = array_coerce_to_slice,
|
||||||
|
});
|
||||||
|
break :blk coertion_value;
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
.success => call_argument_value_index,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
panic("{s} call has argument count mismatch: call has {}, function declaration has {}", .{ switch (method_object.invalid) {
|
panic("{s} call has argument count mismatch: call has {}, function declaration has {}", .{ switch (method_object.invalid) {
|
||||||
@ -550,7 +584,6 @@ const Analyzer = struct {
|
|||||||
|
|
||||||
fn processCall(analyzer: *Analyzer, scope_index: Scope.Index, node_index: Node.Index) !Call.Index {
|
fn processCall(analyzer: *Analyzer, scope_index: Scope.Index, node_index: Node.Index) !Call.Index {
|
||||||
const node = analyzer.getScopeNode(scope_index, node_index);
|
const node = analyzer.getScopeNode(scope_index, node_index);
|
||||||
logln(.sema, .call, "Node index: {}. Left index: {}", .{ node_index.uniqueInteger(), node.left.uniqueInteger() });
|
|
||||||
assert(!node.left.invalid);
|
assert(!node.left.invalid);
|
||||||
var is_field_access = false;
|
var is_field_access = false;
|
||||||
|
|
||||||
@ -703,7 +736,8 @@ const Analyzer = struct {
|
|||||||
switch (analyzer.module.values.array.get(switch_expression_value_index).*) {
|
switch (analyzer.module.values.array.get(switch_expression_value_index).*) {
|
||||||
.enum_field => |e_field_index| {
|
.enum_field => |e_field_index| {
|
||||||
const e_field = analyzer.module.types.enum_fields.get(e_field_index);
|
const e_field = analyzer.module.types.enum_fields.get(e_field_index);
|
||||||
const enum_type = analyzer.module.types.enums.get(e_field.parent);
|
const enum_type_general = analyzer.module.types.array.get(e_field.parent);
|
||||||
|
const enum_type = analyzer.module.types.enums.get(enum_type_general.@"enum");
|
||||||
const enum_field_name = analyzer.module.getName(e_field.name);
|
const enum_field_name = analyzer.module.getName(e_field.name);
|
||||||
_ = enum_field_name;
|
_ = enum_field_name;
|
||||||
|
|
||||||
@ -807,7 +841,10 @@ const Analyzer = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const range_start_index = try analyzer.unresolvedAllocate(scope_index, expect_type, range_node.left);
|
const range_start_index = try analyzer.unresolvedAllocate(scope_index, expect_type, range_node.left);
|
||||||
const range_end_index = try analyzer.unresolvedAllocate(scope_index, expect_type, range_node.right);
|
const range_end_index = switch (range_node.right.invalid) {
|
||||||
|
true => Value.Index.invalid,
|
||||||
|
false => try analyzer.unresolvedAllocate(scope_index, expect_type, range_node.right),
|
||||||
|
};
|
||||||
|
|
||||||
return Range{
|
return Range{
|
||||||
.start = range_start_index,
|
.start = range_start_index,
|
||||||
@ -825,6 +862,30 @@ const Analyzer = struct {
|
|||||||
return maybe_payload_name;
|
return maybe_payload_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn whileLoop(analyzer: *Analyzer, parent_scope_index: Scope.Index, expect_type: ExpectType, while_node_index: Node.Index) !Loop.Index {
|
||||||
|
_ = expect_type;
|
||||||
|
const while_loop_node = analyzer.getScopeNode(parent_scope_index, while_node_index);
|
||||||
|
assert(while_loop_node.id == .simple_while);
|
||||||
|
// TODO: complete
|
||||||
|
const scope_index = parent_scope_index;
|
||||||
|
const condition_index = try analyzer.unresolvedAllocate(scope_index, ExpectType.boolean, while_loop_node.left);
|
||||||
|
const body_index = try analyzer.unresolvedAllocate(scope_index, ExpectType.boolean, while_loop_node.right);
|
||||||
|
const reaches_end = switch (analyzer.module.values.array.get(body_index).*) {
|
||||||
|
.block => |block_index| analyzer.module.values.blocks.get(block_index).reaches_end,
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
};
|
||||||
|
|
||||||
|
const loop_index = try analyzer.module.values.loops.append(analyzer.allocator, .{
|
||||||
|
.pre = Value.Index.invalid,
|
||||||
|
.condition = condition_index,
|
||||||
|
.body = body_index,
|
||||||
|
.post = Value.Index.invalid,
|
||||||
|
.reaches_end = reaches_end,
|
||||||
|
});
|
||||||
|
|
||||||
|
return loop_index;
|
||||||
|
}
|
||||||
|
|
||||||
fn forLoop(analyzer: *Analyzer, parent_scope_index: Scope.Index, expect_type: ExpectType, for_node_index: Node.Index) !Loop.Index {
|
fn forLoop(analyzer: *Analyzer, parent_scope_index: Scope.Index, expect_type: ExpectType, for_node_index: Node.Index) !Loop.Index {
|
||||||
const for_loop_node = analyzer.getScopeNode(parent_scope_index, for_node_index);
|
const for_loop_node = analyzer.getScopeNode(parent_scope_index, for_node_index);
|
||||||
assert(for_loop_node.id == .for_loop);
|
assert(for_loop_node.id == .for_loop);
|
||||||
@ -835,6 +896,8 @@ const Analyzer = struct {
|
|||||||
.parent = parent_scope_index,
|
.parent = parent_scope_index,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
logln(.sema, .type, "Creating for loop scope #{}. Parent: #{}", .{ scope_index.uniqueInteger(), parent_scope_index.uniqueInteger() });
|
||||||
|
|
||||||
const for_condition_node = analyzer.getScopeNode(scope_index, for_loop_node.left);
|
const for_condition_node = analyzer.getScopeNode(scope_index, for_loop_node.left);
|
||||||
assert(for_condition_node.id == .for_condition);
|
assert(for_condition_node.id == .for_condition);
|
||||||
|
|
||||||
@ -866,7 +929,7 @@ const Analyzer = struct {
|
|||||||
.type = Type.boolean,
|
.type = Type.boolean,
|
||||||
.left = try analyzer.doIdentifierString(scope_index, ExpectType{
|
.left = try analyzer.doIdentifierString(scope_index, ExpectType{
|
||||||
.type_index = Type.usize,
|
.type_index = Type.usize,
|
||||||
}, payload_name),
|
}, payload_name, scope_index),
|
||||||
.right = for_range.end,
|
.right = for_range.end,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1242,11 +1305,15 @@ const Analyzer = struct {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn doIdentifierString(analyzer: *Analyzer, scope_index: Scope.Index, expect_type: ExpectType, identifier: []const u8) !Value.Index {
|
fn doIdentifierString(analyzer: *Analyzer, from_scope_index: Scope.Index, expect_type: ExpectType, identifier: []const u8, in_scope_index: Scope.Index) !Value.Index {
|
||||||
logln(.sema, .identifier, "Referencing identifier: \"{s}\"", .{identifier});
|
logln(.sema, .identifier, "Referencing identifier: \"{s}\" from scope #{} in scope #{}", .{ identifier, from_scope_index.uniqueInteger(), in_scope_index.uniqueInteger() });
|
||||||
const identifier_hash = try analyzer.processIdentifier(identifier);
|
const identifier_hash = try analyzer.processIdentifier(identifier);
|
||||||
|
|
||||||
if (analyzer.lookupDeclarationInCurrentAndParentScopes(scope_index, identifier_hash)) |lookup| {
|
// if (equal(u8, identifier, "write")) {
|
||||||
|
// @breakpoint();
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (analyzer.lookupDeclarationInCurrentAndParentScopes(from_scope_index, identifier_hash)) |lookup| {
|
||||||
const declaration_index = lookup.declaration;
|
const declaration_index = lookup.declaration;
|
||||||
const declaration = analyzer.module.values.declarations.get(declaration_index);
|
const declaration = analyzer.module.values.declarations.get(declaration_index);
|
||||||
|
|
||||||
@ -1286,9 +1353,9 @@ const Analyzer = struct {
|
|||||||
// logln(.sema, .identifier, "Declaration mutability: {s}. Is comptime: {}", .{ @tagName(declaration.mutability), init_value.isComptime(analyzer.module) });
|
// logln(.sema, .identifier, "Declaration mutability: {s}. Is comptime: {}", .{ @tagName(declaration.mutability), init_value.isComptime(analyzer.module) });
|
||||||
|
|
||||||
assert(!declaration.type.invalid);
|
assert(!declaration.type.invalid);
|
||||||
logln(.sema, .identifier, "About to typecheck identifier: \"{s}\"", .{identifier});
|
// logln(.sema, .identifier, "About to typecheck identifier: \"{s}\"", .{identifier});
|
||||||
const typecheck_result = try analyzer.typeCheck(expect_type, declaration.type);
|
const typecheck_result = try analyzer.typeCheck(expect_type, declaration.type);
|
||||||
logln(.sema, .identifier, "Done typecheck identifier: \"{s}\"", .{identifier});
|
// logln(.sema, .identifier, "Done typecheck identifier: \"{s}\"", .{identifier});
|
||||||
|
|
||||||
assert(!declaration.type.eq(pointer_to_any_type));
|
assert(!declaration.type.eq(pointer_to_any_type));
|
||||||
assert(!declaration.type.eq(optional_pointer_to_any_type));
|
assert(!declaration.type.eq(optional_pointer_to_any_type));
|
||||||
@ -1388,13 +1455,31 @@ const Analyzer = struct {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
panic("Identifier \"{s}\" not found in scope", .{identifier});
|
logln(.sema, .type, "Identifier \"{s}\" not found as a declaration from scope #{} referenced in scope #{}", .{ identifier, from_scope_index.uniqueInteger(), in_scope_index.uniqueInteger() });
|
||||||
|
const from_scope = analyzer.module.values.scopes.get(from_scope_index);
|
||||||
|
const scope_type = analyzer.module.types.array.get(from_scope.type);
|
||||||
|
switch (scope_type.*) {
|
||||||
|
.@"struct" => |struct_index| {
|
||||||
|
const struct_type = analyzer.module.types.structs.get(struct_index);
|
||||||
|
for (struct_type.fields.items) |struct_field_index| {
|
||||||
|
const struct_field = analyzer.module.types.container_fields.get(struct_field_index);
|
||||||
|
if (struct_field.name == identifier_hash) {
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
}
|
||||||
|
|
||||||
|
unreachable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn doIdentifier(analyzer: *Analyzer, scope_index: Scope.Index, expect_type: ExpectType, node_token: Token.Index, node_scope_index: Scope.Index) !Value.Index {
|
fn doIdentifier(analyzer: *Analyzer, scope_index: Scope.Index, expect_type: ExpectType, node_token: Token.Index, node_scope_index: Scope.Index) !Value.Index {
|
||||||
const identifier = analyzer.tokenIdentifier(node_scope_index, node_token);
|
const identifier = analyzer.tokenIdentifier(node_scope_index, node_token);
|
||||||
return try analyzer.doIdentifierString(scope_index, expect_type, identifier);
|
return try analyzer.doIdentifierString(scope_index, expect_type, identifier, node_scope_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolveInteger(analyzer: *Analyzer, scope_index: Scope.Index, value_index: Value.Index) usize {
|
fn resolveInteger(analyzer: *Analyzer, scope_index: Scope.Index, value_index: Value.Index) usize {
|
||||||
@ -1450,6 +1535,8 @@ const Analyzer = struct {
|
|||||||
.token = node.token,
|
.token = node.token,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
logln(.sema, .type, "Creating function scope #{}. Parent #{}", .{ function_scope_index.uniqueInteger(), scope_index.uniqueInteger() });
|
||||||
|
|
||||||
const function_prototype_index = try analyzer.functionPrototype(function_scope_index, node.left);
|
const function_prototype_index = try analyzer.functionPrototype(function_scope_index, node.left);
|
||||||
const function_prototype = analyzer.module.types.function_prototypes.get(function_prototype_index);
|
const function_prototype = analyzer.module.types.function_prototypes.get(function_prototype_index);
|
||||||
assert(!function_prototype.attributes.@"extern");
|
assert(!function_prototype.attributes.@"extern");
|
||||||
@ -1457,7 +1544,6 @@ const Analyzer = struct {
|
|||||||
const expected_type = ExpectType{
|
const expected_type = ExpectType{
|
||||||
.type_index = analyzer.functionPrototypeReturnType(function_prototype_index),
|
.type_index = analyzer.functionPrototypeReturnType(function_prototype_index),
|
||||||
};
|
};
|
||||||
logln(.sema, .fn_return_type, "Return type: #{}", .{expected_type.type_index.uniqueInteger()});
|
|
||||||
const function_body = try analyzer.block(function_scope_index, expected_type, node.right);
|
const function_body = try analyzer.block(function_scope_index, expected_type, node.right);
|
||||||
|
|
||||||
const prototype_type_index = try analyzer.module.types.array.append(analyzer.allocator, .{
|
const prototype_type_index = try analyzer.module.types.array.append(analyzer.allocator, .{
|
||||||
@ -1552,10 +1638,15 @@ const Analyzer = struct {
|
|||||||
const right_value = analyzer.module.values.array.get(right_index);
|
const right_value = analyzer.module.values.array.get(right_index);
|
||||||
|
|
||||||
switch (right_value.*) {
|
switch (right_value.*) {
|
||||||
.function_definition, .type, .enum_field => break :blk right_value.*,
|
.function_definition,
|
||||||
.declaration_reference => break :blk right_value.*,
|
.type,
|
||||||
|
.enum_field,
|
||||||
|
.declaration_reference,
|
||||||
|
.integer,
|
||||||
|
=> break :blk right_value.*,
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
|
||||||
logln(.sema, .node, "Right: {}", .{right_value});
|
logln(.sema, .node, "Right: {}", .{right_value});
|
||||||
// struct_scope.declarations.get(identifier);
|
// struct_scope.declarations.get(identifier);
|
||||||
@ -1571,8 +1662,26 @@ const Analyzer = struct {
|
|||||||
break enum_field_index;
|
break enum_field_index;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@panic("No enum found");
|
const right_index = try analyzer.doIdentifier(enum_type.scope, ExpectType.none, node.right.value, scope_index);
|
||||||
|
const right_value = analyzer.module.values.array.get(right_index);
|
||||||
|
|
||||||
|
switch (right_value.*) {
|
||||||
|
.function_definition,
|
||||||
|
.type,
|
||||||
|
.enum_field,
|
||||||
|
.declaration_reference,
|
||||||
|
.integer,
|
||||||
|
=> break :blk right_value.*,
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
}
|
||||||
|
//
|
||||||
|
|
||||||
|
logln(.sema, .node, "Right: {}", .{right_value});
|
||||||
|
// struct_scope.declarations.get(identifier);
|
||||||
|
|
||||||
|
unreachable;
|
||||||
};
|
};
|
||||||
|
|
||||||
const enum_field = analyzer.module.types.enum_fields.get(result);
|
const enum_field = analyzer.module.types.enum_fields.get(result);
|
||||||
const enum_field_name = analyzer.module.getName(enum_field.name).?;
|
const enum_field_name = analyzer.module.getName(enum_field.name).?;
|
||||||
logln(.sema, .node, "Enum field name resolution: {s}", .{enum_field_name});
|
logln(.sema, .node, "Enum field name resolution: {s}", .{enum_field_name});
|
||||||
@ -1734,38 +1843,10 @@ const Analyzer = struct {
|
|||||||
.node_list => analyzer.getScopeNodeList(scope_index, list_node),
|
.node_list => analyzer.getScopeNodeList(scope_index, list_node),
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
|
const file = analyzer.module.values.scopes.get(scope_index).file;
|
||||||
var field_list = try ArrayList(Enum.Field.Index).initCapacity(analyzer.allocator, field_node_list.items.len);
|
const enum_type = try analyzer.processContainerType(value_index, scope_index, field_node_list.items, file, node_index, .@"enum");
|
||||||
const enum_index = try analyzer.module.types.enums.addOne(analyzer.allocator);
|
|
||||||
const type_index = try analyzer.module.types.array.append(analyzer.allocator, .{
|
|
||||||
.@"enum" = enum_index,
|
|
||||||
});
|
|
||||||
|
|
||||||
for (field_node_list.items) |field_node_index| {
|
|
||||||
const field_node = analyzer.getScopeNode(scope_index, field_node_index);
|
|
||||||
const identifier = analyzer.tokenIdentifier(scope_index, field_node.token);
|
|
||||||
logln(.sema, .node, "Enum field: {s}", .{identifier});
|
|
||||||
assert(field_node.left.invalid);
|
|
||||||
|
|
||||||
const enum_hash_name = try analyzer.processIdentifier(identifier);
|
|
||||||
|
|
||||||
const enum_field_index = try analyzer.module.types.enum_fields.append(analyzer.allocator, .{
|
|
||||||
.name = enum_hash_name,
|
|
||||||
.value = Value.Index.invalid,
|
|
||||||
.parent = enum_index,
|
|
||||||
});
|
|
||||||
|
|
||||||
field_list.appendAssumeCapacity(enum_field_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
analyzer.module.types.enums.get(enum_index).* = .{
|
|
||||||
.scope = Scope.Index.invalid,
|
|
||||||
.fields = field_list,
|
|
||||||
.type = type_index,
|
|
||||||
};
|
|
||||||
|
|
||||||
break :blk .{
|
break :blk .{
|
||||||
.type = type_index,
|
.type = enum_type,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
.assign => try analyzer.processAssignment(scope_index, node_index),
|
.assign => try analyzer.processAssignment(scope_index, node_index),
|
||||||
@ -1806,7 +1887,7 @@ const Analyzer = struct {
|
|||||||
const left_node = analyzer.getScopeNode(scope_index, node.left);
|
const left_node = analyzer.getScopeNode(scope_index, node.left);
|
||||||
const nodes = analyzer.getScopeNodeList(scope_index, left_node);
|
const nodes = analyzer.getScopeNodeList(scope_index, left_node);
|
||||||
const scope = analyzer.module.values.scopes.get(scope_index);
|
const scope = analyzer.module.values.scopes.get(scope_index);
|
||||||
const struct_type = try analyzer.structType(value_index, scope_index, nodes.items, scope.file, node_index);
|
const struct_type = try analyzer.processContainerType(value_index, scope_index, nodes.items, scope.file, node_index, .@"struct");
|
||||||
break :blk .{
|
break :blk .{
|
||||||
.type = struct_type,
|
.type = struct_type,
|
||||||
};
|
};
|
||||||
@ -1951,13 +2032,17 @@ const Analyzer = struct {
|
|||||||
.slice => |slice| slice.element_type,
|
.slice => |slice| slice.element_type,
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
|
const is_const = switch (analyzer.module.types.array.get(expression_to_slice_type).*) {
|
||||||
|
.pointer => |pointer| pointer.@"const",
|
||||||
|
.slice => |slice| slice.@"const",
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
};
|
||||||
const slice_index = try analyzer.module.values.slices.append(analyzer.allocator, .{
|
const slice_index = try analyzer.module.values.slices.append(analyzer.allocator, .{
|
||||||
.sliceable = expression_to_slice_index,
|
.sliceable = expression_to_slice_index,
|
||||||
.range = try analyzer.range(scope_index, node.right),
|
.range = try analyzer.range(scope_index, node.right),
|
||||||
.type = try analyzer.getSliceType(.{
|
.type = try analyzer.getSliceType(.{
|
||||||
.element_type = element_type,
|
.element_type = element_type,
|
||||||
.@"const" = true,
|
.@"const" = is_const,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -2026,6 +2111,8 @@ const Analyzer = struct {
|
|||||||
|
|
||||||
for (struct_type.fields.items) |struct_field_index| {
|
for (struct_type.fields.items) |struct_field_index| {
|
||||||
const struct_field = analyzer.module.types.container_fields.get(struct_field_index);
|
const struct_field = analyzer.module.types.container_fields.get(struct_field_index);
|
||||||
|
const struct_field_name = analyzer.module.getName(struct_field.name).?;
|
||||||
|
logln(.sema, .type, "struct field name in container literal: {s}", .{struct_field_name});
|
||||||
|
|
||||||
var value_index = Value.Index.invalid;
|
var value_index = Value.Index.invalid;
|
||||||
|
|
||||||
@ -2050,9 +2137,17 @@ const Analyzer = struct {
|
|||||||
|
|
||||||
if (value_index.invalid) {
|
if (value_index.invalid) {
|
||||||
if (!struct_field.default_value.invalid) {
|
if (!struct_field.default_value.invalid) {
|
||||||
value_index = struct_field.default_value;
|
const default_value: Value.Index = switch (analyzer.module.values.array.get(struct_field.default_value).*) {
|
||||||
|
.unresolved => |unresolved| blk: {
|
||||||
|
try analyzer.resolveNode(struct_field.default_value, struct_type.scope, ExpectType{
|
||||||
|
.type_index = struct_field.type,
|
||||||
|
}, unresolved.node_index);
|
||||||
|
break :blk (&struct_field.default_value).*;
|
||||||
|
},
|
||||||
|
else => struct_field.default_value,
|
||||||
|
};
|
||||||
|
value_index = default_value;
|
||||||
} else {
|
} else {
|
||||||
const struct_field_name = analyzer.module.getName(struct_field.name).?;
|
|
||||||
std.debug.panic("Field \"{s}\" forgotten in struct initialization", .{struct_field_name});
|
std.debug.panic("Field \"{s}\" forgotten in struct initialization", .{struct_field_name});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2159,10 +2254,10 @@ const Analyzer = struct {
|
|||||||
const type_node = analyzer.getScopeNode(scope_index, node_index);
|
const type_node = analyzer.getScopeNode(scope_index, node_index);
|
||||||
const type_index: Type.Index = switch (type_node.id) {
|
const type_index: Type.Index = switch (type_node.id) {
|
||||||
.identifier => blk: {
|
.identifier => blk: {
|
||||||
const token = analyzer.getScopeToken(scope_index, type_node.token);
|
// const token = analyzer.getScopeToken(scope_index, type_node.token);
|
||||||
const source_file = analyzer.getScopeSourceFile(scope_index);
|
// const source_file = analyzer.getScopeSourceFile(scope_index);
|
||||||
const identifier = tokenBytes(token, source_file);
|
// const identifier = tokenBytes(token, source_file);
|
||||||
logln(.sema, .type, "Identifier: \"{s}\"", .{identifier});
|
// logln(.sema, .type, "Identifier: \"{s}\"", .{identifier});
|
||||||
const resolved_value_index = try analyzer.doIdentifier(scope_index, ExpectType.type, type_node.token, scope_index);
|
const resolved_value_index = try analyzer.doIdentifier(scope_index, ExpectType.type, type_node.token, scope_index);
|
||||||
const resolved_value = analyzer.module.values.array.get(resolved_value_index);
|
const resolved_value = analyzer.module.values.array.get(resolved_value_index);
|
||||||
break :blk switch (resolved_value.*) {
|
break :blk switch (resolved_value.*) {
|
||||||
@ -2173,7 +2268,6 @@ const Analyzer = struct {
|
|||||||
.keyword_noreturn => Type.noreturn,
|
.keyword_noreturn => Type.noreturn,
|
||||||
inline .signed_integer_type, .unsigned_integer_type => |int_type_signedness| blk: {
|
inline .signed_integer_type, .unsigned_integer_type => |int_type_signedness| blk: {
|
||||||
const bit_count: u16 = @intCast(type_node.left.value);
|
const bit_count: u16 = @intCast(type_node.left.value);
|
||||||
logln(.sema, .type, "Bit count: {}", .{bit_count});
|
|
||||||
break :blk switch (bit_count) {
|
break :blk switch (bit_count) {
|
||||||
inline 8, 16, 32, 64 => |hardware_bit_count| Type.Integer.getIndex(.{
|
inline 8, 16, 32, 64 => |hardware_bit_count| Type.Integer.getIndex(.{
|
||||||
.bit_count = hardware_bit_count,
|
.bit_count = hardware_bit_count,
|
||||||
@ -2250,12 +2344,19 @@ const Analyzer = struct {
|
|||||||
.@"const" = is_const,
|
.@"const" = is_const,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.slice_type => blk: {
|
.slice_type,
|
||||||
|
.const_slice_type,
|
||||||
|
=> blk: {
|
||||||
const element_type = try resolveType(analyzer, .{
|
const element_type = try resolveType(analyzer, .{
|
||||||
.scope_index = scope_index,
|
.scope_index = scope_index,
|
||||||
.node_index = type_node.right,
|
.node_index = type_node.right,
|
||||||
});
|
});
|
||||||
const is_const = false;
|
|
||||||
|
const is_const = switch (type_node.id) {
|
||||||
|
.slice_type => false,
|
||||||
|
.const_slice_type => true,
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
|
||||||
break :blk try analyzer.getSliceType(.{
|
break :blk try analyzer.getSliceType(.{
|
||||||
.element_type = element_type,
|
.element_type = element_type,
|
||||||
@ -2443,7 +2544,7 @@ const Analyzer = struct {
|
|||||||
|
|
||||||
while (expression_iterator.next()) |expression_name| {
|
while (expression_iterator.next()) |expression_name| {
|
||||||
const result = switch (before_expression.invalid) {
|
const result = switch (before_expression.invalid) {
|
||||||
true => try analyzer.doIdentifierString(scope_index, ExpectType.type, expression_name),
|
true => try analyzer.doIdentifierString(scope_index, ExpectType.type, expression_name, scope_index),
|
||||||
false => blk: {
|
false => blk: {
|
||||||
const expression_name_hash = try analyzer.processIdentifier(expression_name);
|
const expression_name_hash = try analyzer.processIdentifier(expression_name);
|
||||||
switch (analyzer.module.values.array.get(before_expression).*) {
|
switch (analyzer.module.values.array.get(before_expression).*) {
|
||||||
@ -2503,20 +2604,28 @@ const Analyzer = struct {
|
|||||||
return before_expression;
|
return before_expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn structType(analyzer: *Analyzer, value_index: Value.Index, parent_scope_index: Scope.Index, struct_nodes: []const Node.Index, struct_file_index: File.Index, struct_node_index: Node.Index) !Type.Index {
|
fn processContainerType(analyzer: *Analyzer, value_index: Value.Index, parent_scope_index: Scope.Index, container_nodes: []const Node.Index, file_index: File.Index, container_node_index: Node.Index, comptime container_type: Compilation.ContainerType) !Type.Index {
|
||||||
const struct_node = analyzer.getFileNode(struct_file_index, struct_node_index);
|
const container_node = analyzer.getFileNode(file_index, container_node_index);
|
||||||
if (struct_nodes.len > 0) {
|
switch (container_type) {
|
||||||
|
.@"struct" => assert(container_node.id == .struct_type),
|
||||||
|
.@"enum" => assert(container_node.id == .enum_type),
|
||||||
|
}
|
||||||
const scope_index = try analyzer.module.values.scopes.append(analyzer.allocator, .{
|
const scope_index = try analyzer.module.values.scopes.append(analyzer.allocator, .{
|
||||||
.parent = parent_scope_index,
|
.parent = parent_scope_index,
|
||||||
.file = struct_file_index,
|
.file = file_index,
|
||||||
.token = struct_node.token,
|
.token = container_node.token,
|
||||||
|
});
|
||||||
|
logln(.sema, .type, "Creating container scope #{}. Parent: #{}", .{
|
||||||
|
scope_index.uniqueInteger(), switch (parent_scope_index.invalid) {
|
||||||
|
true => 0xffff_ffff,
|
||||||
|
false => parent_scope_index.uniqueInteger(),
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const is_file = parent_scope_index.invalid;
|
const is_file = parent_scope_index.invalid;
|
||||||
const backing_type = blk: {
|
const backing_type = blk: {
|
||||||
if (!is_file) {
|
if (!is_file) {
|
||||||
if (analyzer.getScopeToken(parent_scope_index, struct_node.token + 1).id == .left_parenthesis) {
|
if (analyzer.getScopeToken(parent_scope_index, container_node.token + 1).id == .left_parenthesis) {
|
||||||
const backing_type_token = analyzer.getScopeToken(parent_scope_index, struct_node.token + 2);
|
const backing_type_token = analyzer.getScopeToken(parent_scope_index, container_node.token + 2);
|
||||||
const source_file = analyzer.getScopeSourceFile(parent_scope_index);
|
const source_file = analyzer.getScopeSourceFile(parent_scope_index);
|
||||||
const token_bytes = tokenBytes(backing_type_token, source_file);
|
const token_bytes = tokenBytes(backing_type_token, source_file);
|
||||||
|
|
||||||
@ -2530,23 +2639,34 @@ const Analyzer = struct {
|
|||||||
break :blk Type.Index.invalid;
|
break :blk Type.Index.invalid;
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct_index = try analyzer.module.types.structs.append(analyzer.allocator, .{
|
const container_descriptor = .{
|
||||||
.scope = scope_index,
|
.scope = scope_index,
|
||||||
.backing_type = backing_type,
|
.backing_type = backing_type,
|
||||||
});
|
};
|
||||||
|
const container_type_descriptor = switch (container_type) {
|
||||||
const struct_type_index = try analyzer.module.types.array.append(analyzer.allocator, .{
|
.@"struct" => blk: {
|
||||||
|
const struct_index = try analyzer.module.types.structs.append(analyzer.allocator, container_descriptor);
|
||||||
|
break :blk Type{
|
||||||
.@"struct" = struct_index,
|
.@"struct" = struct_index,
|
||||||
});
|
};
|
||||||
|
},
|
||||||
|
.@"enum" => blk: {
|
||||||
|
const enum_index = try analyzer.module.types.enums.append(analyzer.allocator, container_descriptor);
|
||||||
|
break :blk Type{
|
||||||
|
.@"enum" = enum_index,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const container_type_index = try analyzer.module.types.array.append(analyzer.allocator, container_type_descriptor);
|
||||||
if (is_file) {
|
if (is_file) {
|
||||||
const file = analyzer.module.values.files.get(struct_file_index);
|
const file = analyzer.module.values.files.get(file_index);
|
||||||
file.type = struct_type_index;
|
file.type = container_type_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
analyzer.module.values.scopes.get(scope_index).type = struct_type_index;
|
analyzer.module.values.scopes.get(scope_index).type = container_type_index;
|
||||||
analyzer.module.values.array.get(value_index).* = .{
|
analyzer.module.values.array.get(value_index).* = .{
|
||||||
.type = struct_type_index,
|
.type = container_type_index,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!analyzer.current_declaration.invalid) {
|
if (!analyzer.current_declaration.invalid) {
|
||||||
@ -2560,8 +2680,13 @@ const Analyzer = struct {
|
|||||||
fields: u32 = 0,
|
fields: u32 = 0,
|
||||||
declarations: u32 = 0,
|
declarations: u32 = 0,
|
||||||
} = .{};
|
} = .{};
|
||||||
for (struct_nodes) |member_index| {
|
|
||||||
const member = analyzer.getFileNode(struct_file_index, member_index);
|
for (container_nodes) |member_index| {
|
||||||
|
const member = analyzer.getFileNode(file_index, member_index);
|
||||||
|
switch (container_type) {
|
||||||
|
.@"struct" => assert(member.id != .enum_field),
|
||||||
|
.@"enum" => assert(member.id != .container_field),
|
||||||
|
}
|
||||||
const member_type = getContainerMemberType(member.id);
|
const member_type = getContainerMemberType(member.id);
|
||||||
|
|
||||||
switch (member_type) {
|
switch (member_type) {
|
||||||
@ -2569,14 +2694,15 @@ const Analyzer = struct {
|
|||||||
.field => result.fields += 1,
|
.field => result.fields += 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break :blk result;
|
break :blk result;
|
||||||
};
|
};
|
||||||
|
|
||||||
var declaration_nodes = try ArrayList(Node.Index).initCapacity(analyzer.allocator, count.declarations);
|
var declaration_nodes = try ArrayList(Node.Index).initCapacity(analyzer.allocator, count.declarations);
|
||||||
var field_nodes = try ArrayList(Node.Index).initCapacity(analyzer.allocator, count.fields);
|
var field_nodes = try ArrayList(Node.Index).initCapacity(analyzer.allocator, count.fields);
|
||||||
|
|
||||||
for (struct_nodes) |member_index| {
|
for (container_nodes) |member_index| {
|
||||||
const member = analyzer.getFileNode(struct_file_index, member_index);
|
const member = analyzer.getFileNode(file_index, member_index);
|
||||||
const member_type = getContainerMemberType(member.id);
|
const member_type = getContainerMemberType(member.id);
|
||||||
const array_list = switch (member_type) {
|
const array_list = switch (member_type) {
|
||||||
.declaration => &declaration_nodes,
|
.declaration => &declaration_nodes,
|
||||||
@ -2586,7 +2712,7 @@ const Analyzer = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (declaration_nodes.items) |declaration_node_index| {
|
for (declaration_nodes.items) |declaration_node_index| {
|
||||||
const declaration_node = analyzer.getFileNode(struct_file_index, declaration_node_index);
|
const declaration_node = analyzer.getFileNode(file_index, declaration_node_index);
|
||||||
switch (declaration_node.id) {
|
switch (declaration_node.id) {
|
||||||
.@"comptime" => {},
|
.@"comptime" => {},
|
||||||
.simple_symbol_declaration => _ = try analyzer.symbolDeclaration(scope_index, declaration_node_index, .global),
|
.simple_symbol_declaration => _ = try analyzer.symbolDeclaration(scope_index, declaration_node_index, .global),
|
||||||
@ -2594,29 +2720,29 @@ const Analyzer = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: consider iterating over scope declarations instead?
|
|
||||||
for (declaration_nodes.items) |declaration_node_index| {
|
|
||||||
const declaration_node = analyzer.getFileNode(struct_file_index, declaration_node_index);
|
|
||||||
switch (declaration_node.id) {
|
|
||||||
.@"comptime" => _ = try analyzer.comptimeBlock(scope_index, declaration_node_index),
|
|
||||||
.simple_symbol_declaration => {},
|
|
||||||
else => |t| @panic(@tagName(t)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
analyzer.module.types.structs.get(struct_index).fields = try ArrayList(Compilation.ContainerField.Index).initCapacity(analyzer.allocator, field_nodes.items.len);
|
|
||||||
|
|
||||||
if (field_nodes.items.len > 0) {
|
if (field_nodes.items.len > 0) {
|
||||||
// This is done in order for the names inside fields not to collision with the declaration ones
|
// This is done in order for the names inside fields not to collision with the declaration ones
|
||||||
const field_scope_index = try analyzer.module.values.scopes.append(analyzer.allocator, .{
|
const field_scope_index = try analyzer.module.values.scopes.append(analyzer.allocator, .{
|
||||||
.token = analyzer.getScopeNode(scope_index, field_nodes.items[0]).token,
|
.token = analyzer.getScopeNode(scope_index, field_nodes.items[0]).token,
|
||||||
.file = struct_file_index,
|
.file = file_index,
|
||||||
.parent = scope_index,
|
.parent = scope_index,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
logln(.sema, .type, "Creating container field scope #{}. Parent: #{}", .{ field_scope_index.uniqueInteger(), scope_index.uniqueInteger() });
|
||||||
|
|
||||||
|
switch (container_type) {
|
||||||
|
.@"struct" => {
|
||||||
|
{
|
||||||
|
const struct_type_general = analyzer.module.types.array.get(container_type_index);
|
||||||
|
const struct_type = analyzer.module.types.structs.get(struct_type_general.@"struct");
|
||||||
|
struct_type.fields = try ArrayList(Compilation.ContainerField.Index).initCapacity(analyzer.allocator, field_nodes.items.len);
|
||||||
|
}
|
||||||
|
|
||||||
for (field_nodes.items) |field_index| {
|
for (field_nodes.items) |field_index| {
|
||||||
const field_node = analyzer.getFileNode(struct_file_index, field_index);
|
const field_node = analyzer.getFileNode(file_index, field_index);
|
||||||
const identifier = analyzer.tokenIdentifier(field_scope_index, field_node.token);
|
const identifier = analyzer.tokenIdentifier(field_scope_index, field_node.token);
|
||||||
|
const file_path = analyzer.module.values.files.get(file_index).relative_path;
|
||||||
|
logln(.sema, .type, "Field node index for '{s}' in file {s}", .{ identifier, file_path });
|
||||||
const identifier_index = try analyzer.processIdentifier(identifier);
|
const identifier_index = try analyzer.processIdentifier(identifier);
|
||||||
const type_index = try analyzer.resolveType(.{
|
const type_index = try analyzer.resolveType(.{
|
||||||
.scope_index = field_scope_index,
|
.scope_index = field_scope_index,
|
||||||
@ -2624,30 +2750,75 @@ const Analyzer = struct {
|
|||||||
.allow_non_primitive_size = !backing_type.invalid,
|
.allow_non_primitive_size = !backing_type.invalid,
|
||||||
});
|
});
|
||||||
|
|
||||||
const default_value = if (field_node.right.invalid) Value.Index.invalid else blk: {
|
const default_value = if (field_node.right.invalid) Value.Index.invalid else try analyzer.module.values.array.append(analyzer.allocator, .{
|
||||||
const index = try analyzer.unresolvedAllocate(field_scope_index, ExpectType{
|
.unresolved = .{
|
||||||
.type_index = type_index,
|
.node_index = field_node.right,
|
||||||
}, field_node.right);
|
},
|
||||||
break :blk index;
|
});
|
||||||
};
|
|
||||||
|
|
||||||
const container_field_index = try analyzer.module.types.container_fields.append(analyzer.allocator, .{
|
const container_field_index = try analyzer.module.types.container_fields.append(analyzer.allocator, .{
|
||||||
.name = identifier_index,
|
.name = identifier_index,
|
||||||
.type = type_index,
|
.type = type_index,
|
||||||
.default_value = default_value,
|
.default_value = default_value,
|
||||||
.parent = struct_type_index,
|
.parent = container_type_index,
|
||||||
});
|
});
|
||||||
|
|
||||||
analyzer.module.types.structs.get(struct_index).fields.appendAssumeCapacity(container_field_index);
|
{
|
||||||
|
const struct_type_general = analyzer.module.types.array.get(container_type_index);
|
||||||
|
const struct_type = analyzer.module.types.structs.get(struct_type_general.@"struct");
|
||||||
|
struct_type.fields.appendAssumeCapacity(container_field_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.@"enum" => {
|
||||||
|
{
|
||||||
|
const enum_type_general = analyzer.module.types.array.get(container_type_index);
|
||||||
|
const enum_type = analyzer.module.types.enums.get(enum_type_general.@"enum");
|
||||||
|
enum_type.fields = try ArrayList(Compilation.Enum.Field.Index).initCapacity(analyzer.allocator, field_nodes.items.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (field_nodes.items) |field_node_index| {
|
||||||
|
const field_node = analyzer.getScopeNode(scope_index, field_node_index);
|
||||||
|
assert(field_node.id == .enum_field);
|
||||||
|
|
||||||
|
const identifier = analyzer.tokenIdentifier(scope_index, field_node.token);
|
||||||
|
logln(.sema, .node, "Enum field: {s}", .{identifier});
|
||||||
|
const enum_value = switch (field_node.left.invalid) {
|
||||||
|
false => try analyzer.unresolvedAllocate(scope_index, ExpectType{
|
||||||
|
.type_index = Type.usize,
|
||||||
|
}, field_node.left),
|
||||||
|
true => Value.Index.invalid,
|
||||||
|
};
|
||||||
|
|
||||||
|
const enum_hash_name = try analyzer.processIdentifier(identifier);
|
||||||
|
|
||||||
|
const enum_field_index = try analyzer.module.types.enum_fields.append(analyzer.allocator, .{
|
||||||
|
.name = enum_hash_name,
|
||||||
|
.value = enum_value,
|
||||||
|
.parent = container_type_index,
|
||||||
|
});
|
||||||
|
|
||||||
|
const enum_type_general = analyzer.module.types.array.get(container_type_index);
|
||||||
|
const enum_type = analyzer.module.types.enums.get(enum_type_general.@"enum");
|
||||||
|
enum_type.fields.appendAssumeCapacity(enum_field_index);
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return struct_type_index;
|
// TODO: consider iterating over scope declarations instead?
|
||||||
} else {
|
for (declaration_nodes.items) |declaration_node_index| {
|
||||||
return Type.Index.invalid;
|
const declaration_node = analyzer.getFileNode(file_index, declaration_node_index);
|
||||||
|
switch (declaration_node.id) {
|
||||||
|
.@"comptime" => _ = try analyzer.comptimeBlock(scope_index, declaration_node_index),
|
||||||
|
.simple_symbol_declaration => {},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return container_type_index;
|
||||||
|
}
|
||||||
|
|
||||||
fn declarationCommon(analyzer: *Analyzer, scope_index: Scope.Index, scope_type: ScopeType, mutability: Compilation.Mutability, name: []const u8, type_index: Type.Index, init_value: Value.Index, argument_index: ?u32) !Declaration.Index {
|
fn declarationCommon(analyzer: *Analyzer, scope_index: Scope.Index, scope_type: ScopeType, mutability: Compilation.Mutability, name: []const u8, type_index: Type.Index, init_value: Value.Index, argument_index: ?u32) !Declaration.Index {
|
||||||
const identifier_index = try analyzer.processIdentifier(name);
|
const identifier_index = try analyzer.processIdentifier(name);
|
||||||
|
|
||||||
@ -2679,6 +2850,7 @@ const Analyzer = struct {
|
|||||||
assert(declaration_node.id == .simple_symbol_declaration);
|
assert(declaration_node.id == .simple_symbol_declaration);
|
||||||
const expected_identifier_token_index = declaration_node.token + 1;
|
const expected_identifier_token_index = declaration_node.token + 1;
|
||||||
const identifier = analyzer.tokenIdentifier(scope_index, expected_identifier_token_index);
|
const identifier = analyzer.tokenIdentifier(scope_index, expected_identifier_token_index);
|
||||||
|
logln(.sema, .type, "Analyzing '{s}' declaration in {s} scope #{}", .{ identifier, @tagName(scope_type), scope_index.uniqueInteger() });
|
||||||
|
|
||||||
const expect_type = switch (declaration_node.left.invalid) {
|
const expect_type = switch (declaration_node.left.invalid) {
|
||||||
false => switch (scope_type) {
|
false => switch (scope_type) {
|
||||||
@ -2740,9 +2912,12 @@ const Analyzer = struct {
|
|||||||
|
|
||||||
fn getContainerMemberType(member_id: Node.Id) MemberType {
|
fn getContainerMemberType(member_id: Node.Id) MemberType {
|
||||||
return switch (member_id) {
|
return switch (member_id) {
|
||||||
.@"comptime" => .declaration,
|
.@"comptime",
|
||||||
.simple_symbol_declaration => .declaration,
|
.simple_symbol_declaration,
|
||||||
.container_field => .field,
|
=> .declaration,
|
||||||
|
.enum_field,
|
||||||
|
.container_field,
|
||||||
|
=> .field,
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -2824,10 +2999,10 @@ const Analyzer = struct {
|
|||||||
.type_index => |type_index| blk: {
|
.type_index => |type_index| blk: {
|
||||||
if (source.eq(type_index)) {
|
if (source.eq(type_index)) {
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
} else {
|
||||||
|
|
||||||
const destination_type = analyzer.module.types.array.get(type_index);
|
const destination_type = analyzer.module.types.array.get(type_index);
|
||||||
const source_type = analyzer.module.types.array.get(source);
|
const source_type = analyzer.module.types.array.get(source);
|
||||||
|
|
||||||
break :blk switch (source_type.*) {
|
break :blk switch (source_type.*) {
|
||||||
.integer => |integer| switch (destination_type.*) {
|
.integer => |integer| switch (destination_type.*) {
|
||||||
.optional => |optional| switch (analyzer.module.types.array.get(optional.element_type).*) {
|
.optional => |optional| switch (analyzer.module.types.array.get(optional.element_type).*) {
|
||||||
@ -2843,10 +3018,27 @@ const Analyzer = struct {
|
|||||||
.pointer => .success,
|
.pointer => .success,
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
},
|
},
|
||||||
|
else => .success,
|
||||||
|
},
|
||||||
|
.@"enum" => |enum_type_descriptor| switch (destination_type.*) {
|
||||||
|
.integer => |integer| {
|
||||||
|
_ = integer;
|
||||||
|
const enum_type = analyzer.module.types.enums.get(enum_type_descriptor);
|
||||||
|
if (!enum_type.backing_type.invalid) {
|
||||||
|
if (enum_type.backing_type.eq(type_index)) {
|
||||||
|
unreachable;
|
||||||
|
} else {
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return .success;
|
||||||
|
}
|
||||||
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
},
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
|
}
|
||||||
},
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
@ -3046,6 +3238,42 @@ const Analyzer = struct {
|
|||||||
},
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
},
|
},
|
||||||
|
.slice => |destination_slice| switch (source_type.*) {
|
||||||
|
.slice => |source_slice| {
|
||||||
|
if (destination_slice.@"const" or destination_slice.@"const" == source_slice.@"const") {
|
||||||
|
if (destination_slice.element_type.eq(source_slice.element_type)) {
|
||||||
|
return .success;
|
||||||
|
} else {
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
@panic("Const mismatch");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.pointer => |source_pointer| {
|
||||||
|
const source_pointer_element_type = analyzer.module.types.array.get(source_pointer.element_type);
|
||||||
|
switch (source_pointer_element_type.*) {
|
||||||
|
.array => |array| {
|
||||||
|
logln(.sema, .type, "Destination slice: {}", .{destination_slice});
|
||||||
|
if (array.element_type.eq(Type.u8)) {
|
||||||
|
if (array.element_type.eq(destination_slice.element_type)) {
|
||||||
|
if (destination_slice.@"const") {
|
||||||
|
if (destination_slice.@"const" == source_pointer.@"const") {
|
||||||
|
if (source_pointer.many) {
|
||||||
|
return .array_coerce_to_slice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
}
|
||||||
|
//
|
||||||
|
unreachable;
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -3329,6 +3557,6 @@ pub fn analyzeFile(value_index: Value.Index, allocator: Allocator, module: *Modu
|
|||||||
const node = file.syntactic_analyzer_result.nodes.items[0];
|
const node = file.syntactic_analyzer_result.nodes.items[0];
|
||||||
const node_list_node = analyzer.getFileNode(file_index, node.left);
|
const node_list_node = analyzer.getFileNode(file_index, node.left);
|
||||||
const nodes = analyzer.getFileNodeList(file_index, node_list_node);
|
const nodes = analyzer.getFileNodeList(file_index, node_list_node);
|
||||||
const result = try analyzer.structType(value_index, Scope.Index.invalid, nodes.items, file_index, .{ .value = 0 });
|
const result = try analyzer.processContainerType(value_index, Scope.Index.invalid, nodes.items, file_index, .{ .value = 0 }, .@"struct");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -115,6 +115,7 @@ pub const Node = struct {
|
|||||||
unsigned_integer_type,
|
unsigned_integer_type,
|
||||||
signed_integer_type,
|
signed_integer_type,
|
||||||
slice_type,
|
slice_type,
|
||||||
|
const_slice_type,
|
||||||
array_type,
|
array_type,
|
||||||
argument_declaration,
|
argument_declaration,
|
||||||
compiler_intrinsic,
|
compiler_intrinsic,
|
||||||
@ -962,6 +963,7 @@ const Analyzer = struct {
|
|||||||
const next_token_index = analyzer.token_i + 1;
|
const next_token_index = analyzer.token_i + 1;
|
||||||
if (next_token_index < analyzer.tokens.len) {
|
if (next_token_index < analyzer.tokens.len) {
|
||||||
const next_token_id = analyzer.tokens[next_token_index].id;
|
const next_token_id = analyzer.tokens[next_token_index].id;
|
||||||
|
const next_to_next_token_id = analyzer.tokens[next_token_index + 1].id;
|
||||||
break :blk switch (token.id) {
|
break :blk switch (token.id) {
|
||||||
.equal => switch (next_token_id) {
|
.equal => switch (next_token_id) {
|
||||||
.equal => .compare_equal,
|
.equal => .compare_equal,
|
||||||
@ -1002,8 +1004,12 @@ const Analyzer = struct {
|
|||||||
else => .divide,
|
else => .divide,
|
||||||
},
|
},
|
||||||
.less => switch (next_token_id) {
|
.less => switch (next_token_id) {
|
||||||
.less => .shift_left,
|
.less => switch (next_to_next_token_id) {
|
||||||
else => unreachable,
|
.equal => unreachable,
|
||||||
|
else => .shift_left,
|
||||||
|
},
|
||||||
|
.equal => .compare_less_or_equal,
|
||||||
|
else => .compare_less_than,
|
||||||
},
|
},
|
||||||
.greater => switch (next_token_id) {
|
.greater => switch (next_token_id) {
|
||||||
.greater => .shift_right,
|
.greater => .shift_right,
|
||||||
@ -1284,10 +1290,14 @@ const Analyzer = struct {
|
|||||||
|
|
||||||
_ = try analyzer.expectToken(.right_bracket);
|
_ = try analyzer.expectToken(.right_bracket);
|
||||||
|
|
||||||
switch (length_expression.invalid) {
|
const is_const = switch (length_expression.invalid) {
|
||||||
true => analyzer.token_i += @intFromBool(analyzer.tokens[analyzer.token_i].id == .fixed_keyword_const),
|
true => blk: {
|
||||||
false => {},
|
const is_constant = analyzer.tokens[analyzer.token_i].id == .fixed_keyword_const;
|
||||||
}
|
analyzer.token_i += @intFromBool(is_constant);
|
||||||
|
break :blk is_constant;
|
||||||
|
},
|
||||||
|
false => false,
|
||||||
|
};
|
||||||
|
|
||||||
const type_expression = try analyzer.typeExpression();
|
const type_expression = try analyzer.typeExpression();
|
||||||
const node = switch (length_expression.invalid) {
|
const node = switch (length_expression.invalid) {
|
||||||
@ -1298,7 +1308,10 @@ const Analyzer = struct {
|
|||||||
.right = type_expression,
|
.right = type_expression,
|
||||||
},
|
},
|
||||||
true => Node{ // TODO: modifiers
|
true => Node{ // TODO: modifiers
|
||||||
.id = .slice_type,
|
.id = switch (is_const) {
|
||||||
|
true => .const_slice_type,
|
||||||
|
false => .slice_type,
|
||||||
|
},
|
||||||
.token = left_bracket,
|
.token = left_bracket,
|
||||||
.left = Node.Index.invalid,
|
.left = Node.Index.invalid,
|
||||||
.right = type_expression,
|
.right = type_expression,
|
||||||
@ -1551,35 +1564,15 @@ const Analyzer = struct {
|
|||||||
},
|
},
|
||||||
.fixed_keyword_enum => blk: {
|
.fixed_keyword_enum => blk: {
|
||||||
analyzer.token_i += 1;
|
analyzer.token_i += 1;
|
||||||
|
|
||||||
_ = try analyzer.expectToken(.left_brace);
|
_ = try analyzer.expectToken(.left_brace);
|
||||||
|
const node_list = try analyzer.containerMembers(.@"enum");
|
||||||
var enum_field_list = Node.List{};
|
_ = try analyzer.expectToken(.right_brace);
|
||||||
while (analyzer.tokens[analyzer.token_i].id != .right_brace) {
|
|
||||||
const enum_name_token = try analyzer.expectToken(.identifier);
|
|
||||||
const value_associated = switch (analyzer.tokens[analyzer.token_i].id) {
|
|
||||||
.comma => comma: {
|
|
||||||
analyzer.token_i += 1;
|
|
||||||
break :comma Node.Index.invalid;
|
|
||||||
},
|
|
||||||
else => |t| @panic(@tagName(t)),
|
|
||||||
};
|
|
||||||
|
|
||||||
const enum_field_node = try analyzer.addNode(.{
|
|
||||||
.id = .enum_field,
|
|
||||||
.token = enum_name_token,
|
|
||||||
.left = value_associated,
|
|
||||||
.right = Node.Index.invalid,
|
|
||||||
});
|
|
||||||
|
|
||||||
try enum_field_list.append(analyzer.allocator, enum_field_node);
|
|
||||||
}
|
|
||||||
|
|
||||||
analyzer.token_i += 1;
|
|
||||||
|
|
||||||
break :blk try analyzer.addNode(.{
|
break :blk try analyzer.addNode(.{
|
||||||
.id = .enum_type,
|
.id = .enum_type,
|
||||||
.token = token_i,
|
.token = token_i,
|
||||||
.left = try analyzer.nodeList(enum_field_list),
|
.left = try analyzer.nodeList(node_list),
|
||||||
.right = Node.Index.invalid,
|
.right = Node.Index.invalid,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -1594,7 +1587,7 @@ const Analyzer = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_ = try analyzer.expectToken(.left_brace);
|
_ = try analyzer.expectToken(.left_brace);
|
||||||
const node_list = try analyzer.containerMembers();
|
const node_list = try analyzer.containerMembers(.@"struct");
|
||||||
_ = try analyzer.expectToken(.right_brace);
|
_ = try analyzer.expectToken(.right_brace);
|
||||||
|
|
||||||
break :blk try analyzer.addNode(.{
|
break :blk try analyzer.addNode(.{
|
||||||
@ -1633,7 +1626,7 @@ const Analyzer = struct {
|
|||||||
if (analyzer.tokens[analyzer.token_i].id == .period and analyzer.token_i + 1 < analyzer.tokens.len and analyzer.tokens[analyzer.token_i + 1].id == .period) {
|
if (analyzer.tokens[analyzer.token_i].id == .period and analyzer.token_i + 1 < analyzer.tokens.len and analyzer.tokens[analyzer.token_i + 1].id == .period) {
|
||||||
analyzer.token_i += 2;
|
analyzer.token_i += 2;
|
||||||
const range_end_expression = switch (analyzer.tokens[analyzer.token_i].id) {
|
const range_end_expression = switch (analyzer.tokens[analyzer.token_i].id) {
|
||||||
.right_bracket => unreachable,
|
.right_bracket => Node.Index.invalid,
|
||||||
else => try analyzer.expression(),
|
else => try analyzer.expression(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1736,11 +1729,12 @@ const Analyzer = struct {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn containerMembers(analyzer: *Analyzer) !ArrayList(Node.Index) {
|
fn containerMembers(analyzer: *Analyzer, comptime container_type: Compilation.ContainerType) !ArrayList(Node.Index) {
|
||||||
var list = ArrayList(Node.Index){};
|
var list = ArrayList(Node.Index){};
|
||||||
while (analyzer.token_i < analyzer.tokens.len and analyzer.tokens[analyzer.token_i].id != .right_brace) {
|
while (analyzer.token_i < analyzer.tokens.len and analyzer.tokens[analyzer.token_i].id != .right_brace) {
|
||||||
const first = analyzer.token_i;
|
const first = analyzer.token_i;
|
||||||
logln(.parser, .container_members, "First token for container member: {s}", .{@tagName(analyzer.tokens[first].id)});
|
logln(.parser, .container_members, "First token for container member: {s}", .{@tagName(analyzer.tokens[first].id)});
|
||||||
|
|
||||||
const member_node_index: Node.Index = switch (analyzer.tokens[first].id) {
|
const member_node_index: Node.Index = switch (analyzer.tokens[first].id) {
|
||||||
.fixed_keyword_comptime => switch (analyzer.tokens[analyzer.token_i + 1].id) {
|
.fixed_keyword_comptime => switch (analyzer.tokens[analyzer.token_i + 1].id) {
|
||||||
.left_brace => blk: {
|
.left_brace => blk: {
|
||||||
@ -1758,13 +1752,19 @@ const Analyzer = struct {
|
|||||||
},
|
},
|
||||||
.identifier => blk: {
|
.identifier => blk: {
|
||||||
analyzer.token_i += 1;
|
analyzer.token_i += 1;
|
||||||
|
switch (container_type) {
|
||||||
|
.@"struct" => {
|
||||||
_ = try analyzer.expectToken(.colon);
|
_ = try analyzer.expectToken(.colon);
|
||||||
|
|
||||||
const field_type = try analyzer.typeExpression();
|
const field_type = try analyzer.typeExpression();
|
||||||
|
|
||||||
const field_default_node = if (analyzer.tokens[analyzer.token_i].id == .equal) b: {
|
const field_default_node = if (analyzer.tokens[analyzer.token_i].id == .equal) b: {
|
||||||
analyzer.token_i += 1;
|
analyzer.token_i += 1;
|
||||||
break :b try analyzer.expression();
|
const default_index = try analyzer.expression();
|
||||||
|
const default_node = analyzer.nodes.items[default_index.unwrap()];
|
||||||
|
_ = default_node;
|
||||||
|
assert(.id != .node_list);
|
||||||
|
break :b default_index;
|
||||||
} else Node.Index.invalid;
|
} else Node.Index.invalid;
|
||||||
|
|
||||||
_ = try analyzer.expectToken(.comma);
|
_ = try analyzer.expectToken(.comma);
|
||||||
@ -1778,6 +1778,28 @@ const Analyzer = struct {
|
|||||||
|
|
||||||
break :blk field_node;
|
break :blk field_node;
|
||||||
},
|
},
|
||||||
|
.@"enum" => {
|
||||||
|
const value_associated = switch (analyzer.tokens[analyzer.token_i].id) {
|
||||||
|
.comma => Node.Index.invalid,
|
||||||
|
else => value: {
|
||||||
|
analyzer.token_i += 1;
|
||||||
|
break :value try analyzer.expression();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
_ = try analyzer.expectToken(.comma);
|
||||||
|
|
||||||
|
const enum_field_node = try analyzer.addNode(.{
|
||||||
|
.id = .enum_field,
|
||||||
|
.token = first,
|
||||||
|
.left = value_associated,
|
||||||
|
.right = Node.Index.invalid,
|
||||||
|
});
|
||||||
|
|
||||||
|
break :blk enum_field_node;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
.fixed_keyword_const, .fixed_keyword_var => try analyzer.symbolDeclaration(),
|
.fixed_keyword_const, .fixed_keyword_var => try analyzer.symbolDeclaration(),
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
@ -1808,7 +1830,7 @@ pub fn analyze(allocator: Allocator, tokens: []const Token, source_file: []const
|
|||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
};
|
};
|
||||||
const node_index = try analyzer.addNode(.{
|
const node_index = try analyzer.addNode(.{
|
||||||
.id = .main,
|
.id = .struct_type,
|
||||||
.token = 0,
|
.token = 0,
|
||||||
.left = Node.Index.invalid,
|
.left = Node.Index.invalid,
|
||||||
.right = Node.Index.invalid,
|
.right = Node.Index.invalid,
|
||||||
@ -1817,12 +1839,11 @@ pub fn analyze(allocator: Allocator, tokens: []const Token, source_file: []const
|
|||||||
assert(node_index.value == 0);
|
assert(node_index.value == 0);
|
||||||
assert(!node_index.invalid);
|
assert(!node_index.invalid);
|
||||||
|
|
||||||
const members = try analyzer.containerMembers();
|
const members = try analyzer.containerMembers(.@"struct");
|
||||||
assert(analyzer.token_i == analyzer.tokens.len);
|
assert(analyzer.token_i == analyzer.tokens.len);
|
||||||
|
|
||||||
const node_list = try analyzer.nodeList(members);
|
const node_list = try analyzer.nodeList(members);
|
||||||
|
|
||||||
analyzer.nodes.items[0].id = .main;
|
|
||||||
analyzer.nodes.items[0].left = node_list;
|
analyzer.nodes.items[0].left = node_list;
|
||||||
|
|
||||||
const end = std.time.Instant.now() catch unreachable;
|
const end = std.time.Instant.now() catch unreachable;
|
||||||
|
13
build.zig
13
build.zig
@ -17,14 +17,16 @@ pub fn build(b: *std.Build) !void {
|
|||||||
exe.unwind_tables = false;
|
exe.unwind_tables = false;
|
||||||
exe.omit_frame_pointer = false;
|
exe.omit_frame_pointer = false;
|
||||||
|
|
||||||
b.installArtifact(exe);
|
const install_exe = b.addInstallArtifact(exe, .{});
|
||||||
|
b.getInstallStep().dependOn(&install_exe.step);
|
||||||
b.installDirectory(.{
|
b.installDirectory(.{
|
||||||
.source_dir = std.Build.LazyPath.relative("lib"),
|
.source_dir = std.Build.LazyPath.relative("lib"),
|
||||||
.install_dir = .bin,
|
.install_dir = .bin,
|
||||||
.install_subdir = "lib",
|
.install_subdir = "lib",
|
||||||
});
|
});
|
||||||
|
|
||||||
const run_command = b.addRunArtifact(exe);
|
const compiler_exe_path = b.fmt("zig-out/bin/{s}", .{install_exe.dest_sub_path});
|
||||||
|
const run_command = b.addSystemCommand(&.{compiler_exe_path});
|
||||||
run_command.step.dependOn(b.getInstallStep());
|
run_command.step.dependOn(b.getInstallStep());
|
||||||
|
|
||||||
const debug_command = switch (@import("builtin").os.tag) {
|
const debug_command = switch (@import("builtin").os.tag) {
|
||||||
@ -34,13 +36,12 @@ pub fn build(b: *std.Build) !void {
|
|||||||
result.addArg("-ex=r");
|
result.addArg("-ex=r");
|
||||||
result.addArgs(&.{ "-ex", "up" });
|
result.addArgs(&.{ "-ex", "up" });
|
||||||
result.addArg("--args");
|
result.addArg("--args");
|
||||||
result.addArtifactArg(exe);
|
|
||||||
break :blk result;
|
break :blk result;
|
||||||
},
|
},
|
||||||
.windows => blk: {
|
.windows => blk: {
|
||||||
const result = b.addSystemCommand(&.{"remedybg"});
|
const result = b.addSystemCommand(&.{"remedybg"});
|
||||||
result.addArg("-g");
|
result.addArg("-g");
|
||||||
result.addArtifactArg(exe);
|
result.addArg(compiler_exe_path);
|
||||||
|
|
||||||
break :blk result;
|
break :blk result;
|
||||||
},
|
},
|
||||||
@ -48,11 +49,13 @@ pub fn build(b: *std.Build) !void {
|
|||||||
// not tested
|
// not tested
|
||||||
const result = b.addSystemCommand(&.{"lldb"});
|
const result = b.addSystemCommand(&.{"lldb"});
|
||||||
result.addArg("--");
|
result.addArg("--");
|
||||||
result.addArtifactArg(exe);
|
result.addArg(compiler_exe_path);
|
||||||
break :blk result;
|
break :blk result;
|
||||||
},
|
},
|
||||||
else => @compileError("OS not supported"),
|
else => @compileError("OS not supported"),
|
||||||
};
|
};
|
||||||
|
debug_command.step.dependOn(b.getInstallStep());
|
||||||
|
debug_command.addArg(compiler_exe_path);
|
||||||
|
|
||||||
if (b.args) |args| {
|
if (b.args) |args| {
|
||||||
run_command.addArgs(args);
|
run_command.addArgs(args);
|
||||||
|
8
ci.sh
8
ci.sh
@ -1,7 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
echo "Testing Nativity with Zig"
|
echo -e "\e[90mCompiling Nativity with Zig...\e[0m"
|
||||||
echo "Compiling Nativity with Zig"
|
|
||||||
nativity_use_llvm=true
|
nativity_use_llvm=true
|
||||||
zig build -Duse_llvm=$nativity_use_llvm
|
zig build -Duse_llvm=$nativity_use_llvm
|
||||||
failed_test_count=0
|
failed_test_count=0
|
||||||
@ -51,10 +50,11 @@ do
|
|||||||
done
|
done
|
||||||
|
|
||||||
printf "\n"
|
printf "\n"
|
||||||
echo "[SUMMARY]"
|
echo -e "\e[35m[SUMMARY]\e[0m"
|
||||||
echo "========="
|
echo -e "\e[35m=========\e[0m"
|
||||||
echo -e "Ran $total_test_count compilations (\e[32m$passed_compilation_count\e[0m succeeded, \e[31m$failed_compilation_count\e[0m failed)."
|
echo -e "Ran $total_test_count compilations (\e[32m$passed_compilation_count\e[0m succeeded, \e[31m$failed_compilation_count\e[0m failed)."
|
||||||
echo -e "Ran $ran_test_count tests (\e[32m $passed_test_count\e[0m passed, \e[31m$failed_test_count\e[0m failed)."
|
echo -e "Ran $ran_test_count tests (\e[32m $passed_test_count\e[0m passed, \e[31m$failed_test_count\e[0m failed)."
|
||||||
|
echo -e "\e[35m=========\e[0m"
|
||||||
|
|
||||||
if [[ "$failed_compilation_count" != "0" ]]; then
|
if [[ "$failed_compilation_count" != "0" ]]; then
|
||||||
printf $"\nFailed compilations:\n"
|
printf $"\nFailed compilations:\n"
|
||||||
|
@ -7,31 +7,6 @@ const system = switch (current) {
|
|||||||
.windows => windows,
|
.windows => windows,
|
||||||
};
|
};
|
||||||
|
|
||||||
const write = fn (file_descriptor: FileDescriptor, bytes_ptr: [&]const u8, bytes_len: usize) ssize {
|
|
||||||
switch (current) {
|
|
||||||
.linux => return #syscall(1, file_descriptor, #cast(bytes_ptr), bytes_len),
|
|
||||||
.macos => return macos.write(file_descriptor, #cast(bytes_ptr), bytes_len),
|
|
||||||
.windows => {
|
|
||||||
var written_bytes: u32 = 0;
|
|
||||||
if (windows.WriteFile(file_descriptor, bytes_ptr, bytes_len, written_bytes.&, false) != 0) {
|
|
||||||
return written_bytes;
|
|
||||||
} else {
|
|
||||||
unreachable;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const FileDescriptor = system.FileDescriptor;
|
|
||||||
|
|
||||||
const print = fn(bytes_ptr: [&]const u8, bytes_len: usize) void {
|
|
||||||
const file_descriptor = switch (current) {
|
|
||||||
.linux, .macos => 2,
|
|
||||||
.windows => windows.GetStdHandle(windows.STD_OUTPUT_HANDLE),
|
|
||||||
};
|
|
||||||
|
|
||||||
_ = write(file_descriptor, bytes_ptr, bytes_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
const exit = fn(exit_code: s32) noreturn {
|
const exit = fn(exit_code: s32) noreturn {
|
||||||
switch (current) {
|
switch (current) {
|
||||||
@ -106,12 +81,12 @@ const max_path_byte_count = switch (current) {
|
|||||||
else => #error("OS not supported"),
|
else => #error("OS not supported"),
|
||||||
};
|
};
|
||||||
|
|
||||||
const currentExecutablePath = fn(allocator: &Allocator) ?[]u8 {
|
const current_executable_path = fn(allocator: &Allocator) ?[]u8 {
|
||||||
switch (current) {
|
switch (current) {
|
||||||
.linux => {
|
.linux => {
|
||||||
var buffer: [max_path_byte_count]u8 = undefined;
|
var buffer: [max_path_byte_count]u8 = undefined;
|
||||||
if (readlink(file_path = "/proc/self/exe", buffer = buffer.&)) |bytes| {
|
if (readlink(file_path = "/proc/self/exe", buffer = buffer.&)) |bytes| {
|
||||||
if (allocator.duplicateBytes(bytes)) |result| {
|
if (allocator.duplicate_bytes(bytes)) |result| {
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
@ -124,6 +99,42 @@ const currentExecutablePath = fn(allocator: &Allocator) ?[]u8 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const FileDescriptor = struct{
|
||||||
|
handle: system.FileDescriptor,
|
||||||
|
|
||||||
|
const write = fn (file_descriptor: FileDescriptor, bytes: []const u8) ?usize {
|
||||||
|
switch (current) {
|
||||||
|
.linux => {
|
||||||
|
const raw_result = #syscall(1, file_descriptor.handle, #cast(bytes.ptr), bytes.len);
|
||||||
|
if (linux.unwrapSyscall(syscall_result = raw_result)) |byte_count| {
|
||||||
|
return byte_count;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => #error("OS not supported"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const StdFileDescriptor = enum {
|
||||||
|
stdin = 0,
|
||||||
|
stdout = 1,
|
||||||
|
stderr = 2,
|
||||||
|
|
||||||
|
const get = fn(descriptor: StdFileDescriptor) FileDescriptor{
|
||||||
|
switch (current) {
|
||||||
|
.linux, .macos => {
|
||||||
|
return FileDescriptor{
|
||||||
|
.handle = #cast(descriptor),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
else => #error("OS not supported"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const linux = #import("os/linux.nat");
|
const linux = #import("os/linux.nat");
|
||||||
const macos = #import("os/macos.nat");
|
const macos = #import("os/macos.nat");
|
||||||
const windows = #import("os/windows.nat");
|
const windows = #import("os/windows.nat");
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
const std = #import("std");
|
const std = #import("std");
|
||||||
|
|
||||||
|
const stdin: FileDescriptor = 0;
|
||||||
|
const stdout: FileDescriptor = 1;
|
||||||
|
const stderr: FileDescriptor = 2;
|
||||||
|
|
||||||
const FileDescriptor = s32;
|
const FileDescriptor = s32;
|
||||||
|
|
||||||
const ProtectionFlags = struct(u32) {
|
const ProtectionFlags = struct(u32) {
|
||||||
|
@ -4,7 +4,6 @@ comptime {
|
|||||||
|
|
||||||
const builtin = #import("builtin.nat");
|
const builtin = #import("builtin.nat");
|
||||||
const os = #import("os.nat");
|
const os = #import("os.nat");
|
||||||
const print = os.print;
|
|
||||||
const start = #import("start.nat");
|
const start = #import("start.nat");
|
||||||
|
|
||||||
const assert = fn(ok: bool) void {
|
const assert = fn(ok: bool) void {
|
||||||
@ -13,6 +12,14 @@ const assert = fn(ok: bool) void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const print = fn(bytes: []const u8) void {
|
||||||
|
const file_descriptor = os.StdFileDescriptor.get(descriptor = .stdout);
|
||||||
|
const file_writer = FileWriter{
|
||||||
|
.descriptor = file_descriptor,
|
||||||
|
};
|
||||||
|
_ = file_writer.writeAll(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
const Allocator = struct {
|
const Allocator = struct {
|
||||||
handler: &const fn(allocator: &Allocator, old_ptr: ?[&]const u8, old_size: usize, new_size: usize, alignment: u16) ?[&]u8,
|
handler: &const fn(allocator: &Allocator, old_ptr: ?[&]const u8, old_size: usize, new_size: usize, alignment: u16) ?[&]u8,
|
||||||
|
|
||||||
@ -32,9 +39,9 @@ const Allocator = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const duplicateBytes = fn (allocator: &Allocator, bytes: []const u8) ?[]u8 {
|
const duplicate_bytes = fn (allocator: &Allocator, bytes: []const u8) ?[]u8 {
|
||||||
if (allocator.allocate(size = bytes.len, alignment = 0)) |result| {
|
if (allocator.allocate(size = bytes.len, alignment = 0)) |result| {
|
||||||
copyBytes(destination = result, source = bytes);
|
copy_bytes(destination = result, source = bytes);
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
@ -89,12 +96,38 @@ const PageAllocator = struct{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getAllocator = fn(page_allocator: &PageAllocator) &Allocator {
|
const get_allocator = fn(page_allocator: &PageAllocator) &Allocator {
|
||||||
return page_allocator.allocator.&;
|
return page_allocator.allocator.&;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const copyBytes = fn(destination: []u8, source: []const u8) void {
|
const Writer = struct{
|
||||||
|
callback: &const fn(writer: &Writer, bytes: []const u8) ?usize,
|
||||||
|
};
|
||||||
|
|
||||||
|
const FileWriter = struct{
|
||||||
|
descriptor: os.FileDescriptor,
|
||||||
|
|
||||||
|
const write = fn(file_writer: FileWriter, bytes: []const u8) ?usize {
|
||||||
|
return file_writer.descriptor.write(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
const writeAll = fn(file_writer: FileWriter, bytes: []const u8) bool {
|
||||||
|
var bytes_written: usize = 0;
|
||||||
|
|
||||||
|
while (bytes_written < bytes.len) {
|
||||||
|
if (file_writer.write(bytes = bytes[bytes_written..])) |iteration_written_byte_count| {
|
||||||
|
bytes_written += iteration_written_byte_count;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes_written == bytes.len;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const copy_bytes = fn(destination: []u8, source: []const u8) void {
|
||||||
assert(ok = destination.len == source.len);
|
assert(ok = destination.len == source.len);
|
||||||
for (0..destination.len) |i| {
|
for (0..destination.len) |i| {
|
||||||
destination[i] = source[i];
|
destination[i] = source[i];
|
||||||
|
@ -4,16 +4,16 @@ const main = fn() s32 {
|
|||||||
const size = 0x1000;
|
const size = 0x1000;
|
||||||
if (std.page_allocator.allocate(size, alignment = 12)) |result| {
|
if (std.page_allocator.allocate(size, alignment = 12)) |result| {
|
||||||
result[0] = 0;
|
result[0] = 0;
|
||||||
std.print(bytes_ptr = "Allocation succeeded. Freeing...\n", bytes_len = 33);
|
std.print(bytes = "Allocation succeeded. Freeing...\n");
|
||||||
if (std.page_allocator.free(bytes_ptr = result.ptr, bytes_len = result.len)) {
|
if (std.page_allocator.free(bytes_ptr = result.ptr, bytes_len = result.len)) {
|
||||||
std.print(bytes_ptr = "Memory freed successfully\n", bytes_len = 26);
|
std.print(bytes = "Memory freed successfully\n");
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
std.print(bytes_ptr = "Memory freed with errors\n", bytes_len = 25);
|
std.print("Memory freed with errors\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
std.print(bytes_ptr = "Allocation failed!\n", bytes_len = 19);
|
std.print(bytes = "Allocation failed!\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
const std = #import("std");
|
const std = #import("std");
|
||||||
|
|
||||||
const main = fn() s32 {
|
const main = fn() s32 {
|
||||||
std.print(bytes_ptr = "Hello world!\n", bytes_len = 13);
|
std.print(bytes = "Hello world!\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,12 @@ const std = #import("std");
|
|||||||
const print = std.print;
|
const print = std.print;
|
||||||
|
|
||||||
const main = fn () s32 {
|
const main = fn () s32 {
|
||||||
if (std.os.currentExecutablePath(allocator = std.page_allocator.allocator.&)) |result| {
|
if (std.os.current_executable_path(allocator = std.page_allocator.allocator.&)) |bytes| {
|
||||||
print(bytes_ptr = result.ptr, bytes_len = result.len);
|
print(bytes);
|
||||||
print(bytes_ptr = "\n", bytes_len = 1);
|
print(bytes = "\n");
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
print(bytes_ptr = "Failed\n", bytes_len = 7);
|
print(bytes = "Failed\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,16 +4,16 @@ const main = fn() s32 {
|
|||||||
const size = 0x1000;
|
const size = 0x1000;
|
||||||
if (std.page_allocator.allocate(size, alignment = 12)) |result| {
|
if (std.page_allocator.allocate(size, alignment = 12)) |result| {
|
||||||
result[0] = 0;
|
result[0] = 0;
|
||||||
std.print(bytes_ptr = "Allocation succeeded. Freeing...\n", bytes_len = 33);
|
std.print(bytes = "Allocation succeeded. Freeing...\n");
|
||||||
if (std.page_allocator.free(bytes_ptr = result.ptr, bytes_len = result.len)) {
|
if (std.page_allocator.free(bytes_ptr = result.ptr, bytes_len = result.len)) {
|
||||||
std.print(bytes_ptr = "Memory freed successfully\n", bytes_len = 26);
|
std.print(bytes = "Memory freed successfully\n");
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
std.print(bytes_ptr = "Memory freed with errors\n", bytes_len = 25);
|
std.print(bytes = "Memory freed with errors\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
std.print(bytes_ptr = "Allocation failed!\n", bytes_len = 19);
|
std.print(bytes = "Allocation failed!\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user