almost working register allocator

This commit is contained in:
David Gonzalez Martin 2023-11-07 15:00:48 -06:00
parent 77e54285f5
commit aefabd6108
5 changed files with 676 additions and 231 deletions

View File

@ -307,12 +307,12 @@ pub const Function = struct {
.phi => {}, .phi => {},
.ret => |ret_index| { .ret => |ret_index| {
const ret = function.ir.returns.get(ret_index); const ret = function.ir.returns.get(ret_index);
switch (ret.instruction.valid) { switch (ret.instruction.invalid) {
true => { false => {
const ret_value = function.ir.instructions.get(ret.instruction).*; const ret_value = function.ir.instructions.get(ret.instruction).*;
try writer.print(" {s}", .{@tagName(ret_value)}); try writer.print(" {s}", .{@tagName(ret_value)});
}, },
false => try writer.writeAll(" void"), true => try writer.writeAll(" void"),
} }
}, },
// .load => |load_index| { // .load => |load_index| {
@ -518,13 +518,13 @@ pub const Builder = struct {
const function_declaration_index = ir_call.function; const function_declaration_index = ir_call.function;
const function_declaration = builder.ir.function_declarations.get(function_declaration_index); const function_declaration = builder.ir.function_declarations.get(function_declaration_index);
const function_definition_index = function_declaration.definition; const function_definition_index = function_declaration.definition;
switch (function_definition_index.valid) { switch (function_definition_index.invalid) {
true => { false => {
const function = builder.ir.function_definitions.get(function_definition_index); const function = builder.ir.function_definitions.get(function_definition_index);
const first_block = function.blocks.items[0]; const first_block = function.blocks.items[0];
break :blk first_block; break :blk first_block;
}, },
false => continue, true => continue,
} }
}, },
.@"unreachable", .ret, .store => continue, .@"unreachable", .ret, .store => continue,
@ -625,10 +625,10 @@ pub const Builder = struct {
.phi => blk: { .phi => blk: {
var did_something = false; var did_something = false;
var head = &instruction.phi; var head = &instruction.phi;
next: while (head.valid) { next: while (!head.invalid) {
const phi = builder.ir.phis.get(head.*); const phi = builder.ir.phis.get(head.*);
const phi_jump = builder.ir.jumps.get(phi.jump); const phi_jump = builder.ir.jumps.get(phi.jump);
assert(phi_jump.source.valid); assert(!phi_jump.source.invalid);
for (reachable_blocks) |block_index| { for (reachable_blocks) |block_index| {
if (phi_jump.source.eq(block_index)) { if (phi_jump.source.eq(block_index)) {
@ -655,12 +655,12 @@ pub const Builder = struct {
var only_value = Instruction.Index.invalid; var only_value = Instruction.Index.invalid;
var it = phi_index; var it = phi_index;
while (it.valid) { while (!it.invalid) {
const phi = builder.ir.phis.get(it); const phi = builder.ir.phis.get(it);
const phi_value = builder.ir.instructions.get(phi.instruction); const phi_value = builder.ir.instructions.get(phi.instruction);
if (phi_value.* == .phi) unreachable; if (phi_value.* == .phi) unreachable;
// TODO: undefined // TODO: undefined
if (only_value.valid) { if (!only_value.invalid) {
if (!only_value.eq(phi.instruction)) { if (!only_value.eq(phi.instruction)) {
break :trivial_blk null; break :trivial_blk null;
} }
@ -675,7 +675,7 @@ pub const Builder = struct {
}; };
if (trivial_phi) |trivial_value| { if (trivial_phi) |trivial_value| {
if (trivial_value.valid) { if (!trivial_value.invalid) {
// Option to delete // Option to delete
const delete = false; const delete = false;
if (delete) { if (delete) {
@ -740,8 +740,8 @@ pub const Builder = struct {
}; };
for (operands) |operand_instruction_index_pointer| { for (operands) |operand_instruction_index_pointer| {
switch (operand_instruction_index_pointer.valid) { switch (operand_instruction_index_pointer.invalid) {
true => { false => {
const operand_value = builder.ir.instructions.get(operand_instruction_index_pointer.*); const operand_value = builder.ir.instructions.get(operand_instruction_index_pointer.*);
switch (operand_value.*) { switch (operand_value.*) {
.copy => |copy_value| { .copy => |copy_value| {
@ -759,7 +759,7 @@ pub const Builder = struct {
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
} }
}, },
false => {}, true => {},
} }
} }
@ -847,13 +847,13 @@ pub const Builder = struct {
var arguments = try ArrayList(Instruction.Index).initCapacity(builder.allocator, sema_syscall.argument_count + 1); var arguments = try ArrayList(Instruction.Index).initCapacity(builder.allocator, sema_syscall.argument_count + 1);
const sema_syscall_number = sema_syscall.number; const sema_syscall_number = sema_syscall.number;
assert(sema_syscall_number.valid); assert(!sema_syscall_number.invalid);
const number_value_index = try builder.emitSyscallArgument(sema_syscall_number); const number_value_index = try builder.emitSyscallArgument(sema_syscall_number);
arguments.appendAssumeCapacity(number_value_index); arguments.appendAssumeCapacity(number_value_index);
for (sema_syscall.getArguments()) |sema_syscall_argument| { for (sema_syscall.getArguments()) |sema_syscall_argument| {
assert(sema_syscall_argument.valid); assert(!sema_syscall_argument.invalid);
const argument_value_index = try builder.emitSyscallArgument(sema_syscall_argument); const argument_value_index = try builder.emitSyscallArgument(sema_syscall_argument);
arguments.appendAssumeCapacity(argument_value_index); arguments.appendAssumeCapacity(argument_value_index);
} }
@ -890,7 +890,7 @@ pub const Builder = struct {
const loop_body_block = try builder.newBlock(); const loop_body_block = try builder.newBlock();
const loop_prologue_block = if (options.emit_exit_block) try builder.newBlock() else BasicBlock.Index.invalid; const loop_prologue_block = if (options.emit_exit_block) try builder.newBlock() else BasicBlock.Index.invalid;
const loop_head_block = switch (condition.valid) { const loop_head_block = switch (!condition.invalid) {
false => loop_body_block, false => loop_body_block,
true => unreachable, true => unreachable,
}; };
@ -902,7 +902,7 @@ pub const Builder = struct {
const sema_body_block = builder.module.blocks.get(sema_loop_body.block); const sema_body_block = builder.module.blocks.get(sema_loop_body.block);
builder.currentFunction().current_basic_block = try builder.blockInsideBasicBlock(sema_body_block, loop_body_block); builder.currentFunction().current_basic_block = try builder.blockInsideBasicBlock(sema_body_block, loop_body_block);
if (loop_prologue_block.valid) { if (!loop_prologue_block.invalid) {
builder.ir.blocks.get(loop_prologue_block).seal(); builder.ir.blocks.get(loop_prologue_block).seal();
} }
@ -921,7 +921,7 @@ pub const Builder = struct {
unreachable; unreachable;
} }
if (loop_prologue_block.valid) { if (!loop_prologue_block.invalid) {
builder.currentFunction().current_basic_block = loop_prologue_block; builder.currentFunction().current_basic_block = loop_prologue_block;
} }
}, },
@ -933,13 +933,13 @@ pub const Builder = struct {
const sema_ret = builder.module.returns.get(sema_ret_index); const sema_ret = builder.module.returns.get(sema_ret_index);
const return_value = try builder.emitReturnValue(sema_ret.value); const return_value = try builder.emitReturnValue(sema_ret.value);
const phi_instruction = builder.ir.instructions.get(builder.currentFunction().return_phi_node); const phi_instruction = builder.ir.instructions.get(builder.currentFunction().return_phi_node);
const phi = switch (phi_instruction.phi.valid) { const phi = switch (phi_instruction.phi.invalid) {
true => unreachable, false => unreachable,
false => (try builder.ir.phis.append(builder.allocator, std.mem.zeroes(Phi))).ptr, true => (try builder.ir.phis.append(builder.allocator, std.mem.zeroes(Phi))).ptr,
}; //builder.ir.phis.get(phi_instruction.phi); }; //builder.ir.phis.get(phi_instruction.phi);
const exit_jump = try builder.jump(.{ const exit_jump = try builder.jump(.{
.source = builder.currentFunction().current_basic_block, .source = builder.currentFunction().current_basic_block,
.destination = switch (phi_instruction.phi.valid) { .destination = switch (!phi_instruction.phi.invalid) {
true => phi.block, true => phi.block,
false => builder.currentFunction().return_phi_block, false => builder.currentFunction().return_phi_block,
}, },
@ -1056,8 +1056,8 @@ pub const Builder = struct {
fn processCall(builder: *Builder, sema_call_index: Compilation.Call.Index) anyerror!Instruction.Index { fn processCall(builder: *Builder, sema_call_index: Compilation.Call.Index) anyerror!Instruction.Index {
const sema_call = builder.module.calls.get(sema_call_index); const sema_call = builder.module.calls.get(sema_call_index);
const sema_argument_list_index = sema_call.arguments; const sema_argument_list_index = sema_call.arguments;
const argument_list: []const Instruction.Index = switch (sema_argument_list_index.valid) { const argument_list: []const Instruction.Index = switch (sema_argument_list_index.invalid) {
true => blk: { false => blk: {
var argument_list = ArrayList(Instruction.Index){}; var argument_list = ArrayList(Instruction.Index){};
const sema_argument_list = builder.module.argument_lists.get(sema_argument_list_index); const sema_argument_list = builder.module.argument_lists.get(sema_argument_list_index);
try argument_list.ensureTotalCapacity(builder.allocator, sema_argument_list.array.items.len); try argument_list.ensureTotalCapacity(builder.allocator, sema_argument_list.array.items.len);
@ -1067,7 +1067,7 @@ pub const Builder = struct {
} }
break :blk argument_list.items; break :blk argument_list.items;
}, },
false => &.{}, true => &.{},
}; };
const call_index = try builder.call(.{ const call_index = try builder.call(.{
@ -1172,15 +1172,15 @@ pub const Builder = struct {
fn jump(builder: *Builder, descriptor: Jump) !Jump.Index { fn jump(builder: *Builder, descriptor: Jump) !Jump.Index {
const destination_block = builder.ir.blocks.get(descriptor.destination); const destination_block = builder.ir.blocks.get(descriptor.destination);
assert(!destination_block.sealed); assert(!destination_block.sealed);
assert(descriptor.source.valid); assert(!descriptor.source.invalid);
const jump_allocation = try builder.ir.jumps.append(builder.allocator, descriptor); const jump_allocation = try builder.ir.jumps.append(builder.allocator, descriptor);
return jump_allocation.index; return jump_allocation.index;
} }
fn append(builder: *Builder, instruction: Instruction) !Instruction.Index { fn append(builder: *Builder, instruction: Instruction) !Instruction.Index {
assert(builder.current_function_index.valid); assert(!builder.current_function_index.invalid);
const current_function = builder.currentFunction(); const current_function = builder.currentFunction();
assert(current_function.current_basic_block.valid); assert(!current_function.current_basic_block.invalid);
return builder.appendToBlock(current_function.current_basic_block, instruction); return builder.appendToBlock(current_function.current_basic_block, instruction);
} }

File diff suppressed because it is too large Load Diff

View File

@ -40,10 +40,10 @@ pub fn BlockList(comptime T: type) type {
index: u6, index: u6,
block: u24, block: u24,
_reserved: bool = false, _reserved: bool = false,
valid: bool = true, invalid: bool = false,
pub const invalid = Index{ pub const invalid = Index{
.valid = false, .invalid = true,
.index = 0, .index = 0,
.block = 0, .block = 0,
}; };
@ -53,7 +53,7 @@ pub fn BlockList(comptime T: type) type {
} }
pub fn uniqueInteger(index: Index) u32 { pub fn uniqueInteger(index: Index) u32 {
assert(index.valid); assert(!index.invalid);
return @as(u30, @truncate(@as(u32, @bitCast(index)))); return @as(u30, @truncate(@as(u32, @bitCast(index))));
} }
@ -114,7 +114,7 @@ pub fn BlockList(comptime T: type) type {
} }
pub fn get(list: *List, index: Index) *T { pub fn get(list: *List, index: Index) *T {
assert(index.valid); assert(!index.invalid);
return &list.blocks.items[index.block].items[index.index]; return &list.blocks.items[index.block].items[index.index];
} }

View File

@ -214,23 +214,23 @@ 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);
print("Node index: {}. Left index: {}\n", .{ node_index.uniqueInteger(), node.left.uniqueInteger() }); print("Node index: {}. Left index: {}\n", .{ node_index.uniqueInteger(), node.left.uniqueInteger() });
assert(node.left.valid); assert(!node.left.invalid);
const left_value_index = switch (node.left.valid) { const left_value_index = switch (!node.left.invalid) {
true => blk: { true => blk: {
const member_or_namespace_node_index = node.left; const member_or_namespace_node_index = node.left;
assert(member_or_namespace_node_index.valid); assert(!member_or_namespace_node_index.invalid);
const this_value_allocation = try analyzer.unresolvedAllocate(scope_index, ExpectType.none, member_or_namespace_node_index); const this_value_allocation = try analyzer.unresolvedAllocate(scope_index, ExpectType.none, member_or_namespace_node_index);
break :blk this_value_allocation.index; break :blk this_value_allocation.index;
}, },
false => unreachable, //Value.Index.invalid, false => unreachable, //Value.Index.invalid,
}; };
const left_type = switch (left_value_index.valid) { const left_type = switch (left_value_index.invalid) {
true => switch (analyzer.module.values.get(left_value_index).*) { false => switch (analyzer.module.values.get(left_value_index).*) {
.function => |function_index| analyzer.module.function_prototypes.get(analyzer.module.types.get(analyzer.module.functions.get(function_index).prototype).function).return_type, .function => |function_index| analyzer.module.function_prototypes.get(analyzer.module.types.get(analyzer.module.functions.get(function_index).prototype).function).return_type,
else => |t| @panic(@tagName(t)), else => |t| @panic(@tagName(t)),
}, },
false => Type.Index.invalid, true => Type.Index.invalid,
}; };
const arguments_index = switch (node.id) { const arguments_index = switch (node.id) {
.call, .call_two => |call_tag| (try analyzer.module.argument_lists.append(analyzer.allocator, .{ .call, .call_two => |call_tag| (try analyzer.module.argument_lists.append(analyzer.allocator, .{
@ -340,8 +340,8 @@ const Analyzer = struct {
for (switch_case_node_list, 0..) |switch_case_node_index, index| { for (switch_case_node_list, 0..) |switch_case_node_index, index| {
_ = index; _ = index;
const switch_case_node = analyzer.getScopeNode(scope_index, switch_case_node_index); const switch_case_node = analyzer.getScopeNode(scope_index, switch_case_node_index);
switch (switch_case_node.left.valid) { switch (switch_case_node.left.invalid) {
true => { false => {
const switch_case_condition_node = analyzer.getScopeNode(scope_index, switch_case_node.left); const switch_case_condition_node = analyzer.getScopeNode(scope_index, switch_case_node.left);
var switch_case_group = ArrayList(u32){}; var switch_case_group = ArrayList(u32){};
switch (switch_case_condition_node.id) { switch (switch_case_condition_node.id) {
@ -390,7 +390,7 @@ const Analyzer = struct {
switch_case_groups.appendAssumeCapacity(switch_case_group); switch_case_groups.appendAssumeCapacity(switch_case_group);
}, },
false => { true => {
unreachable; unreachable;
// if (existing_enums.items.len == enum_type.fields.items.len) { // if (existing_enums.items.len == enum_type.fields.items.len) {
// unreachable; // unreachable;
@ -433,9 +433,9 @@ const Analyzer = struct {
fn processAssignment(analyzer: *Analyzer, scope_index: Scope.Index, node_index: Node.Index) !Value { fn processAssignment(analyzer: *Analyzer, scope_index: Scope.Index, node_index: Node.Index) !Value {
const node = analyzer.getScopeNode(scope_index, node_index); const node = analyzer.getScopeNode(scope_index, node_index);
assert(node.id == .assign); assert(node.id == .assign);
const assignment = switch (node.left.valid) { const assignment = switch (node.left.invalid) {
// In an assignment, the node being invalid means a discarding underscore, like this: ```_ = result``` // In an assignment, the node being invalid means a discarding underscore, like this: ```_ = result```
false => { true => {
var result = Value{ var result = Value{
.unresolved = .{ .unresolved = .{
.node_index = node.right, .node_index = node.right,
@ -446,7 +446,7 @@ const Analyzer = struct {
return result; return result;
}, },
true => { false => {
// const id = analyzer.tokenIdentifier(.token); // const id = analyzer.tokenIdentifier(.token);
// print("id: {s}\n", .{id}); // print("id: {s}\n", .{id});
// const left = try analyzer.expression(scope_index, ExpectType.none, statement_node.left); // const left = try analyzer.expression(scope_index, ExpectType.none, statement_node.left);
@ -470,9 +470,9 @@ const Analyzer = struct {
fn processReturn(analyzer: *Analyzer, scope_index: Scope.Index, expect_type: ExpectType, node_index: Node.Index) !Value { fn processReturn(analyzer: *Analyzer, scope_index: Scope.Index, expect_type: ExpectType, node_index: Node.Index) !Value {
const node = analyzer.getScopeNode(scope_index, node_index); const node = analyzer.getScopeNode(scope_index, node_index);
const return_expression: Value.Index = switch (node_index.valid) { const return_expression: Value.Index = switch (node_index.invalid) {
// TODO: expect type // TODO: expect type
true => ret: { false => ret: {
const return_value_allocation = try analyzer.module.values.addOne(analyzer.allocator); const return_value_allocation = try analyzer.module.values.addOne(analyzer.allocator);
return_value_allocation.ptr.* = .{ return_value_allocation.ptr.* = .{
.unresolved = .{ .unresolved = .{
@ -482,7 +482,7 @@ const Analyzer = struct {
try analyzer.resolveNode(return_value_allocation.ptr, scope_index, expect_type, node.left); try analyzer.resolveNode(return_value_allocation.ptr, scope_index, expect_type, node.left);
break :ret return_value_allocation.index; break :ret return_value_allocation.index;
}, },
false => @panic("TODO: ret void"), true => @panic("TODO: ret void"),
}; };
const return_value_allocation = try analyzer.module.returns.append(analyzer.allocator, .{ const return_value_allocation = try analyzer.module.returns.append(analyzer.allocator, .{
@ -501,7 +501,7 @@ const Analyzer = struct {
fn lookupDeclarationInCurrentAndParentScopes(analyzer: *Analyzer, scope_index: Scope.Index, identifier_hash: u32) ?DeclarationLookup { fn lookupDeclarationInCurrentAndParentScopes(analyzer: *Analyzer, scope_index: Scope.Index, identifier_hash: u32) ?DeclarationLookup {
var scope_iterator = scope_index; var scope_iterator = scope_index;
while (scope_iterator.valid) { while (!scope_iterator.invalid) {
const scope = analyzer.module.scopes.get(scope_iterator); const scope = analyzer.module.scopes.get(scope_iterator);
if (scope.declarations.get(identifier_hash)) |declaration_index| { if (scope.declarations.get(identifier_hash)) |declaration_index| {
return .{ return .{
@ -535,8 +535,8 @@ const Analyzer = struct {
const declaration = analyzer.module.declarations.get(declaration_index); const declaration = analyzer.module.declarations.get(declaration_index);
// Up until now, only arguments have no initialization value // Up until now, only arguments have no initialization value
const typecheck_result = switch (declaration.init_value.valid) { const typecheck_result = switch (declaration.init_value.invalid) {
true => blk: { false => blk: {
const init_value = analyzer.module.values.get(declaration.init_value); const init_value = analyzer.module.values.get(declaration.init_value);
print("Declaration found: {}\n", .{init_value}); print("Declaration found: {}\n", .{init_value});
const is_unresolved = init_value.* == .unresolved; const is_unresolved = init_value.* == .unresolved;
@ -560,14 +560,14 @@ const Analyzer = struct {
const typecheck_result = try analyzer.typeCheck(expect_type, declaration.type); const typecheck_result = try analyzer.typeCheck(expect_type, declaration.type);
if (init_value.isComptime() and declaration.mutability == .@"const") { if (init_value.isComptime() and declaration.mutability == .@"const") {
assert(declaration.init_value.valid); assert(!declaration.init_value.invalid);
assert(typecheck_result == .success); assert(typecheck_result == .success);
return declaration.init_value; return declaration.init_value;
} }
break :blk typecheck_result; break :blk typecheck_result;
}, },
false => try analyzer.typeCheck(expect_type, declaration.type), true => try analyzer.typeCheck(expect_type, declaration.type),
}; };
const ref_allocation = try analyzer.module.values.append(analyzer.allocator, .{ const ref_allocation = try analyzer.module.values.append(analyzer.allocator, .{
@ -580,7 +580,7 @@ const Analyzer = struct {
else => declaration.type, else => declaration.type,
}, },
.flexible_integer => blk: { .flexible_integer => blk: {
assert(declaration.type.valid); assert(!declaration.type.invalid);
break :blk declaration.type; break :blk declaration.type;
}, },
}, },
@ -627,7 +627,7 @@ const Analyzer = struct {
}, },
.compiler_intrinsic => { .compiler_intrinsic => {
const argument_list_node_index = node.left; const argument_list_node_index = node.left;
assert(argument_list_node_index.valid); assert(!argument_list_node_index.invalid);
const node_list_node = analyzer.getScopeNode(scope_index, argument_list_node_index); const node_list_node = analyzer.getScopeNode(scope_index, argument_list_node_index);
const node_list = analyzer.getScopeNodeList(scope_index, node_list_node); const node_list = analyzer.getScopeNodeList(scope_index, node_list_node);
@ -692,7 +692,7 @@ const Analyzer = struct {
}, },
false => false_block: { false => false_block: {
const file_type = import_file.file.ptr.type; const file_type = import_file.file.ptr.type;
assert(file_type.valid); assert(!file_type.invalid);
break :false_block file_type; break :false_block file_type;
}, },
}, },
@ -714,7 +714,7 @@ const Analyzer = struct {
}; };
const number_allocation = try analyzer.unresolvedAllocate(scope_index, argument_expect_type, argument_nodes.items[0]); const number_allocation = try analyzer.unresolvedAllocate(scope_index, argument_expect_type, argument_nodes.items[0]);
const number = number_allocation.index; const number = number_allocation.index;
assert(number.valid); assert(!number.invalid);
var arguments = std.mem.zeroes([6]Value.Index); var arguments = std.mem.zeroes([6]Value.Index);
for (argument_nodes.items[1..], 0..) |argument_node_index, argument_index| { for (argument_nodes.items[1..], 0..) |argument_node_index, argument_index| {
const argument_allocation = try analyzer.unresolvedAllocate(scope_index, argument_expect_type, argument_node_index); const argument_allocation = try analyzer.unresolvedAllocate(scope_index, argument_expect_type, argument_node_index);
@ -840,7 +840,7 @@ const Analyzer = struct {
const left_allocation = try analyzer.unresolvedAllocate(scope_index, ExpectType.none, node.left); const left_allocation = try analyzer.unresolvedAllocate(scope_index, ExpectType.none, node.left);
switch (left_allocation.ptr.*) { switch (left_allocation.ptr.*) {
.type => |type_index| { .type => |type_index| {
if (type_index.valid) { if (!type_index.invalid) {
const left_type = analyzer.module.types.get(type_index); const left_type = analyzer.module.types.get(type_index);
switch (left_type.*) { switch (left_type.*) {
.@"struct" => |struct_index| { .@"struct" => |struct_index| {
@ -930,7 +930,7 @@ const Analyzer = struct {
const field_node = analyzer.getScopeNode(scope_index, field_node_index); const field_node = analyzer.getScopeNode(scope_index, field_node_index);
const identifier = analyzer.tokenIdentifier(scope_index, field_node.token); const identifier = analyzer.tokenIdentifier(scope_index, field_node.token);
print("Enum field: {s}\n", .{identifier}); print("Enum field: {s}\n", .{identifier});
assert(!field_node.left.valid); assert(field_node.left.invalid);
const enum_hash_name = try analyzer.processIdentifier(identifier); const enum_hash_name = try analyzer.processIdentifier(identifier);
@ -1049,9 +1049,9 @@ const Analyzer = struct {
const arguments_node_index = simple_function_prototype_node.left; const arguments_node_index = simple_function_prototype_node.left;
const return_type_node_index = simple_function_prototype_node.right; const return_type_node_index = simple_function_prototype_node.right;
const arguments: ?[]const Declaration.Index = switch (arguments_node_index.valid) { const arguments: ?[]const Declaration.Index = switch (arguments_node_index.invalid) {
false => null, true => null,
true => blk: { false => blk: {
const argument_list_node = analyzer.getScopeNode(scope_index, arguments_node_index); const argument_list_node = analyzer.getScopeNode(scope_index, arguments_node_index);
// print("Function prototype argument list node: {}\n", .{function_prototype_node.left.uniqueInteger()}); // print("Function prototype argument list node: {}\n", .{function_prototype_node.left.uniqueInteger()});
const argument_node_list = switch (argument_list_node.id) { const argument_node_list = switch (argument_list_node.id) {
@ -1161,7 +1161,7 @@ const Analyzer = struct {
const scope = new_scope.ptr; const scope = new_scope.ptr;
const scope_index = new_scope.index; const scope_index = new_scope.index;
const is_file = !parent_scope_index.valid; const is_file = parent_scope_index.invalid;
assert(is_file); assert(is_file);
const struct_allocation = try analyzer.module.structs.append(analyzer.allocator, .{ const struct_allocation = try analyzer.module.structs.append(analyzer.allocator, .{
@ -1171,7 +1171,7 @@ const Analyzer = struct {
.@"struct" = struct_allocation.index, .@"struct" = struct_allocation.index,
}); });
if (!parent_scope_index.valid) { if (parent_scope_index.invalid) {
file.type = type_allocation.index; file.type = type_allocation.index;
} }
@ -1270,14 +1270,14 @@ const Analyzer = struct {
fn symbolDeclaration(analyzer: *Analyzer, scope_index: Scope.Index, node_index: Node.Index, scope_type: ScopeType) !Declaration.Index { fn symbolDeclaration(analyzer: *Analyzer, scope_index: Scope.Index, node_index: Node.Index, scope_type: ScopeType) !Declaration.Index {
const declaration_node = analyzer.getScopeNode(scope_index, node_index); const declaration_node = analyzer.getScopeNode(scope_index, node_index);
assert(declaration_node.id == .simple_symbol_declaration); assert(declaration_node.id == .simple_symbol_declaration);
const expect_type = switch (declaration_node.left.valid) { const expect_type = switch (declaration_node.left.invalid) {
true => switch (scope_type) { false => switch (scope_type) {
.local => ExpectType{ .local => ExpectType{
.type_index = try analyzer.resolveType(scope_index, declaration_node.left), .type_index = try analyzer.resolveType(scope_index, declaration_node.left),
}, },
.global => ExpectType.none, .global => ExpectType.none,
}, },
false => ExpectType.none, true => ExpectType.none,
}; };
const mutability: Compilation.Mutability = switch (analyzer.getScopeToken(scope_index, declaration_node.token).id) { const mutability: Compilation.Mutability = switch (analyzer.getScopeToken(scope_index, declaration_node.token).id) {
.fixed_keyword_const => .@"const", .fixed_keyword_const => .@"const",
@ -1292,7 +1292,7 @@ const Analyzer = struct {
} }
// TODO: Check if it is a keyword // TODO: Check if it is a keyword
assert(declaration_node.right.valid); assert(!declaration_node.right.invalid);
const argument = null; const argument = null;
assert(argument == null); assert(argument == null);

View File

@ -36,24 +36,24 @@ pub const Node = packed struct(u128) {
pub const Index = packed struct(u32) { pub const Index = packed struct(u32) {
value: u31, value: u31,
valid: bool = true, invalid: bool = false,
pub const invalid = Index{ pub const invalid = Index{
.value = 0, .value = 0,
.valid = false, .invalid = true,
}; };
pub fn get(index: Index) ?u32 { pub fn get(index: Index) ?u32 {
return if (index.valid) index.value else null; return if (index.invvalid) null else index.value;
} }
pub fn unwrap(index: Index) u32 { pub fn unwrap(index: Index) u32 {
assert(index.valid); assert(!index.invalid);
return index.value; return index.value;
} }
pub fn uniqueInteger(index: Index) u32 { pub fn uniqueInteger(index: Index) u32 {
assert(index.valid); assert(!index.invalid);
return index.value; return index.value;
} }
}; };
@ -677,7 +677,7 @@ const Analyzer = struct {
fn expressionPrecedence(analyzer: *Analyzer, minimum_precedence: i32) !Node.Index { fn expressionPrecedence(analyzer: *Analyzer, minimum_precedence: i32) !Node.Index {
var result = try analyzer.prefixExpression(); var result = try analyzer.prefixExpression();
if (result.valid) { if (!result.invalid) {
const prefix_node = analyzer.nodes.items[result.unwrap()]; const prefix_node = analyzer.nodes.items[result.unwrap()];
std.debug.print("Prefix: {}\n", .{prefix_node.id}); std.debug.print("Prefix: {}\n", .{prefix_node.id});
} }
@ -906,7 +906,7 @@ const Analyzer = struct {
while (true) { while (true) {
const suffix_operator = try analyzer.suffixOperator(result); const suffix_operator = try analyzer.suffixOperator(result);
if (suffix_operator.valid) { if (!suffix_operator.invalid) {
result = suffix_operator; result = suffix_operator;
} else { } else {
if (analyzer.tokens[analyzer.token_i].id == .left_parenthesis) { if (analyzer.tokens[analyzer.token_i].id == .left_parenthesis) {
@ -1183,7 +1183,7 @@ pub fn analyze(allocator: Allocator, tokens: []const Token, source_file: []const
}); });
assert(node_index.value == 0); assert(node_index.value == 0);
assert(node_index.valid); assert(!node_index.invalid);
std.debug.print("Start Parsing file root members\n", .{}); std.debug.print("Start Parsing file root members\n", .{});
const members = try analyzer.containerMembers(); const members = try analyzer.containerMembers();