commit 7dbb86654df902f9b7767f78bee7ad213215fec1
parent 8b00f7222527f071a7f4b00b07c884acf7285107
Author: Drew DeVault <sir@cmpwn.com>
Date: Wed, 23 Dec 2020 14:21:43 -0500
Implement const bindings
Diffstat:
5 files changed, 72 insertions(+), 3 deletions(-)
diff --git a/include/ast.h b/include/ast.h
@@ -103,6 +103,7 @@ struct ast_expression_binarithm {
struct ast_expression_binding {
char *name;
struct ast_type *type;
+ unsigned int flags;
struct ast_expression *initializer;
struct ast_expression_binding *next;
};
diff --git a/include/type_store.h b/include/type_store.h
@@ -23,4 +23,7 @@ const struct type *type_store_lookup_atype(
const struct type *builtin_type_for_storage(
enum type_storage storage, bool is_const);
+const struct type *type_store_lookup_with_flags(struct type_store *store,
+ const struct type *type, unsigned int flags);
+
#endif
diff --git a/src/check.c b/src/check.c
@@ -71,8 +71,11 @@ check_expr_assign(struct context *ctx,
assert(0); // TODO
} else {
assert(expr->assign.object->type == EXPR_ACCESS); // Invariant
+ const struct scope_object *object =
+ expr->assign.object->access.object;
+ expect(!(object->type->flags & TYPE_CONST), "Cannot assign to const object");
// TODO: Test assignability rules:
- assert(expr->assign.object->result->storage == expr->assign.value->result->storage);
+ assert(object->type->storage == expr->assign.value->result->storage);
}
}
@@ -153,7 +156,8 @@ check_expr_binding(struct context *ctx,
&ctx->store, abinding->type);
// TODO: Check assignability of initializer
} else {
- type = initializer->result;
+ type = type_store_lookup_with_flags(&ctx->store,
+ initializer->result, abinding->flags);
}
const struct scope_object *obj = scope_insert(
@@ -178,7 +182,7 @@ check_expr_constant(struct context *ctx,
{
trace(TR_CHECK, "constant");
expr->type = EXPR_CONSTANT;
- expr->result = builtin_type_for_storage(aexpr->constant.storage, true);
+ expr->result = builtin_type_for_storage(aexpr->constant.storage, false);
switch (aexpr->constant.storage) {
case TYPE_STORAGE_I8:
diff --git a/src/parse.c b/src/parse.c
@@ -744,6 +744,7 @@ parse_binding_list(struct parser *par)
want(par, T_NAME, &tok);
binding->name = tok.name;
binding->initializer = calloc(1, sizeof(struct ast_expression));
+ binding->flags = flags;
switch (lex(par->lex, &tok)) {
case T_COLON:
diff --git a/src/type_store.c b/src/type_store.c
@@ -165,6 +165,13 @@ builtin_for_atype(const struct ast_type *atype)
return builtin_type_for_storage(atype->storage, is_const);
}
+static const struct type *
+builtin_for_type(const struct type *type)
+{
+ bool is_const = (type->flags & TYPE_CONST) != 0;
+ return builtin_type_for_storage(type->storage, is_const);
+}
+
static bool
type_eq_atype(struct type_store *store,
const struct type *type,
@@ -229,6 +236,13 @@ type_eq_atype(struct type_store *store,
assert(0); // Unreachable
}
+static bool
+type_eq_type(struct type_store *store,
+ const struct type *a, const struct type *b)
+{
+ assert(0); // TODO
+}
+
static void
type_init_from_atype(struct type_store *store,
struct type *type,
@@ -284,6 +298,14 @@ type_init_from_atype(struct type_store *store,
}
}
+static void
+type_init_from_type(struct type_store *store,
+ struct type *type,
+ const struct type *atype)
+{
+ assert(0); // TODO
+}
+
const struct type *
type_store_lookup_atype(struct type_store *store, const struct ast_type *atype)
{
@@ -308,3 +330,41 @@ type_store_lookup_atype(struct type_store *store, const struct ast_type *atype)
type_init_from_atype(store, &bucket->type, atype);
return &bucket->type;
}
+
+// Used internally for looking up modified forms of other types
+static const struct type *
+type_store_lookup_type(struct type_store *store, const struct type *type)
+{
+ const struct type *builtin = builtin_for_type(type);
+ if (builtin) {
+ return builtin;
+ }
+
+ unsigned long hash = type_hash(store, type);
+ struct type_bucket **next = &store->buckets[hash % TYPE_STORE_BUCKETS];
+
+ struct type_bucket *bucket;
+ while (*next) {
+ bucket = *next;
+ if (type_eq_type(store, &bucket->type, type)) {
+ return &bucket->type;
+ }
+ next = &bucket->next;
+ }
+
+ bucket = *next = calloc(1, sizeof(struct type_bucket));
+ type_init_from_type(store, &bucket->type, type);
+ return &bucket->type;
+}
+
+const struct type *
+type_store_lookup_with_flags(struct type_store *store,
+ const struct type *type, unsigned int flags)
+{
+ if ((type->flags & ~flags) == flags) {
+ return type;
+ }
+ struct type new = *type;
+ new.flags |= flags;
+ return type_store_lookup_type(store, &new);
+}