From 35af4ba4fc21a4b2357c50e6b02a2e3e4b236e88 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Wed, 21 Apr 2021 15:07:16 +0200 Subject: treewide: rework internal data type system Instead of relying on json_object values internally, use custom types to represent the different ucode value types which brings a number of advantages compared to the previous approach: - Due to the use of tagged pointers, small integer, string and bool values can be stored directly in the pointer addresses, vastly reducing required heap memory - Ability to create circular data structures such as `let o; o = { test: o };` - Ability to register custom `tostring()` function through prototypes - Initial mark/sweep GC implementation to tear down circular object graphs on VM deinit The change also paves the way for possible future extensions such as constant variables and meta methods for custom ressource types. Signed-off-by: Jo-Philipp Wich --- lib.h | 151 ++++++++++++++++-------------------------------------------------- 1 file changed, 36 insertions(+), 115 deletions(-) (limited to 'lib.h') diff --git a/lib.h b/lib.h index c14d11d..aad9a9d 100644 --- a/lib.h +++ b/lib.h @@ -19,185 +19,106 @@ #include "vm.h" #include "lexer.h" -#include "object.h" typedef struct { const char *name; - uc_cfn_ptr func; + uc_cfn_ptr_t func; } uc_cfunction_list; -typedef struct { - /* value operations */ - struct { - uc_prototype *(*proto)(uc_prototype *); - uc_cfunction *(*cfunc)(const char *, uc_cfn_ptr); - json_object *(*dbl)(double); - uc_regexp *(*regexp)(const char *, bool, bool, bool, char **); - uc_ressource *(*ressource)(json_object *, uc_ressource_type *, void *); - enum json_type (*tonumber)(json_object *, int64_t *, double *); - } value; - - /* ressource operations */ - struct { - uc_ressource_type *(*define)(const char *, uc_prototype *, void (*)(void *)); - uc_ressource *(*create)(json_object *, uc_ressource_type *, void *); - void **(*data)(json_object *, const char *); - uc_prototype *(*proto)(json_object *); - } ressource; - - /* VM operations */ - struct { - uc_exception_type_t (*call)(uc_vm *, bool, size_t); - json_object *(*peek)(uc_vm *, size_t); - json_object *(*pop)(uc_vm *); - void (*push)(uc_vm *, json_object *); - void (*raise)(uc_vm *, uc_exception_type_t, const char *, ...); - } vm; -} uc_ops; - -extern const uc_ops uc; - -void uc_lib_init(uc_prototype *scope); - -void format_source_context(char **msg, size_t *msglen, uc_source *src, size_t off, bool compact); -void format_error_context(char **msg, size_t *msglen, uc_source *src, json_object *stacktrace, size_t off); +void uc_lib_init(uc_value_t *scope); + +bool format_source_context(uc_stringbuf_t *buf, uc_source *src, size_t off, bool compact); +bool format_error_context(uc_stringbuf_t *buf, uc_source *src, uc_value_t *stacktrace, size_t off); /* vm helper */ static inline void * -_uc_get_self(const uc_ops *ops, uc_vm *vm, const char *expected_type) +_uc_get_self(uc_vm *vm, const char *expected_type) { - return ops->ressource.data(vm->callframes.entries[vm->callframes.count - 1].ctx, expected_type); + return ucv_ressource_dataptr(vm->callframes.entries[vm->callframes.count - 1].ctx, expected_type); } -#define uc_get_self(...) _uc_get_self(ops, vm, __VA_ARGS__) +#define uc_get_self(...) _uc_get_self(vm, __VA_ARGS__) -static inline json_object * -_uc_get_arg(const uc_ops *ops, uc_vm *vm, size_t nargs, size_t n) +static inline uc_value_t * +_uc_get_arg(uc_vm *vm, size_t nargs, size_t n) { if (n >= nargs) return NULL; - return ops->vm.peek(vm, nargs - n - 1); + return uc_vm_stack_peek(vm, nargs - n - 1); } -#define uc_get_arg(...) _uc_get_arg(ops, vm, nargs, __VA_ARGS__) +#define uc_get_arg(...) _uc_get_arg(vm, nargs, __VA_ARGS__) -#define uc_call(nargs) ops->vm.call(vm, false, nargs) -#define uc_push_val(val) ops->vm.push(vm, val) -#define uc_pop_val() ops->vm.pop(vm) +#define uc_call(nargs) uc_vm_call(vm, false, nargs) +#define uc_push_val(val) uc_vm_stack_push(vm, val) +#define uc_pop_val() uc_vm_stack_pop(vm) /* value helper */ -static inline json_object * -_uc_alloc_proto(const uc_ops *ops, uc_prototype *parent) -{ - return ops->value.proto(parent)->header.jso; -} - -static inline json_object * -_uc_alloc_cfunc(const uc_ops *ops, const char *name, uc_cfn_ptr fptr) -{ - return ops->value.cfunc(name, fptr)->header.jso; -} - -static inline json_object * -_uc_alloc_double(const uc_ops *ops, double dbl) -{ - return ops->value.dbl(dbl); -} - -static inline json_object * -_uc_alloc_regexp(const uc_ops *ops, const char *pattern, bool global, bool icase, bool newline, char **errp) +static inline uc_value_t * +uc_alloc_ressource(uc_ressource_type_t *type, void *data) { - uc_regexp *re = ops->value.regexp(pattern, global, icase, newline, errp); - - return re ? re->header.jso : NULL; -} - -static inline json_object * -_uc_alloc_ressource(const uc_ops *ops, uc_ressource_type *type, void *data) -{ - uc_ressource *res = ops->value.ressource(xjs_new_object(), type, data); - - return res ? res->header.jso : NULL; + return ucv_ressource_new(type, data); } -#define uc_alloc_proto(...) _uc_alloc_proto(ops, __VA_ARGS__) -#define uc_alloc_cfunc(...) _uc_alloc_cfunc(ops, __VA_ARGS__) -#define uc_alloc_double(...) _uc_alloc_double(ops, __VA_ARGS__) -#define uc_alloc_regexp(...) _uc_alloc_regexp(ops, __VA_ARGS__) -#define uc_alloc_ressource(...) _uc_alloc_ressource(ops, __VA_ARGS__) - -static inline json_type -_uc_to_number(const uc_ops *ops, json_object *v, int64_t *n, double *d) +static inline uc_type_t +uc_to_number(uc_value_t *v, int64_t *n, double *d) { - return ops->value.tonumber(v, n, d); + return uc_cast_number(v, n, d); } static inline double -_uc_to_double(const uc_ops *ops, json_object *v) +uc_to_double(uc_value_t *v) { int64_t n; double d; - return (ops->value.tonumber(v, &n, &d) == json_type_double) ? d : (double)n; + return (uc_cast_number(v, &n, &d) == UC_DOUBLE) ? d : (double)n; } static inline int64_t -_uc_to_int64(const uc_ops *ops, json_object *v) +uc_to_int64(uc_value_t *v) { int64_t n; double d; - return (ops->value.tonumber(v, &n, &d) == json_type_double) ? (int64_t)d : n; + return (uc_cast_number(v, &n, &d) == UC_DOUBLE) ? (int64_t)d : n; } -#define uc_to_number(...) _uc_to_number(ops, __VA_ARGS__) -#define uc_to_double(...) _uc_to_double(ops, __VA_ARGS__) -#define uc_to_int64(...) _uc_to_int64(ops, __VA_ARGS__) - /* ressource type helper */ -static inline uc_ressource_type * -_uc_declare_type(const uc_ops *ops, const char *name, const uc_cfunction_list *list, size_t len, void (*freefn)(void *)) +static inline uc_ressource_type_t * +_uc_declare_type(const char *name, const uc_cfunction_list *list, size_t len, void (*freefn)(void *)) { - uc_prototype *proto = ops->value.proto(NULL); + uc_value_t *proto = ucv_object_new(NULL); while (len-- > 0) - json_object_object_add(proto->header.jso, list[len].name, - _uc_alloc_cfunc(ops, list[len].name, list[len].func)); + ucv_object_add(proto, list[len].name, + ucv_cfunction_new(list[len].name, list[len].func)); - return ops->ressource.define(name, proto, freefn); + return ucv_ressource_type_add(name, proto, freefn); } #define uc_declare_type(name, functions, freefn) \ - _uc_declare_type(ops, name, functions, ARRAY_SIZE(functions), freefn) + _uc_declare_type(name, functions, ARRAY_SIZE(functions), freefn) /* prototype helper */ -static inline bool -uc_add_proto_val(uc_prototype *proto, const char *key, json_object *value) -{ - if (!proto) - return false; - - return json_object_object_add(proto->header.jso, key, value); -} - static inline void -_uc_add_proto_functions(const uc_ops *ops, uc_prototype *proto, const uc_cfunction_list *list, size_t len) +_uc_add_proto_functions(uc_value_t *proto, const uc_cfunction_list *list, size_t len) { while (len-- > 0) - json_object_object_add(proto->header.jso, list[len].name, - _uc_alloc_cfunc(ops, list[len].name, list[len].func)); + ucv_object_add(proto, list[len].name, + ucv_cfunction_new(list[len].name, list[len].func)); } #define uc_add_proto_functions(proto, functions) \ - _uc_add_proto_functions(ops, proto, functions, ARRAY_SIZE(functions)) + _uc_add_proto_functions(proto, functions, ARRAY_SIZE(functions)) #endif /* __LIB_H_ */ -- cgit v1.2.3