about summary refs log tree commit diff
path: root/boot/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'boot/parse.c')
-rw-r--r--boot/parse.c40
1 files changed, 39 insertions, 1 deletions
diff --git a/boot/parse.c b/boot/parse.c
index ed00f94..3870e6c 100644
--- a/boot/parse.c
+++ b/boot/parse.c
@@ -225,6 +225,7 @@ parser_node_type(struct Parser* p, struct Parser_Error* error)
     // for now, we only support a single type name.
     // in the future, we might want to support more complex types.
     return (struct Type_Node){
+        .type = TYPE_NAME,
         .name = type_name,
         .span = token.span,
         .location = token.location,
@@ -287,6 +288,42 @@ parser_expression_primary_group(struct Parser* p, struct Parser_Error* error)
 }
 
 struct Expression*
+parser_expression_function(struct Parser* p, struct Parser_Error* error)
+{
+    struct Token fun_token = CHECK(parser_need(p, TOKEN_WORD_FUN, error));
+    CHECK(parser_need(p, TOKEN_ROUND_OPEN, error));
+
+    struct Expression_Function fun = { 0 };
+    while (!parser_probe(p, TOKEN_ROUND_CLOSE)) {
+        struct Token name_token = CHECK(parser_need(p, TOKEN_NAME, error));
+        struct String name = name_token.value.name;
+
+        struct Type_Node type = { 0 };
+
+        struct Token next = parser_peek(p);
+        if (!token_is(&next, TOKEN_ROUND_CLOSE) && !token_is(&next, TOKEN_COMMA))
+            type = CHECK(parser_node_type(p, error));
+
+        if (parser_probe(p, TOKEN_COMMA)) parser_next(p);
+
+        check(fun.parameter_count < EXPRESSION_FUNCTION_MAX_PARAMS, "too many function parameters");
+        fun.parameters[fun.parameter_count++] = (struct Expression_Function_Parameter){
+            .name = name,
+            .type = type,
+        };
+    }
+    parser_next(p);
+
+    if (!parser_probe(p, TOKEN_CURLY_OPEN)) fun.return_type = CHECK(parser_node_type(p, error));
+
+    fun.body = CHECK(parser_block_node(p, error));
+
+    return expression_new(
+        EXPRESSION_FUNCTION, (union Expression_Value){ .function = fun },
+        span_merge(fun_token.span, fun.body.span), fun_token.location);
+}
+
+struct Expression*
 parser_expression_primary(struct Parser* p, struct Parser_Error* error)
 {
     struct Token token = parser_peek(p);
@@ -304,6 +341,8 @@ parser_expression_primary(struct Parser* p, struct Parser_Error* error)
         return parser_expression_primary_boolean(p, error);
     case TOKEN_ROUND_OPEN:
         return parser_expression_primary_group(p, error);
+    case TOKEN_WORD_FUN:
+        return parser_expression_function(p, error);
     default:
         *error = parser_error(PARSER_ERROR_EXPECTED_PRIMARY_EXPRESSION);
         return nil;
@@ -522,7 +561,6 @@ parser_statement_declaration(struct Parser* p, struct Parser_Error* error)
     union Statement_Value value = {
         .declaration = {
             .names = names,
-            .has_type = true,
             .type = type,
             .initializer = initializer,
         },