harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 0f8aea205dcc546002d9c30d5119c590b7045db0
parent 03e62282e5d921a43107ebdf32473629342fa538
Author: Drew DeVault <sir@cmpwn.com>
Date:   Fri, 23 Apr 2021 08:02:58 -0400

parse: implement insert expressions

Signed-off By: Drew DeVault <sir@cmpwn.com>

Diffstat:
Minclude/ast.h | 7+++++++
Minclude/expr.h | 1+
Minclude/lex.h | 1+
Msrc/check.c | 4++++
Msrc/eval.c | 1+
Msrc/gen.c | 2++
Msrc/lex.c | 1+
Msrc/parse.c | 54++++++++++++++++++++++++++++++++++++++++++------------
8 files changed, 59 insertions(+), 12 deletions(-)

diff --git a/include/ast.h b/include/ast.h @@ -240,6 +240,12 @@ struct ast_expression_if { struct ast_expression *true_branch, *false_branch; }; +struct ast_expression_insert { + struct ast_expression *expr; + struct ast_expression *variadic; + struct ast_append_values *values; +}; + struct ast_expression_list { struct ast_expression *expr; struct ast_expression_list *next; @@ -346,6 +352,7 @@ struct ast_expression { struct ast_expression_for _for; struct ast_expression_free free; struct ast_expression_if _if; + struct ast_expression_insert insert; struct ast_expression_list list; struct ast_expression_match match; struct ast_expression_measure measure; diff --git a/include/expr.h b/include/expr.h @@ -26,6 +26,7 @@ enum expr_type { EXPR_FOR, EXPR_FREE, EXPR_IF, + EXPR_INSERT, EXPR_LIST, EXPR_MATCH, EXPR_MEASURE, diff --git a/include/lex.h b/include/lex.h @@ -40,6 +40,7 @@ enum lexical_token { T_I64, T_I8, T_IF, + T_INSERT, T_INT, T_IS, T_LEN, diff --git a/src/check.c b/src/check.c @@ -2485,6 +2485,8 @@ check_expression(struct context *ctx, case EXPR_IF: errors = check_expr_if(ctx, aexpr, expr, hint, errors); break; + case EXPR_INSERT: + assert(0); // TODO case EXPR_LIST: errors = check_expr_list(ctx, aexpr, expr, hint, errors); break; @@ -2922,6 +2924,8 @@ expr_is_specified(struct context *ctx, const struct ast_expression *aexpr) return expr_is_specified(ctx, aexpr->_if.cond) && expr_is_specified(ctx, aexpr->_if.true_branch) && expr_is_specified(ctx, aexpr->_if.false_branch); + case EXPR_INSERT: + assert(0); // TODO case EXPR_LIST: for (const struct ast_expression_list *list = &aexpr->list; list; list = list->next) { diff --git a/src/eval.c b/src/eval.c @@ -652,6 +652,7 @@ eval_expr(struct context *ctx, struct expression *in, struct expression *out) case EXPR_FOR: case EXPR_FREE: case EXPR_IF: + case EXPR_INSERT: case EXPR_LIST: case EXPR_MATCH: case EXPR_PROPAGATE: diff --git a/src/gen.c b/src/gen.c @@ -2646,6 +2646,8 @@ gen_expression(struct gen_context *ctx, case EXPR_IF: gen_expr_if(ctx, expr, out); break; + case EXPR_INSERT: + assert(0); // TODO case EXPR_LIST: gen_expr_list(ctx, expr, out); break; diff --git a/src/lex.c b/src/lex.c @@ -48,6 +48,7 @@ static const char *tokens[] = { [T_I64] = "i64", [T_I8] = "i8", [T_IF] = "if", + [T_INSERT] = "insert", [T_INT] = "int", [T_IS] = "is", [T_LEN] = "len", diff --git a/src/parse.c b/src/parse.c @@ -1247,15 +1247,49 @@ parse_allocation_expression(struct lexer *lexer) synassert(false, &tok, T_COMMA, T_RPAREN, T_EOF); } break; + case T_FREE: + exp = mkexpr(&tok.loc); + exp->type = EXPR_FREE; + want(lexer, T_LPAREN, NULL); + exp->free.expr = parse_expression(lexer); + want(lexer, T_RPAREN, NULL); + break; + default: + assert(0); + } + return exp; +} + +static struct ast_expression * +parse_slice_mutation(struct lexer *lexer) +{ + struct ast_expression *exp = NULL; + struct token tok = {0}; + switch (lex(lexer, &tok)) { case T_APPEND: + case T_INSERT: exp = mkexpr(&tok.loc); - exp->type = EXPR_APPEND; + exp->type = tok.token == T_APPEND ? EXPR_APPEND : EXPR_INSERT; want(lexer, T_LPAREN, NULL); + + struct ast_append_values **next; // Easier to parse an expression and let check limit it to // object-selector/*unary-expression - exp->append.expr = parse_expression(lexer); + switch (exp->type) { + case EXPR_APPEND: + exp->append.expr = parse_expression(lexer); + next = &exp->append.values; + break; + case EXPR_INSERT: + exp->insert.expr = parse_expression(lexer); + next = &exp->insert.values; + break; + default: + assert(0); + } + want(lexer, T_COMMA, NULL); - struct ast_append_values **next = &exp->append.values; + while (tok.token != T_RPAREN) { if (lex(lexer, &tok) == T_ELLIPSIS) { exp->append.variadic = @@ -1285,13 +1319,6 @@ parse_allocation_expression(struct lexer *lexer) next = &(*next)->next; } break; - case T_FREE: - exp = mkexpr(&tok.loc); - exp->type = EXPR_FREE; - want(lexer, T_LPAREN, NULL); - exp->free.expr = parse_expression(lexer); - want(lexer, T_RPAREN, NULL); - break; case T_DELETE: exp = mkexpr(&tok.loc); exp->type = EXPR_DELETE; @@ -1398,11 +1425,14 @@ parse_builtin_expression(struct lexer *lexer) struct token tok; switch (lex(lexer, &tok)) { case T_ALLOC: - case T_APPEND: case T_FREE: - case T_DELETE: unlex(lexer, &tok); return parse_allocation_expression(lexer); + case T_APPEND: + case T_DELETE: + case T_INSERT: + unlex(lexer, &tok); + return parse_slice_mutation(lexer); case T_ABORT: case T_ASSERT: case T_STATIC: