summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-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);