#include #include #include "val.h" #include "mem.h" #include "ht.h" #include "util.h" static ObjString *objstring_create(State*, char*, size_t, uint32_t); ObjString *objstring_copy(State *S, char *src, size_t len) { uint32_t hash = hash_string(src, len); ObjString *interned = ht_findstring(S, &S->strings, src, len, hash); if (interned != NULL) return interned; char *d = NEW_ARR(S, char, 1+len); memcpy(d, src, len); d[len] = '\0'; return objstring_create(S, d, len, hash); } ObjString *objstring_copy_cstr(State *S, char *str) { size_t len = strlen(str); return objstring_copy(S, str, len); } ObjString *objstring_take(State *S, char *src, size_t len) { uint32_t hash = hash_string(src, len); ObjString *interned = ht_findstring(S, &S->strings, src, len, hash); if (interned != NULL) { FREE_ARR(S, src, char, len+1); return interned; }; return objstring_create(S, src, len, hash); } static ObjString *objstring_create(State *S, char *src, size_t len, uint32_t hash) { // assumes already deduplicated // and data is already owned ObjString *o = NEW_OBJ(S, ObjString, OTY_STRING); o->len = len; o->d = src; o->hash = hash; ht_put(S, &S->strings, o, VAL_TRUE); return o; } ObjFunc *objfunc_new(State *S, uint8_t arity) { ObjFunc *o = NEW_OBJ(S, ObjFunc, OTY_FUNC); o->ch = chunk_new(S); o->arity = arity; return o; } ObjArr *objarr_new(State *S) { ObjArr *o = NEW_OBJ(S, ObjArr, OTY_ARR); o->len = 0; o->cap = 0; o->d = NULL; return o; } Val objarr_get(State *S, ObjArr *arr, size_t ix) { CHECK(ix < arr->len, "array index out of bounds"); return arr->d[ix]; } void objarr_append(State *S, ObjArr *arr, Val v) { if (arr->len == arr->cap) { size_t newsz = (arr->cap == 0 ? 8 : arr->cap * 2); arr->d = RENEW_ARR(S, arr->d, Val, arr->cap, newsz); arr->cap = newsz; } arr->d[arr->len++] = v; } void objarr_put(State *S, ObjArr *arr, size_t ix, Val v) { CHECK(ix <= arr->len, "array index out of bounds"); if (ix == arr->len) { objarr_append(S, arr, v); } else { arr->d[ix] = v; } } void objarr_insert(State *S, ObjArr *arr, size_t ix, Val v) { CHECK(ix <= arr->len, "array index out of bounds"); if (ix == arr->len) { objarr_append(S, arr, v); } else { if (arr->len == arr->cap) { size_t newsz = (arr->cap == 0 ? 8 : arr->cap * 2); arr->d = RENEW_ARR(S, arr->d, Val, arr->cap, newsz); arr->cap = newsz; } memmove(&arr->d[ix+1], &arr->d[ix], (arr->len-ix)*sizeof(Val)); arr->d[ix] = v; } } static void print_val_h(Val v, int depth); void print_val(Val v) { print_val_h(v, 8); } static void print_val_h(Val v, int depth) { switch (v.ty) { case TY_NIL: printf("nil"); break; case TY_NUM: printf("%g",AS_NUM(v)); break; case TY_BOOL: printf("%s",AS_BOOL(v) ? "true" : "false"); break; case TY_OBJ: switch (AS_OBJ(v)->oty) { case OTY_STRING: printf("%s", AS_CSTRING(v)); break; case OTY_FUNC: printf(""); break; case OTY_ARR:; ObjArr *a = AS_ARR(v); if (depth <= 0) printf(""); else { printf("["); for (int i = 0; i < a->len ; i++) { print_val_h(a->d[i], depth-1); if (i < a->len - 1) printf(" "); } printf("]"); } break; } break; case TY_CFUNC: printf(""); break; } } void println_val(Val v) { print_val(v); putchar('\n'); } bool is_truthy(Val v) { if (IS_BOOL(v)) return AS_BOOL(v); if (IS_NIL(v)) return false; return true; } bool val_equal(Val a, Val b) { if (a.ty != b.ty) return false; switch (a.ty) { case TY_NIL: return true; case TY_NUM: return AS_NUM(a) == AS_NUM(b); case TY_BOOL: return AS_BOOL(a) == AS_BOOL(b); case TY_OBJ: return AS_OBJ(a) == AS_OBJ(b); case TY_CFUNC: return AS_CFUNC(a) == AS_CFUNC(b); default: return false; } } const char *typename_str(Val v) { switch(v.ty) { case TY_NIL: return "nil"; case TY_NUM: return "num"; case TY_BOOL: return "bool"; case TY_OBJ: switch (AS_OBJ(v)->oty) { case OTY_STRING: return "String"; case OTY_FUNC: return "Func"; case OTY_ARR: return "Arr"; } break; case TY_CFUNC: return "cfunc"; } return "???"; } int val_type(Val v) { if (IS_OBJ(v)) return AS_OBJ(v)->oty; else return v.ty; }