diff options
author | ubq323 <ubq323@ubq323.website> | 2024-06-26 19:27:42 +0100 |
---|---|---|
committer | ubq323 <ubq323@ubq323.website> | 2024-06-26 19:27:42 +0100 |
commit | 2e62b41072738142dea9f0b5dd5d2d22455c7616 (patch) | |
tree | f47ce547de39fb69b02eb70990c9485489f1e574 | |
parent | 6deeb9630d4b4e7d672ab851dcd4fe3d0d3d2865 (diff) |
add arrays, appending, getting length, indexing
-rw-r--r-- | lib.c | 24 | ||||
-rw-r--r-- | tests/arr1.bth | 9 | ||||
-rw-r--r-- | tests/arr1.out | 5 | ||||
-rw-r--r-- | tests/nilcall.bth | 1 | ||||
-rw-r--r-- | tests/nilcall.out | 1 | ||||
-rw-r--r-- | util.h | 2 | ||||
-rw-r--r-- | val.c | 54 | ||||
-rw-r--r-- | val.h | 27 | ||||
-rw-r--r-- | vm.c | 12 |
9 files changed, 125 insertions, 10 deletions
@@ -21,6 +21,26 @@ static Val fn_say(State *S, int nargs, Val *args) { } +// lists +static Val fn_arr(State *S, int nargs, Val *args) { + CHECK(nargs == 0, "need 0 args to arr"); + ObjArr *o = objarr_new(S); + return VAL_OBJ(o); +} +static Val fn_append(State *S, int nargs, Val *args) { + CHECK(nargs == 2, "need 2 args to append"); + CHECK(IS_ARR(args[0]), "can only append to arr"); + ObjArr *a = AS_ARR(args[0]); + objarr_append(S, a, args[1]); + return args[0]; +} +static Val fn_len(State *S, int nargs, Val *args) { + CHECK(nargs == 1, "need 1 arg to len"); + CHECK(IS_ARR(args[0]), "can only take length of arr"); + ObjArr *a = AS_ARR(args[0]); + return VAL_NUM(a->len); +} + typedef struct { @@ -31,6 +51,10 @@ static BuiltinFunc builtin_funcs[] = { { "clock", fn_clock }, { "say", fn_say }, { "write", fn_write }, + + { "arr", fn_arr }, + { "append", fn_append }, + { "len", fn_len }, { 0 }, }; diff --git a/tests/arr1.bth b/tests/arr1.bth new file mode 100644 index 0000000..0d06759 --- /dev/null +++ b/tests/arr1.bth @@ -0,0 +1,9 @@ +(set A (arr)) +(say A) +(say (len A)) +(append A 10) +(append A 20) +(append A 30) +(say A) +(say (len A)) +(say (A 1)) diff --git a/tests/arr1.out b/tests/arr1.out new file mode 100644 index 0000000..3e5e246 --- /dev/null +++ b/tests/arr1.out @@ -0,0 +1,5 @@ +[ ] +0 +[ 10 20 30 ] +3 +20 diff --git a/tests/nilcall.bth b/tests/nilcall.bth new file mode 100644 index 0000000..27ff7a2 --- /dev/null +++ b/tests/nilcall.bth @@ -0,0 +1 @@ +(nil 4) diff --git a/tests/nilcall.out b/tests/nilcall.out new file mode 100644 index 0000000..ba2231b --- /dev/null +++ b/tests/nilcall.out @@ -0,0 +1 @@ +cannot call nil @@ -3,7 +3,7 @@ #include <stdio.h> -#define CHECK(cond, ...) do { if (!(cond)) { fprintf(stderr, __VA_ARGS__); exit(1); } } while(0) +#define CHECK(cond, ...) do { if (!(cond)) { fprintf(stderr, __VA_ARGS__); putchar('\n'); exit(1); } } while(0) #define ERROR(...) CHECK(false, __VA_ARGS__) @@ -3,6 +3,7 @@ #include "val.h" #include "mem.h" #include "ht.h" +#include "util.h" static ObjString *objstring_create(State*, char*, size_t, uint32_t); @@ -55,7 +56,40 @@ ObjFunc *objfunc_new(State *S, uint8_t arity) { } -void print_val(Val v) { +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; + } +} + +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"); @@ -72,12 +106,25 @@ void print_val(Val v) { printf("%s", AS_CSTRING(v)); break; case OTY_FUNC: - printf("[function Function]"); + printf("<func>"); + break; + case OTY_ARR:; + ObjArr *a = AS_ARR(v); + if (depth <= 0) + printf("<arr>"); + else { + printf("[ "); + for (int i = 0; i < a->len; i++) { + print_val_h(a->d[i], depth-1); + printf(" "); + } + printf("]"); + } break; } break; case TY_CFUNC: - printf("[cfunc]"); + printf("<cfunc>"); break; } } @@ -116,6 +163,7 @@ const char *typename_str(Val v) { 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"; @@ -41,6 +41,7 @@ bool val_equal(Val a, Val b); typedef enum { OTY_STRING, OTY_FUNC, + OTY_ARR, } ObjTy; typedef struct _obj { @@ -53,13 +54,8 @@ typedef struct { uint32_t hash; char *d; } ObjString; -#include "chunk.h" -typedef struct { - Obj obj; - Chunk ch; - uint8_t arity; -} ObjFunc; +#include "chunk.h" // Constructs a new objstring from the given C string, // creating its own fresh copy of the data. @@ -69,8 +65,25 @@ ObjString *objstring_copy_cstr(State *s, char *str); // taking ownership of the provided data. ObjString *objstring_take(State *S, char *src, size_t len); +typedef struct { + Obj obj; + Chunk ch; + uint8_t arity; +} ObjFunc; ObjFunc *objfunc_new(State *S, uint8_t arity); +typedef struct { + Obj obj; + size_t len; + size_t cap; + Val *d; +} ObjArr; + +ObjArr *objarr_new(State *S); +Val objarr_get(State *S, ObjArr *arr, size_t ix); +void objarr_append(State *S, ObjArr *arr, Val v); +void objarr_put(State *S, ObjArr *arr, size_t ix, Val v); + #define IS_NIL(x) (x.ty == TY_NIL) #define IS_NUM(x) (x.ty == TY_NUM) #define IS_BOOL(x) (x.ty == TY_BOOL) @@ -79,6 +92,7 @@ ObjFunc *objfunc_new(State *S, uint8_t arity); #define IS_STRING(x) (is_obj_ty((x), OTY_STRING)) #define IS_FUNC(x) (is_obj_ty((x), OTY_FUNC)) +#define IS_ARR(x) (is_obj_ty((x), OTY_ARR)) #define AS_NUM(x) (x.as.d) #define AS_BOOL(x) (x.as.b) @@ -88,6 +102,7 @@ ObjFunc *objfunc_new(State *S, uint8_t arity); #define AS_STRING(x) ((ObjString*)AS_OBJ(x)) #define AS_CSTRING(x) (AS_STRING(x)->d) #define AS_FUNC(x) ((ObjFunc*)AS_OBJ(x)) +#define AS_ARR(x) ((ObjArr*)AS_OBJ(x)) #define VAL_NIL ((Val){.ty=TY_NIL}) #define VAL_NUM(x) ((Val){.ty=TY_NUM, .as.d=(x) }) @@ -10,6 +10,7 @@ #include "mem.h" #include "dis.h" #include "com.h" +#include "util.h" @@ -196,6 +197,17 @@ int runvm(State *S) { Val res = AS_CFUNC(callee)(S, len - 1, firstarg); th->sp -= len; PUSH(res); + } else if (IS_ARR(callee)) { + ObjArr *arr = AS_ARR(callee); + CHECK(len == 2, "can only index arr with single argument"); + Val vix = PEEK(); + CHECK(IS_NUM(vix), "can only index numerically"); + size_t ix = (size_t)AS_NUM(vix); + Val res = objarr_get(S, arr, ix); + th->sp -= 2; + PUSH(res); + } else { + ERROR("cannot call %s",typename_str(callee)); } break; } |