From 78b2eb23c32f2f577347192ad6bc8412840a283c Mon Sep 17 00:00:00 2001 From: Max Wash Date: Wed, 26 Mar 2025 21:10:12 +0000 Subject: [PATCH] lang: ast: implement () operator parsing the () operator can be used to call lambdas in a more functional way than the standard message-send syntax for example, with a lambda stored in variable `x`: x(a:2 b:6). is equivalent to x call(a:2 b:6). --- lang/ast/expr/arith.c | 63 ++++++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/lang/ast/expr/arith.c b/lang/ast/expr/arith.c index 729204f..7657426 100644 --- a/lang/ast/expr/arith.c +++ b/lang/ast/expr/arith.c @@ -506,7 +506,8 @@ struct token_parse_result arith_parse_in( if (expr_terminates_at_token(state, IVY_KW_IN)) { /* treat this as a statement terminator. */ - struct token_parse_result result = expr_finalise_and_return(ctx, state); + struct token_parse_result result + = expr_finalise_and_return(ctx, state); result.r_flags |= PARSE_REPEAT_TOKEN; return result; } @@ -592,16 +593,19 @@ struct token_parse_result arith_parse_left_paren( } if (state->s_prev_token == IVY_TOK_IDENT) { - /* this is the opening parenthesis for a complex message. */ - b_queue_entry *msg_entry - = b_queue_pop_back(&state->s_operator_stack); + /* this might be the opening parenthesis for a complex message. */ + b_queue_entry *msg_entry = b_queue_last(&state->s_operator_stack); struct ivy_ast_node *msg = b_unbox(struct ivy_ast_node, msg_entry, n_entry); if (msg->n_type != IVY_AST_MSG) { - return PARSE_RESULT(IVY_ERR_INTERNAL_FAILURE, 0); + /* this is not a complex message, it's probably a + * call-operator */ + goto not_complex_msg; } + b_queue_pop_back(&state->s_operator_stack); + struct expr_parser_state *msg_expr = (struct expr_parser_state *)parser_push_state( ctx, IVY_AST_EXPR, 0); @@ -614,8 +618,28 @@ struct token_parse_result arith_parse_left_paren( return PARSE_RESULT(IVY_OK, 0); } - /* a sub-expression surrounded by parentheses is parsed by creating - * a sub-expression parser state */ +not_complex_msg: + if (state->s_prev_component == EXPR_CMP_OPERAND) { + /* this is the opening parenthesis for a call-operator */ + struct ivy_ast_msg_node *msg + = (struct ivy_ast_msg_node *)ast_node_create(IVY_AST_MSG); + msg->n_sel = unary_selector_from_token( + ivy_token_create_ident("call")); + + struct expr_parser_state *msg_expr + = (struct expr_parser_state *)parser_push_state( + ctx, IVY_AST_EXPR, 0); + + msg_expr->s_msg = (struct ivy_ast_msg_node *)msg; + msg_expr->s_sub_type = EXPR_SUBTYPE_COMPLEX_MSG; + msg_expr->s_type = EXPR_TYPE_ARITH; + msg_expr->s_subexpr_depth = state->s_subexpr_depth + 1; + + return PARSE_RESULT(IVY_OK, 0); + } + + /* this is a generic parenthesis-enclosed sub-expression. + * create a new sub-expr parser to handle it */ struct expr_parser_state *sub_expr = (struct expr_parser_state *)parser_push_state( ctx, IVY_AST_EXPR, 0); @@ -666,7 +690,8 @@ struct token_parse_result arith_parse_left_brace( return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); } - if (state->s_prev_component != EXPR_CMP_OPERATOR && state->s_prev_component != EXPR_CMP_NONE) { + if (state->s_prev_component != EXPR_CMP_OPERATOR + && state->s_prev_component != EXPR_CMP_NONE) { return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); } @@ -696,15 +721,19 @@ struct token_parse_result arith_parse_left_bracket( return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); } - if (state->s_prev_component == EXPR_CMP_OPERAND || state->s_prev_component == EXPR_CMP_MSG) { + if (state->s_prev_component == EXPR_CMP_OPERAND + || state->s_prev_component == EXPR_CMP_MSG) { /* subscript operator */ state->s_prev_token = IVY_SYM_LEFT_BRACKET; - struct ivy_ast_op_node *subscript = (struct ivy_ast_op_node *)ast_node_create(IVY_AST_OP); + struct ivy_ast_op_node *subscript + = (struct ivy_ast_op_node *)ast_node_create(IVY_AST_OP); subscript->n_op = ivy_operator_get_by_id(IVY_OP_SUBSCRIPT); arith_push_operator(state, (struct ivy_ast_node *)subscript); - struct expr_parser_state *index = (struct expr_parser_state *)parser_push_state(ctx, IVY_AST_EXPR, 0); + struct expr_parser_state *index + = (struct expr_parser_state *)parser_push_state( + ctx, IVY_AST_EXPR, 0); expr_add_terminator(index, IVY_SYM_RIGHT_BRACKET); index->s_subexpr_depth = state->s_subexpr_depth + 1; @@ -1185,8 +1214,10 @@ struct token_parse_result arith_parse_comma( /* empty tuple member expression. */ return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); } - - if (state->s_sub_type == EXPR_SUBTYPE_PAREN && b_queue_empty(&state->s_output_queue) && b_queue_empty(&state->s_operator_stack)) { + + if (state->s_sub_type == EXPR_SUBTYPE_PAREN + && b_queue_empty(&state->s_output_queue) + && b_queue_empty(&state->s_operator_stack)) { parser_pop_state(ctx, 0); } else { /* the tuple parser will handle the parentheses for us. */ @@ -1230,8 +1261,8 @@ struct token_parse_result arith_parse_label( * next argument. terminate here and propagate this label to the * parent keyword-message parser context. */ struct ivy_ast_node *expr = NULL; - struct token_parse_result result = expr_finalise(ctx, - state, IVY_PRECEDENCE_ASSIGN, &expr); + struct token_parse_result result + = expr_finalise(ctx, state, IVY_PRECEDENCE_ASSIGN, &expr); if (result.r_status != IVY_OK) { return result; } @@ -1336,4 +1367,4 @@ enum ivy_status arith_add_child( } return IVY_OK; -} \ No newline at end of file +}