Merge pull request #169 from birth-software/arena-changes
Arena changes
This commit is contained in:
commit
f4a26be735
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -3,10 +3,11 @@ const Allocator = std.mem.Allocator;
|
||||
const assert = std.debug.assert;
|
||||
const log = std.log;
|
||||
|
||||
const data_structures = @import("../library.zig");
|
||||
const enumFromString = data_structures.enumFromString;
|
||||
const MyAllocator = data_structures.MyAllocator;
|
||||
const UnpinnedArray = data_structures.UnpinnedArray;
|
||||
const library = @import("../library.zig");
|
||||
const byte_equal = library.byte_equal;
|
||||
const enumFromString = library.enumFromString;
|
||||
const MyAllocator = library.MyAllocator;
|
||||
const PinnedArray = library.PinnedArray;
|
||||
|
||||
const Compilation = @import("../Compilation.zig");
|
||||
const File = Compilation.File;
|
||||
@ -43,31 +44,31 @@ pub const Logger = enum {
|
||||
});
|
||||
};
|
||||
|
||||
pub fn analyze(allocator: *MyAllocator, text: []const u8, token_buffer: *Token.Buffer) !Result {
|
||||
pub fn analyze(text: []const u8, token_buffer: *Token.Buffer) !Result {
|
||||
assert(text.len <= std.math.maxInt(u32));
|
||||
const len: u32 = @intCast(text.len);
|
||||
|
||||
var lexer = Result{
|
||||
.offset = token_buffer.getOffset(),
|
||||
.line_offset = token_buffer.getLineOffset(),
|
||||
.offset = @enumFromInt(token_buffer.tokens.length),
|
||||
.line_offset = token_buffer.line_offsets.length,
|
||||
.count = 0,
|
||||
.line_count = 0,
|
||||
};
|
||||
|
||||
const time_start = std.time.Instant.now() catch unreachable;
|
||||
|
||||
try token_buffer.line_offsets.append(allocator, 0);
|
||||
_ = token_buffer.line_offsets.append(0);
|
||||
|
||||
for (text, 0..) |byte, index| {
|
||||
if (byte == '\n') {
|
||||
try token_buffer.line_offsets.append(allocator, @intCast(index + 1));
|
||||
_ = token_buffer.line_offsets.append(@intCast(index + 1));
|
||||
}
|
||||
}
|
||||
|
||||
var index: u32 = 0;
|
||||
var line_index: u32 = lexer.line_offset;
|
||||
|
||||
try token_buffer.ensure_with_capacity(allocator, len / 3);
|
||||
// try token_buffer.ensure_with_capacity(allocator, len / 3);
|
||||
|
||||
// logln(.lexer, .end, "START LEXER - TOKEN OFFSET: {} - LINE OFFSET: {}", .{ Token.unwrap(lexer.offset), lexer.line_offset });
|
||||
|
||||
@ -110,7 +111,7 @@ pub fn analyze(allocator: *MyAllocator, text: []const u8, token_buffer: *Token.B
|
||||
const string = text[start_index..][0 .. index - start_index];
|
||||
break :blk if (enumFromString(Compilation.FixedKeyword, string)) |fixed_keyword| switch (fixed_keyword) {
|
||||
inline else => |comptime_fixed_keyword| @field(Token.Id, "fixed_keyword_" ++ @tagName(comptime_fixed_keyword)),
|
||||
} else if (data_structures.byte_equal(string, "_")) .discard else .identifier;
|
||||
} else if (byte_equal(string, "_")) .discard else .identifier;
|
||||
},
|
||||
'0'...'9' => blk: {
|
||||
// Detect other non-decimal literals
|
||||
@ -481,7 +482,7 @@ pub fn analyze(allocator: *MyAllocator, text: []const u8, token_buffer: *Token.B
|
||||
},
|
||||
// Asm statement (special treatment)
|
||||
'`' => {
|
||||
token_buffer.append_with_capacity(.{
|
||||
_ = token_buffer.tokens.append(.{
|
||||
.id = .operator_backtick,
|
||||
.line = line_index,
|
||||
.offset = start_index,
|
||||
@ -495,6 +496,7 @@ pub fn analyze(allocator: *MyAllocator, text: []const u8, token_buffer: *Token.B
|
||||
const start_ch = text[start_i];
|
||||
|
||||
switch (start_ch) {
|
||||
'\r' => index += 1,
|
||||
'\n' => {
|
||||
index += 1;
|
||||
line_index += 1;
|
||||
@ -508,7 +510,7 @@ pub fn analyze(allocator: *MyAllocator, text: []const u8, token_buffer: *Token.B
|
||||
}
|
||||
}
|
||||
|
||||
token_buffer.append_with_capacity(.{
|
||||
_ = token_buffer.tokens.append(.{
|
||||
.id = .identifier,
|
||||
.offset = start_i,
|
||||
.length = index - start_i,
|
||||
@ -516,7 +518,7 @@ pub fn analyze(allocator: *MyAllocator, text: []const u8, token_buffer: *Token.B
|
||||
});
|
||||
},
|
||||
',' => {
|
||||
token_buffer.append_with_capacity(.{
|
||||
_ = token_buffer.tokens.append(.{
|
||||
.id = .operator_comma,
|
||||
.line = line_index,
|
||||
.offset = start_i,
|
||||
@ -525,7 +527,7 @@ pub fn analyze(allocator: *MyAllocator, text: []const u8, token_buffer: *Token.B
|
||||
index += 1;
|
||||
},
|
||||
';' => {
|
||||
token_buffer.append_with_capacity(.{
|
||||
_ = token_buffer.tokens.append(.{
|
||||
.id = .operator_semicolon,
|
||||
.line = line_index,
|
||||
.offset = start_i,
|
||||
@ -534,7 +536,7 @@ pub fn analyze(allocator: *MyAllocator, text: []const u8, token_buffer: *Token.B
|
||||
index += 1;
|
||||
},
|
||||
'{' => {
|
||||
token_buffer.append_with_capacity(.{
|
||||
_ = token_buffer.tokens.append(.{
|
||||
.id = .operator_left_brace,
|
||||
.line = line_index,
|
||||
.offset = start_i,
|
||||
@ -543,7 +545,7 @@ pub fn analyze(allocator: *MyAllocator, text: []const u8, token_buffer: *Token.B
|
||||
index += 1;
|
||||
},
|
||||
'}' => {
|
||||
token_buffer.append_with_capacity(.{
|
||||
_ = token_buffer.tokens.append(.{
|
||||
.id = .operator_right_brace,
|
||||
.line = line_index,
|
||||
.offset = start_i,
|
||||
@ -572,7 +574,7 @@ pub fn analyze(allocator: *MyAllocator, text: []const u8, token_buffer: *Token.B
|
||||
}
|
||||
}
|
||||
|
||||
token_buffer.append_with_capacity(.{
|
||||
_ = token_buffer.tokens.append(.{
|
||||
.id = .number_literal,
|
||||
.line = line_index,
|
||||
.offset = start_i,
|
||||
@ -582,11 +584,18 @@ pub fn analyze(allocator: *MyAllocator, text: []const u8, token_buffer: *Token.B
|
||||
else => unreachable,
|
||||
}
|
||||
},
|
||||
else => unreachable,
|
||||
else => {
|
||||
var ch_array : [64]u8 = undefined;
|
||||
try Compilation.write(.panic, "TODO char: 0x");
|
||||
const ch_fmt = library.format_int(&ch_array, start_ch, 16, false);
|
||||
try Compilation.write(.panic, ch_fmt);
|
||||
try Compilation.write(.panic, "\n");
|
||||
std.posix.exit(0);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
token_buffer.append_with_capacity(.{
|
||||
_ = token_buffer.tokens.append(.{
|
||||
.id = .operator_backtick,
|
||||
.line = line_index,
|
||||
.length = 1,
|
||||
@ -606,21 +615,16 @@ pub fn analyze(allocator: *MyAllocator, text: []const u8, token_buffer: *Token.B
|
||||
const end_index = index;
|
||||
const token_length = end_index - start_index;
|
||||
|
||||
token_buffer.append_with_capacity(.{
|
||||
_ = token_buffer.tokens.append(.{
|
||||
.id = token_id,
|
||||
.offset = start_index,
|
||||
.length = token_length,
|
||||
.line = line_index,
|
||||
});
|
||||
// const line_offset = token_buffer.line_offsets.pointer[line_index];
|
||||
// const column = start_index - line_offset;
|
||||
// logln(.lexer, .new_token, "T at line {}, column {}, byte offset {}, with length {} -line offset: {}- ({s})", .{ line_index, column, start_index, token_length, line_offset, @tagName(token_id) });
|
||||
}
|
||||
|
||||
// logln(.lexer, .end, "END LEXER - TOKEN OFFSET: {} - LINE OFFSET: {}", .{ Token.unwrap(lexer.offset), lexer.line_offset });
|
||||
|
||||
lexer.count = Token.sub(token_buffer.getOffset(), lexer.offset);
|
||||
lexer.line_count = token_buffer.getLineOffset() - lexer.line_offset;
|
||||
lexer.count = token_buffer.tokens.length - @intFromEnum(lexer.offset);
|
||||
lexer.line_count = token_buffer.line_offsets.length - lexer.line_offset;
|
||||
|
||||
const time_end = std.time.Instant.now() catch unreachable;
|
||||
lexer.time = time_end.since(time_start);
|
||||
|
@ -2,10 +2,14 @@ const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const assert = std.debug.assert;
|
||||
|
||||
const data_structures = @import("../library.zig");
|
||||
const UnpinnedArray = data_structures.UnpinnedArray;
|
||||
const BlockList = data_structures.BlockList;
|
||||
const enumFromString = data_structures.enumFromString;
|
||||
const library = @import("../library.zig");
|
||||
const Arena = library.Arena;
|
||||
const byte_equal = library.byte_equal;
|
||||
const BlockList = library.BlockList;
|
||||
const BoundedArray = library.BoundedArray;
|
||||
const enumFromString = library.enumFromString;
|
||||
const PinnedArray = library.PinnedArray;
|
||||
const MyAllocator = library.MyAllocator;
|
||||
|
||||
const lexer = @import("lexer.zig");
|
||||
|
||||
@ -62,8 +66,10 @@ pub const Node = struct {
|
||||
token: Token.Index,
|
||||
id: Id,
|
||||
|
||||
pub const List = BlockList(@This(), enum {});
|
||||
pub usingnamespace List.Index;
|
||||
// TODO: this is dangerous
|
||||
pub const StackList = BoundedArray(Node.Index, 512);
|
||||
|
||||
pub const Index = PinnedArray(Node).Index;
|
||||
|
||||
pub const Range = struct {
|
||||
start: u32,
|
||||
@ -226,11 +232,12 @@ const Analyzer = struct {
|
||||
lexer: lexer.Result,
|
||||
token_i: Token.Index,
|
||||
token_buffer: *Token.Buffer,
|
||||
nodes: *Node.List,
|
||||
node_lists: *UnpinnedArray(UnpinnedArray(Node.Index)),
|
||||
nodes: *PinnedArray(Node),
|
||||
node_lists: *PinnedArray([]const Node.Index),
|
||||
source_file: []const u8,
|
||||
allocator: Allocator,
|
||||
my_allocator: *data_structures.MyAllocator,
|
||||
my_allocator: *MyAllocator,
|
||||
arena: *Arena,
|
||||
suffix_depth: usize = 0,
|
||||
|
||||
fn expectToken(analyzer: *Analyzer, expected_token_id: Token.Id) !Token.Index {
|
||||
@ -259,18 +266,14 @@ const Analyzer = struct {
|
||||
}
|
||||
|
||||
fn getTokenOffset(analyzer: *Analyzer, token_index: Token.Index) u32 {
|
||||
const index = Token.unwrap(token_index);
|
||||
assert(index < analyzer.token_buffer.length);
|
||||
const offset = analyzer.token_buffer.offsets[index];
|
||||
return offset;
|
||||
const token = analyzer.token_buffer.tokens.get(token_index);
|
||||
return token.offset;
|
||||
}
|
||||
|
||||
fn peekTokenAhead(analyzer: *Analyzer, ahead_offset: u32) Token.Id {
|
||||
const token_index = Token.addInt(analyzer.token_i, ahead_offset);
|
||||
const index = Token.unwrap(token_index);
|
||||
assert(index < analyzer.token_buffer.length);
|
||||
const token = analyzer.token_buffer.ids[index];
|
||||
return token;
|
||||
const index = @intFromEnum(analyzer.token_i) + ahead_offset;
|
||||
const token = analyzer.token_buffer.tokens.get_unchecked(index);
|
||||
return token.id;
|
||||
}
|
||||
|
||||
fn peekToken(analyzer: *Analyzer) Token.Id {
|
||||
@ -280,11 +283,11 @@ const Analyzer = struct {
|
||||
|
||||
fn hasTokens(analyzer: *Analyzer) bool {
|
||||
const token_end = analyzer.getTokenEnd();
|
||||
return Token.unwrap(analyzer.token_i) < token_end;
|
||||
return @intFromEnum(analyzer.token_i) < token_end;
|
||||
}
|
||||
|
||||
fn getTokenEnd(analyzer: *const Analyzer) u32 {
|
||||
return @intFromEnum(Token.addInt(analyzer.lexer.offset, analyzer.lexer.count));
|
||||
return @intFromEnum(analyzer.lexer.offset) + analyzer.lexer.count;
|
||||
}
|
||||
|
||||
fn consumeToken(analyzer: *Analyzer) void {
|
||||
@ -292,29 +295,26 @@ const Analyzer = struct {
|
||||
}
|
||||
|
||||
fn consumeTokens(analyzer: *Analyzer, token_count: u32) void {
|
||||
assert(Token.unwrap(Token.addInt(analyzer.token_i, token_count)) <= analyzer.getTokenEnd());
|
||||
assert((@intFromEnum(analyzer.token_i) + token_count) <= analyzer.getTokenEnd());
|
||||
// log(.parser, .consume_token, "Consuming {} {s}: ", .{ token_count, if (token_count == 1) "token" else "tokens" });
|
||||
|
||||
for (0..token_count) |i_usize| {
|
||||
const i: u32 = @intCast(i_usize);
|
||||
const token_id = analyzer.peekTokenAhead(i);
|
||||
_ = token_id; // autofix
|
||||
const token_index = Token.addInt(analyzer.token_i, i);
|
||||
const token_bytes = analyzer.bytes(token_index);
|
||||
_ = token_bytes; // autofix
|
||||
// log(.parser, .consume_token, "{s}, '{s}'", .{ @tagName(token_id), token_bytes });
|
||||
}
|
||||
// for (0..token_count) |i_usize| {
|
||||
// const i: u32 = @intCast(i_usize);
|
||||
// const token_id = analyzer.peekTokenAhead(i);
|
||||
// _ = token_id; // autofix
|
||||
// const token_index = @intFromEnum(analyzer.token_i) + i;
|
||||
// const token_bytes = analyzer.bytes(token_index);
|
||||
// _ = token_bytes; // autofix
|
||||
// // log(.parser, .consume_token, "{s}, '{s}'", .{ @tagName(token_id), token_bytes });
|
||||
// }
|
||||
|
||||
// log(.parser, .consume_token, "\n", .{});
|
||||
analyzer.token_i = Token.addInt(analyzer.token_i, token_count);
|
||||
analyzer.token_i = @enumFromInt(@intFromEnum(analyzer.token_i) + token_count);
|
||||
}
|
||||
|
||||
fn bytes(analyzer: *const Analyzer, token_index: Token.Index) []const u8 {
|
||||
const index = Token.unwrap(token_index);
|
||||
assert(index < analyzer.token_buffer.length);
|
||||
const offset = analyzer.token_buffer.offsets[index];
|
||||
const len = analyzer.token_buffer.lengths[index];
|
||||
const slice = analyzer.source_file[offset..][0..len];
|
||||
const token = analyzer.token_buffer.tokens.get(token_index);
|
||||
const slice = analyzer.source_file[token.offset..][0..token.length];
|
||||
return slice;
|
||||
}
|
||||
|
||||
@ -340,13 +340,14 @@ const Analyzer = struct {
|
||||
const attribute_node_index: Node.Index = if (analyzer.peekToken() == .operator_colon) b: {
|
||||
analyzer.consumeToken();
|
||||
|
||||
var list = UnpinnedArray(Node.Index){};
|
||||
var stack_list = Node.StackList{};
|
||||
|
||||
while (analyzer.peekToken() != .operator_assign) {
|
||||
const identifier = try analyzer.expectToken(.identifier);
|
||||
const identifier_name = analyzer.bytes(identifier);
|
||||
|
||||
const attribute_node = inline for (@typeInfo(Compilation.Debug.Declaration.Global.Attribute).Enum.fields) |enum_field| {
|
||||
if (data_structures.byte_equal(identifier_name, enum_field.name)) {
|
||||
if (byte_equal(identifier_name, enum_field.name)) {
|
||||
const attribute = @field(Compilation.Debug.Declaration.Global.Attribute, enum_field.name);
|
||||
const attribute_node = switch (attribute) {
|
||||
.@"export",
|
||||
@ -361,7 +362,8 @@ const Analyzer = struct {
|
||||
break attribute_node;
|
||||
}
|
||||
} else @panic(identifier_name);
|
||||
try list.append(analyzer.my_allocator, attribute_node);
|
||||
|
||||
stack_list.appendAssumeCapacity(attribute_node);
|
||||
|
||||
switch (analyzer.peekToken()) {
|
||||
.operator_assign => {},
|
||||
@ -370,7 +372,7 @@ const Analyzer = struct {
|
||||
}
|
||||
}
|
||||
|
||||
break :b try analyzer.nodeList(list);
|
||||
break :b try analyzer.nodeList(&stack_list);
|
||||
} else .null;
|
||||
|
||||
break :blk try analyzer.addNode(.{
|
||||
@ -427,14 +429,14 @@ const Analyzer = struct {
|
||||
|
||||
fn functionPrototype(analyzer: *Analyzer) !Node.Index {
|
||||
const token = analyzer.token_i;
|
||||
var attribute_and_return_type_node_list = UnpinnedArray(Node.Index){};
|
||||
var attribute_and_return_type_node_list = Node.StackList{};
|
||||
|
||||
while (analyzer.peekToken() != .operator_left_parenthesis) {
|
||||
const identifier = try analyzer.expectToken(.identifier);
|
||||
const identifier_name = analyzer.bytes(identifier);
|
||||
|
||||
const attribute_node = inline for (@typeInfo(Compilation.Function.Attribute).Enum.fields) |enum_field| {
|
||||
if (data_structures.byte_equal(identifier_name, enum_field.name)) {
|
||||
if (byte_equal(identifier_name, enum_field.name)) {
|
||||
const attribute = @field(Compilation.Function.Attribute, enum_field.name);
|
||||
const attribute_node = switch (attribute) {
|
||||
.naked => try analyzer.addNode(.{
|
||||
@ -460,7 +462,7 @@ const Analyzer = struct {
|
||||
}
|
||||
} else @panic(identifier_name);
|
||||
|
||||
try attribute_and_return_type_node_list.append(analyzer.my_allocator, attribute_node);
|
||||
attribute_and_return_type_node_list.appendAssumeCapacity(attribute_node);
|
||||
|
||||
if (analyzer.peekToken() == .operator_comma) analyzer.consumeToken();
|
||||
}
|
||||
@ -469,13 +471,13 @@ const Analyzer = struct {
|
||||
|
||||
const arguments = try analyzer.argumentList(.operator_left_parenthesis, .operator_right_parenthesis);
|
||||
const return_type = try analyzer.typeExpression();
|
||||
try attribute_and_return_type_node_list.append(analyzer.my_allocator, return_type);
|
||||
attribute_and_return_type_node_list.appendAssumeCapacity(return_type);
|
||||
|
||||
const function_prototype = try analyzer.addNode(.{
|
||||
.id = .function_prototype,
|
||||
.token = token,
|
||||
.left = arguments,
|
||||
.right = try analyzer.nodeList(attribute_and_return_type_node_list),
|
||||
.right = try analyzer.nodeList(&attribute_and_return_type_node_list),
|
||||
});
|
||||
|
||||
return function_prototype;
|
||||
@ -486,7 +488,7 @@ const Analyzer = struct {
|
||||
_ = try analyzer.expectToken(start_token);
|
||||
}
|
||||
|
||||
var list = UnpinnedArray(Node.Index){};
|
||||
var list = Node.StackList{};
|
||||
|
||||
while (analyzer.peekToken() != end_token) {
|
||||
const identifier_token = analyzer.token_i;
|
||||
@ -508,7 +510,7 @@ const Analyzer = struct {
|
||||
analyzer.consumeToken();
|
||||
}
|
||||
|
||||
try list.append(analyzer.my_allocator, try analyzer.addNode(.{
|
||||
list.appendAssumeCapacity(try analyzer.addNode(.{
|
||||
.id = id,
|
||||
.token = identifier_token,
|
||||
.left = type_expression,
|
||||
@ -518,8 +520,8 @@ const Analyzer = struct {
|
||||
|
||||
_ = try analyzer.expectToken(end_token);
|
||||
|
||||
if (list.length != 0) {
|
||||
return try analyzer.nodeList(list);
|
||||
if (list.len != 0) {
|
||||
return try analyzer.nodeList(&list);
|
||||
} else {
|
||||
return Node.Index.null;
|
||||
}
|
||||
@ -533,7 +535,7 @@ const Analyzer = struct {
|
||||
|
||||
fn block(analyzer: *Analyzer) anyerror!Node.Index {
|
||||
const left_brace = try analyzer.expectToken(.operator_left_brace);
|
||||
var list = UnpinnedArray(Node.Index){};
|
||||
var list = Node.StackList{};
|
||||
|
||||
while (analyzer.peekToken() != .operator_right_brace) {
|
||||
const first_statement_token = analyzer.peekToken();
|
||||
@ -550,7 +552,7 @@ const Analyzer = struct {
|
||||
=> try analyzer.symbolDeclaration(),
|
||||
};
|
||||
|
||||
try list.append(analyzer.my_allocator, statement_index);
|
||||
list.appendAssumeCapacity(statement_index);
|
||||
}
|
||||
|
||||
_ = try analyzer.expectToken(.operator_right_brace);
|
||||
@ -558,7 +560,7 @@ const Analyzer = struct {
|
||||
return try analyzer.addNode(.{
|
||||
.id = .block,
|
||||
.token = left_brace,
|
||||
.left = try analyzer.nodeList(list),
|
||||
.left = try analyzer.nodeList(&list),
|
||||
.right = Node.Index.null,
|
||||
});
|
||||
}
|
||||
@ -596,7 +598,7 @@ const Analyzer = struct {
|
||||
// logln(.parser, .@"switch", "Parsed switch expression...", .{});
|
||||
_ = try analyzer.expectToken(.operator_left_brace);
|
||||
|
||||
var list = UnpinnedArray(Node.Index){};
|
||||
var list = Node.StackList{};
|
||||
|
||||
while (analyzer.peekToken() != .operator_right_brace) {
|
||||
const case_token = analyzer.token_i;
|
||||
@ -607,7 +609,7 @@ const Analyzer = struct {
|
||||
break :blk Node.Index.null;
|
||||
},
|
||||
else => blk: {
|
||||
var array_list = UnpinnedArray(Node.Index){};
|
||||
var array_list = Node.StackList{};
|
||||
while (true) {
|
||||
const token = analyzer.token_i;
|
||||
const left = try analyzer.expression();
|
||||
@ -625,7 +627,7 @@ const Analyzer = struct {
|
||||
else => left,
|
||||
};
|
||||
|
||||
try array_list.append(analyzer.my_allocator, switch_case_node);
|
||||
array_list.appendAssumeCapacity(switch_case_node);
|
||||
|
||||
switch (analyzer.peekToken()) {
|
||||
.operator_comma => analyzer.consumeToken(),
|
||||
@ -634,10 +636,10 @@ const Analyzer = struct {
|
||||
}
|
||||
}
|
||||
|
||||
break :blk switch (array_list.length) {
|
||||
break :blk switch (array_list.len) {
|
||||
0 => unreachable,
|
||||
1 => array_list.pointer[0],
|
||||
else => try analyzer.nodeList(array_list),
|
||||
1 => array_list.buffer[0],
|
||||
else => try analyzer.nodeList(&array_list),
|
||||
};
|
||||
},
|
||||
};
|
||||
@ -658,7 +660,7 @@ const Analyzer = struct {
|
||||
.right = expr,
|
||||
});
|
||||
|
||||
try list.append(analyzer.my_allocator, node);
|
||||
list.appendAssumeCapacity(node);
|
||||
}
|
||||
|
||||
_ = try analyzer.expectToken(.operator_right_brace);
|
||||
@ -667,7 +669,7 @@ const Analyzer = struct {
|
||||
.id = .@"switch",
|
||||
.token = switch_token,
|
||||
.left = switch_expression,
|
||||
.right = try analyzer.nodeList(list),
|
||||
.right = try analyzer.nodeList(&list),
|
||||
});
|
||||
}
|
||||
|
||||
@ -743,7 +745,7 @@ const Analyzer = struct {
|
||||
const token = try analyzer.expectToken(.fixed_keyword_for);
|
||||
_ = try analyzer.expectToken(.operator_left_parenthesis);
|
||||
|
||||
var for_expression_list = UnpinnedArray(Node.Index){};
|
||||
var for_expression_list = Node.StackList{};
|
||||
|
||||
while (analyzer.peekToken() != .operator_right_parenthesis) {
|
||||
const expression_token = analyzer.token_i;
|
||||
@ -768,7 +770,7 @@ const Analyzer = struct {
|
||||
else => |t| @panic(@tagName(t)),
|
||||
};
|
||||
|
||||
try for_expression_list.append(analyzer.my_allocator, node_index);
|
||||
for_expression_list.appendAssumeCapacity(node_index);
|
||||
|
||||
switch (analyzer.peekToken()) {
|
||||
.operator_comma => analyzer.consumeToken(),
|
||||
@ -781,7 +783,7 @@ const Analyzer = struct {
|
||||
|
||||
_ = try analyzer.expectToken(.operator_bar);
|
||||
|
||||
var payload_nodes = UnpinnedArray(Node.Index){};
|
||||
var payload_nodes = Node.StackList{};
|
||||
|
||||
while (analyzer.peekToken() != .operator_bar) {
|
||||
const payload_token = analyzer.token_i;
|
||||
@ -799,7 +801,7 @@ const Analyzer = struct {
|
||||
else => |t| @panic(@tagName(t)),
|
||||
}
|
||||
|
||||
try payload_nodes.append(analyzer.my_allocator, try analyzer.addNode(.{
|
||||
payload_nodes.appendAssumeCapacity(try analyzer.addNode(.{
|
||||
.id = id,
|
||||
.token = payload_token,
|
||||
.left = Node.Index.null,
|
||||
@ -809,15 +811,15 @@ const Analyzer = struct {
|
||||
|
||||
_ = try analyzer.expectToken(.operator_bar);
|
||||
|
||||
if (payload_nodes.length != for_expression_list.length) {
|
||||
if (payload_nodes.len != for_expression_list.len) {
|
||||
unreachable;
|
||||
}
|
||||
|
||||
const for_condition_node = try analyzer.addNode(.{
|
||||
.id = .for_condition,
|
||||
.token = token,
|
||||
.left = try analyzer.nodeList(for_expression_list),
|
||||
.right = try analyzer.nodeList(payload_nodes),
|
||||
.left = try analyzer.nodeList(&for_expression_list),
|
||||
.right = try analyzer.nodeList(&payload_nodes),
|
||||
});
|
||||
|
||||
const true_expression = switch (analyzer.peekToken()) {
|
||||
@ -933,22 +935,22 @@ const Analyzer = struct {
|
||||
const intrinsic_name = analyzer.bytes(intrinsic_token)[1..];
|
||||
|
||||
const intrinsic_id = inline for (@typeInfo(Compilation.IntrinsicId).Enum.fields) |enum_field| {
|
||||
if (data_structures.byte_equal(enum_field.name, intrinsic_name)) {
|
||||
if (byte_equal(enum_field.name, intrinsic_name)) {
|
||||
break @field(Compilation.IntrinsicId, enum_field.name);
|
||||
}
|
||||
} else @panic(intrinsic_name);
|
||||
|
||||
var list = UnpinnedArray(Node.Index){};
|
||||
var list = Node.StackList{};
|
||||
|
||||
if (intrinsic_id == .@"asm") {
|
||||
const backtick = try analyzer.expectToken(.operator_backtick);
|
||||
var instruction_list = UnpinnedArray(Node.Index){};
|
||||
var instruction_list = Node.StackList{};
|
||||
|
||||
while (analyzer.peekToken() != .operator_backtick) {
|
||||
const instruction_token = analyzer.token_i;
|
||||
const instruction_name = try analyzer.identifierNode();
|
||||
|
||||
var operand_list = UnpinnedArray(Node.Index){};
|
||||
var operand_list = Node.StackList{};
|
||||
while (analyzer.peekToken() != .operator_semicolon) {
|
||||
const node = switch (analyzer.peekToken()) {
|
||||
.identifier => try analyzer.addNode(.{
|
||||
@ -990,7 +992,7 @@ const Analyzer = struct {
|
||||
.operator_semicolon => {},
|
||||
else => |t| @panic(@tagName(t)),
|
||||
}
|
||||
try operand_list.append(analyzer.my_allocator, node);
|
||||
operand_list.appendAssumeCapacity(node);
|
||||
}
|
||||
|
||||
analyzer.consumeToken();
|
||||
@ -999,10 +1001,10 @@ const Analyzer = struct {
|
||||
.id = .assembly_instruction,
|
||||
.token = instruction_token,
|
||||
.left = instruction_name,
|
||||
.right = try analyzer.nodeList(operand_list),
|
||||
.right = try analyzer.nodeList(&operand_list),
|
||||
});
|
||||
|
||||
try instruction_list.append(analyzer.my_allocator, instruction);
|
||||
instruction_list.appendAssumeCapacity(instruction);
|
||||
}
|
||||
|
||||
_ = try analyzer.expectToken(.operator_backtick);
|
||||
@ -1011,15 +1013,15 @@ const Analyzer = struct {
|
||||
const assembly_block = try analyzer.addNode(.{
|
||||
.id = .assembly_code_block,
|
||||
.token = backtick,
|
||||
.left = try analyzer.nodeList(instruction_list),
|
||||
.left = try analyzer.nodeList(&instruction_list),
|
||||
.right = .null,
|
||||
});
|
||||
try list.append(analyzer.my_allocator, assembly_block);
|
||||
list.appendAssumeCapacity(assembly_block);
|
||||
|
||||
const intrinsic = try analyzer.addNode(.{
|
||||
.id = .intrinsic,
|
||||
.token = intrinsic_token,
|
||||
.left = try analyzer.nodeList(list),
|
||||
.left = try analyzer.nodeList(&list),
|
||||
.right = @enumFromInt(@intFromEnum(intrinsic_id)),
|
||||
});
|
||||
|
||||
@ -1027,7 +1029,7 @@ const Analyzer = struct {
|
||||
} else {
|
||||
while (analyzer.peekToken() != .operator_right_parenthesis) {
|
||||
const parameter = try analyzer.expression();
|
||||
try list.append(analyzer.my_allocator, parameter);
|
||||
list.appendAssumeCapacity(parameter);
|
||||
|
||||
switch (analyzer.peekToken()) {
|
||||
.operator_comma => analyzer.consumeToken(),
|
||||
@ -1043,7 +1045,7 @@ const Analyzer = struct {
|
||||
return try analyzer.addNode(.{
|
||||
.id = .intrinsic,
|
||||
.token = intrinsic_token,
|
||||
.left = try analyzer.nodeList(list),
|
||||
.left = try analyzer.nodeList(&list),
|
||||
.right = @enumFromInt(@intFromEnum(intrinsic_id)),
|
||||
});
|
||||
}
|
||||
@ -1454,7 +1456,7 @@ const Analyzer = struct {
|
||||
fn pointerOrArrayTypeExpression(analyzer: *Analyzer, expected: PointerOrArrayTypeExpectedExpression) !Node.Index {
|
||||
const first = analyzer.token_i;
|
||||
|
||||
var list = UnpinnedArray(Node.Index){};
|
||||
var list = Node.StackList{};
|
||||
|
||||
const expression_type: Node.Id = switch (expected) {
|
||||
.single_pointer_type => blk: {
|
||||
@ -1463,7 +1465,7 @@ const Analyzer = struct {
|
||||
break :blk .pointer_type;
|
||||
},
|
||||
.many_pointer_type => blk: {
|
||||
try list.append(analyzer.my_allocator, try analyzer.addNode(.{
|
||||
list.appendAssumeCapacity(try analyzer.addNode(.{
|
||||
.id = .many_pointer_expression,
|
||||
.token = analyzer.token_i,
|
||||
.left = Node.Index.null,
|
||||
@ -1473,7 +1475,7 @@ const Analyzer = struct {
|
||||
_ = try analyzer.expectToken(.operator_ampersand);
|
||||
switch (analyzer.peekToken()) {
|
||||
.operator_right_bracket => {},
|
||||
.operator_colon => try list.append(analyzer.my_allocator, try analyzer.parseTermination()),
|
||||
.operator_colon => list.appendAssumeCapacity(try analyzer.parseTermination()),
|
||||
else => |t| @panic(@tagName(t)),
|
||||
}
|
||||
_ = try analyzer.expectToken(.operator_right_bracket);
|
||||
@ -1488,17 +1490,17 @@ const Analyzer = struct {
|
||||
break :blk .slice_type;
|
||||
},
|
||||
.operator_colon => {
|
||||
try list.append(analyzer.my_allocator, try analyzer.parseTermination());
|
||||
list.appendAssumeCapacity(try analyzer.parseTermination());
|
||||
_ = try analyzer.expectToken(.operator_right_bracket);
|
||||
break :blk .slice_type;
|
||||
},
|
||||
else => {
|
||||
const length_expression = try analyzer.expression();
|
||||
try list.append(analyzer.my_allocator, length_expression);
|
||||
list.appendAssumeCapacity(length_expression);
|
||||
|
||||
switch (analyzer.peekToken()) {
|
||||
.operator_right_bracket => {},
|
||||
.operator_colon => try list.append(analyzer.my_allocator, try analyzer.parseTermination()),
|
||||
.operator_colon => list.appendAssumeCapacity(try analyzer.parseTermination()),
|
||||
else => |t| @panic(@tagName(t)),
|
||||
}
|
||||
|
||||
@ -1523,17 +1525,17 @@ const Analyzer = struct {
|
||||
analyzer.consumeTokens(@intFromBool(analyzer.peekToken() == .fixed_keyword_const));
|
||||
|
||||
if (const_node != .null) {
|
||||
try list.append(analyzer.my_allocator, const_node);
|
||||
list.appendAssumeCapacity(const_node);
|
||||
}
|
||||
} else {
|
||||
assert(list.length > 0);
|
||||
assert(list.len > 0);
|
||||
}
|
||||
|
||||
const type_expression = try analyzer.typeExpression();
|
||||
assert(type_expression != .null);
|
||||
try list.append(analyzer.my_allocator, type_expression);
|
||||
list.appendAssumeCapacity(type_expression);
|
||||
|
||||
const node_list = try analyzer.nodeList(list);
|
||||
const node_list = try analyzer.nodeList(&list);
|
||||
|
||||
const node = Node{
|
||||
.id = expression_type,
|
||||
@ -1542,15 +1544,7 @@ const Analyzer = struct {
|
||||
.right = Node.Index.null,
|
||||
};
|
||||
|
||||
// logln(.parser, .pointer_like_type_expression, "ARRAY START\n===========", .{});
|
||||
// for (list.slice()) |ni| {
|
||||
// const n = analyzer.nodes.get(ni);
|
||||
// logln(.parser, .pointer_like_type_expression, "{s} node element: {s}", .{ @tagName(expression_type), @tagName(n.id) });
|
||||
// }
|
||||
// logln(.parser, .pointer_like_type_expression, "ARRAY END\n=========", .{});
|
||||
|
||||
const node_index = try analyzer.addNode(node);
|
||||
// logln(.parser, .pointer_like_type_expression, "Pointer end", .{});
|
||||
|
||||
switch (analyzer.peekToken()) {
|
||||
.operator_comma,
|
||||
@ -1642,7 +1636,7 @@ const Analyzer = struct {
|
||||
const left_parenthesis = analyzer.token_i;
|
||||
analyzer.consumeToken();
|
||||
|
||||
var expression_list = UnpinnedArray(Node.Index){};
|
||||
var expression_list = Node.StackList{};
|
||||
// logln(.parser, .suffix, "[DEPTH={}] Initializating suffix call-like expression", .{analyzer.suffix_depth});
|
||||
while (analyzer.peekToken() != .operator_right_parenthesis) {
|
||||
const current_token = analyzer.token_i;
|
||||
@ -1661,7 +1655,7 @@ const Analyzer = struct {
|
||||
});
|
||||
}
|
||||
|
||||
try expression_list.append(analyzer.my_allocator, parameter);
|
||||
expression_list.appendAssumeCapacity(parameter);
|
||||
|
||||
switch (analyzer.peekToken()) {
|
||||
.operator_right_parenthesis => {},
|
||||
@ -1681,7 +1675,7 @@ const Analyzer = struct {
|
||||
.id = .call,
|
||||
.token = left_parenthesis,
|
||||
.left = result,
|
||||
.right = try analyzer.nodeList(expression_list),
|
||||
.right = try analyzer.nodeList(&expression_list),
|
||||
});
|
||||
} else {
|
||||
return result;
|
||||
@ -1695,7 +1689,7 @@ const Analyzer = struct {
|
||||
fn containerLiteral(analyzer: *Analyzer, type_node: Node.Index) anyerror!Node.Index {
|
||||
const token = try analyzer.expectToken(.operator_left_brace);
|
||||
|
||||
var list = UnpinnedArray(Node.Index){};
|
||||
var list = Node.StackList{};
|
||||
|
||||
const InitializationType = enum {
|
||||
anonymous,
|
||||
@ -1724,7 +1718,7 @@ const Analyzer = struct {
|
||||
.right = Node.Index.null,
|
||||
});
|
||||
|
||||
try list.append(analyzer.my_allocator, field_initialization);
|
||||
list.appendAssumeCapacity(field_initialization);
|
||||
switch (analyzer.peekToken()) {
|
||||
.operator_comma => analyzer.consumeToken(),
|
||||
else => {},
|
||||
@ -1735,7 +1729,7 @@ const Analyzer = struct {
|
||||
else => |t| @panic(@tagName(t)),
|
||||
},
|
||||
else => blk: {
|
||||
try list.append(analyzer.my_allocator, try analyzer.anonymousExpression());
|
||||
list.appendAssumeCapacity(try analyzer.anonymousExpression());
|
||||
_ = try analyzer.expectToken(.operator_comma);
|
||||
break :blk .anonymous;
|
||||
},
|
||||
@ -1752,7 +1746,7 @@ const Analyzer = struct {
|
||||
else => {},
|
||||
}
|
||||
|
||||
try list.append(analyzer.my_allocator, field_expression_initializer);
|
||||
list.appendAssumeCapacity(field_expression_initializer);
|
||||
break :blk .anonymous;
|
||||
},
|
||||
else => |t| @panic(@tagName(t)),
|
||||
@ -1796,7 +1790,7 @@ const Analyzer = struct {
|
||||
},
|
||||
.token = token,
|
||||
.left = type_node,
|
||||
.right = try analyzer.nodeList(list),
|
||||
.right = try analyzer.nodeList(&list),
|
||||
});
|
||||
}
|
||||
|
||||
@ -1814,7 +1808,7 @@ const Analyzer = struct {
|
||||
|
||||
fn processContainerType(analyzer: *Analyzer, maybe_token_id: ?Token.Id) !Node.Index {
|
||||
const token_i = if (maybe_token_id) |tid| try analyzer.expectToken(tid) else analyzer.token_i;
|
||||
assert(Token.unwrap(analyzer.token_i) < analyzer.token_buffer.length);
|
||||
assert(@intFromEnum(analyzer.token_i) < analyzer.token_buffer.tokens.length);
|
||||
const token_id = maybe_token_id orelse .fixed_keyword_struct;
|
||||
const container_type: Compilation.ContainerType = switch (token_id) {
|
||||
.fixed_keyword_struct => .@"struct",
|
||||
@ -1832,10 +1826,10 @@ const Analyzer = struct {
|
||||
|
||||
const parameters_node = if (analyzer.hasTokens() and analyzer.peekToken() == .operator_left_parenthesis) b: {
|
||||
analyzer.consumeToken();
|
||||
var list = UnpinnedArray(Node.Index){};
|
||||
var list = Node.StackList{};
|
||||
while (analyzer.peekToken() != .operator_right_parenthesis) {
|
||||
const parameter_node = try analyzer.expression();
|
||||
try list.append(analyzer.my_allocator, parameter_node);
|
||||
list.appendAssumeCapacity(parameter_node);
|
||||
switch (analyzer.peekToken()) {
|
||||
.operator_comma => analyzer.consumeToken(),
|
||||
else => {},
|
||||
@ -1844,11 +1838,11 @@ const Analyzer = struct {
|
||||
|
||||
analyzer.consumeToken();
|
||||
|
||||
break :b try analyzer.nodeList(list);
|
||||
break :b try analyzer.nodeList(&list);
|
||||
} else Node.Index.null;
|
||||
|
||||
if (maybe_token_id) |_| _ = try analyzer.expectToken(.operator_left_brace);
|
||||
var node_list = UnpinnedArray(Node.Index){};
|
||||
var list = Node.StackList{};
|
||||
|
||||
while (analyzer.hasTokens() and analyzer.peekToken() != .operator_right_brace) {
|
||||
const first = analyzer.token_i;
|
||||
@ -1933,7 +1927,7 @@ const Analyzer = struct {
|
||||
// logln(.parser, .container_members, "Container member {s}", .{@tagName(member_node.id)});
|
||||
assert(member_node.id != .identifier);
|
||||
|
||||
try node_list.append(analyzer.my_allocator, member_node_index);
|
||||
list.appendAssumeCapacity(member_node_index);
|
||||
}
|
||||
|
||||
if (maybe_token_id) |_| _ = try analyzer.expectToken(.operator_right_brace);
|
||||
@ -1953,7 +1947,7 @@ const Analyzer = struct {
|
||||
return try analyzer.addNode(.{
|
||||
.id = node_id,
|
||||
.token = token_i,
|
||||
.left = try analyzer.nodeList(node_list),
|
||||
.left = try analyzer.nodeList(&list),
|
||||
.right = parameters_node,
|
||||
});
|
||||
}
|
||||
@ -2141,7 +2135,7 @@ const Analyzer = struct {
|
||||
} else Node.Index.null;
|
||||
|
||||
_ = try analyzer.expectToken(.operator_left_brace);
|
||||
var list = UnpinnedArray(Node.Index){};
|
||||
var list = Node.StackList{};
|
||||
|
||||
while (analyzer.peekToken() != .operator_right_brace) {
|
||||
const tok_i = analyzer.token_i;
|
||||
@ -2167,7 +2161,7 @@ const Analyzer = struct {
|
||||
.right = value_associated,
|
||||
});
|
||||
|
||||
try list.append(analyzer.my_allocator, error_field_node);
|
||||
list.appendAssumeCapacity(error_field_node);
|
||||
}
|
||||
|
||||
analyzer.consumeToken();
|
||||
@ -2175,7 +2169,7 @@ const Analyzer = struct {
|
||||
break :blk try analyzer.addNode(.{
|
||||
.id = .error_type,
|
||||
.token = token_i,
|
||||
.left = try analyzer.nodeList(list),
|
||||
.left = try analyzer.nodeList(&list),
|
||||
.right = backing_type,
|
||||
});
|
||||
},
|
||||
@ -2323,7 +2317,7 @@ const Analyzer = struct {
|
||||
.right = blk: {
|
||||
const t = analyzer.token_i;
|
||||
analyzer.consumeToken();
|
||||
break :blk Node.wrap(Token.unwrap(t));
|
||||
break :blk @enumFromInt(@intFromEnum(t));
|
||||
},
|
||||
}),
|
||||
else => |t| @panic(@tagName(t)),
|
||||
@ -2335,7 +2329,8 @@ const Analyzer = struct {
|
||||
}
|
||||
|
||||
fn addNode(analyzer: *Analyzer, node: Node) !Node.Index {
|
||||
const node_index = try analyzer.nodes.append(analyzer.my_allocator, node);
|
||||
const node_pointer = analyzer.nodes.append(node);
|
||||
const node_index = analyzer.nodes.get_index(node_pointer);
|
||||
// logln(.parser, .node_creation, "Adding node #{} {s} to file #{} (left: {}, right: {})", .{ Node.unwrap(node_index), @tagName(node.id), File.unwrap(analyzer.file_index), switch (node.left) {
|
||||
// .null => 0xffff_ffff,
|
||||
// else => Node.unwrap(node.left),
|
||||
@ -2358,12 +2353,14 @@ const Analyzer = struct {
|
||||
return node_index;
|
||||
}
|
||||
|
||||
fn nodeList(analyzer: *Analyzer, node_list: UnpinnedArray(Node.Index)) !Node.Index {
|
||||
fn nodeList(analyzer: *Analyzer, stack_list: *Node.StackList) !Node.Index {
|
||||
const heap_list = try analyzer.arena.new_array(Node.Index, stack_list.len);
|
||||
@memcpy(heap_list, stack_list.slice());
|
||||
const index = analyzer.node_lists.length;
|
||||
try analyzer.node_lists.append(analyzer.my_allocator, node_list);
|
||||
_ = analyzer.node_lists.append(heap_list);
|
||||
return try analyzer.addNode(.{
|
||||
.id = .node_list,
|
||||
.token = Token.wrap(0),
|
||||
.token = @enumFromInt(0),
|
||||
.left = @enumFromInt(index),
|
||||
.right = Node.Index.null,
|
||||
});
|
||||
@ -2384,7 +2381,7 @@ const Analyzer = struct {
|
||||
};
|
||||
|
||||
// Here it is assumed that left brace is consumed
|
||||
pub fn analyze(allocator: Allocator, my_allocator: *data_structures.MyAllocator, lexer_result: lexer.Result, source_file: []const u8, token_buffer: *Token.Buffer, node_list: *Node.List, node_lists: *UnpinnedArray(UnpinnedArray(Node.Index))) !Result {
|
||||
pub fn analyze(allocator: Allocator, my_allocator: *MyAllocator, arena: *Arena, lexer_result: lexer.Result, source_file: []const u8, token_buffer: *Token.Buffer, node_list: *PinnedArray(Node), node_lists: *PinnedArray([]const Node.Index)) !Result {
|
||||
const start = std.time.Instant.now() catch unreachable;
|
||||
var analyzer = Analyzer{
|
||||
.lexer = lexer_result,
|
||||
@ -2396,6 +2393,7 @@ pub fn analyze(allocator: Allocator, my_allocator: *data_structures.MyAllocator,
|
||||
.my_allocator = my_allocator,
|
||||
.nodes = node_list,
|
||||
.node_lists = node_lists,
|
||||
.arena = arena,
|
||||
};
|
||||
const main_node_index = try analyzer.processContainerType(null);
|
||||
|
||||
|
@ -11,13 +11,13 @@ pub fn assert(ok: bool) void {
|
||||
pub const Allocator = std.mem.Allocator;
|
||||
pub const BoundedArray = std.BoundedArray;
|
||||
|
||||
pub const Arena = struct{
|
||||
pub const Arena = struct {
|
||||
position: u64,
|
||||
commit_position: u64,
|
||||
alignment: u64,
|
||||
size: u64,
|
||||
|
||||
pub const Temporary = struct{
|
||||
pub const Temporary = struct {
|
||||
arena: *Arena,
|
||||
position: u64,
|
||||
};
|
||||
@ -26,7 +26,7 @@ pub const Arena = struct{
|
||||
|
||||
pub fn init(requested_size: u64) !*Arena {
|
||||
var size = requested_size;
|
||||
const size_roundup_granularity = 64 * 1024 * 1024;
|
||||
const size_roundup_granularity = commit_granularity;
|
||||
size += size_roundup_granularity - 1;
|
||||
size -= size % size_roundup_granularity;
|
||||
const initial_commit_size = commit_granularity;
|
||||
@ -35,7 +35,7 @@ pub const Arena = struct{
|
||||
const reserved_memory = try reserve(size);
|
||||
try commit(reserved_memory, initial_commit_size);
|
||||
|
||||
const arena: *Arena = @ptrCast(reserved_memory);
|
||||
const arena: *Arena = @alignCast(@ptrCast(reserved_memory));
|
||||
arena.* = .{
|
||||
.position = @sizeOf(Arena),
|
||||
.commit_position = initial_commit_size,
|
||||
@ -55,7 +55,7 @@ pub const Arena = struct{
|
||||
const result = base + arena.position + alignment;
|
||||
arena.position += size + alignment;
|
||||
|
||||
if (arena.commit_position < arena.position - arena.commit_position) {
|
||||
if (arena.commit_position < arena.position) {
|
||||
var size_to_commit = arena.position - arena.commit_position;
|
||||
size_to_commit += commit_granularity - 1;
|
||||
size_to_commit -= size_to_commit % commit_granularity;
|
||||
@ -71,127 +71,205 @@ pub const Arena = struct{
|
||||
}
|
||||
}
|
||||
|
||||
pub inline fn new(arena: *Arena, comptime T: type) !*T{
|
||||
const result: *T = @ptrCast(try arena.allocate(@sizeOf(T)));
|
||||
pub inline fn new(arena: *Arena, comptime T: type) !*T {
|
||||
const result: *T = @ptrCast(@alignCast(try arena.allocate(@sizeOf(T))));
|
||||
return result;
|
||||
}
|
||||
|
||||
pub inline fn new_array(arena: *Arena, comptime T: type, count: usize) ![]T {
|
||||
const result: [*]T = @ptrCast(try arena.allocate(@sizeOf(T) * count));
|
||||
return result;
|
||||
const result: [*]T = @ptrCast(@alignCast(try arena.allocate(@sizeOf(T) * count)));
|
||||
return result[0..count];
|
||||
}
|
||||
};
|
||||
|
||||
pub fn reserve(size: u64) ![*]u8{
|
||||
pub fn DynamicBoundedArray(comptime T: type) type {
|
||||
return struct {
|
||||
pointer: [*]T = @constCast((&[_]T{}).ptr),
|
||||
length: u32 = 0,
|
||||
capacity: u32 = 0,
|
||||
|
||||
const Array = @This();
|
||||
|
||||
pub fn init(arena: *Arena, count: u32) !Array {
|
||||
const array = try arena.new_array(T, count);
|
||||
return Array{
|
||||
.pointer = array.ptr,
|
||||
.length = 0,
|
||||
.capacity = count,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn append(array: *Array, item: T) void {
|
||||
const index = array.length;
|
||||
assert(index < array.capacity);
|
||||
array.pointer[index] = item;
|
||||
array.length += 1;
|
||||
}
|
||||
|
||||
pub fn append_slice(array: *Array, items: []const T) void {
|
||||
const count: u32 = @intCast(items.len);
|
||||
const index = array.length;
|
||||
assert(index + count <= array.capacity);
|
||||
@memcpy(array.pointer[index..][0..count], items);
|
||||
array.length += count;
|
||||
}
|
||||
|
||||
pub fn slice(array: *Array) []T {
|
||||
return array.pointer[0..array.length];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const pinned_array_page_size = 2 * 1024 * 1024;
|
||||
const pinned_array_max_size = std.math.maxInt(u32) - pinned_array_page_size;
|
||||
const pinned_array_default_granularity = pinned_array_page_size;
|
||||
|
||||
// This must be used with big arrays, which are not resizeable (can't be cleared)
|
||||
pub fn PinnedArray(comptime T: type) type {
|
||||
return PinnedArrayAdvanced(T, null);
|
||||
}
|
||||
|
||||
// This must be used with big arrays, which are not resizeable (can't be cleared)
|
||||
pub fn PinnedArrayAdvanced(comptime T: type, comptime MaybeIndex: ?type) type {
|
||||
return struct {
|
||||
pointer: [*]T = @constCast((&[_]T{}).ptr),
|
||||
length: u32 = 0,
|
||||
granularity: u32 = 0,
|
||||
|
||||
pub const Index = if (MaybeIndex) |I| getIndexForType(T, I) else enum(u32) {
|
||||
null = 0xffff_ffff,
|
||||
_,
|
||||
};
|
||||
|
||||
const Array = @This();
|
||||
|
||||
pub fn const_slice(array: *const Array) []const T {
|
||||
return array.pointer[0..array.length];
|
||||
}
|
||||
|
||||
pub fn slice(array: *Array) []T {
|
||||
return array.pointer[0..array.length];
|
||||
}
|
||||
|
||||
pub fn get_unchecked(array: *Array, index: u32) *T {
|
||||
const array_slice = array.slice();
|
||||
return &array_slice[index];
|
||||
}
|
||||
|
||||
pub fn get(array: *Array, index: Index) *T {
|
||||
assert(index != .null);
|
||||
const i = @intFromEnum(index);
|
||||
return array.get_unchecked(i);
|
||||
}
|
||||
|
||||
pub fn get_index(array: *Array, item: *T) Index {
|
||||
const many_item: [*]T = @ptrCast(item);
|
||||
const result = @intFromPtr(many_item) - @intFromPtr(array.pointer);
|
||||
assert(result < pinned_array_max_size);
|
||||
return @enumFromInt(@divExact(result, @sizeOf(T)));
|
||||
}
|
||||
|
||||
pub fn init(granularity: u32) !Array {
|
||||
assert(granularity & 0xfff == 0);
|
||||
const raw_ptr = try reserve(pinned_array_max_size);
|
||||
try commit(raw_ptr, granularity);
|
||||
return Array{
|
||||
.pointer = @alignCast(@ptrCast(raw_ptr)),
|
||||
.length = 0,
|
||||
.granularity = granularity,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn init_with_default_granularity() !Array {
|
||||
return try Array.init(pinned_array_default_granularity);
|
||||
}
|
||||
|
||||
pub fn ensure_capacity(array: *Array, additional: u32) void {
|
||||
const length = array.length;
|
||||
const size = length * @sizeOf(T);
|
||||
const granularity_aligned_size = align_forward(size, array.granularity);
|
||||
const new_size = size + additional * @sizeOf(T);
|
||||
if (granularity_aligned_size < new_size) {
|
||||
assert((length + additional) * @sizeOf(T) <= pinned_array_max_size);
|
||||
const new_granularity_aligned_size = align_forward(new_size, array.granularity);
|
||||
const ptr: [*]u8 = @ptrCast(array.pointer);
|
||||
commit(ptr + granularity_aligned_size, new_granularity_aligned_size - granularity_aligned_size) catch unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn append(array: *Array, item: T) *T {
|
||||
array.ensure_capacity(1);
|
||||
return array.append_with_capacity(item);
|
||||
}
|
||||
|
||||
pub fn append_index(array: *Array, item: T) Index {
|
||||
return array.get_index(array.append(item));
|
||||
}
|
||||
|
||||
pub fn append_slice(array: *Array, items: []const T) void {
|
||||
array.ensure_capacity(@intCast(items.len));
|
||||
array.append_slice_with_capacity(items);
|
||||
}
|
||||
|
||||
pub fn append_with_capacity(array: *Array, item: T) *T {
|
||||
const index = array.length;
|
||||
assert(index * @sizeOf(T) < pinned_array_max_size);
|
||||
array.length += 1;
|
||||
const ptr = &array.pointer[index];
|
||||
ptr.* = item;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
pub fn append_slice_with_capacity(array: *Array, items: []const T) void {
|
||||
const index = array.length;
|
||||
const count: u32 = @intCast(items.len);
|
||||
assert((index + count - 1) * @sizeOf(T) < pinned_array_max_size);
|
||||
array.length += count;
|
||||
@memcpy(array.pointer[index..][0..count], items);
|
||||
}
|
||||
|
||||
pub fn insert(array: *@This(), index: u32, item: T) void {
|
||||
assert(index < array.length);
|
||||
array.ensure_capacity(1);
|
||||
const src = array.slice()[index..];
|
||||
array.length += 1;
|
||||
const dst = array.slice()[index + 1..];
|
||||
copy_backwards(T, dst, src);
|
||||
array.slice()[index] = item;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn reserve(size: u64) ![*]u8 {
|
||||
return switch (os) {
|
||||
.linux, .macos => try std.posix.mmap(null, size, std.posix.PROT.NONE, .{
|
||||
.linux, .macos => (try std.posix.mmap(null, size, std.posix.PROT.NONE, .{
|
||||
.ANONYMOUS = true,
|
||||
.TYPE = .PRIVATE,
|
||||
}, -1, 0),
|
||||
}, -1, 0)).ptr,
|
||||
.windows => @ptrCast(try std.os.windows.VirtualAlloc(null, size, std.os.windows.MEM_RESERVE, std.os.windows.PAGE_READWRITE)),
|
||||
else => @compileError("OS not supported"),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn commit(bytes: [*]u8, size: u64) !void{
|
||||
pub fn commit(bytes: [*]u8, size: u64) !void {
|
||||
const slice = bytes[0..size];
|
||||
return switch (os) {
|
||||
.linux, .macos => try std.posix.mprotect(@alignCast(slice), std.posix.PROT.WRITE | std.posix.PROT.READ),
|
||||
.windows => _ = try std.os.windows.VirtualAlloc(bytes, size, std.os.windows.MEM_COMMIT, std.os.windows.PAGE_READWRITE),
|
||||
else => @compileError("OS not supported"),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn BlockList(comptime T: type, comptime E: type) type {
|
||||
const item_count = 64;
|
||||
|
||||
return struct {
|
||||
blocks: UnpinnedArray(*Block) = .{},
|
||||
len: usize = 0,
|
||||
|
||||
const Block = BoundedArray(T, item_count);
|
||||
const List = @This();
|
||||
|
||||
pub const Index = getIndexForType(T, E);
|
||||
pub const ElementIndex = Index.Index;
|
||||
|
||||
pub fn wrapSplit(block: usize, element: usize) ElementIndex {
|
||||
return @enumFromInt(block * item_count + element);
|
||||
}
|
||||
|
||||
pub fn get(list: *List, index: ElementIndex) *T {
|
||||
assert(index != .null);
|
||||
const i: u32 = @intFromEnum(index);
|
||||
const block_index = i / item_count;
|
||||
const element_index = i % item_count;
|
||||
assert(block_index < list.blocks.length);
|
||||
const block = list.blocks.pointer[block_index];
|
||||
const block_slice = block.buffer[0..block.len];
|
||||
const element = &block_slice[element_index];
|
||||
return element;
|
||||
}
|
||||
|
||||
pub fn append(list: *List, allocator: *MyAllocator, element: T) !ElementIndex {
|
||||
const result = try list.addOne(allocator);
|
||||
list.get(result).* = element;
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn addOne(list: *List, allocator: *MyAllocator) !ElementIndex {
|
||||
const block_index = try list.getFreeBlock(allocator);
|
||||
assert(block_index < list.blocks.length);
|
||||
const block = list.blocks.pointer[block_index];
|
||||
const index = block.len;
|
||||
_ = try block.addOne();
|
||||
list.len += 1;
|
||||
return @enumFromInt(block_index * item_count + index);
|
||||
}
|
||||
|
||||
fn getFreeBlock(list: *List, allocator: *MyAllocator) !usize {
|
||||
for (list.blocks.slice(), 0..) |block, i| {
|
||||
block.ensureUnusedCapacity(1) catch continue;
|
||||
return i;
|
||||
} else {
|
||||
const new_block = try allocator.allocate_one(Block);
|
||||
new_block.* = .{};
|
||||
const block_index = list.blocks.length;
|
||||
try list.blocks.append(allocator, new_block);
|
||||
return block_index;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn indexOf(list: *List, elem: *const T) ElementIndex {
|
||||
const address = @intFromPtr(elem);
|
||||
for (list.blocks.items, 0..) |block, block_index| {
|
||||
const base = @intFromPtr(&block.buffer[0]);
|
||||
const top = base + @sizeOf(T) * item_count;
|
||||
if (address >= base and address < top) {
|
||||
const result: u32 = @intCast(block_index * item_count + @divExact(address - base, @sizeOf(T)));
|
||||
return Index.wrap(result);
|
||||
}
|
||||
}
|
||||
|
||||
@panic("not found");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn getIndexForType(comptime T: type, comptime E: type) type {
|
||||
assert(@typeInfo(E) == .Enum);
|
||||
_ = T;
|
||||
const MAX = std.math.maxInt(IndexType);
|
||||
const MAX = std.math.maxInt(u32);
|
||||
|
||||
const EnumField = std.builtin.Type.EnumField;
|
||||
comptime var fields: []const EnumField = &.{};
|
||||
// comptime var enum_value: comptime_int = 0;
|
||||
fields = fields ++ @typeInfo(E).Enum.fields;
|
||||
|
||||
// for (names) |name| {
|
||||
// fields = fields ++ [1]EnumField{.{
|
||||
// .name = name,
|
||||
// .value = enum_value,
|
||||
// }};
|
||||
// enum_value += 1;
|
||||
// }
|
||||
|
||||
fields = fields ++ [1]EnumField{.{
|
||||
.name = "null",
|
||||
.value = MAX,
|
||||
@ -199,47 +277,17 @@ pub fn getIndexForType(comptime T: type, comptime E: type) type {
|
||||
|
||||
const Result = @Type(.{
|
||||
.Enum = .{
|
||||
.tag_type = IndexType,
|
||||
.tag_type = u32,
|
||||
.fields = fields,
|
||||
.decls = &.{},
|
||||
.is_exhaustive = false,
|
||||
},
|
||||
});
|
||||
|
||||
return struct {
|
||||
pub const Index = Result;
|
||||
|
||||
pub fn unwrap(this: Index) IndexType {
|
||||
assert(this != .null);
|
||||
return @intFromEnum(this);
|
||||
}
|
||||
|
||||
pub fn wrap(value: IndexType) Index {
|
||||
assert(value < MAX);
|
||||
return @enumFromInt(value);
|
||||
}
|
||||
|
||||
pub fn addInt(this: Index, value: IndexType) Index {
|
||||
const this_int = @intFromEnum(this);
|
||||
return @enumFromInt(this_int + value);
|
||||
}
|
||||
|
||||
pub fn subInt(this: Index, value: IndexType) IndexType {
|
||||
const this_int = @intFromEnum(this);
|
||||
return this_int - value;
|
||||
}
|
||||
|
||||
pub fn add(a: Index, b: Index) Index {
|
||||
return @enumFromInt(@intFromEnum(a) + @intFromEnum(b));
|
||||
}
|
||||
|
||||
pub fn sub(a: Index, b: Index) IndexType {
|
||||
return @intFromEnum(a) - @intFromEnum(b);
|
||||
}
|
||||
};
|
||||
return Result;
|
||||
}
|
||||
|
||||
pub fn my_hash(bytes: []const u8) IndexType {
|
||||
pub fn my_hash(bytes: []const u8) u32 {
|
||||
const fnv_offset = 14695981039346656037;
|
||||
const fnv_prime = 1099511628211;
|
||||
var result: u64 = fnv_offset;
|
||||
@ -301,47 +349,37 @@ pub fn byte_equal_terminated(a: [*:0]const u8, b: [*:0]const u8) bool {
|
||||
return byte_equal(a_slice, b_slice);
|
||||
}
|
||||
|
||||
const MapResult = struct {
|
||||
key_pointer: *anyopaque,
|
||||
value_pointer: *anyopaque,
|
||||
capacity: IndexType,
|
||||
};
|
||||
const pinned_hash_map_page_size = 2 * 1024 * 1024;
|
||||
const pinned_hash_map_max_size = std.math.maxInt(u32) - pinned_hash_map_page_size;
|
||||
const pinned_hash_map_default_granularity = pinned_hash_map_page_size;
|
||||
|
||||
fn ensure_capacity_hashmap(allocator: *MyAllocator, current_capacity: IndexType, desired_capacity: IndexType, key_pointer: [*]u8, value_pointer: [*]u8, length: IndexType, key_size: IndexType, key_alignment: u16, value_size: IndexType, value_alignment: u16) !MapResult {
|
||||
var new_capacity = @max(current_capacity, initial_item_count);
|
||||
while (new_capacity < desired_capacity) {
|
||||
new_capacity *= factor;
|
||||
}
|
||||
|
||||
if (new_capacity > current_capacity) {
|
||||
const old_key_slice = key_pointer[0 .. length * key_size];
|
||||
const old_value_slice = value_pointer[0 .. length * value_size];
|
||||
const new_key_slice = try allocator.reallocate(old_key_slice, new_capacity * key_size, key_alignment);
|
||||
const new_value_slice = try allocator.reallocate(old_value_slice, new_capacity * value_size, value_alignment);
|
||||
|
||||
return .{
|
||||
.key_pointer = new_key_slice.ptr,
|
||||
.value_pointer = new_value_slice.ptr,
|
||||
.capacity = new_capacity,
|
||||
};
|
||||
} else {
|
||||
return .{
|
||||
.capacity = current_capacity,
|
||||
.key_pointer = key_pointer,
|
||||
.value_pointer = value_pointer,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn MyHashMap(comptime K: type, comptime V: type) type {
|
||||
// const K = []const u8;
|
||||
pub fn PinnedHashMap(comptime K: type, comptime V: type) type {
|
||||
return struct {
|
||||
key_pointer: [*]K = undefined,
|
||||
value_pointer: [*]V = undefined,
|
||||
length: IndexType = 0,
|
||||
capacity: IndexType = 0,
|
||||
key_pointer: [*]K,
|
||||
value_pointer: [*]V,
|
||||
length: u32,
|
||||
granularity: u32,
|
||||
committed: u32,
|
||||
|
||||
pub fn get_pointer(map: *@This(), key: K) ?*V {
|
||||
const Map = @This();
|
||||
|
||||
pub fn init(granularity: u32) !Map {
|
||||
assert(granularity & 0xfff == 0);
|
||||
const key_raw_pointer = try reserve(pinned_hash_map_max_size);
|
||||
try commit(key_raw_pointer, granularity);
|
||||
const value_raw_pointer = try reserve(pinned_hash_map_max_size);
|
||||
try commit(value_raw_pointer, granularity);
|
||||
|
||||
return Map{
|
||||
.key_pointer = @alignCast(@ptrCast(key_raw_pointer)),
|
||||
.value_pointer = @alignCast(@ptrCast(value_raw_pointer)),
|
||||
.length = 0,
|
||||
.granularity = granularity,
|
||||
.committed = 1,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn get_pointer(map: *Map, key: K) ?*V {
|
||||
for (map.keys(), 0..) |k, i| {
|
||||
const is_equal = switch (@typeInfo(K)) {
|
||||
.Pointer => |pointer| switch (pointer.size) {
|
||||
@ -368,35 +406,57 @@ pub fn MyHashMap(comptime K: type, comptime V: type) type {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn put(map: *@This(), allocator: *MyAllocator, key: K, value: V) !void {
|
||||
if (map.get_pointer(key)) |value_ptr| {
|
||||
value_ptr.* = value;
|
||||
pub fn put(map: *@This(), key: K, value: V) !void {
|
||||
if (map.get_pointer(key)) |value_pointer| {
|
||||
value_pointer.* = value;
|
||||
} else {
|
||||
const len = map.length;
|
||||
try map.ensure_capacity(allocator, len + 1);
|
||||
map.ensure_capacity(len + 1);
|
||||
map.put_at_with_capacity(len, key, value);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn put_no_clobber(map: *@This(), allocator: *MyAllocator, key: K, value: V) !void {
|
||||
pub fn put_no_clobber(map: *@This(), key: K, value: V) !void {
|
||||
assert(map.get_pointer(key) == null);
|
||||
const len = map.length;
|
||||
try map.ensure_capacity(allocator, len + 1);
|
||||
map.ensure_capacity(len + 1);
|
||||
map.put_at_with_capacity(len, key, value);
|
||||
}
|
||||
|
||||
fn put_at_with_capacity(map: *@This(), index: IndexType, key: K, value: V) void {
|
||||
fn put_at_with_capacity(map: *@This(), index: u32, key: K, value: V) void {
|
||||
map.length += 1;
|
||||
assert(index < map.length);
|
||||
map.key_pointer[index] = key;
|
||||
map.value_pointer[index] = value;
|
||||
}
|
||||
|
||||
pub fn ensure_capacity(map: *@This(), allocator: *MyAllocator, desired_capacity: IndexType) !void {
|
||||
const result = try ensure_capacity_hashmap(allocator, map.capacity, desired_capacity, @ptrCast(map.key_pointer), @ptrCast(map.value_pointer), map.length, @sizeOf(K), @alignOf(K), @sizeOf(V), @alignOf(V));
|
||||
map.capacity = result.capacity;
|
||||
map.key_pointer = @ptrCast(@alignCast(result.key_pointer));
|
||||
map.value_pointer = @ptrCast(@alignCast(result.value_pointer));
|
||||
fn ensure_capacity(map: *Map, additional: u32) void {
|
||||
const length = map.length;
|
||||
assert((length + additional) * @sizeOf(K) <= pinned_array_max_size);
|
||||
|
||||
{
|
||||
const key_size = length * @sizeOf(K);
|
||||
const key_granularity_aligned_size = align_forward(key_size, map.granularity);
|
||||
const key_new_size = key_size + additional * @sizeOf(K);
|
||||
|
||||
if (key_granularity_aligned_size < key_new_size) {
|
||||
const new_key_granularity_aligned_size = align_forward(key_new_size, map.granularity);
|
||||
const key_pointer: [*]u8 = @ptrCast(map.key_pointer);
|
||||
commit(key_pointer + key_granularity_aligned_size, new_key_granularity_aligned_size - key_granularity_aligned_size) catch unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const value_size = length * @sizeOf(V);
|
||||
const value_granularity_aligned_size = align_forward(value_size, map.granularity);
|
||||
const value_new_size = value_size + additional * @sizeOf(K);
|
||||
|
||||
if (value_granularity_aligned_size < value_new_size) {
|
||||
const new_value_granularity_aligned_size = align_forward(value_new_size, map.granularity);
|
||||
const value_pointer: [*]u8 = @ptrCast(map.value_pointer);
|
||||
commit(value_pointer + value_granularity_aligned_size, new_value_granularity_aligned_size - value_granularity_aligned_size) catch unreachable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn keys(map: *@This()) []K {
|
||||
@ -406,6 +466,10 @@ pub fn MyHashMap(comptime K: type, comptime V: type) type {
|
||||
pub fn values(map: *@This()) []V {
|
||||
return map.value_pointer[0..map.length];
|
||||
}
|
||||
|
||||
pub fn clear(map: *Map) void {
|
||||
map.length = 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -530,105 +594,6 @@ pub const PageAllocator = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub const IndexType = if (@sizeOf(usize) >= 8) u32 else usize;
|
||||
|
||||
const ArrayCapacity = struct {
|
||||
pointer: *anyopaque,
|
||||
capacity: IndexType,
|
||||
};
|
||||
|
||||
fn ensure_capacity_array(allocator: *MyAllocator, current_capacity: IndexType, desired_capacity: IndexType, pointer: [*]u8, length: IndexType, element_size: IndexType, element_alignment: u16) !ArrayCapacity {
|
||||
var new_capacity = @max(current_capacity, initial_item_count);
|
||||
while (new_capacity < desired_capacity) {
|
||||
new_capacity *= factor;
|
||||
}
|
||||
if (new_capacity > current_capacity) {
|
||||
const old_byte_slice = pointer[0 .. length * element_size];
|
||||
const new_byte_capacity = new_capacity * element_size;
|
||||
const new_slice = try allocator.reallocate(old_byte_slice, new_byte_capacity, element_alignment);
|
||||
return .{
|
||||
.pointer = new_slice.ptr,
|
||||
.capacity = new_capacity,
|
||||
};
|
||||
} else {
|
||||
return .{
|
||||
.pointer = pointer,
|
||||
.capacity = current_capacity,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const initial_item_count = 16;
|
||||
const factor = 2;
|
||||
|
||||
pub fn UnpinnedArray(comptime T: type) type {
|
||||
return struct {
|
||||
pointer: [*]T = undefined,
|
||||
length: IndexType = 0,
|
||||
capacity: IndexType = 0,
|
||||
|
||||
pub fn initialize_with_capacity(allocator: *MyAllocator, item_count: IndexType) !@This() {
|
||||
var array = @This(){};
|
||||
try array.ensure_capacity(allocator, item_count);
|
||||
return array;
|
||||
}
|
||||
|
||||
pub fn ensure_capacity(array: *@This(), allocator: *MyAllocator, desired_capacity: IndexType) !void {
|
||||
const result = try ensure_capacity_array(allocator, array.capacity, desired_capacity, @ptrCast(array.pointer), array.length, @sizeOf(T), @alignOf(T));
|
||||
array.pointer = @ptrCast(@alignCast(result.pointer));
|
||||
array.capacity = result.capacity;
|
||||
}
|
||||
|
||||
pub fn append(array: *@This(), allocator: *MyAllocator, item: T) !void {
|
||||
try array.ensure_capacity(allocator, array.length + 1);
|
||||
array.append_with_capacity(item);
|
||||
}
|
||||
|
||||
pub fn append_slice(array: *@This(), allocator: *MyAllocator, items: []const T) !void {
|
||||
try array.ensure_capacity(allocator, @intCast(array.length + items.len));
|
||||
@memcpy(array.pointer[array.length..][0..items.len], items);
|
||||
array.length += @intCast(items.len);
|
||||
}
|
||||
|
||||
pub fn append_with_capacity(array: *@This(), item: T) void {
|
||||
assert(array.length < array.capacity);
|
||||
array.pointer[array.length] = item;
|
||||
array.length += 1;
|
||||
}
|
||||
|
||||
pub fn slice(array: *@This()) []T {
|
||||
return array.pointer[0..array.length];
|
||||
}
|
||||
|
||||
pub fn insert(array: *@This(), allocator: *MyAllocator, index: IndexType, item: T) !void {
|
||||
assert(index < array.length);
|
||||
if (array.length + 1 <= array.capacity) {
|
||||
const after_count = array.length - index;
|
||||
copy_backwards(T, array.pointer[index + 1 ..][0..after_count], array.pointer[index..][0..after_count]);
|
||||
} else {
|
||||
const new_capacity = array.capacity * 2;
|
||||
const new_slice = try allocator.allocate(new_capacity * @sizeOf(T), @alignOf(T));
|
||||
const new_typed_slice: []T = @as([*]T, @ptrCast(@alignCast(new_slice.ptr)))[0..new_capacity];
|
||||
@memcpy(new_typed_slice[0..index], array.pointer[0..index]);
|
||||
const after_count = array.length - index;
|
||||
@memcpy(new_typed_slice[index + 1 ..][0..after_count], array.pointer[index..][0..after_count]);
|
||||
try allocator.free(@as([*]u8, @ptrCast(@alignCast(array.slice().ptr)))[0 .. array.capacity * @sizeOf(T)]);
|
||||
array.pointer = new_typed_slice.ptr;
|
||||
array.capacity = new_capacity;
|
||||
}
|
||||
|
||||
array.pointer[index] = item;
|
||||
array.length += 1;
|
||||
}
|
||||
|
||||
pub fn pop(array: *@This()) T {
|
||||
assert(array.length > 0);
|
||||
array.length -= 1;
|
||||
return array.pointer[array.length];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn copy_backwards(comptime T: type, destination: []T, source: []const T) void {
|
||||
@setRuntimeSafety(false);
|
||||
assert(destination.len >= source.len);
|
||||
@ -639,41 +604,6 @@ fn copy_backwards(comptime T: type, destination: []T, source: []const T) void {
|
||||
}
|
||||
}
|
||||
|
||||
test {
|
||||
var page_allocator = PageAllocator{};
|
||||
const allocator = &page_allocator.allocator;
|
||||
var foo = UnpinnedArray(u32){};
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
try foo.append(allocator, 1);
|
||||
}
|
||||
|
||||
pub fn equal(a: anytype, b: @TypeOf(a)) bool {
|
||||
const T = @TypeOf(a);
|
||||
|
||||
|
@ -3,97 +3,97 @@ const assert = std.debug.assert;
|
||||
const linker = @import("linker.zig");
|
||||
|
||||
const library = @import("../library.zig");
|
||||
const UnpinnedArray = library.UnpinnedArray;
|
||||
const PinnedArray = library.PinnedArray;
|
||||
|
||||
const Compilation = @import("../Compilation.zig");
|
||||
const write = Compilation.write;
|
||||
|
||||
pub fn link(context: *const Compilation.Context, options: linker.Options) !void {
|
||||
assert(options.backend == .lld);
|
||||
var argv = UnpinnedArray([]const u8){};
|
||||
var argv = try PinnedArray([]const u8).init_with_default_granularity();
|
||||
const driver_program = switch (@import("builtin").os.tag) {
|
||||
.windows => "lld-link",
|
||||
.linux => "ld.lld",
|
||||
.macos => "ld64.lld",
|
||||
else => @compileError("OS not supported"),
|
||||
};
|
||||
try argv.append(context.my_allocator, driver_program);
|
||||
try argv.append(context.my_allocator, "--error-limit=0");
|
||||
_ = argv.append(driver_program);
|
||||
_ = argv.append("--error-limit=0");
|
||||
|
||||
// const output_path = out_path orelse "a.out";
|
||||
try argv.append(context.my_allocator, "-o");
|
||||
try argv.append(context.my_allocator, options.output_file_path);
|
||||
_ = argv.append("-o");
|
||||
_ = argv.append(options.output_file_path);
|
||||
|
||||
try argv.append_slice(context.my_allocator, options.extra_arguments);
|
||||
argv.append_slice(options.extra_arguments);
|
||||
|
||||
for (options.objects) |object| {
|
||||
try argv.append(context.my_allocator, object.path);
|
||||
_ = argv.append(object.path);
|
||||
}
|
||||
|
||||
const ci = @import("configuration").ci;
|
||||
switch (@import("builtin").os.tag) {
|
||||
.macos => {
|
||||
try argv.append(context.my_allocator, "-dynamic");
|
||||
try argv.append_slice(context.my_allocator, &.{ "-platform_version", "macos", "13.4.1", "13.3" });
|
||||
try argv.append(context.my_allocator, "-arch");
|
||||
try argv.append(context.my_allocator, switch (@import("builtin").cpu.arch) {
|
||||
_ = argv.append("-dynamic");
|
||||
argv.append_slice(&.{ "-platform_version", "macos", "13.4.1", "13.3" });
|
||||
_ = argv.append("-arch");
|
||||
_ = argv.append(switch (@import("builtin").cpu.arch) {
|
||||
.aarch64 => "arm64",
|
||||
else => |t| @panic(@tagName(t)),
|
||||
});
|
||||
|
||||
try argv.append_slice(context.my_allocator, &.{ "-syslibroot", "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk" });
|
||||
argv.append_slice(&.{ "-syslibroot", "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk" });
|
||||
|
||||
if (!library.ends_with_slice(options.output_file_path, ".dylib")) {
|
||||
try argv.append_slice(context.my_allocator, &.{ "-e", "_main" });
|
||||
argv.append_slice(&.{ "-e", "_main" });
|
||||
}
|
||||
|
||||
try argv.append(context.my_allocator, "-lSystem");
|
||||
_ = argv.append("-lSystem");
|
||||
|
||||
if (options.link_libcpp) {
|
||||
try argv.append(context.my_allocator, "-L/Library/Developer/CommandLineTools/SDKs/MacOSX13.3.sdk/usr/lib");
|
||||
try argv.append(context.my_allocator, "-lc++");
|
||||
_ = argv.append("-L/Library/Developer/CommandLineTools/SDKs/MacOSX13.3.sdk/usr/lib");
|
||||
_ = argv.append("-lc++");
|
||||
}
|
||||
},
|
||||
.linux => {
|
||||
if (ci) {
|
||||
if (options.link_libcpp) {
|
||||
assert(options.link_libc);
|
||||
try argv.append(context.my_allocator, "/lib/x86_64-linux-gnu/libstdc++.so.6");
|
||||
_ = argv.append("/lib/x86_64-linux-gnu/libstdc++.so.6");
|
||||
}
|
||||
|
||||
if (options.link_libc) {
|
||||
try argv.append(context.my_allocator, "/lib/x86_64-linux-gnu/crt1.o");
|
||||
try argv.append(context.my_allocator, "/lib/x86_64-linux-gnu/crti.o");
|
||||
try argv.append_slice(context.my_allocator, &.{ "-L", "/lib/x86_64-linux-gnu" });
|
||||
try argv.append_slice(context.my_allocator, &.{ "-dynamic-linker", "/lib64/ld-linux-x86-64.so.2" });
|
||||
try argv.append(context.my_allocator, "--as-needed");
|
||||
try argv.append(context.my_allocator, "-lm");
|
||||
try argv.append(context.my_allocator, "-lpthread");
|
||||
try argv.append(context.my_allocator, "-lc");
|
||||
try argv.append(context.my_allocator, "-ldl");
|
||||
try argv.append(context.my_allocator, "-lrt");
|
||||
try argv.append(context.my_allocator, "-lutil");
|
||||
try argv.append(context.my_allocator, "/lib/x86_64-linux-gnu/crtn.o");
|
||||
_ = argv.append("/lib/x86_64-linux-gnu/crt1.o");
|
||||
_ = argv.append("/lib/x86_64-linux-gnu/crti.o");
|
||||
argv.append_slice(&.{ "-L", "/lib/x86_64-linux-gnu" });
|
||||
argv.append_slice(&.{ "-dynamic-linker", "/lib64/ld-linux-x86-64.so.2" });
|
||||
_ = argv.append("--as-needed");
|
||||
_ = argv.append("-lm");
|
||||
_ = argv.append("-lpthread");
|
||||
_ = argv.append("-lc");
|
||||
_ = argv.append("-ldl");
|
||||
_ = argv.append("-lrt");
|
||||
_ = argv.append("-lutil");
|
||||
_ = argv.append("/lib/x86_64-linux-gnu/crtn.o");
|
||||
}
|
||||
} else {
|
||||
if (options.link_libcpp) {
|
||||
assert(options.link_libc);
|
||||
try argv.append(context.my_allocator, "/usr/lib/libstdc++.so");
|
||||
_ = argv.append("/usr/lib/libstdc++.so");
|
||||
}
|
||||
|
||||
if (options.link_libc) {
|
||||
try argv.append(context.my_allocator, "/usr/lib/crt1.o");
|
||||
try argv.append(context.my_allocator, "/usr/lib/crti.o");
|
||||
try argv.append_slice(context.my_allocator, &.{ "-L", "/usr/lib" });
|
||||
try argv.append_slice(context.my_allocator, &.{ "-dynamic-linker", "/lib64/ld-linux-x86-64.so.2" });
|
||||
try argv.append(context.my_allocator, "--as-needed");
|
||||
try argv.append(context.my_allocator, "-lm");
|
||||
try argv.append(context.my_allocator, "-lpthread");
|
||||
try argv.append(context.my_allocator, "-lc");
|
||||
try argv.append(context.my_allocator, "-ldl");
|
||||
try argv.append(context.my_allocator, "-lrt");
|
||||
try argv.append(context.my_allocator, "-lutil");
|
||||
try argv.append(context.my_allocator, "/usr/lib/crtn.o");
|
||||
_ = argv.append("/usr/lib/crt1.o");
|
||||
_ = argv.append("/usr/lib/crti.o");
|
||||
argv.append_slice(&.{ "-L", "/usr/lib" });
|
||||
argv.append_slice(&.{ "-dynamic-linker", "/lib64/ld-linux-x86-64.so.2" });
|
||||
_ = argv.append("--as-needed");
|
||||
_ = argv.append("-lm");
|
||||
_ = argv.append("-lpthread");
|
||||
_ = argv.append("-lc");
|
||||
_ = argv.append("-ldl");
|
||||
_ = argv.append("-lrt");
|
||||
_ = argv.append("-lutil");
|
||||
_ = argv.append("/usr/lib/crtn.o");
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -102,10 +102,10 @@ pub fn link(context: *const Compilation.Context, options: linker.Options) !void
|
||||
}
|
||||
|
||||
for (options.libraries) |lib| {
|
||||
try argv.append(context.my_allocator, try std.mem.concat(context.allocator, u8, &.{ "-l", lib.path }));
|
||||
_ = argv.append(try std.mem.concat(context.allocator, u8, &.{ "-l", lib.path }));
|
||||
}
|
||||
|
||||
const argv_zero_terminated = try Compilation.argsCopyZ(context.allocator, argv.slice());
|
||||
const argv_zero_terminated = try Compilation.argsCopyZ(context.allocator, argv.const_slice());
|
||||
|
||||
var stdout_ptr: [*]const u8 = undefined;
|
||||
var stdout_len: usize = 0;
|
||||
@ -121,7 +121,7 @@ pub fn link(context: *const Compilation.Context, options: linker.Options) !void
|
||||
if (!result) {
|
||||
const stdout = stdout_ptr[0..stdout_len];
|
||||
const stderr = stderr_ptr[0..stderr_len];
|
||||
for (argv.slice()) |arg| {
|
||||
for (argv.const_slice()) |arg| {
|
||||
try write(.panic, arg);
|
||||
try write(.panic, " ");
|
||||
}
|
||||
|
@ -26,26 +26,21 @@ var my_allocator = PageAllocator{};
|
||||
pub fn main() !void {
|
||||
var arena_allocator = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||
const allocator = arena_allocator.allocator();
|
||||
var arg_it = try std.process.ArgIterator.initWithAllocator(allocator);
|
||||
var args = library.UnpinnedArray([]const u8){};
|
||||
const arguments: []const []const u8 = try std.process.argsAlloc(allocator);
|
||||
const context = try Compilation.createContext(allocator, &my_allocator.allocator);
|
||||
while (arg_it.next()) |arg| {
|
||||
try args.append(context.my_allocator, arg);
|
||||
}
|
||||
const arguments = args.slice();
|
||||
const debug_args = false;
|
||||
if (debug_args and @import("builtin").os.tag != .windows) {
|
||||
assert(arguments.len > 0);
|
||||
const home_dir = std.posix.getenv("HOME") orelse unreachable;
|
||||
const timestamp = std.time.milliTimestamp();
|
||||
var argument_list = std.ArrayList(u8).init(std.heap.page_allocator);
|
||||
for (arguments) |arg| {
|
||||
argument_list.appendSlice(arg) catch {};
|
||||
argument_list.append(' ') catch {};
|
||||
}
|
||||
argument_list.append('\n') catch {};
|
||||
std.fs.cwd().writeFile(std.fmt.allocPrint(std.heap.page_allocator, "{s}/dev/nativity/nat/invocation_log_{}", .{ home_dir, timestamp }) catch unreachable, argument_list.items) catch {};
|
||||
}
|
||||
// const debug_args = false;
|
||||
// if (debug_args and @import("builtin").os.tag != .windows) {
|
||||
// assert(arguments.len > 0);
|
||||
// const home_dir = std.posix.getenv("HOME") orelse unreachable;
|
||||
// const timestamp = std.time.milliTimestamp();
|
||||
// var argument_list = PinnedArray(u8){};
|
||||
// for (arguments) |arg| {
|
||||
// argument_list.append_slice(context.my_allocator, arg) catch {};
|
||||
// argument_list.append(context.my_allocator, ' ') catch {};
|
||||
// }
|
||||
// argument_list.append(context.my_allocator, '\n') catch {};
|
||||
// std.fs.cwd().writeFile(std.fmt.allocPrint(std.heap.page_allocator, "{s}/dev/nativity/nat/invocation_log_{}", .{ home_dir, timestamp }) catch unreachable, argument_list.slice()) catch {};
|
||||
// }
|
||||
|
||||
if (arguments.len <= 1) {
|
||||
return error.InvalidInput;
|
||||
|
@ -141,7 +141,7 @@ const Arena = struct{
|
||||
const result = base + arena.position + alignment;
|
||||
arena.position += size + alignment;
|
||||
|
||||
if (arena.commit_position < arena.position - arena.commit_position) {
|
||||
if (arena.commit_position < arena.position) {
|
||||
var size_to_commit = arena.position - arena.commit_position;
|
||||
size_to_commit += commit_granularity - 1;
|
||||
size_to_commit -= size_to_commit % commit_granularity;
|
||||
|
Loading…
x
Reference in New Issue
Block a user