diff --git a/src/compiler.bbb b/src/compiler.bbb index b2825a9..a7c996d 100644 --- a/src/compiler.bbb +++ b/src/compiler.bbb @@ -5926,7 +5926,96 @@ parse_right = fn (module: &Module, scope: &Scope, builder: ValueBuilder) &Value if (left.id == .macro) { - #trap(); + >declaration = left.content.macro; + + if (!macro_declaration_is_generic(declaration)) + { + report_error(); + } + + >instantiation_line = get_line(module); + >instantiation_column = get_column(module); + >original_constant_argument_count = declaration.constant_arguments.length; + >constant_arguments = arena_allocate_slice[ConstantArgument](module.arena, original_constant_argument_count); + >constant_argument_count: u64 = 0; + + while (1) + { + skip_space(module); + + if (consume_character_if_match(module, right_bracket)) + { + break; + } + + >constant_argument_index = constant_argument_count; + if (constant_argument_index == original_constant_argument_count) + { + report_error(); + } + + >constant_argument = declaration.constant_arguments[constant_argument_index]; + + switch (constant_argument.id) + { + .value => + { + #trap(); + }, + .type => + { + >argument_type = parse_type(module, scope); + constant_arguments[constant_argument_index] = { + .name = constant_argument.name, + .content = { + .type = argument_type, + }, + .id = .type, + }; + }, + } + + constant_argument_count += 1; + + skip_space(module); + consume_character_if_match(module, ','); + } + + skip_space(module); + + expect_character(module, left_parenthesis); + + if (original_constant_argument_count != constant_argument_count) + { + report_error(); + } + + >instantiation_arguments = parse_call_arguments(module, scope); + + result.& = { + .content = { + .macro_instantiation = { + .declaration = declaration, + .instantiation_function = module.current_function, + .declaration_arguments = zero, + .instantiation_arguments = instantiation_arguments, + .constant_arguments = constant_arguments, + .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 { @@ -7170,12 +7259,55 @@ parse = fn (module: &Module) void if (is_generic) { + while (1) + { + skip_space(module); + + if (consume_character_if_match(module, right_bracket)) + { + break; + } + + >argument_name = arena_duplicate_string(module.arena, parse_identifier(module)); + + skip_space(module); + + >has_value = consume_character_if_match(module, ':'); + + >constant_argument_index = constant_argument_count; + + if (has_value) + { + #trap(); + } + else + { + >ty = new_type(module, { + .id = .unresolved, + .name = argument_name, + .scope = ¯o_declaration.scope, + zero, + }); + + constant_argument_buffer[constant_argument_index] = { + .name = argument_name, + .content = { + .type = ty, + }, + .id = .type, + }; + } + + constant_argument_count += 1; + } + + skip_space(module); + // END OF SCOPE if (constant_argument_count == 0) { report_error(); } - #trap(); } else { @@ -16929,6 +17061,7 @@ names: [_][]u8 = "slice_array_literal", "slice_only_start", "basic_macro", + "generic_macro", ]; [export] main = fn [cc(c)] (argument_count: u32, argv: &&u8, envp: &&u8) s32