nativity/lib/std/std.nat
David Gonzalez Martin 347ba162a8 Implement fork
2023-12-02 23:47:49 -06:00

145 lines
4.2 KiB
Plaintext

comptime {
_ = start;
}
const build = #import("build.nat");
const builtin = #import("builtin.nat");
const os = #import("os.nat");
const start = #import("start.nat");
const assert = fn(ok: bool) void {
if (!ok) {
unreachable;
}
}
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 {
handler: &const fn(allocator: &Allocator, old_ptr: ?[&]const u8, old_size: usize, new_size: usize, alignment: u16) ?[&]u8,
const allocate = fn (allocator: &Allocator, size: usize, alignment: u16) ?[]u8 {
if (allocator.handler(allocator, old_ptr = null, old_size = 0, new_size = size, alignment)) |result| {
return result[0..size];
} else {
return null;
}
}
const free = fn (allocator: &Allocator, bytes_ptr: [&]const u8, bytes_len: usize) bool {
if (allocator.handler(allocator, old_ptr = bytes_ptr, old_size = bytes_len, new_size = 0, alignment = 0)) |_| {
return true;
} else {
return false;
}
}
const duplicate_bytes = fn (allocator: &Allocator, bytes: []const u8) ?[]u8 {
if (allocator.allocate(size = bytes.len, alignment = 0)) |result| {
copy_bytes(destination = result, source = bytes);
return result;
} else {
return null;
}
}
};
const PageAllocator = struct{
allocator: Allocator = .{
.handler = handler.&,
},
const allocate = fn (a: &PageAllocator, size: usize, alignment: u16) ?[]u8 {
const result = a.allocator.allocate(size, alignment);
return result;
}
const free = fn (a: &PageAllocator, bytes_ptr: [&]const u8, bytes_len: usize) bool {
const result = a.allocator.free(bytes_ptr, bytes_len);
return result;
}
const handler = fn (allocator: &Allocator, maybe_old_ptr: ?[&]const u8, old_size: usize, new_size: usize, alignment: u16) ?[&]u8{
var maybe_new_ptr: ?[&]u8 = null;
if (new_size > 0) {
const general_protection_flags = os.ProtectionFlags{
.read = true,
.write = true,
.execute = false,
};
const general_map_flags = os.MapFlags{
.reserve = true,
.commit = true,
};
maybe_new_ptr = os.allocate_virtual_memory(address = null, length = new_size, general_protection_flags, general_map_flags);
}
if (maybe_old_ptr) |old_ptr| {
if (maybe_new_ptr) |new_ptr| {
unreachable;
}
const result = os.free_virtual_memory(bytes_ptr = old_ptr, bytes_len = old_size);
if (result) {
return #cast(old_ptr);
} else {
return null;
}
} else {
return maybe_new_ptr;
}
}
const get_allocator = fn(page_allocator: &PageAllocator) &Allocator {
return page_allocator.allocator.&;
}
};
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);
for (0..destination.len) |i| {
destination[i] = source[i];
}
}
const Target = struct {
cpu: builtin.Cpu,
os: builtin.Os,
abi: builtin.Abi,
};
var page_allocator = PageAllocator{};