about summary refs log tree commit diff
path: root/boot/tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'boot/tree.c')
-rw-r--r--boot/tree.c116
1 files changed, 79 insertions, 37 deletions
diff --git a/boot/tree.c b/boot/tree.c
index dff0858..adee06a 100644
--- a/boot/tree.c
+++ b/boot/tree.c
@@ -408,6 +408,22 @@ struct Function_Header_Node
 
 void function_header_node_print(const struct Function_Header_Node* header);
 
+// a declaration of a variable, constant, or other binding, without a mutability
+// signifier, like `let` or `var`.
+// the mutability is determined by some outside context, where
+// a bare declaration in a for-loop, for example, is always mutable.
+struct Bare_Declaration_Node
+{
+    struct String_Array names;
+    struct Expression* initializer;
+    struct Type_Node* type;
+
+    struct Span span;
+    struct Cursor location;
+};
+
+void bare_declaration_node_print(const struct Bare_Declaration_Node* declaration);
+
 enum Type_Node_Type
 {
     TYPE_NODE_NONE,
@@ -936,9 +952,7 @@ statement_declaration_kind_from_token(const struct Token* token)
 struct Statement_Value_Declaration
 {
     enum Statement_Declaration_Kind kind;
-    struct String_Array names;
-    struct Expression* initializer;
-    struct Type_Node* type;
+    struct Bare_Declaration_Node inner;
 };
 
 struct Statement_Value_Block
@@ -959,13 +973,20 @@ struct Statement_Value_Conditional
     uint condition_count;
 };
 
+enum Statement_Loop_Style {
+    STATEMENT_LOOP_STYLE_NONE,
+    STATEMENT_LOOP_STYLE_C, // for i int = 0; i < 10; ++i {}
+    STATEMENT_LOOP_STYLE_FOR_EACH, // for x Obj = list {}
+    STATEMENT_LOOP_STYLE_WHILE, // while true {}
+    STATEMENT_LOOP_STYLE_ENDLESS, // while {}
+};
+
+// stands for both `for` and `while` loops.
 struct Statement_Value_Loop
 {
-    // exists for iterator-style + c-style loops.
-    struct Statement* declaration;
-    // exists for all loop types, except for infinite loops.
+    enum Statement_Loop_Style style;
+    struct Bare_Declaration_Node declaration;
     struct Expression* condition;
-    // exists for c-style loops.
     struct Expression* iteration;
 
     struct Block_Node body;
@@ -1033,6 +1054,27 @@ block_node_print(const struct Block_Node* block)
     printf(")");
 }
 
+void
+bare_declaration_node_print(const struct Bare_Declaration_Node* declaration)
+{
+    printf("(declaration ");
+    STRING_ARRAY_FOR_EACH(i, name, declaration->names)
+    {
+        printf("%s ", name.data);
+    }
+    if (!type_node_is_none(declaration->type)) {
+        type_node_print(declaration->type);
+        printf(" ");
+    }
+
+    if (declaration->initializer) {
+        printf("(initializer ");
+        expression_print(declaration->initializer);
+        printf(")");
+    }
+    printf(")");
+}
+
 struct Statement*
 statement_new(
     enum Statement_Kind kind, union Statement_Value value, struct Span span, struct Cursor location)
@@ -1063,24 +1105,12 @@ statement_print(const struct Statement* statement)
         break;
     }
     case STATEMENT_DECLARATION: {
-        printf("(declaration ");
         if (statement->value.declaration.kind == STATEMENT_DECLARATION_VARIABLE)
-            printf("variable ");
+            printf("(variable ");
         else if (statement->value.declaration.kind == STATEMENT_DECLARATION_CONSTANT)
-            printf("constant ");
+            printf("(constant ");
 
-        STRING_ARRAY_FOR_EACH(i, name, statement->value.declaration.names)
-        {
-            printf("%s ", name.data);
-        }
-        if (type_node_is_none(statement->value.declaration.type))
-            type_node_print(statement->value.declaration.type);
-
-        if (statement->value.declaration.initializer) {
-            printf("(initializer ");
-            expression_print(statement->value.declaration.initializer);
-            printf(")");
-        }
+        bare_declaration_node_print(&statement->value.declaration.inner);
         printf(")");
         break;
     }
@@ -1109,25 +1139,37 @@ statement_print(const struct Statement* statement)
     }
     case STATEMENT_LOOP: {
         printf("(loop ");
-        if (statement->value.loop.declaration) {
-            printf("(declaration ");
-            statement_print(statement->value.loop.declaration);
-            printf(") ");
-        }
 
-        if (statement->value.loop.condition) {
-            printf("(condition ");
-            expression_print(statement->value.loop.condition);
-            printf(") ");
-        }
-
-        if (statement->value.loop.iteration) {
-            printf("(iteration ");
-            expression_print(statement->value.loop.iteration);
-            printf(") ");
+        switch (statement->value.loop.style) {
+            case STATEMENT_LOOP_STYLE_C:
+                printf("c-style ");
+                bare_declaration_node_print(&statement->value.loop.declaration);
+                printf(" (condition ");
+                expression_print(statement->value.loop.condition);
+                printf(") (iteration ");
+                expression_print(statement->value.loop.iteration);
+                printf(") ");
+                break;
+            case STATEMENT_LOOP_STYLE_FOR_EACH:
+                printf("for-each ");
+                bare_declaration_node_print(&statement->value.loop.declaration);
+                printf(" ");
+                break;
+            case STATEMENT_LOOP_STYLE_WHILE:
+                printf("while (condition ");
+                expression_print(statement->value.loop.condition);
+                printf(") ");
+                break;
+            case STATEMENT_LOOP_STYLE_ENDLESS:
+                printf("endless ");
+                break;
+            default:
+                failure("unexpected loop style in `statement_print`");
+                break;
         }
 
         block_node_print(&statement->value.loop.body);
+        printf(")");
         break;
     }
     case STATEMENT_RETURN: {