add named arguments

This commit is contained in:
David Gonzalez Martin 2023-11-21 10:44:36 -06:00
parent 956c6ec2d9
commit 4acf1c36f1
5 changed files with 76 additions and 22 deletions

View File

@ -887,12 +887,6 @@ pub const Module = struct {
fn addString(map: *StringKeyMap([]const u8), allocator: Allocator, string: []const u8) !u32 { fn addString(map: *StringKeyMap([]const u8), allocator: Allocator, string: []const u8) !u32 {
const lookup_result = try map.getOrPut(allocator, string, string); const lookup_result = try map.getOrPut(allocator, string, string);
{
const lookup_name = map.getValue(lookup_result.key) orelse unreachable;
assert(equal(u8, lookup_name, string));
}
return lookup_result.key; return lookup_result.key;
} }

View File

@ -302,14 +302,66 @@ const Analyzer = struct {
const argument_declarations = function_prototype.arguments.?; const argument_declarations = function_prototype.arguments.?;
logln(.sema, .call, "Argument declaration count: {}. Argument node list count: {}\n", .{ argument_declarations.len, call_argument_node_list.len }); logln(.sema, .call, "Argument declaration count: {}. Argument node list count: {}\n", .{ argument_declarations.len, call_argument_node_list.len });
var argument_array = ArrayList(Value.Index){}; var argument_array = ArrayList(Value.Index){};
if (argument_declarations.len == call_argument_node_list.len) { if (argument_declarations.len == call_argument_node_list.len) {
for (argument_declarations, call_argument_node_list) |argument_declaration_index, argument_node_index| { for (argument_declarations, call_argument_node_list, 0..) |argument_declaration_index, argument_node_index, index| {
const argument_declaration = analyzer.module.declarations.get(argument_declaration_index); const argument_declaration = analyzer.module.declarations.get(argument_declaration_index);
// const argument_declaration_type = analyzer.module.types.get(argument_declaration.type); const argument_node = analyzer.getScopeNode(scope_index, argument_node_index);
// assert(argument_declaration.type.valid); const value_node_index = switch (argument_node.id) {
.identifier => blk: {
const identifier = analyzer.tokenIdentifier(scope_index, argument_node.token);
const identifier_hash = try analyzer.processIdentifier(identifier);
if (identifier_hash == argument_declaration.name) {
break :blk argument_node_index;
} else {
const call_site_name = analyzer.module.getName(identifier_hash).?;
const definition_site_name = analyzer.module.getName(argument_declaration.name).?;
const function_name = analyzer.module.getName(analyzer.module.function_name_map.get(function_index).?).?;
std.debug.panic("At function '{s}' call, argument #{} must be named the same way. Call site was name '{s}' while function definition has it named as '{s}'", .{ function_name, index, call_site_name, definition_site_name });
}
},
.named_argument => blk: {
const identifier_node = analyzer.getScopeNode(scope_index, argument_node.left);
if (identifier_node.id != .identifier) {
@panic("expected identifier");
}
const identifier = analyzer.tokenIdentifier(scope_index, identifier_node.token);
const identifier_hash = try analyzer.processIdentifier(identifier);
if (identifier_hash == argument_declaration.name) {
break :blk argument_node.right;
} else {
const call_site_name = analyzer.module.getName(identifier_hash).?;
const definition_site_name = analyzer.module.getName(argument_declaration.name).?;
const function_name = analyzer.module.getName(analyzer.module.function_name_map.get(function_index).?).?;
std.debug.panic("At function '{s}' call, argument #{} must be named the same way. Call site was name '{s}' while function definition has it named as '{s}'", .{ function_name, index, call_site_name, definition_site_name });
}
},
else => |node_id| {
const definition_site_name = analyzer.module.getName(argument_declaration.name).?;
const function_name = analyzer.module.getName(analyzer.module.function_name_map.get(function_index).?).?;
std.debug.panic("Argument #{} of call to function '{s}' of type {s} must be named as '{s}'", .{ index, function_name, @tagName(node_id), definition_site_name });
},
};
const call_argument_allocation = try analyzer.unresolvedAllocate(scope_index, ExpectType{ const call_argument_allocation = try analyzer.unresolvedAllocate(scope_index, ExpectType{
.type_index = argument_declaration.type, .type_index = argument_declaration.type,
}, argument_node_index); }, value_node_index);
// switch (call_argument_allocation.ptr.*) {
// .integer,
// .string_literal,
// => {},
// .declaration_reference => |declaration_reference| {
// if (call_argument_declaration.name != argument_declaration.name) {
// const call_site_name = analyzer.module.getName(call_argument_declaration.name).?;
// const definition_site_name = analyzer.module.getName(argument_declaration.name).?;
// const function_name = analyzer.module.getName(analyzer.module.function_name_map.get(function_index).?).?;
// std.debug.panic("At function '{s}' call, argument #{} must be named the same way. Call site was name '{s}' while function definition has it named as '{s}'", .{ function_name, index, call_site_name, definition_site_name });
// }
// },
// else => |t| @panic(@tagName(t)),
// }
try call_argument_allocation.ptr.typeCheck(analyzer.module, argument_declaration.type); try call_argument_allocation.ptr.typeCheck(analyzer.module, argument_declaration.type);
// const call_argument_type_index = call_argument_allocation.ptr.getType(analyzer.module); // const call_argument_type_index = call_argument_allocation.ptr.getType(analyzer.module);
// const call_argument_type = analyzer.module.types.get(call_argument_type_index); // const call_argument_type = analyzer.module.types.get(call_argument_type_index);

View File

@ -163,6 +163,7 @@ pub const Node = packed struct(u128) {
shift_left = 69, shift_left = 69,
shift_right = 70, shift_right = 70,
bool_type = 71, bool_type = 71,
named_argument = 72,
}; };
}; };
@ -1082,21 +1083,28 @@ const Analyzer = struct {
var expression_list = ArrayList(Node.Index){}; var expression_list = ArrayList(Node.Index){};
while (analyzer.tokens[analyzer.token_i].id != .right_parenthesis) { while (analyzer.tokens[analyzer.token_i].id != .right_parenthesis) {
const current_token = analyzer.tokens[analyzer.token_i]; const current_token = analyzer.token_i;
logln(.parser, .suffix, "Current token: {s}\n", .{@tagName(current_token.id)}); var parameter = try analyzer.expression();
const parameter = try analyzer.expression();
try expression_list.append(analyzer.allocator, parameter);
const parameter_node = analyzer.nodes.items[parameter.unwrap()]; const parameter_node = analyzer.nodes.items[parameter.unwrap()];
logln(.parser, .suffix, "Paremeter node: {s}\n", .{@tagName(parameter_node.id)}); logln(.parser, .suffix, "Paremeter node: {s}\n", .{@tagName(parameter_node.id)});
const next_token = analyzer.tokens[analyzer.token_i]; if (analyzer.tokens[analyzer.token_i].id == .equal) {
logln(.parser, .suffix, "next token: {s}\n", .{@tagName(next_token.id)}); analyzer.token_i += 1;
analyzer.token_i += @intFromBool(switch (next_token.id) {
.comma => true, parameter = try analyzer.addNode(.{
.colon, .right_brace, .right_bracket => unreachable, .id = .named_argument,
.right_parenthesis => false, .token = current_token,
else => |t| @panic(@tagName(t)), .left = parameter,
.right = try analyzer.expression(),
}); });
} }
try expression_list.append(analyzer.allocator, parameter);
switch (analyzer.tokens[analyzer.token_i].id) {
.comma => analyzer.token_i += 1,
.right_parenthesis => {},
.colon, .right_brace, .right_bracket => unreachable,
else => |t| @panic(@tagName(t)),
}
}
_ = try analyzer.expectToken(.right_parenthesis); _ = try analyzer.expectToken(.right_parenthesis);
// const is_comma = analyzer.tokens[analyzer.token_i].id == .comma; // const is_comma = analyzer.tokens[analyzer.token_i].id == .comma;

View File

@ -5,5 +5,5 @@ comptime {
const _start = fn () noreturn { const _start = fn () noreturn {
const result = #import("main").main(); const result = #import("main").main();
std.os.exit(result); std.os.exit(exit_code = result);
} }

View File

@ -1,6 +1,6 @@
const std = #import("std"); const std = #import("std");
const main = fn() s32 { const main = fn() s32 {
std.print("Hello world!\n", 13); std.print(bytes_ptr = "Hello world!\n", bytes_len = 13);
return 0; return 0;
} }