about summary refs log tree commit diff
path: root/boot/parse.c
diff options
context:
space:
mode:
authorMel <mel@rnrd.eu>2025-06-24 20:07:41 +0200
committerMel <mel@rnrd.eu>2025-06-24 20:07:41 +0200
commit47c5a0ecc6fccc3bfe0b5394d7297e635ab23184 (patch)
treebd99364fa76cfff6664b233a1e6682a63fdbd020 /boot/parse.c
parenta63977f56a4c3dc4c53f0befe65c8252cc5c9b0b (diff)
downloadcatskill-47c5a0ecc6fccc3bfe0b5394d7297e635ab23184.tar.zst
catskill-47c5a0ecc6fccc3bfe0b5394d7297e635ab23184.zip
Parse named arguments, thus enabling type constructions
Signed-off-by: Mel <mel@rnrd.eu>
Diffstat (limited to 'boot/parse.c')
-rw-r--r--boot/parse.c36
1 files changed, 29 insertions, 7 deletions
diff --git a/boot/parse.c b/boot/parse.c
index 3d2706f..ac324f9 100644
--- a/boot/parse.c
+++ b/boot/parse.c
@@ -705,7 +705,7 @@ parser_expression_member(struct Parser* p, struct Parser_Error* error)
 {
     struct Expression* left = CHECK(parser_expression_primary(p, error));
 
-    // NOTE: see `parser_expression_postfix_call`.
+    // NOTE: see `parser_expression_postfix_call_or_construct`.
     while (parser_probe(p, TOKEN_DOT)) {
         parser_next(p);
         struct Token name_token = CHECK(parser_need(p, TOKEN_NAME, error));
@@ -720,31 +720,53 @@ parser_expression_member(struct Parser* p, struct Parser_Error* error)
 }
 
 struct Expression*
-parser_expression_postfix_call(
+parser_expression_postfix_call_or_construct(
     struct Parser* p, struct Expression* subject, struct Parser_Error* error)
 {
     // NOTE: because of the way the parser works, we have to parse all subsequent
-    // call expressions in the same loop.
+    // call/construct expressions in the same loop.
     // this is the case with an expression like `meow_function()(123)`,
     // where the hypothetical `meow_function` returns a function pointer.
+
+    // calls and constructs look identical in the parser.
+    // * call: `meow_function(123, "hello")`
+    // * construct: `Meow(num = 123, str = "hello")`
     while (parser_probe(p, TOKEN_ROUND_OPEN)) {
         parser_next(p);
 
+        struct String_Array argument_names = string_array_new();
         struct Expression *arguments_head = nil, *arguments_current = nil;
         while (!parser_probe(p, TOKEN_ROUND_CLOSE)) {
+
+            // check if we have a named argument.
+            struct String name = string_empty();
+            struct Token name_token = parser_peek(p), next = parser_peek_further(p);
+            if (token_is(&name_token, TOKEN_NAME) && token_is(&next, TOKEN_ASSIGN)) {
+                parser_next(p);
+                parser_next(p);
+                name = name_token.value.name;
+            }
+
             struct Expression* argument = CHECK(parser_expression(p, error));
             if (!arguments_head)
                 arguments_head = argument;
             else
                 arguments_current->next = argument;
             arguments_current = argument;
+
+            // if we have a named argument, we need to add it to the names array,
+            // otherwise we just add an empty string.
+            string_array_add(&argument_names, name);
+
             if (parser_probe(p, TOKEN_COMMA)) parser_next(p);
         }
 
         struct Token token = CHECK(parser_need(p, TOKEN_ROUND_CLOSE, error));
         struct Span span = span_merge(subject->span, token.span);
-        union Expression_Value value = { .call = { subject, arguments_head } };
-        subject = expression_new(EXPRESSION_CALL, value, span, token.location);
+        union Expression_Value value = {
+            .call_or_construct = { subject, arguments_head, argument_names }
+        };
+        subject = expression_new(EXPRESSION_CALL_OR_CONSTRUCT, value, span, token.location);
     }
 
     return subject;
@@ -754,7 +776,7 @@ struct Expression*
 parser_expression_postfix_subscript(
     struct Parser* p, struct Expression* subject, struct Parser_Error* error)
 {
-    // NOTE: see `parser_expression_postfix_call`.
+    // NOTE: see `parser_expression_postfix_call_or_construct`.
     while (parser_probe(p, TOKEN_SQUARE_OPEN)) {
         parser_next(p);
 
@@ -776,7 +798,7 @@ parser_expression_postfix(struct Parser* p, struct Parser_Error* error)
     struct Token token = parser_peek(p);
     switch (token.kind) {
     case TOKEN_ROUND_OPEN:
-        return parser_expression_postfix_call(p, expression, error);
+        return parser_expression_postfix_call_or_construct(p, expression, error);
     case TOKEN_SQUARE_OPEN:
         return parser_expression_postfix_subscript(p, expression, error);
     default:;