diff options
author | Jo-Philipp Wich <jo@mein.io> | 2022-07-28 10:44:19 +0200 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2022-07-28 13:18:30 +0200 |
commit | 3a6f9cbc8c1356ccf309f3bb8bdd5b895fb2e01a (patch) | |
tree | caf8ce88be697031b21b774b4e209d7c8ac677f6 | |
parent | b738f3adbe76fb4bd446f1de1f0ece71cf6b78e8 (diff) |
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 <jo@mein.io>
-rw-r--r-- | include/ucode/types.h | 25 | ||||
-rw-r--r-- | 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 @@ -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); |