summaryrefslogtreecommitdiffhomepage
path: root/types.h
diff options
context:
space:
mode:
Diffstat (limited to 'types.h')
-rw-r--r--types.h428
1 files changed, 428 insertions, 0 deletions
diff --git a/types.h b/types.h
new file mode 100644
index 0000000..9dab246
--- /dev/null
+++ b/types.h
@@ -0,0 +1,428 @@
+/*
+ * Copyright (C) 2021 Jo-Philipp Wich <jo@mein.io>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __TYPES_H_
+#define __TYPES_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <regex.h>
+#include <json-c/json.h>
+
+#include "util.h"
+
+
+/* Value types and generic value header */
+
+typedef enum uc_type_t {
+ UC_NULL,
+ UC_INTEGER,
+ UC_BOOLEAN,
+ UC_STRING,
+ UC_DOUBLE,
+ UC_ARRAY,
+ UC_OBJECT,
+ UC_REGEXP,
+ UC_FUNCTION,
+ UC_CFUNCTION,
+ UC_CLOSURE,
+ UC_UPVALUE,
+ UC_RESSOURCE
+} uc_type_t;
+
+typedef struct uc_value_t {
+ uint32_t type:4;
+ uint32_t mark:1;
+ uint32_t u64:1;
+ uint32_t refcount:26;
+} uc_value_t;
+
+
+/* Constant list defintions */
+
+typedef struct {
+ size_t isize;
+ size_t dsize;
+ uint64_t *index;
+ char *data;
+} uc_value_list;
+
+
+/* Source buffer defintions */
+
+uc_declare_vector(uc_lineinfo, uint8_t);
+
+typedef struct {
+ char *filename, *buffer;
+ FILE *fp;
+ size_t usecount, off;
+ uc_lineinfo lineinfo;
+} uc_source;
+
+
+/* Bytecode chunk defintions */
+
+typedef struct {
+ size_t from, to, target, slot;
+} uc_ehrange;
+
+typedef struct {
+ size_t from, to, slot, nameidx;
+} uc_varrange;
+
+uc_declare_vector(uc_ehranges, uc_ehrange);
+uc_declare_vector(uc_variables, uc_varrange);
+uc_declare_vector(uc_offsetinfo, uint8_t);
+
+typedef struct {
+ size_t count;
+ uint8_t *entries;
+ uc_value_list constants;
+ uc_ehranges ehranges;
+ struct {
+ uc_variables variables;
+ uc_value_list varnames;
+ uc_offsetinfo offsets;
+ } debuginfo;
+} uc_chunk;
+
+
+/* Value type structures */
+
+typedef struct uc_weakref_t {
+ struct uc_weakref_t *prev;
+ struct uc_weakref_t *next;
+} uc_weakref_t;
+
+typedef struct {
+ uc_value_t header;
+ double dbl;
+} uc_double_t;
+
+typedef struct {
+ uc_value_t header;
+ union {
+ int64_t s64;
+ uint64_t u64;
+ } i;
+} uc_integer_t;
+
+typedef struct {
+ uc_value_t header;
+ size_t length;
+ char str[];
+} uc_string_t;
+
+typedef struct {
+ uc_value_t header;
+ uc_weakref_t ref;
+ size_t count;
+ uc_value_t *proto;
+ uc_value_t **entries;
+} uc_array_t;
+
+typedef struct {
+ uc_value_t header;
+ uc_weakref_t ref;
+ uc_value_t *proto;
+ struct lh_table *table;
+} uc_object_t;
+
+typedef struct {
+ uc_value_t header;
+ regex_t regexp;
+ bool icase, newline, global;
+ char source[];
+} uc_regexp_t;
+
+typedef struct {
+ uc_value_t header;
+ bool arrow, vararg;
+ size_t nargs;
+ size_t nupvals;
+ size_t srcpos;
+ uc_chunk chunk;
+ uc_source *source;
+ char name[];
+} uc_function_t;
+
+typedef struct uc_upvalref_t {
+ uc_value_t header;
+ size_t slot;
+ bool closed;
+ uc_value_t *value;
+ struct uc_upvalref_t *next;
+} uc_upvalref_t;
+
+typedef struct {
+ uc_value_t header;
+ uc_weakref_t ref;
+ bool is_arrow;
+ uc_function_t *function;
+ uc_upvalref_t **upvals;
+} uc_closure_t;
+
+typedef struct uc_vm uc_vm;
+typedef uc_value_t *(*uc_cfn_ptr_t)(uc_vm *, size_t);
+
+typedef struct {
+ uc_value_t header;
+ uc_cfn_ptr_t cfn;
+ char name[];
+} uc_cfunction_t;
+
+typedef struct {
+ uc_value_t header;
+ size_t type;
+ void *data;
+} uc_ressource_t;
+
+typedef struct {
+ const char *name;
+ uc_value_t *proto;
+ void (*free)(void *);
+} uc_ressource_type_t;
+
+uc_declare_vector(uc_ressource_types_t, uc_ressource_type_t);
+
+
+/* Parser definitions */
+
+typedef struct {
+ bool lstrip_blocks;
+ bool trim_blocks;
+ bool strict_declarations;
+} uc_parse_config;
+
+
+/* VM definitions */
+
+typedef enum {
+ EXCEPTION_NONE,
+ EXCEPTION_SYNTAX,
+ EXCEPTION_RUNTIME,
+ EXCEPTION_TYPE,
+ EXCEPTION_REFERENCE,
+ EXCEPTION_USER
+} uc_exception_type_t;
+
+typedef struct {
+ uc_exception_type_t type;
+ uc_value_t *stacktrace;
+ char *message;
+} uc_exception;
+
+typedef struct {
+ uint8_t *ip;
+ uc_closure_t *closure;
+ uc_cfunction_t *cfunction;
+ size_t stackframe;
+ uc_value_t *ctx;
+ bool mcall;
+} uc_callframe;
+
+uc_declare_vector(uc_callframes, uc_callframe);
+uc_declare_vector(uc_stack, uc_value_t *);
+
+struct uc_vm {
+ uc_stack stack;
+ uc_exception exception;
+ uc_callframes callframes;
+ uc_upvalref_t *open_upvals;
+ uc_parse_config *config;
+ uc_value_t *globals;
+ uc_source *sources;
+ uc_weakref_t values;
+ union {
+ uint32_t u32;
+ int32_t s32;
+ uint16_t u16;
+ int16_t s16;
+ uint8_t u8;
+ int8_t s8;
+ } arg;
+ size_t spread_values;
+ uint8_t trace;
+};
+
+
+/* Value API */
+
+typedef struct printbuf uc_stringbuf_t;
+
+void ucv_free(uc_value_t *, bool);
+void ucv_put(uc_value_t *);
+
+uc_value_t *ucv_get(uc_value_t *uv);
+
+uc_type_t ucv_type(uc_value_t *);
+const char *ucv_typename(uc_value_t *);
+
+uc_value_t *ucv_boolean_new(bool);
+bool ucv_boolean_get(uc_value_t *);
+
+uc_value_t *ucv_string_new(const char *);
+uc_value_t *ucv_string_new_length(const char *, size_t);
+size_t ucv_string_length(uc_value_t *);
+
+char *_ucv_string_get(uc_value_t **);
+#define ucv_string_get(uv) _ucv_string_get((uc_value_t **)&uv)
+
+uc_stringbuf_t *ucv_stringbuf_new(void);
+uc_value_t *ucv_stringbuf_finish(uc_stringbuf_t *);
+
+void _ucv_stringbuf_append(uc_stringbuf_t *, const char *, size_t);
+
+#define _ucv_is_literal(str) ("" str)
+#define ucv_stringbuf_append(buf, str) _ucv_stringbuf_append(buf, _ucv_is_literal(str), sizeof(str) - 1)
+#define ucv_stringbuf_addstr(buf, str, len) _ucv_stringbuf_append(buf, str, len)
+#define ucv_stringbuf_printf(buf, fmt, ...) sprintbuf(buf, fmt, __VA_ARGS__)
+
+uc_value_t *ucv_int64_new(int64_t);
+uc_value_t *ucv_uint64_new(uint64_t);
+int64_t ucv_int64_get(uc_value_t *);
+uint64_t ucv_uint64_get(uc_value_t *);
+
+uc_value_t *ucv_double_new(double);
+double ucv_double_get(uc_value_t *);
+
+uc_value_t *ucv_array_new(uc_vm *);
+uc_value_t *ucv_array_new_length(uc_vm *, size_t);
+uc_value_t *ucv_array_get(uc_value_t *, size_t);
+uc_value_t *ucv_array_pop(uc_value_t *);
+uc_value_t *ucv_array_push(uc_value_t *, uc_value_t *);
+uc_value_t *ucv_array_shift(uc_value_t *);
+uc_value_t *ucv_array_unshift(uc_value_t *, uc_value_t *);
+void ucv_array_sort(uc_value_t *, int (*)(const void *, const void *));
+bool ucv_array_delete(uc_value_t *, size_t, size_t);
+bool ucv_array_set(uc_value_t *, size_t, uc_value_t *);
+size_t ucv_array_length(uc_value_t *);
+
+uc_value_t *ucv_object_new(uc_vm *);
+uc_value_t *ucv_object_get(uc_value_t *, const char *, bool *);
+bool ucv_object_add(uc_value_t *, const char *, uc_value_t *);
+bool ucv_object_delete(uc_value_t *, const char *);
+size_t ucv_object_length(uc_value_t *);
+
+#define ucv_object_foreach(obj, key, val) \
+ char *key = NULL; \
+ uc_value_t *val = NULL; \
+ struct lh_entry *entry##key; \
+ struct lh_entry *entry_next##key = NULL; \
+ for (entry##key = (ucv_type(obj) == UC_OBJECT) ? ((uc_object_t *)obj)->table->head : NULL; \
+ (entry##key ? (key = (char *)lh_entry_k(entry##key), \
+ val = (uc_value_t *)lh_entry_v(entry##key), \
+ entry_next##key = entry##key->next, entry##key) \
+ : 0); \
+ entry##key = entry_next##key)
+
+uc_value_t *ucv_function_new(const char *, size_t, uc_source *);
+size_t ucv_function_srcpos(uc_value_t *, size_t);
+
+uc_value_t *ucv_cfunction_new(const char *, uc_cfn_ptr_t);
+
+uc_value_t *ucv_closure_new(uc_vm *, uc_function_t *, bool);
+
+uc_ressource_type_t *ucv_ressource_type_add(const char *, uc_value_t *, void (*)(void *));
+uc_ressource_type_t *ucv_ressource_type_lookup(const char *);
+
+uc_value_t *ucv_ressource_new(uc_ressource_type_t *, void *);
+void **ucv_ressource_dataptr(uc_value_t *, const char *);
+
+uc_value_t *ucv_regexp_new(const char *, bool, bool, bool, char **);
+
+uc_value_t *ucv_upvalref_new(size_t);
+
+uc_value_t *ucv_prototype_get(uc_value_t *);
+bool ucv_prototype_set(uc_value_t *, uc_value_t *);
+
+uc_value_t *ucv_property_get(uc_value_t *, const char *);
+
+uc_value_t *ucv_from_json(uc_vm *, json_object *);
+json_object *ucv_to_json(uc_value_t *);
+
+char *ucv_to_string(uc_vm *, uc_value_t *);
+char *ucv_to_jsonstring(uc_vm *, uc_value_t *);
+void ucv_to_stringbuf(uc_vm *, uc_stringbuf_t *, uc_value_t *, bool);
+
+static inline bool
+ucv_is_callable(uc_value_t *uv)
+{
+ switch (ucv_type(uv)) {
+ case UC_CLOSURE:
+ case UC_CFUNCTION:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+static inline bool
+ucv_is_arrowfn(uc_value_t *uv)
+{
+ uc_closure_t *closure = (uc_closure_t *)uv;
+
+ return (ucv_type(uv) == UC_CLOSURE && closure->is_arrow);
+}
+
+static inline bool
+ucv_is_u64(uc_value_t *uv)
+{
+ return (((uintptr_t)uv & 3) == 0 && uv != NULL && uv->u64 == true);
+}
+
+static inline bool
+ucv_is_scalar(uc_value_t *uv)
+{
+ switch (ucv_type(uv)) {
+ case UC_NULL:
+ case UC_BOOLEAN:
+ case UC_DOUBLE:
+ case UC_INTEGER:
+ case UC_STRING:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+static inline bool
+ucv_is_marked(uc_value_t *uv)
+{
+ return (((uintptr_t)uv & 3) == 0 && uv != NULL && uv->mark == true);
+}
+
+static inline void
+ucv_set_mark(uc_value_t *uv)
+{
+ if (((uintptr_t)uv & 3) == 0 && uv != NULL)
+ uv->mark = true;
+}
+
+static inline void
+ucv_clear_mark(uc_value_t *uv)
+{
+ if (((uintptr_t)uv & 3) == 0 && uv != NULL)
+ uv->mark = false;
+}
+
+bool ucv_equal(uc_value_t *, uc_value_t *);
+
+void ucv_gc(uc_vm *, bool);
+
+#endif /* __TYPES_H_ */