commit b74b70a610d9f6b226dac14cabf945cd84ef3290
parent ea6d4c92cd331f1177eaea69e41d3d91a116b130
Author: Drew DeVault <sir@cmpwn.com>
Date: Sat, 26 Dec 2020 13:47:37 -0500
check: implement index access
Diffstat:
4 files changed, 39 insertions(+), 15 deletions(-)
diff --git a/include/ast.h b/include/ast.h
@@ -102,7 +102,7 @@ struct ast_expression_access {
union {
struct identifier ident;
struct {
- struct ast_expression *object;
+ struct ast_expression *array;
struct ast_expression *index;
};
// TODO: Field selection
diff --git a/include/expr.h b/include/expr.h
@@ -38,9 +38,15 @@ enum access_type {
};
struct expression_access {
- const struct scope_object *object;
enum access_type type;
- // TODO: Details for index, field selection
+ union {
+ const struct scope_object *object;
+ struct {
+ struct expression *array;
+ struct expression *index;
+ };
+ // TODO: Field selection
+ };
};
struct expression_assign {
diff --git a/src/check.c b/src/check.c
@@ -41,18 +41,36 @@ check_expr_access(struct context *ctx,
const struct ast_expression *aexpr,
struct expression *expr)
{
- char buf[1024];
- identifier_unparse_static(&aexpr->access.ident, buf, sizeof(buf));
-
- trace(TR_CHECK, "access %s", buf);
+ trace(TR_CHECK, "access");
expr->type = EXPR_ACCESS;
-
- const struct scope_object *obj = scope_lookup(
- ctx->scope, &aexpr->access.ident);
- expect(obj, "Unknown object %s", buf);
-
- expr->result = obj->type;
- expr->access.object = obj;
+ expr->access.type = aexpr->access.type;
+
+ const struct scope_object *obj;
+ switch (expr->access.type) {
+ case ACCESS_IDENTIFIER:
+ obj = scope_lookup(ctx->scope, &aexpr->access.ident);
+ char buf[1024];
+ identifier_unparse_static(&aexpr->access.ident, buf, sizeof(buf));
+ expect(obj, "Unknown object", buf);
+ expr->result = obj->type;
+ expr->access.object = obj;
+ break;
+ case ACCESS_INDEX:
+ expr->access.array = xcalloc(1, sizeof(struct expression));
+ expr->access.index = xcalloc(1, sizeof(struct expression));
+ check_expression(ctx, aexpr->access.array, expr->access.array);
+ check_expression(ctx, aexpr->access.index, expr->access.index);
+ const struct type *atype = expr->access.array->result;
+ const struct type *itype = expr->access.index->result;
+ expect(atype->storage == TYPE_STORAGE_ARRAY
+ || atype->storage == TYPE_STORAGE_SLICE,
+ "Cannot index non-array, non-slice object");
+ expect(type_is_integer(itype), "Cannot use non-integer type as slice/array index");
+ expr->result = atype->array.members;
+ break;
+ case ACCESS_FIELD:
+ assert(0); // TODO
+ }
}
static void
diff --git a/src/parse.c b/src/parse.c
@@ -876,7 +876,7 @@ parse_index_slice_expression(struct parser *par, struct ast_expression *lvalue)
if (!is_slice) {
exp->type = EXPR_ACCESS;
exp->access.type = ACCESS_INDEX;
- exp->access.object = lvalue;
+ exp->access.array = lvalue;
exp->access.index = start;
trleave(TR_PARSE, "slice-index (index)");
return exp;