Pass 'basic_macro'

This commit is contained in:
David Gonzalez Martin 2025-06-17 05:44:10 -06:00
parent 156fed3166
commit ba80b65c3f
2 changed files with 245 additions and 12 deletions

View File

@ -1045,6 +1045,8 @@ Value = struct;
Local = struct; Local = struct;
Block = struct; Block = struct;
Module = struct; Module = struct;
MacroDeclaration = struct;
MacroInstantiation = struct;
ScopeKind = enum ScopeKind = enum
{ {
@ -1779,7 +1781,7 @@ ValueId = enum
variable, variable,
local, local,
unary_type, unary_type,
macro_reference, macro,
call, call,
array_initialization, array_initialization,
array_expression, array_expression,
@ -1797,6 +1799,7 @@ ValueId = enum
undefined, undefined,
select, select,
string_to_enum, string_to_enum,
macro_instantiation,
} }
ValueConstantInteger = struct ValueConstantInteger = struct
@ -2023,6 +2026,41 @@ ValueStringToEnum = struct
string: &Value, 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 ValueContent = union
{ {
constant_integer: ValueConstantInteger, constant_integer: ValueConstantInteger,
@ -2042,6 +2080,8 @@ ValueContent = union
aggregate_initialization: ValueAggregateInitialization, aggregate_initialization: ValueAggregateInitialization,
select: ValueSelect, select: ValueSelect,
string_to_enum: ValueStringToEnum, string_to_enum: ValueStringToEnum,
macro: &MacroDeclaration,
macro_instantiation: MacroInstantiation,
} }
ValueKind = enum ValueKind = enum
@ -2126,12 +2166,18 @@ void_offset: u64 = i128_offset + 2;
MacroDeclaration = struct 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; [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; 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 reference_identifier = fn (module: &Module, current_scope: &Scope, identifier: []u8, kind: ValueKind) &Value
{ {
assert(!string_equal(identifier, "")); assert(!string_equal(identifier, ""));
@ -4936,9 +4988,22 @@ reference_identifier = fn (module: &Module, current_scope: &Scope, identifier: [
>macro_declaration = module.first_macro_declaration; >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 => .function =>
@ -4994,8 +5059,26 @@ reference_identifier = fn (module: &Module, current_scope: &Scope, identifier: [
} }
}, },
.macro_declaration => .macro_declaration =>
{
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(); #trap();
}
}
for (&argument: macro_declaration.arguments)
{
if (string_equal(identifier, argument.variable.name))
{
variable = &argument.variable;
break;
}
}
}, },
.macro_instantiation => .macro_instantiation =>
{ {
@ -5761,9 +5844,44 @@ parse_right = fn (module: &Module, scope: &Scope, builder: ValueBuilder) &Value
switch (left.id) 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 => else =>
{ {
@ -5789,7 +5907,7 @@ parse_right = fn (module: &Module, scope: &Scope, builder: ValueBuilder) &Value
result = new_value(module); result = new_value(module);
if (left.id == .macro_reference) if (left.id == .macro)
{ {
#trap(); #trap();
} }
@ -7016,7 +7134,118 @@ parse = fn (module: &Module) void
}, },
.macro => .macro =>
{ {
>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(); #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 = &macro_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 => .opaque =>
{ {
@ -10647,6 +10876,10 @@ analyze_type = fn (module: &Module, value: &Value, expected_type: &Type, analysi
value_type = expected_type; value_type = expected_type;
}, },
.macro_instantiation =>
{
#trap();
},
else => else =>
{ {
#trap(); #trap();
@ -16223,6 +16456,7 @@ names: [_][]u8 =
"pointer_struct_initialization", "pointer_struct_initialization",
"slice_array_literal", "slice_array_literal",
"slice_only_start", "slice_only_start",
"basic_macro",
]; ];
[export] main = fn [cc(c)] (argument_count: u32, argv: &&u8, envp: &&u8) s32 [export] main = fn [cc(c)] (argument_count: u32, argv: &&u8, envp: &&u8) s32

View File

@ -1029,7 +1029,6 @@ struct MacroDeclaration
{ {
Slice<Argument> arguments; Slice<Argument> arguments;
Slice<ConstantArgument> constant_arguments; Slice<ConstantArgument> constant_arguments;
TypeList types;
Type* return_type; Type* return_type;
Block* block; Block* block;
String name; String name;