#ifndef __USCRIPT_VAL_H__ #define __USCRIPT_VAL_H__ #include "common.h" #define get_num(v) (v.dat.number) #define get_bool(v) (v.dat.boolean) #define get_obj(v) (v.dat.obj) #define get_str(v) (v.dat.str) #define get_proto(v) (v.dat.proto) #define get_func(v) (v.dat.func) #define get_upval(v) (v.dat.upval) #define create_num(n) ((struct us_val){.type=VAL_NUM, .dat={.number=(n)}}) #define create_bool(b) ((struct us_val){.type=VAL_BOOL, .dat={.boolean=(b)}}) #define create_zilch() ((struct us_val){.type=VAL_ZILCH, .dat={.number=0}}) #define wrap_str(o) ((struct us_val){.type=VAL_STR, .dat={.str=(o)}}) #define wrap_proto(o) ((struct us_val){.type=VAL_PROTO, .dat={.proto=(o)}}) #define wrap_func(o) ((struct us_val){.type=VAL_FUNC, .dat={.func=(o)}}) #define wrap_upval(o) ((struct us_val){.type=VAL_UPVAL, .dat={.upval=(o)}}) #define val_is_obj(v) (v.type >= VAL_STR) #define proto_add_byte(func, op) da_append(u8, &(func)->bytecode, op) enum val_type { VAL_NUM, VAL_BOOL, VAL_ZILCH, // Do not place any new object types before VAL_STR. Object types are // detected by doing a comparison with VAL_STR. See val_is_obj(). VAL_STR, VAL_PROTO, VAL_FUNC, VAL_UPVAL, }; struct us_val { enum val_type type; union { double number; bool boolean; struct us_obj *obj; struct us_str *str; struct us_proto *proto; struct us_func *func; struct us_upval *upval; } dat; }; struct us_obj { // We don't need the object header for now; it will be useful in the // future, though. u8 _placeholder; }; struct us_str { struct us_obj header; char *chars; size_t len; }; struct us_proto { struct us_obj header; const struct us_str *name; struct us_val constants[UINT8_MAX]; u8 *bytecode; // dyn_arr int* upval_locs; int upvalc; int argc; bool is_variadic; u8 nconstants; }; struct us_func { struct us_obj header; struct us_proto *proto; struct us_upval **upvals; }; struct us_upval { struct us_obj header; struct us_val *loc; struct us_val closed; struct us_upval *next; }; struct us_str *take_str(char *chars, int len); struct us_str *copy_str(const char *chars, int len); struct us_proto *create_proto(struct us_str *name); struct us_func *create_func(struct us_proto *proto); struct us_upval *create_upval(struct us_val *val); void free_val(struct us_val v); void proto_add_const(struct us_proto *func, struct us_val v); bool vals_eql(struct us_val a, struct us_val b); char *val_to_str(struct us_val v, int *len_out); #endif // __USCRIPT_VAL_H__