From 957c64c7b8b5e98d8a03dd84c7e27e7991fb9dbc Mon Sep 17 00:00:00 2001 From: iamcheeseman Date: Mon, 6 Apr 2026 17:04:05 -0400 Subject: Initial commit --- uscript/val.c | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 uscript/val.c (limited to 'uscript/val.c') diff --git a/uscript/val.c b/uscript/val.c new file mode 100644 index 0000000..d713645 --- /dev/null +++ b/uscript/val.c @@ -0,0 +1,204 @@ +#include "val.h" + +#include +#include + +#include "dyn_arr.h" +#include "vm.h" + +#define STR_NUM_FMT "%g" +#define STR_FUNC_FMT "" + +static +void init_obj(struct us_val val, struct us_obj *obj) +{ + (void)obj; // nothing to init yet + da_append(struct us_val, &vm.objs, val); +} + +struct us_str *take_str(char *chars, int len) +{ + if (len < 0) + len = strlen(chars); + struct us_str *str = mem_alloc(sizeof(struct us_str)); + str->chars = chars; + str->len = len; + init_obj(wrap_str(str), &str->header); + return str; +} + +struct us_str *copy_str(const char *chars, int len) +{ + if (len < 0) + len = strlen(chars); + char *copy = mem_alloc(len + 1); + memcpy(copy, chars, len); + copy[len] = '\0'; + return take_str(copy, len); +} + +struct us_proto *create_proto(struct us_str *name) +{ + struct us_proto *proto = mem_alloc(sizeof(struct us_proto)); + proto->name = name; + proto->bytecode = da_create(u8, 0); + proto->upvalc = 0; + proto->argc = 0; + proto->is_variadic = false; + proto->nconstants = 0; + init_obj(wrap_proto(proto), &proto->header); + return proto; +} + +struct us_func *create_func(struct us_proto *proto) +{ + struct us_func *func = mem_alloc(sizeof(struct us_func)); + func->proto = proto; + func->upvals = mem_alloc(sizeof(struct us_upval*) * proto->upvalc); + init_obj(wrap_func(func), &func->header); + return func; +} + +struct us_upval *create_upval(struct us_val *val) +{ + struct us_upval *upval = mem_alloc(sizeof(struct us_upval)); + upval->loc = val; + upval->closed = create_zilch(); + upval->next = NULL; + init_obj(wrap_upval(upval), &upval->header); + return upval; +} + +void free_val(struct us_val v) +{ + switch (v.type) { + case VAL_STR: { + struct us_str *str = get_str(v); + mem_free(str->chars); + mem_free(str); + break; + } + case VAL_PROTO: { + struct us_proto *proto = get_proto(v); + da_free(proto->bytecode); + mem_free(proto->upval_locs); + mem_free(proto); + break; + } + case VAL_FUNC: { + struct us_func *func = get_func(v); + mem_free(func->upvals); + mem_free(func); + break; + } + case VAL_UPVAL: + mem_free(get_obj(v)); + break; + case VAL_NUM: + case VAL_BOOL: + case VAL_ZILCH: + break; + } +} + +void proto_add_const(struct us_proto *proto, struct us_val v) +{ + proto->constants[proto->nconstants] = v; + proto_add_byte(proto, BC_LOAD); + proto_add_byte(proto, proto->nconstants++); +} + +bool vals_eql(struct us_val a, struct us_val b) +{ + if (a.type != b.type) + return false; + + switch (a.type) { + case VAL_NUM: return get_num(a) == get_num(b); + case VAL_BOOL: return get_bool(a) == get_bool(b); + case VAL_ZILCH: return true; + case VAL_STR: { + struct us_str *a_str = get_str(a); + struct us_str *b_str = get_str(b); + return a_str->len == b_str->len && + memcmp(a_str->chars, b_str->chars, a_str->len) == 0; + } + case VAL_FUNC: + case VAL_UPVAL: + case VAL_PROTO: return get_obj(a) == get_obj(b); + } + + // unreachable + return false; +} + +char *val_to_str(struct us_val v, int *len_out) +{ + // TODO: have this function return a us_str so that we own the memory, + // and so concatenation of strings is faster. + + switch (v.type) { + case VAL_NUM: { + int len = snprintf(NULL, 0, STR_NUM_FMT, get_num(v)); + char *str = mem_alloc(sizeof(char) * (len + 1)); + snprintf(str, len + 1, STR_NUM_FMT, get_num(v)); + if (len_out) + *len_out = len; + return str; + } + case VAL_BOOL: { + const char *bool_str = get_bool(v) ? "true" : "false"; + char *str = mem_alloc(strlen(bool_str) + 1); + strcpy(str, bool_str); + if (len_out) + *len_out = strlen(bool_str); + return str; + } + case VAL_ZILCH: { + const char *zilch_str = "zilch"; + char *str = mem_alloc(strlen(zilch_str) + 1); + strcpy(str, zilch_str); + if (len_out) + *len_out = strlen(zilch_str); + return str; + } + case VAL_STR: { + const struct us_str *us_str = get_str(v); + char *str = mem_alloc(sizeof(char) * us_str->len + 1); + strncpy(str, us_str->chars, us_str->len); + str[us_str->len] = 0; + if (len_out) + *len_out = us_str->len; + return str; + } + case VAL_PROTO: { + const struct us_proto *proto = get_proto(v); + int len = snprintf( + NULL, + 0, + STR_FUNC_FMT, + proto->name->chars, + (void*)proto + ); + char *str = mem_alloc(sizeof(char) * (len + 1)); + snprintf( + str, + len + 1, + STR_FUNC_FMT, + proto->name->chars, + (void*)proto + ); + if (len_out) + *len_out = len; + return str; + } + case VAL_FUNC: + return val_to_str(wrap_proto(get_func(v)->proto), len_out); + case VAL_UPVAL: + return val_to_str(*get_upval(v)->loc, len_out); + } + + // unreachable + return NULL; +} + -- cgit v1.3-2-g0d8e