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:
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: