about summary refs log tree commit diff
path: root/boot
diff options
context:
space:
mode:
authorMel <mel@rnrd.eu>2025-07-05 20:27:08 +0200
committerMel <mel@rnrd.eu>2025-07-05 20:27:08 +0200
commitb71f85a7c3ee9e36b6eab9f113436fa990f6e561 (patch)
treede0dac0dff1802106c97478fce84452224233b36 /boot
parentcfbb769306fea6433c1d3e568a4f9742883a0cc9 (diff)
downloadcatskill-b71f85a7c3ee9e36b6eab9f113436fa990f6e561.tar.zst
catskill-b71f85a7c3ee9e36b6eab9f113436fa990f6e561.zip
Try (?) & must (!) expressions
Signed-off-by: Mel <mel@rnrd.eu>
Diffstat (limited to 'boot')
-rw-r--r--boot/parse.c33
-rw-r--r--boot/tests/parse/try_must.cskt0
-rw-r--r--boot/tree.c14
-rw-r--r--boot/visit.c34
4 files changed, 81 insertions, 0 deletions
diff --git a/boot/parse.c b/boot/parse.c
index 7b40fb1..c08d247 100644
--- a/boot/parse.c
+++ b/boot/parse.c
@@ -896,6 +896,34 @@ parser_expression_postfix_subscript(
 }
 
 struct Expression*
+parser_expression_postfix_try(
+    struct Parser* p, struct Expression* subject, struct Parser_Error* error)
+{
+    while (parser_probe(p, TOKEN_QUESTION)) {
+        struct Token question_token = parser_next(p);
+
+        struct Span span = span_merge(subject->span, question_token.span);
+        union Expression_Value value = { .try = { subject } };
+        subject = expression_new(EXPRESSION_TRY, value, span, subject->location);
+    }
+    return subject;
+}
+
+struct Expression*
+parser_expression_postfix_must(
+    struct Parser* p, struct Expression* subject, struct Parser_Error* error)
+{
+    while (parser_probe(p, TOKEN_BANG)) {
+        struct Token bang_token = parser_next(p);
+
+        struct Span span = span_merge(subject->span, bang_token.span);
+        union Expression_Value value = { .try = { subject } };
+        subject = expression_new(EXPRESSION_MUST, value, span, subject->location);
+    }
+    return subject;
+}
+
+struct Expression*
 parser_expression_postfix(struct Parser* p, struct Parser_Error* error)
 {
     struct Expression* expression = CHECK(parser_expression_member(p, error));
@@ -906,6 +934,11 @@ parser_expression_postfix(struct Parser* p, struct Parser_Error* error)
         return parser_expression_postfix_call_or_construct(p, expression, error);
     case TOKEN_SQUARE_OPEN:
         return parser_expression_postfix_subscript(p, expression, error);
+
+    case TOKEN_QUESTION:
+        return parser_expression_postfix_try(p, expression, error);
+    case TOKEN_BANG:
+        return parser_expression_postfix_must(p, expression, error);
     default:;
     }
 
diff --git a/boot/tests/parse/try_must.cskt b/boot/tests/parse/try_must.cskt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/boot/tests/parse/try_must.cskt
diff --git a/boot/tree.c b/boot/tree.c
index dc22bfd..3c808f8 100644
--- a/boot/tree.c
+++ b/boot/tree.c
@@ -688,6 +688,8 @@ enum Expression_Kind
     EXPRESSION_SUBSCRIPT,
     EXPRESSION_MEMBER,
     EXPRESSION_INCREMENT_DECREMENT,
+    EXPRESSION_TRY,
+    EXPRESSION_MUST,
 
     EXPRESSION_FUNCTION,
     EXPRESSION_TYPE,
@@ -766,6 +768,16 @@ struct Expression_Increment_Decrement
     enum Increment_Decrement_Operation operation;
 };
 
+struct Expression_Try
+{
+    struct Expression* expression;
+};
+
+struct Expression_Must
+{
+    struct Expression* expression;
+};
+
 struct Expression_Function
 {
     struct Function_Header_Node header;
@@ -791,6 +803,8 @@ union Expression_Value
     struct Expression_Subscript subscript;
     struct Expression_Member member;
     struct Expression_Increment_Decrement increment_decrement;
+    struct Expression_Try try;
+    struct Expression_Must must;
     struct Expression_Function function;
     struct Expression_Type type;
 };
diff --git a/boot/visit.c b/boot/visit.c
index 3cc3e55..c1dd797 100644
--- a/boot/visit.c
+++ b/boot/visit.c
@@ -45,6 +45,8 @@ struct Visit_Table
     void (*visit_expression_subscript)(struct Visit* visitor, struct Expression* expr);
     void (*visit_expression_member)(struct Visit* visitor, struct Expression* expr);
     void (*visit_expression_increment_decrement)(struct Visit* visitor, struct Expression* expr);
+    void (*visit_expression_try)(struct Visit* visitor, struct Expression* expr);
+    void (*visit_expression_must)(struct Visit* visitor, struct Expression* expr);
     void (*visit_expression_function)(struct Visit* visitor, struct Expression* expr);
 
     void (*visit_type_node)(struct Visit* visitor, struct Type_Node* node);
@@ -219,6 +221,12 @@ walk_expression(struct Visit* visit, struct Expression* expression)
     case EXPRESSION_INCREMENT_DECREMENT:
         VISIT(visit_expression_increment_decrement, expression);
         break;
+    case EXPRESSION_TRY:
+        VISIT(visit_expression_try, expression);
+        break;
+    case EXPRESSION_MUST:
+        VISIT(visit_expression_must, expression);
+        break;
     case EXPRESSION_FUNCTION:
         VISIT(visit_expression_function, expression);
         break;
@@ -286,6 +294,10 @@ walk_expression_increment_decrement(struct Visit* visit, struct Expression* expr
     VISIT(visit_expression, expression->value.increment_decrement.subject);
 }
 
+WALK_LEAF_FUNCTION(walk_expression_try, struct Expression*);
+
+WALK_LEAF_FUNCTION(walk_expression_must, struct Expression*);
+
 void
 walk_expression_function(struct Visit* visit, struct Expression* expression)
 {
@@ -815,6 +827,26 @@ printer_visit_expression_increment_decrement(struct Visit* visit, struct Express
 }
 
 void
+printer_visit_expression_try(struct Visit* visit, struct Expression* expr)
+{
+    TREE_PRINTER_PREAMBLE
+
+    PRINT("(try ");
+    VISIT(visit_expression, expr->value.try.expression);
+    PRINT(")");
+}
+
+void
+printer_visit_expression_must(struct Visit* visit, struct Expression* expr)
+{
+    TREE_PRINTER_PREAMBLE
+
+    PRINT("(must ");
+    VISIT(visit_expression, expr->value.must.expression);
+    PRINT(")");
+}
+
+void
 printer_visit_expression_function(struct Visit* visit, struct Expression* expr)
 {
     TREE_PRINTER_PREAMBLE
@@ -1064,6 +1096,8 @@ struct Visit_Table printer_visit_functions = {
     .visit_expression_subscript = printer_visit_expression_subscript,
     .visit_expression_member = printer_visit_expression_member,
     .visit_expression_increment_decrement = printer_visit_expression_increment_decrement,
+    .visit_expression_try = printer_visit_expression_try,
+    .visit_expression_must = printer_visit_expression_must,
     .visit_expression_function = printer_visit_expression_function,
 
     .visit_type_node = printer_visit_type_node,