chore: remove trailing whitespace from README.md line 42
This commit is contained in:
+401
-1
@@ -1661,6 +1661,156 @@ static bool _rava_vm_execute_instruction(RavaVM_t *vm, RavaCallFrame_t *frame, R
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_ARRAYLIST_NEW: {
|
||||
RavaArrayList_t *list = rava_arraylist_create();
|
||||
rava_stack_push(stack, rava_value_arraylist(list));
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_ARRAYLIST_ADD: {
|
||||
RavaValue_t value = rava_stack_pop(stack);
|
||||
RavaValue_t list_val = rava_stack_pop(stack);
|
||||
if (list_val.type == RAVA_VAL_ARRAYLIST) {
|
||||
rava_arraylist_add(list_val.data.arraylist_val, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_ARRAYLIST_GET: {
|
||||
RavaValue_t index_or_key = rava_stack_pop(stack);
|
||||
RavaValue_t coll_val = rava_stack_pop(stack);
|
||||
if (coll_val.type == RAVA_VAL_ARRAYLIST) {
|
||||
rava_stack_push(stack, rava_arraylist_get(coll_val.data.arraylist_val, (size_t)rava_value_as_int(index_or_key)));
|
||||
} else if (coll_val.type == RAVA_VAL_HASHMAP && index_or_key.type == RAVA_VAL_STRING) {
|
||||
rava_stack_push(stack, rava_hashmap_get(coll_val.data.hashmap_val, index_or_key.data.string_val));
|
||||
} else {
|
||||
rava_stack_push(stack, rava_value_null());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_ARRAYLIST_SET: {
|
||||
RavaValue_t value = rava_stack_pop(stack);
|
||||
RavaValue_t index = rava_stack_pop(stack);
|
||||
RavaValue_t list_val = rava_stack_pop(stack);
|
||||
if (list_val.type == RAVA_VAL_ARRAYLIST) {
|
||||
rava_arraylist_set(list_val.data.arraylist_val, (size_t)rava_value_as_int(index), value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_ARRAYLIST_SIZE: {
|
||||
RavaValue_t coll_val = rava_stack_pop(stack);
|
||||
if (coll_val.type == RAVA_VAL_ARRAYLIST) {
|
||||
rava_stack_push(stack, rava_value_int((int32_t)rava_arraylist_size(coll_val.data.arraylist_val)));
|
||||
} else if (coll_val.type == RAVA_VAL_HASHMAP) {
|
||||
rava_stack_push(stack, rava_value_int((int32_t)rava_hashmap_size(coll_val.data.hashmap_val)));
|
||||
} else {
|
||||
rava_stack_push(stack, rava_value_int(0));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_ARRAYLIST_REMOVE: {
|
||||
RavaValue_t index_or_key = rava_stack_pop(stack);
|
||||
RavaValue_t coll_val = rava_stack_pop(stack);
|
||||
if (coll_val.type == RAVA_VAL_ARRAYLIST) {
|
||||
rava_stack_push(stack, rava_arraylist_remove(coll_val.data.arraylist_val, (size_t)rava_value_as_int(index_or_key)));
|
||||
} else if (coll_val.type == RAVA_VAL_HASHMAP && index_or_key.type == RAVA_VAL_STRING) {
|
||||
rava_stack_push(stack, rava_hashmap_remove(coll_val.data.hashmap_val, index_or_key.data.string_val));
|
||||
} else {
|
||||
rava_stack_push(stack, rava_value_null());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_ARRAYLIST_CLEAR: {
|
||||
RavaValue_t coll_val = rava_stack_pop(stack);
|
||||
if (coll_val.type == RAVA_VAL_ARRAYLIST) {
|
||||
rava_arraylist_clear(coll_val.data.arraylist_val);
|
||||
} else if (coll_val.type == RAVA_VAL_HASHMAP) {
|
||||
rava_hashmap_clear(coll_val.data.hashmap_val);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_ARRAYLIST_ISEMPTY: {
|
||||
RavaValue_t list_val = rava_stack_pop(stack);
|
||||
if (list_val.type == RAVA_VAL_ARRAYLIST) {
|
||||
rava_stack_push(stack, rava_value_boolean(rava_arraylist_isempty(list_val.data.arraylist_val)));
|
||||
} else {
|
||||
rava_stack_push(stack, rava_value_boolean(true));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_HASHMAP_NEW: {
|
||||
RavaHashMap_t *map = rava_hashmap_create();
|
||||
rava_stack_push(stack, rava_value_hashmap(map));
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_HASHMAP_PUT: {
|
||||
RavaValue_t value = rava_stack_pop(stack);
|
||||
RavaValue_t key_val = rava_stack_pop(stack);
|
||||
RavaValue_t map_val = rava_stack_pop(stack);
|
||||
if (map_val.type == RAVA_VAL_HASHMAP && key_val.type == RAVA_VAL_STRING) {
|
||||
rava_hashmap_put(map_val.data.hashmap_val, key_val.data.string_val, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_HASHMAP_GET: {
|
||||
RavaValue_t key_val = rava_stack_pop(stack);
|
||||
RavaValue_t map_val = rava_stack_pop(stack);
|
||||
if (map_val.type == RAVA_VAL_HASHMAP && key_val.type == RAVA_VAL_STRING) {
|
||||
rava_stack_push(stack, rava_hashmap_get(map_val.data.hashmap_val, key_val.data.string_val));
|
||||
} else {
|
||||
rava_stack_push(stack, rava_value_null());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_HASHMAP_REMOVE: {
|
||||
RavaValue_t key_val = rava_stack_pop(stack);
|
||||
RavaValue_t map_val = rava_stack_pop(stack);
|
||||
if (map_val.type == RAVA_VAL_HASHMAP && key_val.type == RAVA_VAL_STRING) {
|
||||
rava_stack_push(stack, rava_hashmap_remove(map_val.data.hashmap_val, key_val.data.string_val));
|
||||
} else {
|
||||
rava_stack_push(stack, rava_value_null());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_HASHMAP_SIZE: {
|
||||
RavaValue_t map_val = rava_stack_pop(stack);
|
||||
if (map_val.type == RAVA_VAL_HASHMAP) {
|
||||
rava_stack_push(stack, rava_value_int((int32_t)rava_hashmap_size(map_val.data.hashmap_val)));
|
||||
} else {
|
||||
rava_stack_push(stack, rava_value_int(0));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_HASHMAP_CONTAINSKEY: {
|
||||
RavaValue_t key_val = rava_stack_pop(stack);
|
||||
RavaValue_t map_val = rava_stack_pop(stack);
|
||||
if (map_val.type == RAVA_VAL_HASHMAP && key_val.type == RAVA_VAL_STRING) {
|
||||
rava_stack_push(stack, rava_value_boolean(rava_hashmap_containskey(map_val.data.hashmap_val, key_val.data.string_val)));
|
||||
} else {
|
||||
rava_stack_push(stack, rava_value_boolean(false));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_HASHMAP_CLEAR: {
|
||||
RavaValue_t map_val = rava_stack_pop(stack);
|
||||
if (map_val.type == RAVA_VAL_HASHMAP) {
|
||||
rava_hashmap_clear(map_val.data.hashmap_val);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_CAST: {
|
||||
RavaValue_t val = rava_stack_pop(stack);
|
||||
RavaType_t *target_type = instr->operand.var.type;
|
||||
@@ -3090,7 +3240,11 @@ static bool _rava_vm_execute_ultrafast(RavaVM_t *vm, RavaMethod_t *entry_method)
|
||||
&&uf_math_abs, &&uf_math_sqrt, &&uf_math_pow, &&uf_math_min, &&uf_math_max,
|
||||
&&uf_math_floor, &&uf_math_ceil, &&uf_math_round,
|
||||
&&uf_math_sin, &&uf_math_cos, &&uf_math_tan, &&uf_math_log, &&uf_math_exp,
|
||||
&&uf_math_random
|
||||
&&uf_math_random,
|
||||
&&uf_arraylist_new, &&uf_arraylist_add, &&uf_arraylist_get, &&uf_arraylist_set,
|
||||
&&uf_arraylist_size, &&uf_arraylist_remove, &&uf_arraylist_clear, &&uf_arraylist_isempty,
|
||||
&&uf_hashmap_new, &&uf_hashmap_put, &&uf_hashmap_get, &&uf_hashmap_remove,
|
||||
&&uf_hashmap_size, &&uf_hashmap_containskey, &&uf_hashmap_clear
|
||||
};
|
||||
|
||||
rava_fastframe_reset();
|
||||
@@ -4248,6 +4402,252 @@ uf_math_random: {
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_arraylist_new: {
|
||||
RavaArrayList_t *list = rava_arraylist_create();
|
||||
UF_PUSH(rava_nanbox_object(list));
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_arraylist_add: {
|
||||
RavaNanboxValue_t val = UF_POP();
|
||||
RavaNanboxValue_t list_nb = UF_POP();
|
||||
RavaArrayList_t *list = (RavaArrayList_t*)rava_nanbox_as_object(list_nb);
|
||||
if (list) {
|
||||
RavaValue_t v;
|
||||
if (rava_nanbox_is_int(val)) {
|
||||
v = rava_value_int(rava_nanbox_to_int(val));
|
||||
} else if (rava_nanbox_is_double(val)) {
|
||||
v = rava_value_double(rava_nanbox_to_double(val));
|
||||
} else {
|
||||
v = rava_value_null();
|
||||
}
|
||||
rava_arraylist_add(list, v);
|
||||
}
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_arraylist_get: {
|
||||
RavaNanboxValue_t idx_nb = UF_POP();
|
||||
RavaNanboxValue_t coll_nb = UF_POP();
|
||||
void *ptr = rava_nanbox_as_object(coll_nb);
|
||||
if (rava_nanbox_is_int(idx_nb)) {
|
||||
RavaArrayList_t *list = (RavaArrayList_t*)ptr;
|
||||
if (list) {
|
||||
RavaValue_t v = rava_arraylist_get(list, (size_t)rava_nanbox_to_int(idx_nb));
|
||||
if (v.type == RAVA_VAL_INT) {
|
||||
UF_PUSH(rava_nanbox_int(v.data.int_val));
|
||||
} else if (v.type == RAVA_VAL_DOUBLE) {
|
||||
UF_PUSH(rava_nanbox_double(v.data.double_val));
|
||||
} else {
|
||||
UF_PUSH(rava_nanbox_null());
|
||||
}
|
||||
} else {
|
||||
UF_PUSH(rava_nanbox_null());
|
||||
}
|
||||
} else if (rava_nanbox_is_string(idx_nb)) {
|
||||
RavaHashMap_t *map = (RavaHashMap_t*)ptr;
|
||||
if (map) {
|
||||
RavaValue_t v = rava_hashmap_get(map, rava_nanbox_as_string(idx_nb));
|
||||
if (v.type == RAVA_VAL_INT) {
|
||||
UF_PUSH(rava_nanbox_int(v.data.int_val));
|
||||
} else if (v.type == RAVA_VAL_DOUBLE) {
|
||||
UF_PUSH(rava_nanbox_double(v.data.double_val));
|
||||
} else {
|
||||
UF_PUSH(rava_nanbox_null());
|
||||
}
|
||||
} else {
|
||||
UF_PUSH(rava_nanbox_null());
|
||||
}
|
||||
} else {
|
||||
UF_PUSH(rava_nanbox_null());
|
||||
}
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_arraylist_set: {
|
||||
RavaNanboxValue_t val = UF_POP();
|
||||
RavaNanboxValue_t idx_nb = UF_POP();
|
||||
RavaNanboxValue_t list_nb = UF_POP();
|
||||
RavaArrayList_t *list = (RavaArrayList_t*)rava_nanbox_as_object(list_nb);
|
||||
if (list) {
|
||||
RavaValue_t v;
|
||||
if (rava_nanbox_is_int(val)) {
|
||||
v = rava_value_int(rava_nanbox_to_int(val));
|
||||
} else if (rava_nanbox_is_double(val)) {
|
||||
v = rava_value_double(rava_nanbox_to_double(val));
|
||||
} else {
|
||||
v = rava_value_null();
|
||||
}
|
||||
rava_arraylist_set(list, (size_t)rava_nanbox_to_int(idx_nb), v);
|
||||
}
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_arraylist_size: {
|
||||
RavaNanboxValue_t coll_nb = UF_POP();
|
||||
void *ptr = rava_nanbox_as_object(coll_nb);
|
||||
if (ptr) {
|
||||
int type = *(int*)ptr;
|
||||
if (type == RAVA_COLLECTION_ARRAYLIST) {
|
||||
UF_PUSH(rava_nanbox_int((int32_t)rava_arraylist_size((RavaArrayList_t*)ptr)));
|
||||
} else if (type == RAVA_COLLECTION_HASHMAP) {
|
||||
UF_PUSH(rava_nanbox_int((int32_t)rava_hashmap_size((RavaHashMap_t*)ptr)));
|
||||
} else {
|
||||
UF_PUSH(rava_nanbox_int(0));
|
||||
}
|
||||
} else {
|
||||
UF_PUSH(rava_nanbox_int(0));
|
||||
}
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_arraylist_remove: {
|
||||
RavaNanboxValue_t idx_or_key = UF_POP();
|
||||
RavaNanboxValue_t coll_nb = UF_POP();
|
||||
void *ptr = rava_nanbox_as_object(coll_nb);
|
||||
if (ptr) {
|
||||
int type = *(int*)ptr;
|
||||
if (type == RAVA_COLLECTION_ARRAYLIST && rava_nanbox_is_int(idx_or_key)) {
|
||||
RavaValue_t v = rava_arraylist_remove((RavaArrayList_t*)ptr, (size_t)rava_nanbox_to_int(idx_or_key));
|
||||
if (v.type == RAVA_VAL_INT) {
|
||||
UF_PUSH(rava_nanbox_int(v.data.int_val));
|
||||
} else {
|
||||
UF_PUSH(rava_nanbox_null());
|
||||
}
|
||||
} else if (type == RAVA_COLLECTION_HASHMAP && rava_nanbox_is_string(idx_or_key)) {
|
||||
RavaValue_t v = rava_hashmap_remove((RavaHashMap_t*)ptr, rava_nanbox_as_string(idx_or_key));
|
||||
if (v.type == RAVA_VAL_INT) {
|
||||
UF_PUSH(rava_nanbox_int(v.data.int_val));
|
||||
} else {
|
||||
UF_PUSH(rava_nanbox_null());
|
||||
}
|
||||
} else {
|
||||
UF_PUSH(rava_nanbox_null());
|
||||
}
|
||||
} else {
|
||||
UF_PUSH(rava_nanbox_null());
|
||||
}
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_arraylist_clear: {
|
||||
RavaNanboxValue_t coll_nb = UF_POP();
|
||||
void *ptr = rava_nanbox_as_object(coll_nb);
|
||||
if (ptr) {
|
||||
int type = *(int*)ptr;
|
||||
if (type == RAVA_COLLECTION_ARRAYLIST) {
|
||||
rava_arraylist_clear((RavaArrayList_t*)ptr);
|
||||
} else if (type == RAVA_COLLECTION_HASHMAP) {
|
||||
rava_hashmap_clear((RavaHashMap_t*)ptr);
|
||||
}
|
||||
}
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_arraylist_isempty: {
|
||||
RavaNanboxValue_t list_nb = UF_POP();
|
||||
RavaArrayList_t *list = (RavaArrayList_t*)rava_nanbox_as_object(list_nb);
|
||||
if (list) {
|
||||
UF_PUSH(rava_nanbox_int(rava_arraylist_isempty(list) ? 1 : 0));
|
||||
} else {
|
||||
UF_PUSH(rava_nanbox_int(1));
|
||||
}
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_hashmap_new: {
|
||||
RavaHashMap_t *map = rava_hashmap_create();
|
||||
UF_PUSH(rava_nanbox_object(map));
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_hashmap_put: {
|
||||
RavaNanboxValue_t val = UF_POP();
|
||||
RavaNanboxValue_t key_nb = UF_POP();
|
||||
RavaNanboxValue_t map_nb = UF_POP();
|
||||
RavaHashMap_t *map = (RavaHashMap_t*)rava_nanbox_as_object(map_nb);
|
||||
if (map && rava_nanbox_is_string(key_nb)) {
|
||||
RavaValue_t v;
|
||||
if (rava_nanbox_is_int(val)) {
|
||||
v = rava_value_int(rava_nanbox_to_int(val));
|
||||
} else if (rava_nanbox_is_double(val)) {
|
||||
v = rava_value_double(rava_nanbox_to_double(val));
|
||||
} else {
|
||||
v = rava_value_null();
|
||||
}
|
||||
rava_hashmap_put(map, rava_nanbox_as_string(key_nb), v);
|
||||
}
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_hashmap_get: {
|
||||
RavaNanboxValue_t key_nb = UF_POP();
|
||||
RavaNanboxValue_t map_nb = UF_POP();
|
||||
RavaHashMap_t *map = (RavaHashMap_t*)rava_nanbox_as_object(map_nb);
|
||||
if (map && rava_nanbox_is_string(key_nb)) {
|
||||
RavaValue_t v = rava_hashmap_get(map, rava_nanbox_as_string(key_nb));
|
||||
if (v.type == RAVA_VAL_INT) {
|
||||
UF_PUSH(rava_nanbox_int(v.data.int_val));
|
||||
} else if (v.type == RAVA_VAL_DOUBLE) {
|
||||
UF_PUSH(rava_nanbox_double(v.data.double_val));
|
||||
} else {
|
||||
UF_PUSH(rava_nanbox_null());
|
||||
}
|
||||
} else {
|
||||
UF_PUSH(rava_nanbox_null());
|
||||
}
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_hashmap_remove: {
|
||||
RavaNanboxValue_t key_nb = UF_POP();
|
||||
RavaNanboxValue_t map_nb = UF_POP();
|
||||
RavaHashMap_t *map = (RavaHashMap_t*)rava_nanbox_as_object(map_nb);
|
||||
if (map && rava_nanbox_is_string(key_nb)) {
|
||||
RavaValue_t v = rava_hashmap_remove(map, rava_nanbox_as_string(key_nb));
|
||||
if (v.type == RAVA_VAL_INT) {
|
||||
UF_PUSH(rava_nanbox_int(v.data.int_val));
|
||||
} else {
|
||||
UF_PUSH(rava_nanbox_null());
|
||||
}
|
||||
} else {
|
||||
UF_PUSH(rava_nanbox_null());
|
||||
}
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_hashmap_size: {
|
||||
RavaNanboxValue_t map_nb = UF_POP();
|
||||
RavaHashMap_t *map = (RavaHashMap_t*)rava_nanbox_as_object(map_nb);
|
||||
if (map) {
|
||||
UF_PUSH(rava_nanbox_int((int32_t)rava_hashmap_size(map)));
|
||||
} else {
|
||||
UF_PUSH(rava_nanbox_int(0));
|
||||
}
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_hashmap_containskey: {
|
||||
RavaNanboxValue_t key_nb = UF_POP();
|
||||
RavaNanboxValue_t map_nb = UF_POP();
|
||||
RavaHashMap_t *map = (RavaHashMap_t*)rava_nanbox_as_object(map_nb);
|
||||
if (map && rava_nanbox_is_string(key_nb)) {
|
||||
UF_PUSH(rava_nanbox_int(rava_hashmap_containskey(map, rava_nanbox_as_string(key_nb)) ? 1 : 0));
|
||||
} else {
|
||||
UF_PUSH(rava_nanbox_int(0));
|
||||
}
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_hashmap_clear: {
|
||||
RavaNanboxValue_t map_nb = UF_POP();
|
||||
RavaHashMap_t *map = (RavaHashMap_t*)rava_nanbox_as_object(map_nb);
|
||||
if (map) {
|
||||
rava_hashmap_clear(map);
|
||||
}
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_done:
|
||||
rava_fastframe_reset();
|
||||
return !vm->had_error;
|
||||
|
||||
+65
-1
@@ -17,7 +17,9 @@ typedef enum {
|
||||
RAVA_VAL_NULL,
|
||||
RAVA_VAL_OBJECT,
|
||||
RAVA_VAL_ARRAY,
|
||||
RAVA_VAL_STRING
|
||||
RAVA_VAL_STRING,
|
||||
RAVA_VAL_ARRAYLIST,
|
||||
RAVA_VAL_HASHMAP
|
||||
} RavaValueType_e;
|
||||
|
||||
typedef struct {
|
||||
@@ -28,6 +30,8 @@ typedef struct {
|
||||
|
||||
typedef struct RavaObject_t RavaObject_t;
|
||||
typedef struct RavaValue_t RavaValue_t;
|
||||
typedef struct RavaArrayList_t RavaArrayList_t;
|
||||
typedef struct RavaHashMap_t RavaHashMap_t;
|
||||
|
||||
#define RAVA_OBJECT_HASH_SIZE 32
|
||||
|
||||
@@ -52,9 +56,36 @@ struct RavaValue_t {
|
||||
RavaObject_t *object_val;
|
||||
RavaArray_t *array_val;
|
||||
char *string_val;
|
||||
RavaArrayList_t *arraylist_val;
|
||||
RavaHashMap_t *hashmap_val;
|
||||
} data;
|
||||
};
|
||||
|
||||
#define RAVA_COLLECTION_ARRAYLIST 1
|
||||
#define RAVA_COLLECTION_HASHMAP 2
|
||||
|
||||
struct RavaArrayList_t {
|
||||
int collection_type;
|
||||
RavaValue_t *data;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
};
|
||||
|
||||
#define RAVA_HASHMAP_BUCKET_SIZE 32
|
||||
|
||||
typedef struct {
|
||||
char *key;
|
||||
RavaValue_t value;
|
||||
bool occupied;
|
||||
} RavaHashMapEntry_t;
|
||||
|
||||
struct RavaHashMap_t {
|
||||
int collection_type;
|
||||
RavaHashMapEntry_t *buckets;
|
||||
size_t bucket_count;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
RavaValue_t *values;
|
||||
size_t capacity;
|
||||
@@ -197,6 +228,20 @@ static inline RavaValue_t rava_value_object(RavaObject_t *obj) {
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline RavaValue_t rava_value_arraylist(RavaArrayList_t *list) {
|
||||
RavaValue_t val;
|
||||
val.type = RAVA_VAL_ARRAYLIST;
|
||||
val.data.arraylist_val = list;
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline RavaValue_t rava_value_hashmap(RavaHashMap_t *map) {
|
||||
RavaValue_t val;
|
||||
val.type = RAVA_VAL_HASHMAP;
|
||||
val.data.hashmap_val = map;
|
||||
return val;
|
||||
}
|
||||
|
||||
RavaValue_t rava_value_string(const char *str);
|
||||
|
||||
int32_t rava_value_as_int(RavaValue_t value);
|
||||
@@ -225,6 +270,25 @@ int rava_object_get_field_index(RavaObject_t *obj, const char *name);
|
||||
RavaValue_t rava_object_get_field_by_index(RavaObject_t *obj, int index);
|
||||
void rava_object_set_field_by_index(RavaObject_t *obj, int index, RavaValue_t value);
|
||||
|
||||
RavaArrayList_t* rava_arraylist_create(void);
|
||||
void rava_arraylist_destroy(RavaArrayList_t *list);
|
||||
void rava_arraylist_add(RavaArrayList_t *list, RavaValue_t value);
|
||||
RavaValue_t rava_arraylist_get(RavaArrayList_t *list, size_t index);
|
||||
void rava_arraylist_set(RavaArrayList_t *list, size_t index, RavaValue_t value);
|
||||
size_t rava_arraylist_size(RavaArrayList_t *list);
|
||||
RavaValue_t rava_arraylist_remove(RavaArrayList_t *list, size_t index);
|
||||
void rava_arraylist_clear(RavaArrayList_t *list);
|
||||
bool rava_arraylist_isempty(RavaArrayList_t *list);
|
||||
|
||||
RavaHashMap_t* rava_hashmap_create(void);
|
||||
void rava_hashmap_destroy(RavaHashMap_t *map);
|
||||
void rava_hashmap_put(RavaHashMap_t *map, const char *key, RavaValue_t value);
|
||||
RavaValue_t rava_hashmap_get(RavaHashMap_t *map, const char *key);
|
||||
RavaValue_t rava_hashmap_remove(RavaHashMap_t *map, const char *key);
|
||||
size_t rava_hashmap_size(RavaHashMap_t *map);
|
||||
bool rava_hashmap_containskey(RavaHashMap_t *map, const char *key);
|
||||
void rava_hashmap_clear(RavaHashMap_t *map);
|
||||
|
||||
RavaStack_t* rava_stack_create(size_t capacity);
|
||||
void rava_stack_destroy(RavaStack_t *stack);
|
||||
void rava_stack_push(RavaStack_t *stack, RavaValue_t value);
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#include "runtime.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define ARRAYLIST_INITIAL_CAPACITY 16
|
||||
|
||||
RavaArrayList_t* rava_arraylist_create(void) {
|
||||
RavaArrayList_t *list = calloc(1, sizeof(RavaArrayList_t));
|
||||
list->collection_type = RAVA_COLLECTION_ARRAYLIST;
|
||||
list->data = calloc(ARRAYLIST_INITIAL_CAPACITY, sizeof(RavaValue_t));
|
||||
list->size = 0;
|
||||
list->capacity = ARRAYLIST_INITIAL_CAPACITY;
|
||||
return list;
|
||||
}
|
||||
|
||||
void rava_arraylist_destroy(RavaArrayList_t *list) {
|
||||
if (!list) return;
|
||||
free(list->data);
|
||||
free(list);
|
||||
}
|
||||
|
||||
void rava_arraylist_add(RavaArrayList_t *list, RavaValue_t value) {
|
||||
if (list->size >= list->capacity) {
|
||||
list->capacity *= 2;
|
||||
list->data = realloc(list->data, list->capacity * sizeof(RavaValue_t));
|
||||
}
|
||||
list->data[list->size++] = value;
|
||||
}
|
||||
|
||||
RavaValue_t rava_arraylist_get(RavaArrayList_t *list, size_t index) {
|
||||
if (index >= list->size) {
|
||||
return rava_value_null();
|
||||
}
|
||||
return list->data[index];
|
||||
}
|
||||
|
||||
void rava_arraylist_set(RavaArrayList_t *list, size_t index, RavaValue_t value) {
|
||||
if (index < list->size) {
|
||||
list->data[index] = value;
|
||||
}
|
||||
}
|
||||
|
||||
size_t rava_arraylist_size(RavaArrayList_t *list) {
|
||||
return list->size;
|
||||
}
|
||||
|
||||
RavaValue_t rava_arraylist_remove(RavaArrayList_t *list, size_t index) {
|
||||
if (index >= list->size) {
|
||||
return rava_value_null();
|
||||
}
|
||||
RavaValue_t removed = list->data[index];
|
||||
for (size_t i = index; i < list->size - 1; i++) {
|
||||
list->data[i] = list->data[i + 1];
|
||||
}
|
||||
list->size--;
|
||||
return removed;
|
||||
}
|
||||
|
||||
void rava_arraylist_clear(RavaArrayList_t *list) {
|
||||
list->size = 0;
|
||||
}
|
||||
|
||||
bool rava_arraylist_isempty(RavaArrayList_t *list) {
|
||||
return list->size == 0;
|
||||
}
|
||||
|
||||
static unsigned int _rava_hash_string(const char *str) {
|
||||
unsigned int hash = 5381;
|
||||
int c;
|
||||
while ((c = *str++)) {
|
||||
hash = ((hash << 5) + hash) + c;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
RavaHashMap_t* rava_hashmap_create(void) {
|
||||
RavaHashMap_t *map = calloc(1, sizeof(RavaHashMap_t));
|
||||
map->collection_type = RAVA_COLLECTION_HASHMAP;
|
||||
map->bucket_count = RAVA_HASHMAP_BUCKET_SIZE;
|
||||
map->buckets = calloc(map->bucket_count, sizeof(RavaHashMapEntry_t));
|
||||
map->size = 0;
|
||||
return map;
|
||||
}
|
||||
|
||||
void rava_hashmap_destroy(RavaHashMap_t *map) {
|
||||
if (!map) return;
|
||||
for (size_t i = 0; i < map->bucket_count; i++) {
|
||||
if (map->buckets[i].occupied) {
|
||||
free(map->buckets[i].key);
|
||||
}
|
||||
}
|
||||
free(map->buckets);
|
||||
free(map);
|
||||
}
|
||||
|
||||
static void _rava_hashmap_resize(RavaHashMap_t *map) {
|
||||
size_t old_count = map->bucket_count;
|
||||
RavaHashMapEntry_t *old_buckets = map->buckets;
|
||||
|
||||
map->bucket_count *= 2;
|
||||
map->buckets = calloc(map->bucket_count, sizeof(RavaHashMapEntry_t));
|
||||
map->size = 0;
|
||||
|
||||
for (size_t i = 0; i < old_count; i++) {
|
||||
if (old_buckets[i].occupied) {
|
||||
rava_hashmap_put(map, old_buckets[i].key, old_buckets[i].value);
|
||||
free(old_buckets[i].key);
|
||||
}
|
||||
}
|
||||
free(old_buckets);
|
||||
}
|
||||
|
||||
void rava_hashmap_put(RavaHashMap_t *map, const char *key, RavaValue_t value) {
|
||||
if (map->size >= map->bucket_count * 7 / 10) {
|
||||
_rava_hashmap_resize(map);
|
||||
}
|
||||
|
||||
unsigned int hash = _rava_hash_string(key);
|
||||
size_t index = hash % map->bucket_count;
|
||||
|
||||
while (map->buckets[index].occupied) {
|
||||
if (strcmp(map->buckets[index].key, key) == 0) {
|
||||
map->buckets[index].value = value;
|
||||
return;
|
||||
}
|
||||
index = (index + 1) % map->bucket_count;
|
||||
}
|
||||
|
||||
map->buckets[index].key = strdup(key);
|
||||
map->buckets[index].value = value;
|
||||
map->buckets[index].occupied = true;
|
||||
map->size++;
|
||||
}
|
||||
|
||||
RavaValue_t rava_hashmap_get(RavaHashMap_t *map, const char *key) {
|
||||
unsigned int hash = _rava_hash_string(key);
|
||||
size_t index = hash % map->bucket_count;
|
||||
size_t start = index;
|
||||
|
||||
while (map->buckets[index].occupied) {
|
||||
if (strcmp(map->buckets[index].key, key) == 0) {
|
||||
return map->buckets[index].value;
|
||||
}
|
||||
index = (index + 1) % map->bucket_count;
|
||||
if (index == start) break;
|
||||
}
|
||||
|
||||
return rava_value_null();
|
||||
}
|
||||
|
||||
RavaValue_t rava_hashmap_remove(RavaHashMap_t *map, const char *key) {
|
||||
unsigned int hash = _rava_hash_string(key);
|
||||
size_t index = hash % map->bucket_count;
|
||||
size_t start = index;
|
||||
|
||||
while (map->buckets[index].occupied) {
|
||||
if (strcmp(map->buckets[index].key, key) == 0) {
|
||||
RavaValue_t removed = map->buckets[index].value;
|
||||
free(map->buckets[index].key);
|
||||
map->buckets[index].key = NULL;
|
||||
map->buckets[index].occupied = false;
|
||||
map->size--;
|
||||
return removed;
|
||||
}
|
||||
index = (index + 1) % map->bucket_count;
|
||||
if (index == start) break;
|
||||
}
|
||||
|
||||
return rava_value_null();
|
||||
}
|
||||
|
||||
size_t rava_hashmap_size(RavaHashMap_t *map) {
|
||||
return map->size;
|
||||
}
|
||||
|
||||
bool rava_hashmap_containskey(RavaHashMap_t *map, const char *key) {
|
||||
unsigned int hash = _rava_hash_string(key);
|
||||
size_t index = hash % map->bucket_count;
|
||||
size_t start = index;
|
||||
|
||||
while (map->buckets[index].occupied) {
|
||||
if (strcmp(map->buckets[index].key, key) == 0) {
|
||||
return true;
|
||||
}
|
||||
index = (index + 1) % map->bucket_count;
|
||||
if (index == start) break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void rava_hashmap_clear(RavaHashMap_t *map) {
|
||||
for (size_t i = 0; i < map->bucket_count; i++) {
|
||||
if (map->buckets[i].occupied) {
|
||||
free(map->buckets[i].key);
|
||||
map->buckets[i].key = NULL;
|
||||
map->buckets[i].occupied = false;
|
||||
}
|
||||
}
|
||||
map->size = 0;
|
||||
}
|
||||
Reference in New Issue
Block a user