From 25849592b36cc55b174c1584935c8b3ba3495352 Mon Sep 17 00:00:00 2001 From: David Gonzalez Martin Date: Thu, 12 Jun 2025 18:37:46 -0600 Subject: [PATCH] Pass 'bits' --- src/compiler.bbb | 216 ++++++++++++++++++++++++++++++++++++++++++++++- src/parser.cpp | 3 +- 2 files changed, 216 insertions(+), 3 deletions(-) diff --git a/src/compiler.bbb b/src/compiler.bbb index b9e2c35..3372727 100644 --- a/src/compiler.bbb +++ b/src/compiler.bbb @@ -1392,6 +1392,14 @@ TypeStruct = struct next: &Type, } +TypeBits = struct +{ + fields: []Field, + backing_type: &Type, + line: u32, + is_implicit_backing_type: u1, +} + TypeContent = union { integer: TypeInteger, @@ -1401,6 +1409,7 @@ TypeContent = union enum_array: TypeEnumArray, enum: TypeEnum, struct: TypeStruct, + bits: TypeBits, } TypeLLVM = struct @@ -1926,6 +1935,22 @@ ValueVaArg = struct type: &Type, } +AggregateInitializationElement = struct +{ + name: []u8, + value: &Value, + line: u32, + column: u32, +} + +ValueAggregateInitialization = struct +{ + elements: []AggregateInitializationElement, + scope: &Scope, + is_constant: u1, + is_zero: u1, +} + ValueContent = union { constant_integer: ValueConstantInteger, @@ -1942,6 +1967,7 @@ ValueContent = union field_access: ValueFieldAccess, string_literal: []u8, va_arg: ValueVaArg, + aggregate_initialization: ValueAggregateInitialization, } ValueKind = enum @@ -4769,6 +4795,94 @@ reference_identifier = fn (module: &Module, current_scope: &Scope, identifier: [ } } +parse_aggregate_initialization = fn (module: &Module, scope: &Scope, builder: ValueBuilder, end_ch: u8) &Value +{ + skip_space(module); + + >element_buffer: [64]AggregateInitializationElement = undefined; + >field_count: u64 = 0; + >is_zero: u1 = 0; + + while (1) + { + skip_space(module); + + if (consume_character_if_match(module, end_ch)) + { + break; + } + + >field_index = field_count; + >checkpoint = get_checkpoint(module); + + if (consume_character_if_match(module, '.')) + { + >name = parse_identifier(module); + skip_space(module); + expect_character(module, '='); + skip_space(module); + + >line = get_line(module); + >column = get_column(module); + + >value = parse_value(module, scope, zero); + skip_space(module); + consume_character_if_match(module, ','); + + element_buffer[field_index] = { + .name = name, + .value = value, + .line = line, + .column = column, + }; + } + else + { + >token = tokenize(module); + is_zero = token.id == .value_keyword and token.content.value_keyword == .zero; + + if (is_zero) + { + skip_space(module); + + if (consume_character_if_match(module, ',')) + { + skip_space(module); + } + + expect_character(module, right_brace); + break; + } + else + { + report_error(); + } + } + + field_count += 1; + } + + >elements = arena_allocate_slice[AggregateInitializationElement](module.arena, field_count); + memcpy(#pointer_cast(elements.pointer), #pointer_cast(&element_buffer), field_count * #byte_size(AggregateInitializationElement)); + + >result = new_value(module); + result.& = { + .content = { + .aggregate_initialization = { + .elements = elements, + .scope = scope, + .is_constant = 0, + .is_zero = is_zero, + }, + }, + .id = .aggregate_initialization, + .kind = builder.kind, + zero, + }; + + return result; +} + parse_left = fn (module: &Module, scope: &Scope, builder: ValueBuilder) &Value { >token = builder.token; @@ -5090,7 +5204,7 @@ parse_left = fn (module: &Module, scope: &Scope, builder: ValueBuilder) &Value }, .left_brace => { - #trap(); + result = parse_aggregate_initialization(module, scope, builder, right_brace); }, .value_keyword => { @@ -5994,7 +6108,100 @@ parse = fn (module: &Module) void { .bits => { - #trap(); + >is_implicit_type = module.content[module.offset] == left_brace; + + >backing_type: &Type = zero; + + if (!is_implicit_type) + { + backing_type = parse_type(module, scope); + } + + skip_space(module); + expect_character(module, left_brace); + + >field_buffer: [64]Field = undefined; + >field_bit_offset: u64 = 0; + >field_count: u64 = 0; + + while (1) + { + skip_space(module); + + if (consume_character_if_match(module, right_brace)) + { + break; + } + + >field_line = get_line(module); + >field_name = parse_identifier(module); + + skip_space(module); + expect_character(module, ':'); + skip_space(module); + + >field_type = parse_type(module, scope); + + >field_bit_count = get_bit_size(field_type); + + skip_space(module); + + consume_character_if_match(module, ','); + + field_buffer[field_count] = { + .name = field_name, + .type = field_type, + .offset = field_bit_offset, + .line = field_line, + }; + + field_bit_offset += field_bit_count; + field_count += 1; + } + + consume_character_if_match(module, ';'); + + >fields = arena_allocate_slice[Field](module.arena, field_count); + memcpy(#pointer_cast(fields.pointer), #pointer_cast(&field_buffer), field_count * #byte_size(Field)); + + >needed_bit_count = #max(next_power_of_two(field_bit_offset), 8); + if (needed_bit_count > #integer_max(u32)) + { + report_error(); + } + + >bit_count = needed_bit_count; + + if (!backing_type) + { + backing_type = integer_type(module, { .bit_count = bit_count, .signed = 0 }); + } + + if (backing_type.id != .integer) + { + report_error(); + } + + >backing_type_bit_size = get_bit_size(backing_type); + if (backing_type_bit_size > 64) + { + report_error(); + } + + new_type(module, { + .content = { + .bits = { + .fields = fields, + .backing_type = backing_type, + .line = global_line, + .is_implicit_backing_type = is_implicit_type, + }, + }, + .id = .bits, + .name = global_name, + .scope = &module.scope, + zero, + }); }, .enum => { @@ -8494,6 +8701,10 @@ analyze_type = fn (module: &Module, value: &Value, expected_type: &Type, analysi value_type = value.content.va_arg.type; typecheck(module, expected_type, value_type); }, + .aggregate_initialization => + { + #trap(); + }, else => { #trap(); @@ -11869,6 +12080,7 @@ names: [_][]u8 = [ "argv", "assignment_operators", "not_pointer", + "bits", ]; [export] main = fn [cc(c)] (argument_count: u32, argv: &&u8, envp: &&u8) s32 diff --git a/src/parser.cpp b/src/parser.cpp index 13a51e3..e42590e 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -3365,7 +3365,8 @@ void parse(Module* module) { skip_space(module); - if (consume_character_if_match(module, right_brace)) { + if (consume_character_if_match(module, right_brace)) + { break; }