From ba80b65c3f66d6fa6091e1e73c62a97ca02493f0 Mon Sep 17 00:00:00 2001 From: David Gonzalez Martin Date: Tue, 17 Jun 2025 05:44:10 -0600 Subject: [PATCH] Pass 'basic_macro' --- src/compiler.bbb | 256 +++++++++++++++++++++++++++++++++++++++++++++-- src/compiler.hpp | 1 - 2 files changed, 245 insertions(+), 12 deletions(-) diff --git a/src/compiler.bbb b/src/compiler.bbb index ee6352f..0f59c80 100644 --- a/src/compiler.bbb +++ b/src/compiler.bbb @@ -1045,6 +1045,8 @@ Value = struct; Local = struct; Block = struct; Module = struct; +MacroDeclaration = struct; +MacroInstantiation = struct; ScopeKind = enum { @@ -1779,7 +1781,7 @@ ValueId = enum variable, local, unary_type, - macro_reference, + macro, call, array_initialization, array_expression, @@ -1797,6 +1799,7 @@ ValueId = enum undefined, select, string_to_enum, + macro_instantiation, } ValueConstantInteger = struct @@ -2023,6 +2026,41 @@ ValueStringToEnum = struct string: &Value, } +ConstantArgumentId = enum +{ + value, + type, +} + +ConstantArgumentContent = union +{ + value: &Value, + type: &Type, +} + +ConstantArgument = struct +{ + name: []u8, + content: ConstantArgumentContent, + id: ConstantArgumentId, +} + +MacroInstantiation = struct +{ + declaration: &MacroDeclaration, + instantiation_function: &Global, + declaration_arguments: []Argument, + instantiation_arguments: []&Value, + constant_arguments: []ConstantArgument, + return_type: &Type, + block: &Block, + scope: Scope, + line: u32, + column: u32, + return_alloca: &LLVMValue, + return_block: &LLVMBasicBlock, +} + ValueContent = union { constant_integer: ValueConstantInteger, @@ -2042,6 +2080,8 @@ ValueContent = union aggregate_initialization: ValueAggregateInitialization, select: ValueSelect, string_to_enum: ValueStringToEnum, + macro: &MacroDeclaration, + macro_instantiation: MacroInstantiation, } ValueKind = enum @@ -2126,12 +2166,18 @@ void_offset: u64 = i128_offset + 2; MacroDeclaration = struct { - foo: u32, + arguments: []Argument, + constant_arguments: []ConstantArgument, + return_type: &Type, + block: &Block, + name: []u8, + scope: Scope, + next: &MacroDeclaration, } -MacroInstantiation = struct +macro_declaration_is_generic = fn (declaration: &MacroDeclaration) u1 { - foo: u32, + return declaration.constant_arguments.length != 0; } [extern] LLVMInitializeX86TargetInfo = fn [cc(c)] () void; @@ -4905,6 +4951,12 @@ tokenize = fn (module: &Module) Token parse_precedence = fn (module: &Module, scope: &Scope, builder: ValueBuilder) &Value; +scope_to_macro_declaration = fn (scope: &Scope) &MacroDeclaration +{ + assert(scope.kind == .macro_declaration); + return #field_parent_pointer(scope, "scope"); +} + reference_identifier = fn (module: &Module, current_scope: &Scope, identifier: []u8, kind: ValueKind) &Value { assert(!string_equal(identifier, "")); @@ -4936,9 +4988,22 @@ reference_identifier = fn (module: &Module, current_scope: &Scope, identifier: [ >macro_declaration = module.first_macro_declaration; - while (macro_declaration != zero) + while (macro_declaration) { - #trap(); + if (string_equal(identifier, macro_declaration.name)) + { + >result = new_value(module); + result.& = { + .content = { + .macro = macro_declaration, + }, + .id = .macro, + zero, + }; + return result; + } + + macro_declaration = macro_declaration.next; } }, .function => @@ -4995,7 +5060,25 @@ reference_identifier = fn (module: &Module, current_scope: &Scope, identifier: [ }, .macro_declaration => { - #trap(); + assert(scope.parent != zero); + >macro_declaration = scope_to_macro_declaration(scope); + + for (&constant_argument: macro_declaration.constant_arguments) + { + if (string_equal(identifier, constant_argument.name)) + { + #trap(); + } + } + + for (&argument: macro_declaration.arguments) + { + if (string_equal(identifier, argument.variable.name)) + { + variable = &argument.variable; + break; + } + } }, .macro_instantiation => { @@ -5761,9 +5844,44 @@ parse_right = fn (module: &Module, scope: &Scope, builder: ValueBuilder) &Value switch (left.id) { - .macro_reference => + .macro => { - #trap(); + >declaration = left.content.macro; + + if (macro_declaration_is_generic(declaration)) + { + report_error(); + } + + >instantiation_line = get_line(module); + >instantiation_column = get_column(module); + + >arguments = parse_call_arguments(module, scope); + + result.& = { + .content = { + .macro_instantiation = { + .declaration = declaration, + .instantiation_function = module.current_function, + .declaration_arguments = zero, + .instantiation_arguments = arguments, + .constant_arguments = zero, + .return_type = declaration.return_type, + .scope = { + .parent = scope, + .line = declaration.scope.line, + .column = declaration.scope.column, + .kind = .macro_instantiation, + zero, + }, + .line = instantiation_line, + .column = instantiation_column, + zero, + }, + }, + .id = .macro_instantiation, + zero, + }; }, else => { @@ -5789,7 +5907,7 @@ parse_right = fn (module: &Module, scope: &Scope, builder: ValueBuilder) &Value result = new_value(module); - if (left.id == .macro_reference) + if (left.id == .macro) { #trap(); } @@ -7016,7 +7134,118 @@ parse = fn (module: &Module) void }, .macro => { - #trap(); + >constant_argument_buffer: [64]ConstantArgument = undefined; + >constant_argument_count: u64 = 0; + + >is_generic = consume_character_if_match(module, left_bracket); + >macro_declaration = arena_allocate[MacroDeclaration](module.arena, 1); + macro_declaration.& = { + .name = global_name, + .scope = { + .parent = scope, + .line = global_line, + .column = global_column, + .kind = .macro_declaration, + zero, + }, + zero, + }; + + if (is_generic) + { + // END OF SCOPE + if (constant_argument_count == 0) + { + report_error(); + } + #trap(); + } + else + { + assert(constant_argument_count == 0); + } + + expect_character(module, left_parenthesis); + + macro_declaration.constant_arguments = arena_allocate_slice[ConstantArgument](module.arena, constant_argument_count); + memcpy(#pointer_cast(macro_declaration.constant_arguments.pointer), #pointer_cast(&constant_argument_buffer), constant_argument_count * #byte_size(ConstantArgument)); + + if (module.first_macro_declaration) + { + assert(module.first_macro_declaration != zero); + module.last_macro_declaration.next = macro_declaration; + } + else + { + assert(!module.first_macro_declaration); + module.first_macro_declaration = macro_declaration; + } + + module.last_macro_declaration = macro_declaration; + module.current_macro_declaration = macro_declaration; + + >scope = ¯o_declaration.scope; + + >argument_buffer: [64]Argument = undefined; + >argument_count: u64 = 0; + + while (1) + { + skip_space(module); + + if (consume_character_if_match(module, right_parenthesis)) + { + break; + } + + >argument_index = argument_count; + + >argument_line = get_line(module); + >argument_column = get_column(module); + + >argument_name = arena_duplicate_string(module.arena, parse_identifier(module)); + + skip_space(module); + expect_character(module, ':'); + skip_space(module); + + >argument_type = parse_type(module, scope); + + >argument = &argument_buffer[argument_index]; + argument.& = { + .variable = { + .type = argument_type, + .scope = scope, + .name = argument_name, + .line = argument_line, + .column = argument_column, + zero, + }, + .index = #truncate(argument_index + 1), + }; + + argument_count += 1; + + skip_space(module); + consume_character_if_match(module, ','); + } + + skip_space(module); + + >return_type = parse_type(module, scope); + macro_declaration.return_type = return_type; + + >arguments = arena_allocate_slice[Argument](module.arena, argument_count); + memcpy(#pointer_cast(arguments.pointer), #pointer_cast(&argument_buffer), argument_count * #byte_size(Argument)); + macro_declaration.arguments = arguments; + + skip_space(module); + + >block = parse_block(module, scope); + macro_declaration.block = block; + + // END OF SCOPE + module.current_macro_declaration = zero; }, .opaque => { @@ -10647,6 +10876,10 @@ analyze_type = fn (module: &Module, value: &Value, expected_type: &Type, analysi value_type = expected_type; }, + .macro_instantiation => + { + #trap(); + }, else => { #trap(); @@ -16223,6 +16456,7 @@ names: [_][]u8 = "pointer_struct_initialization", "slice_array_literal", "slice_only_start", + "basic_macro", ]; [export] main = fn [cc(c)] (argument_count: u32, argv: &&u8, envp: &&u8) s32 diff --git a/src/compiler.hpp b/src/compiler.hpp index 1f7cb18..24d4233 100644 --- a/src/compiler.hpp +++ b/src/compiler.hpp @@ -1029,7 +1029,6 @@ struct MacroDeclaration { Slice arguments; Slice constant_arguments; - TypeList types; Type* return_type; Block* block; String name;