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