diff --git a/src/compiler.bbb b/src/compiler.bbb index ee6352f..72d0ec5 100644 --- a/src/compiler.bbb +++ b/src/compiler.bbb @@ -1045,6 +1045,7 @@ Value = struct; Local = struct; Block = struct; Module = struct; +MacroDeclaration = struct; ScopeKind = enum { @@ -1779,7 +1780,7 @@ ValueId = enum variable, local, unary_type, - macro_reference, + macro, call, array_initialization, array_expression, @@ -2042,6 +2043,7 @@ ValueContent = union aggregate_initialization: ValueAggregateInitialization, select: ValueSelect, string_to_enum: ValueStringToEnum, + macro: &MacroDeclaration, } ValueKind = enum @@ -2124,9 +2126,34 @@ value_is_constant = fn (value: &Value) u1 i128_offset: u64 = 64 * 2; void_offset: u64 = i128_offset + 2; +ConstantArgumentId = enum +{ + value, + type, +} + +ConstantArgumentContent = struct +{ + value: &Value, + type: &Type, +} + +ConstantArgument = struct +{ + name: []u8, + content: ConstantArgumentContent, + id: ConstantArgumentId, +} + MacroDeclaration = struct { - foo: u32, + arguments: []Argument, + constant_arguments: []ConstantArgument, + return_type: &Type, + block: &Block, + name: []u8, + scope: Scope, + next: &MacroDeclaration, } MacroInstantiation = struct @@ -4905,6 +4932,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 +4969,21 @@ 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, + }; + } + + macro_declaration = macro_declaration.next; } }, .function => @@ -4995,7 +5040,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,7 +5824,7 @@ parse_right = fn (module: &Module, scope: &Scope, builder: ValueBuilder) &Value switch (left.id) { - .macro_reference => + .macro => { #trap(); }, @@ -5789,7 +5852,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 +7079,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 => { @@ -16223,6 +16397,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;