From 3a6f9cbc8c1356ccf309f3bb8bdd5b895fb2e01a Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Thu, 28 Jul 2022 10:44:19 +0200 Subject: types: add ability to mark array and object values as constant The upcoming module import support requires constant object values to implement module wildcard import. Reuse the existing u64 bit in ucv heads to mark array or object values as constant and add corresponding `ucv_is_constant()` and `ucv_set_constant()` helpers. Signed-off-by: Jo-Philipp Wich --- include/ucode/types.h | 25 +++++++++++++++++++++++-- types.c | 16 ++++++++-------- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/include/ucode/types.h b/include/ucode/types.h index d1e01a1..314dbc8 100644 --- a/include/ucode/types.h +++ b/include/ucode/types.h @@ -47,7 +47,7 @@ typedef enum uc_type { typedef struct uc_value { uint32_t type:4; uint32_t mark:1; - uint32_t u64:1; + uint32_t u64_or_constant:1; uint32_t refcount:26; } uc_value_t; @@ -448,7 +448,28 @@ ucv_is_arrowfn(uc_value_t *uv) static inline bool ucv_is_u64(uc_value_t *uv) { - return (((uintptr_t)uv & 3) == 0 && uv != NULL && uv->u64 == true); + return (((uintptr_t)uv & 3) == 0 && uv != NULL && uv->u64_or_constant == true && + uv->type == UC_INTEGER); +} + +static inline bool +ucv_is_constant(uc_value_t *uv) +{ + return (((uintptr_t)uv & 3) == 0 && uv != NULL && uv->u64_or_constant == true && + (uv->type == UC_ARRAY || uv->type == UC_OBJECT)); +} + +static inline bool +ucv_set_constant(uc_value_t *uv, bool constant) +{ + if (((uintptr_t)uv & 3) == 0 && uv != NULL && uv->u64_or_constant != constant && + (uv->type == UC_ARRAY || uv->type == UC_OBJECT)) { + uv->u64_or_constant = constant; + + return true; + } + + return false; } static inline bool diff --git a/types.c b/types.c index 4f5088c..9700d8f 100644 --- a/types.c +++ b/types.c @@ -470,7 +470,7 @@ ucv_int64_new(int64_t n) integer = xalloc(sizeof(*integer)); integer->header.type = UC_INTEGER; integer->header.refcount = 1; - integer->header.u64 = 0; + integer->header.u64_or_constant = 0; integer->i.s64 = n; return &integer->header; @@ -492,7 +492,7 @@ ucv_uint64_new(uint64_t n) integer = xalloc(sizeof(*integer)); integer->header.type = UC_INTEGER; integer->header.refcount = 1; - integer->header.u64 = 1; + integer->header.u64_or_constant = 1; integer->i.u64 = n; return &integer->header; @@ -520,7 +520,7 @@ ucv_uint64_get(uc_value_t *uv) case UC_INTEGER: integer = (uc_integer_t *)uv; - if (integer->header.u64) + if (integer->header.u64_or_constant) return integer->i.u64; if (integer->i.s64 >= 0) @@ -574,10 +574,10 @@ ucv_int64_get(uc_value_t *uv) case UC_INTEGER: integer = (uc_integer_t *)uv; - if (integer->header.u64 && integer->i.u64 <= (uint64_t)INT64_MAX) + if (integer->header.u64_or_constant && integer->i.u64 <= (uint64_t)INT64_MAX) return (int64_t)integer->i.u64; - if (!integer->header.u64) + if (!integer->header.u64_or_constant) return integer->i.s64; errno = ERANGE; @@ -715,7 +715,7 @@ ucv_array_push(uc_value_t *uv, uc_value_t *item) { uc_array_t *array = (uc_array_t *)uv; - if (ucv_type(uv) != UC_ARRAY) + if (ucv_type(uv) != UC_ARRAY || uv->u64_or_constant) return NULL; ucv_array_set(uv, array->count, item); @@ -899,7 +899,7 @@ ucv_object_add(uc_value_t *uv, const char *key, uc_value_t *val) unsigned long hash; void *k; - if (ucv_type(uv) != UC_OBJECT) + if (ucv_type(uv) != UC_OBJECT || uv->u64_or_constant) return false; hash = lh_get_hash(object->table, (const void *)key); @@ -932,7 +932,7 @@ ucv_object_delete(uc_value_t *uv, const char *key) { uc_object_t *object = (uc_object_t *)uv; - if (ucv_type(uv) != UC_OBJECT) + if (ucv_type(uv) != UC_OBJECT || uv->u64_or_constant) return false; return (lh_table_delete(object->table, key) == 0); -- cgit v1.2.3