harec

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

commit 7dbb86654df902f9b7767f78bee7ad213215fec1
parent 8b00f7222527f071a7f4b00b07c884acf7285107
Author: Drew DeVault <sir@cmpwn.com>
Date:   Wed, 23 Dec 2020 14:21:43 -0500

Implement const bindings

Diffstat:
Minclude/ast.h | 1+
Minclude/type_store.h | 3+++
Msrc/check.c | 10+++++++---
Msrc/parse.c | 1+
Msrc/type_store.c | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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); +}