harec

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

commit 92912c78b5fd86669d51b2ea4cc0187b0c5973aa
parent 1aa3c60e6e7966c322a84f152beb7b905455009a
Author: Eyal Sawady <ecs@d2evs.net>
Date:   Sun, 21 Feb 2021 18:06:18 -0500

lex, parse, check: implement delete

Diffstat:
Minclude/ast.h | 5+++++
Minclude/expr.h | 6++++++
Minclude/lex.h | 1+
Msrc/check.c | 38++++++++++++++++++++++++++++++++++++++
Msrc/dump.c | 3+++
Msrc/eval.c | 1+
Msrc/gen.c | 2++
Msrc/lex.c | 1+
Msrc/parse.c | 9+++++++++
9 files changed, 66 insertions(+), 0 deletions(-)

diff --git a/include/ast.h b/include/ast.h @@ -218,6 +218,10 @@ struct ast_expression_defer { struct ast_expression *deferred; }; +struct ast_expression_delete { + struct ast_expression *expr; +}; + struct ast_expression_for { char *label; struct location label_loc; @@ -334,6 +338,7 @@ struct ast_expression { struct ast_expression_constant constant; struct ast_expression_control control; struct ast_expression_defer defer; + struct ast_expression_delete delete; struct ast_expression_for _for; struct ast_expression_free free; struct ast_expression_if _if; diff --git a/include/expr.h b/include/expr.h @@ -21,6 +21,7 @@ enum expr_type { EXPR_CONSTANT, EXPR_CONTINUE, EXPR_DEFER, + EXPR_DELETE, EXPR_FOR, EXPR_FREE, EXPR_IF, @@ -181,6 +182,10 @@ struct expression_defer { struct expression *deferred; }; +struct expression_delete { + struct expression *expr; +}; + struct expression_for { char *label; struct scope *scope; @@ -307,6 +312,7 @@ struct expression { struct expression_cast cast; union expression_constant constant; struct expression_defer defer; + struct expression_delete delete; struct expression_control control; struct expression_for _for; struct expression_free free; diff --git a/include/lex.h b/include/lex.h @@ -25,6 +25,7 @@ enum lexical_token { T_CONTINUE, T_DEF, T_DEFER, + T_DELETE, T_ELSE, T_ENUM, T_EXPORT, diff --git a/src/check.c b/src/check.c @@ -1141,6 +1141,41 @@ check_expr_defer(struct context *ctx, } static void +check_expr_delete(struct context *ctx, + const struct ast_expression *aexpr, + struct expression *expr, + const struct type *hint) +{ + expr->type = EXPR_DELETE; + expr->result = &builtin_type_void; + struct expression *dexpr = expr->delete.expr = + xcalloc(1, sizeof(struct expression)); + check_expression(ctx, aexpr->delete.expr, expr->delete.expr, NULL); + const struct type *otype = NULL; + switch (dexpr->type) { + case EXPR_SLICE: + otype = dexpr->slice.object->result; + break; + case EXPR_ACCESS: + expect(&aexpr->delete.expr->loc, dexpr->access.type == ACCESS_INDEX, + "Deleted expression must be slicing or indexing expression"); + otype = dexpr->access.array->result; + break; + default: + expect(&aexpr->delete.expr->loc, false, + "Deleted expression must be slicing or indexing expression"); + } + otype = type_dealias(otype); + while (otype->storage == STORAGE_POINTER) { + otype = type_dealias(otype->pointer.referent); + } + expect(&aexpr->delete.expr->loc, otype->storage == STORAGE_SLICE, + "delete must operate on a slice"); + expect(&aexpr->delete.expr->loc, !(otype->flags & TYPE_CONST), + "delete must operate on a mutable slice"); +} + +static void check_expr_control(struct context *ctx, const struct ast_expression *aexpr, struct expression *expr, @@ -1972,6 +2007,9 @@ check_expression(struct context *ctx, case EXPR_DEFER: check_expr_defer(ctx, aexpr, expr, hint); break; + case EXPR_DELETE: + check_expr_delete(ctx, aexpr, expr, hint); + break; case EXPR_FOR: check_expr_for(ctx, aexpr, expr, hint); break; diff --git a/src/dump.c b/src/dump.c @@ -340,6 +340,9 @@ dump_expr(const struct expression *expr, int depth) case EXPR_DEFER: fprintf(stderr, "defer"); break; + case EXPR_DELETE: + fprintf(stderr, "delete"); + break; case EXPR_FOR: fprintf(stderr, "for"); break; diff --git a/src/eval.c b/src/eval.c @@ -539,6 +539,7 @@ eval_expr(struct context *ctx, struct expression *in, struct expression *out) case EXPR_CONTINUE: case EXPR_CALL: case EXPR_DEFER: + case EXPR_DELETE: case EXPR_FOR: case EXPR_FREE: case EXPR_IF: diff --git a/src/gen.c b/src/gen.c @@ -2451,6 +2451,8 @@ gen_expression(struct gen_context *ctx, case EXPR_DEFER: gen_expr_defer(ctx, expr, out); break; + case EXPR_DELETE: + assert(0); // TODO case EXPR_FOR: gen_expr_for(ctx, expr, out); break; diff --git a/src/lex.c b/src/lex.c @@ -34,6 +34,7 @@ static const char *tokens[] = { [T_CONTINUE] = "continue", [T_DEF] = "def", [T_DEFER] = "defer", + [T_DELETE] = "delete", [T_ELSE] = "else", [T_ENUM] = "enum", [T_EXPORT] = "export", diff --git a/src/parse.c b/src/parse.c @@ -1328,6 +1328,14 @@ parse_allocation_expression(struct lexer *lexer) exp->free.expr = parse_simple_expression(lexer); want(lexer, T_RPAREN, NULL); break; + case T_DELETE: + trace(TR_PARSE, "delete"); + exp = mkexpr(&tok.loc); + exp->type = EXPR_DELETE; + want(lexer, T_LPAREN, NULL); + exp->delete.expr = parse_simple_expression(lexer); + want(lexer, T_RPAREN, NULL); + break; default: assert(0); } @@ -1347,6 +1355,7 @@ parse_postfix_expression(struct lexer *lexer, struct ast_expression *lvalue) case T_ALLOC: case T_APPEND: case T_FREE: + case T_DELETE: synassert(lvalue == NULL, &tok, T_LPAREN, T_DOT, T_LBRACKET, T_EOF); unlex(lexer, &tok);