summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2022-07-28 10:44:19 +0200
committerJo-Philipp Wich <jo@mein.io>2022-07-28 13:18:30 +0200
commit3a6f9cbc8c1356ccf309f3bb8bdd5b895fb2e01a (patch)
treecaf8ce88be697031b21b774b4e209d7c8ac677f6
parentb738f3adbe76fb4bd446f1de1f0ece71cf6b78e8 (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.h25
-rw-r--r--types.c16
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);