From fc0a943ae838f23c72de519f51424f8e6bfc945c Mon Sep 17 00:00:00 2001 From: Max Wash Date: Thu, 5 Dec 2024 16:53:59 +0000 Subject: [PATCH] lang: ast: improve cascade operator recipient resolution the cascade operator now uses the precedence of the last message parsed to determine the recipient of the subsequent messages, reducing the need for parentheses and making the semantics of the operator more predictable. all messages in a cascade now inherit the precedence of the first message in the cascade. --- lang/ast/expr/arith.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/lang/ast/expr/arith.c b/lang/ast/expr/arith.c index 4bfaa62..eb548de 100644 --- a/lang/ast/expr/arith.c +++ b/lang/ast/expr/arith.c @@ -670,14 +670,32 @@ static enum ivy_status begin_cascade_operation(struct ivy_parser *ctx) first_msg = expr_finalise_keyword_msg(state); parser_pop_state(ctx, 0); } else { + /* we need to find who the first message in the cascade is being sent to. */ + enum ivy_operator_precedence min_precedence = IVY_PRECEDENCE_CASCADE; + + struct ivy_ast_node *prev = b_unbox( + struct ivy_ast_node, + b_queue_last(&state->s_operator_stack), n_entry); + if (prev && prev->n_type == IVY_AST_MSG) { + /* unary complex messages (which will be found on the operator stack) have a very high + * precedence (much higher than most arithmetic operators), so the recipient will be much + * narrower. this also means that any subsequent messages in the cascade inherit this high + * precedence, regardless of their type. */ + min_precedence = IVY_PRECEDENCE_UNARY_MSG; + } + struct ivy_ast_node *expr = NULL; enum ivy_status status - = expr_finalise_arith(state, &expr, IVY_PRECEDENCE_CASCADE); + = expr_finalise_arith(state, &expr, min_precedence); if (status != IVY_OK) { return status; } if (expr->n_type != IVY_AST_MSG) { + /* the recipient and first message of the cascade operation is ambiguous due + * to operator precedence. this is usually resolved by adding parentheses + * (either around the recipient or around the cascade) to make the recipient + * and first message clear. */ return IVY_ERR_BAD_SYNTAX; }