From 065c4cfac1208444f94f5769377f78b0ce42d429 Mon Sep 17 00:00:00 2001 From: bakpakin Date: Sat, 20 Jan 2018 11:04:30 -0500 Subject: [PATCH] Gitignore was ignore files. --- .gitignore | 3 +- src/include/dst/dst.h | 204 +++++++++++++++++ src/include/dst/dstasm.h | 47 ++++ src/include/dst/dstcompile.h | 77 +++++++ src/include/dst/dstconfig.h | 131 +++++++++++ src/include/dst/dstopcodes.h | 90 ++++++++ src/include/dst/dstparse.h | 79 +++++++ src/include/dst/dststate.h | 55 +++++ src/include/dst/dststl.h | 62 +++++ src/include/dst/dsttypes.h | 422 +++++++++++++++++++++++++++++++++++ 10 files changed, 1169 insertions(+), 1 deletion(-) create mode 100644 src/include/dst/dst.h create mode 100644 src/include/dst/dstasm.h create mode 100644 src/include/dst/dstcompile.h create mode 100644 src/include/dst/dstconfig.h create mode 100644 src/include/dst/dstopcodes.h create mode 100644 src/include/dst/dstparse.h create mode 100644 src/include/dst/dststate.h create mode 100644 src/include/dst/dststl.h create mode 100644 src/include/dst/dsttypes.h diff --git a/.gitignore b/.gitignore index 61f5c4f4..88bce3bd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # Target dst -build +!*/**/dst +/build # Generated files *.gen.h diff --git a/src/include/dst/dst.h b/src/include/dst/dst.h new file mode 100644 index 00000000..096b12f9 --- /dev/null +++ b/src/include/dst/dst.h @@ -0,0 +1,204 @@ +/* +* Copyright (c) 2017 Calvin Rose +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to +* deal in the Software without restriction, including without limitation the +* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +* sell copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +* IN THE SOFTWARE. +*/ + +#ifndef DST_H_defined +#define DST_H_defined + +#include +#include +#include +#include + +#include "dstconfig.h" +#include "dsttypes.h" +#include "dststate.h" + +/* Array functions */ +DstArray *dst_array(int32_t capacity); +DstArray *dst_array_init(DstArray *array, int32_t capacity); +void dst_array_deinit(DstArray *array); +void dst_array_ensure(DstArray *array, int32_t capacity); +void dst_array_setcount(DstArray *array, int32_t count); +void dst_array_push(DstArray *array, Dst x); +Dst dst_array_pop(DstArray *array); +Dst dst_array_peek(DstArray *array); + +/* Buffer functions */ +DstBuffer *dst_buffer(int32_t capacity); +DstBuffer *dst_buffer_init(DstBuffer *buffer, int32_t capacity); +void dst_buffer_deinit(DstBuffer *buffer); +void dst_buffer_ensure(DstBuffer *buffer, int32_t capacity); +int dst_buffer_extra(DstBuffer *buffer, int32_t n); +int dst_buffer_push_bytes(DstBuffer *buffer, const uint8_t *string, int32_t len); +int dst_buffer_push_cstring(DstBuffer *buffer, const char *cstring); +int dst_buffer_push_u8(DstBuffer *buffer, uint8_t x); +int dst_buffer_push_u16(DstBuffer *buffer, uint16_t x); +int dst_buffer_push_u32(DstBuffer *buffer, uint32_t x); +int dst_buffer_push_u64(DstBuffer *buffer, uint64_t x); + +/* Tuple */ +#define dst_tuple_raw(t) ((int32_t *)(t) - 2) +#define dst_tuple_length(t) (dst_tuple_raw(t)[0]) +#define dst_tuple_hash(t) ((dst_tuple_raw(t)[1])) +Dst *dst_tuple_begin(int32_t length); +const Dst *dst_tuple_end(Dst *tuple); +const Dst *dst_tuple_n(Dst *values, int32_t n); +int dst_tuple_equal(const Dst *lhs, const Dst *rhs); +int dst_tuple_compare(const Dst *lhs, const Dst *rhs); + +/* String/Symbol functions */ +#define dst_string_raw(s) ((int32_t *)(s) - 2) +#define dst_string_length(s) (dst_string_raw(s)[0]) +#define dst_string_hash(s) ((dst_string_raw(s)[1])) +uint8_t *dst_string_begin(int32_t length); +const uint8_t *dst_string_end(uint8_t *str); +const uint8_t *dst_string(const uint8_t *buf, int32_t len); +const uint8_t *dst_cstring(const char *cstring); +int dst_string_compare(const uint8_t *lhs, const uint8_t *rhs); +int dst_string_equal(const uint8_t *lhs, const uint8_t *rhs); +int dst_string_equalconst(const uint8_t *lhs, const uint8_t *rhs, int32_t rlen, int32_t rhash); +const uint8_t *dst_string_unique(const uint8_t *buf, int32_t len); +const uint8_t *dst_cstring_unique(const char *s); +const uint8_t *dst_description(Dst x); +const uint8_t *dst_short_description(Dst x); +const uint8_t *dst_to_string(Dst x); +const char *dst_to_zerostring(Dst x); +#define dst_cstringv(cstr) dst_wrap_string(dst_cstring(cstr)) +#define dst_stringv(str, len) dst_wrap_string(dst_string((str), (len))) +const uint8_t *dst_formatc(const char *format, ...); +void dst_puts(const uint8_t *str); + +/* Symbol functions */ +const uint8_t *dst_symbol(const uint8_t *str, int32_t len); +const uint8_t *dst_symbol_from_string(const uint8_t *str); +const uint8_t *dst_csymbol(const char *str); +const uint8_t *dst_symbol_gen(const uint8_t *buf, int32_t len); +#define dst_symbolv(str, len) dst_wrap_symbol(dst_symbol((str), (len))) +#define dst_csymbolv(cstr) dst_wrap_symbol(dst_csymbol(cstr)) + +/* Structs */ +#define dst_struct_raw(t) ((int32_t *)(t) - 4) +#define dst_struct_length(t) (dst_struct_raw(t)[0]) +#define dst_struct_capacity(t) (dst_struct_raw(t)[1]) +#define dst_struct_hash(t) (dst_struct_raw(t)[2]) +/* Do something with the 4th header slot - flags? */ +DstKV *dst_struct_begin(int32_t count); +void dst_struct_put(DstKV *st, Dst key, Dst value); +const DstKV *dst_struct_end(DstKV *st); +Dst dst_struct_get(const DstKV *st, Dst key); +const DstKV *dst_struct_next(const DstKV *st, const DstKV *kv); +DstTable *dst_struct_to_table(const DstKV *st); +int dst_struct_equal(const DstKV *lhs, const DstKV *rhs); +int dst_struct_compare(const DstKV *lhs, const DstKV *rhs); +const DstKV *dst_struct_find(const DstKV *st, Dst key); + +/* Table functions */ +DstTable *dst_table(int32_t capacity); +DstTable *dst_table_init(DstTable *table, int32_t capacity); +void dst_table_deinit(DstTable *table); +Dst dst_table_get(DstTable *t, Dst key); +Dst dst_table_remove(DstTable *t, Dst key); +void dst_table_put(DstTable *t, Dst key, Dst value); +const DstKV *dst_table_next(DstTable *t, const DstKV *kv); +const DstKV *dst_table_to_struct(DstTable *t); +void dst_table_merge_table(DstTable *table, DstTable *other); +void dst_table_merge_struct(DstTable *table, const DstKV *other); +DstKV *dst_table_find(DstTable *t, Dst key); + +/* Fiber */ +DstFiber *dst_fiber(int32_t capacity); +#define dst_stack_frame(s) ((DstStackFrame *)((s) - DST_FRAME_SIZE)) +#define dst_fiber_frame(f) dst_stack_frame((f)->data + (f)->frame) +DstFiber *dst_fiber_reset(DstFiber *fiber); +void dst_fiber_setcapacity(DstFiber *fiber, int32_t n); +void dst_fiber_push(DstFiber *fiber, Dst x); +void dst_fiber_push2(DstFiber *fiber, Dst x, Dst y); +void dst_fiber_push3(DstFiber *fiber, Dst x, Dst y, Dst z); +void dst_fiber_pushn(DstFiber *fiber, const Dst *arr, int32_t n); +void dst_fiber_funcframe(DstFiber *fiber, DstFunction *func); +void dst_fiber_funcframe_tail(DstFiber *fiber, DstFunction *func); +void dst_fiber_cframe(DstFiber *fiber); +void dst_fiber_popframe(DstFiber *fiber); + +/* Treat similar types through uniform interfaces for iteration */ +int dst_seq_view(Dst seq, const Dst **data, int32_t *len); +int dst_chararray_view(Dst str, const uint8_t **data, int32_t *len); +int dst_hashtable_view(Dst tab, const DstKV **data, int32_t *len, int32_t *cap); + +/* Abstract */ +#define dst_abstract_header(u) ((DstAbstractHeader *)(u) - 1) +#define dst_abstract_type(u) (dst_abstract_header(u)->type) +#define dst_abstract_size(u) (dst_abstract_header(u)->size) +void *dst_abstract(const DstAbstractType *type, size_t size); + +/* GC */ +void dst_mark(Dst x); +void dst_sweep(); +void dst_collect(); +void dst_clear_memory(); +void dst_gcroot(Dst root); +int dst_gcunroot(Dst root); +int dst_gcunrootall(Dst root); +#define dst_maybe_collect() do {\ + if (dst_vm_next_collection >= dst_vm_gc_interval) dst_collect(); } while (0) + +/* Functions */ +DstFuncDef *dst_funcdef_alloc(); +DstFunction *dst_function(DstFuncDef *def, DstFunction *parent); + +/* Misc */ +int dst_equals(Dst x, Dst y); +int32_t dst_hash(Dst x); +int dst_compare(Dst x, Dst y); +Dst dst_get(Dst ds, Dst key); +void dst_put(Dst ds, Dst key, Dst value); +const DstKV *dst_next(Dst ds, const DstKV *kv); +int32_t dst_length(Dst x); +int32_t dst_capacity(Dst x); +Dst dst_getindex(Dst ds, int32_t index); +void dst_setindex(Dst ds, Dst value, int32_t index); +int dst_cstrcmp(const uint8_t *str, const char *other); + +/* Native */ +DstCFunction dst_native(const char *name, const uint8_t **error); + +/* VM functions */ +int dst_init(); +void dst_deinit(); +int dst_run(Dst callee, Dst *returnreg); + +/* C Function helpers */ +#define dst_throw(a, e) (*((a).ret) = dst_cstringv(e), 1) +#define dst_throwv(a, v) (*((a).ret) = (v), 1) +#define dst_return(a, v) (*((a).ret) = (v), 0) + +/* Env helpers */ +void dst_env_def(DstTable *env, const char *name, Dst val); +void dst_env_var(DstTable *env, const char *name, Dst val); +void dst_env_cfuns(DstTable *env, const DstReg *cfuns); +Dst dst_env_resolve(DstTable *env, const char *name); +DstTable *dst_env_arg(DstArgs args); + +/* STL */ +DstTable *dst_stl_env(); + +#endif /* DST_H_defined */ diff --git a/src/include/dst/dstasm.h b/src/include/dst/dstasm.h new file mode 100644 index 00000000..7e63fe96 --- /dev/null +++ b/src/include/dst/dstasm.h @@ -0,0 +1,47 @@ +/* +* Copyright (c) 2017 Calvin Rose +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to +* deal in the Software without restriction, including without limitation the +* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +* sell copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +* IN THE SOFTWARE. +*/ + +#ifndef DST_ASM_H_defined +#define DST_ASM_H_defined + +#include "dsttypes.h" + +/* Assembly */ +typedef enum DstAssembleStatus DstAssembleStatus; +typedef struct DstAssembleResult DstAssembleResult; +typedef struct DstAssembleOptions DstAssembleOptions; +enum DstAssembleStatus { + DST_ASSEMBLE_OK, + DST_ASSEMBLE_ERROR +}; +struct DstAssembleResult { + DstFuncDef *funcdef; + const uint8_t *error; + DstAssembleStatus status; +}; +DstAssembleResult dst_asm(Dst source, int flags); +Dst dst_disasm(DstFuncDef *def); +Dst dst_asm_decode_instruction(uint32_t instr); +int dst_asm_cfun(DstArgs args); +int dst_disasm_cfun(DstArgs args); + +#endif /* DST_ASM_H_defined */ diff --git a/src/include/dst/dstcompile.h b/src/include/dst/dstcompile.h new file mode 100644 index 00000000..a64b609f --- /dev/null +++ b/src/include/dst/dstcompile.h @@ -0,0 +1,77 @@ +/* +* Copyright (c) 2017 Calvin Rose +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to +* deal in the Software without restriction, including without limitation the +* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +* sell copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +* IN THE SOFTWARE. +*/ + +#ifndef DST_COMPILE_H_defined +#define DST_COMPILE_H_defined + +#include "dsttypes.h" +#include "dstparse.h" + +typedef enum DstCompileStatus DstCompileStatus; +typedef struct DstCompileOptions DstCompileOptions; +typedef struct DstCompileResult DstCompileResult; +enum DstCompileStatus { + DST_COMPILE_OK, + DST_COMPILE_ERROR +}; +struct DstCompileResult { + DstCompileStatus status; + DstFuncDef *funcdef; + const uint8_t *error; + int32_t error_start; + int32_t error_end; +}; +DstCompileResult dst_compile(Dst source, DstTable *env, int flags); +int dst_compile_cfun(DstArgs args); + +/* Context - for executing dst in the interpretted form. */ +typedef struct DstContext DstContext; + +void dst_context_init(DstContext *c, DstTable *env); +void dst_context_deinit(DstContext *c); +int dst_context_repl(DstContext *c, DstTable *env); +int dst_context_file(DstContext *c, DstTable *env, const char *path); +int dst_context_run(DstContext *c, int flags); + +/* Parse structs */ +typedef enum { + DST_CONTEXT_ERROR_PARSE, + DST_CONTEXT_ERROR_COMPILE, + DST_CONTEXT_ERROR_RUNTIME +} DstContextErrorType; + +/* Evaluation context. Encapsulates parsing and compiling for easier integration + * with client programs. */ +struct DstContext { + DstTable *env; + DstBuffer buffer; + void *user; + int32_t index; + + int (*read_chunk)(DstContext *self); + void (*on_error)(DstContext *self, DstContextErrorType type, Dst err, size_t start, size_t end); + void (*on_value)(DstContext *self, Dst value); + void (*deinit)(DstContext *self); +}; + + +#endif /* DST_COMPILE_H_defined */ diff --git a/src/include/dst/dstconfig.h b/src/include/dst/dstconfig.h new file mode 100644 index 00000000..de061a10 --- /dev/null +++ b/src/include/dst/dstconfig.h @@ -0,0 +1,131 @@ +/* +* Copyright (c) 2017 Calvin Rose +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to +* deal in the Software without restriction, including without limitation the +* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +* sell copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +* IN THE SOFTWARE. +*/ + +#ifndef DST_CONFIG_H_defined +#define DST_CONFIG_H_defined + +#include + +#define DST_VERSION "0.0.0" + +/* + * Detect OS and endianess. + * From webkit source. There is likely some extreneous + * detection for unsupported platforms + */ + +/* Check Unix */ +#if defined(_AIX) \ + || defined(__APPLE__) /* Darwin */ \ + || defined(__FreeBSD__) || defined(__DragonFly__) \ + || defined(__FreeBSD_kernel__) \ + || defined(__GNU__) /* GNU/Hurd */ \ + || defined(__linux__) \ + || defined(__NetBSD__) \ + || defined(__OpenBSD__) \ + || defined(__QNXNTO__) \ + || defined(sun) || defined(__sun) /* Solaris */ \ + || defined(unix) || defined(__unix) || defined(__unix__) +#define DST_UNIX 1 +#endif + +/* Check Windows */ +#if defined(WIN32) || defined(_WIN32) +#define DST_WINDOWS 1 +#endif + +/* Check 64-bit vs 32-bit */ +#if ((defined(__x86_64__) || defined(_M_X64)) \ + && (defined(DST_UNIX) || defined(DST_WINDOWS))) \ + || (defined(__ia64__) && defined(__LP64__)) /* Itanium in LP64 mode */ \ + || defined(__alpha__) /* DEC Alpha */ \ + || (defined(__sparc__) && defined(__arch64__) || defined (__sparcv9)) /* BE */ \ + || defined(__s390x__) /* S390 64-bit (BE) */ \ + || (defined(__ppc64__) || defined(__PPC64__)) \ + || defined(__aarch64__) /* ARM 64-bit */ +#define DST_64 1 +#else +#define DST_32 1 +#endif + +/* Check big endian */ +#if defined(__MIPSEB__) /* MIPS 32-bit */ \ + || defined(__ppc__) || defined(__PPC__) /* CPU(PPC) - PowerPC 32-bit */ \ + || defined(__powerpc__) || defined(__powerpc) || defined(__POWERPC__) \ + || defined(_M_PPC) || defined(__PPC) \ + || defined(__ppc64__) || defined(__PPC64__) /* PowerPC 64-bit */ \ + || defined(__sparc) /* Sparc 32bit */ \ + || defined(__sparc__) /* Sparc 64-bit */ \ + || defined(__s390x__) /* S390 64-bit */ \ + || defined(__s390__) /* S390 32-bit */ \ + || defined(__ARMEB__) /* ARM big endian */ \ + || ((defined(__CC_ARM) || defined(__ARMCC__)) /* ARM RealView compiler */ \ + && defined(__BIG_ENDIAN)) +#define DST_BIG_ENDIAN 1 +#else +#define DST_LITTLE_ENDIAN 1 +#endif + +/* Handle runtime errors */ +#ifndef dst_exit +#include +#include +#define dst_exit(m) do { \ + printf("runtime error at line %d in file %s: %s\n",\ + __LINE__,\ + __FILE__,\ + (m));\ + exit(-1);\ +} while (0) +#endif + +#ifndef DST_NOASSERT +#define dst_assert(c, m) do { \ + if (!(c)) dst_exit((m)); \ +} while (0) +#endif + +/* What to do when out of memory */ +#ifndef DST_OUT_OF_MEMORY +#include +#define DST_OUT_OF_MEMORY do { printf("out of memory\n"); exit(1); } while (0) +#endif + +/* Helper for debugging */ +#define dst_trace(x) dst_puts(dst_formatc("DST TRACE %s, %d: %v\n", __FILE__, __LINE__, x)) + +/* Prevent some recursive functions from recursing too deeply + * ands crashing (the parser). Instead, error out. */ +#define DST_RECURSION_GUARD 1000 + +/* Use nanboxed values - uses 8 bytes per value instead of 12 or 16. */ +#define DST_NANBOX +#define DST_NANBOX_47 + +/* Alignment for pointers */ +#ifdef DST_32 +#define DST_WALIGN 4 +#else +#define DST_WALIGN 8 +#endif + +#endif /* DST_CONFIG_H_defined */ diff --git a/src/include/dst/dstopcodes.h b/src/include/dst/dstopcodes.h new file mode 100644 index 00000000..298af8a5 --- /dev/null +++ b/src/include/dst/dstopcodes.h @@ -0,0 +1,90 @@ +/* +* Copyright (c) 2017 Calvin Rose +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to +* deal in the Software without restriction, including without limitation the +* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +* sell copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +* IN THE SOFTWARE. +*/ + +#ifndef DST_OPCODES_H_defined +#define DST_OPCODES_H_defined + +typedef enum DstOpCode DstOpCode; +enum DstOpCode { + DOP_NOOP, + DOP_ERROR, + DOP_TYPECHECK, + DOP_RETURN, + DOP_RETURN_NIL, + DOP_ADD_INTEGER, + DOP_ADD_IMMEDIATE, + DOP_ADD_REAL, + DOP_ADD, + DOP_SUBTRACT_INTEGER, + DOP_SUBTRACT_REAL, + DOP_SUBTRACT, + DOP_MULTIPLY_INTEGER, + DOP_MULTIPLY_IMMEDIATE, + DOP_MULTIPLY_REAL, + DOP_MULTIPLY, + DOP_DIVIDE_INTEGER, + DOP_DIVIDE_IMMEDIATE, + DOP_DIVIDE_REAL, + DOP_DIVIDE, + DOP_BAND, + DOP_BOR, + DOP_BXOR, + DOP_BNOT, + DOP_SHIFT_LEFT, + DOP_SHIFT_LEFT_IMMEDIATE, + DOP_SHIFT_RIGHT, + DOP_SHIFT_RIGHT_IMMEDIATE, + DOP_SHIFT_RIGHT_UNSIGNED, + DOP_SHIFT_RIGHT_UNSIGNED_IMMEDIATE, + DOP_MOVE_FAR, + DOP_MOVE_NEAR, + DOP_JUMP, + DOP_JUMP_IF, + DOP_JUMP_IF_NOT, + DOP_GREATER_THAN, + DOP_LESS_THAN, + DOP_EQUALS, + DOP_COMPARE, + DOP_LOAD_NIL, + DOP_LOAD_TRUE, + DOP_LOAD_FALSE, + DOP_LOAD_INTEGER, + DOP_LOAD_CONSTANT, + DOP_LOAD_UPVALUE, + DOP_LOAD_SELF, + DOP_SET_UPVALUE, + DOP_CLOSURE, + DOP_PUSH, + DOP_PUSH_2, + DOP_PUSH_3, + DOP_PUSH_ARRAY, + DOP_CALL, + DOP_TAILCALL, + DOP_TRANSFER, + DOP_GET, + DOP_PUT, + DOP_GET_INDEX, + DOP_PUT_INDEX, + DOP_LENGTH +}; + +#endif diff --git a/src/include/dst/dstparse.h b/src/include/dst/dstparse.h new file mode 100644 index 00000000..a74e2563 --- /dev/null +++ b/src/include/dst/dstparse.h @@ -0,0 +1,79 @@ +/* +* Copyright (c) 2017 Calvin Rose +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to +* deal in the Software without restriction, including without limitation the +* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +* sell copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +* IN THE SOFTWARE. +*/ + +#ifndef DST_PARSE_H_defined +#define DST_PARSE_H_defined + +#include "dsttypes.h" + +typedef enum DstParserStatus DstParserStatus; +typedef struct DstParseState DstParseState; +typedef struct DstParser DstParser; + +/* ASTs are simple wrappers around values. They contain information about sourcemapping + * and other meta data. Possibly types? They are used mainly during compilation and parsing */ +struct DstAst { + Dst value; + int32_t source_start; + int32_t source_end; + int flags; +}; + +/* AST */ +Dst dst_ast_wrap(Dst x, int32_t start, int32_t end); +DstAst *dst_ast_node(Dst x); +Dst dst_ast_unwrap1(Dst x); +Dst dst_ast_unwrap(Dst x); + +/* Number scanning */ +Dst dst_scan_number(const uint8_t *src, int32_t len); +int32_t dst_scan_integer(const uint8_t *str, int32_t len, int *err); +double dst_scan_real(const uint8_t *str, int32_t len, int *err); + +enum DstParserStatus { + DST_PARSE_ROOT, + DST_PARSE_ERROR, + DST_PARSE_FULL, + DST_PARSE_PENDING +}; + +struct DstParser { + Dst* argstack; + DstParseState *states; + uint8_t *buf; + const char *error; + size_t index; + int lookback; + int flags; +}; + +/* Parsing */ +#define DST_PARSEFLAG_SOURCEMAP 1 +void dst_parser_init(DstParser *parser, int flags); +void dst_parser_deinit(DstParser *parser); +int dst_parser_consume(DstParser *parser, uint8_t c); +DstParserStatus dst_parser_status(DstParser *parser); +Dst dst_parser_produce(DstParser *parser); +const char *dst_parser_error(DstParser *parser); +int dst_parse_cfun(DstArgs args); + +#endif /* DST_PARSE_H_defined */ diff --git a/src/include/dst/dststate.h b/src/include/dst/dststate.h new file mode 100644 index 00000000..9b36ea4a --- /dev/null +++ b/src/include/dst/dststate.h @@ -0,0 +1,55 @@ +/* +* Copyright (c) 2017 Calvin Rose +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to +* deal in the Software without restriction, including without limitation the +* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +* sell copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +* IN THE SOFTWARE. +*/ + +#ifndef DST_STATE_H_defined +#define DST_STATE_H_defined + +#include +#include "dstconfig.h" +#include "dsttypes.h" + +/* Names of all of the types */ +extern const char *dst_type_names[16]; + +/* The VM state. Rather than a struct that is passed + * around, the vm state is global for simplicity. */ + +/* Garbage collection */ +extern void *dst_vm_blocks; +extern uint32_t dst_vm_gc_interval; +extern uint32_t dst_vm_next_collection; + +/* Immutable value cache */ +extern const uint8_t **dst_vm_cache; +extern uint32_t dst_vm_cache_capacity; +extern uint32_t dst_vm_cache_count; +extern uint32_t dst_vm_cache_deleted; + +/* GC roots */ +extern Dst *dst_vm_roots; +extern uint32_t dst_vm_root_count; +extern uint32_t dst_vm_root_capacity; + +/* GC roots - TODO consider a top level fiber pool (per thread?) */ +extern DstFiber *dst_vm_fiber; + +#endif /* DST_STATE_H_defined */ diff --git a/src/include/dst/dststl.h b/src/include/dst/dststl.h new file mode 100644 index 00000000..f55ed1f1 --- /dev/null +++ b/src/include/dst/dststl.h @@ -0,0 +1,62 @@ +/* +* Copyright (c) 2017 Calvin Rose +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to +* deal in the Software without restriction, including without limitation the +* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +* sell copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +* IN THE SOFTWARE. +*/ + +#ifndef DST_MATH_H_defined +#define DST_MATH_H_defined + +#include "dsttypes.h" + +/* Basic C Functions. These are good + * candidates for optimizations like bytecode + * inlining and costant folding. They are exposed publicly + * so that compiles can inject them into funcdefs. Later, a + * different serialization mechanism might be used for cfunctions. */ + +int dst_load_native(DstArgs args); +int dst_int(DstArgs args); +int dst_real(DstArgs args); +int dst_add(DstArgs args); +int dst_subtract(DstArgs args); +int dst_multiply(DstArgs args); +int dst_divide(DstArgs args); +int dst_modulo(DstArgs args); +int dst_band(DstArgs args); +int dst_bor(DstArgs args); +int dst_bxor(DstArgs args); +int dst_lshift(DstArgs arsg); +int dst_rshift(DstArgs args); +int dst_lshiftu(DstArgs args); + +/* Native type constructors */ +int dst_cfun_table(DstArgs args); +int dst_cfun_array(DstArgs args); +int dst_cfun_struct(DstArgs args); +int dst_cfun_tuple(DstArgs args); + +/* Initialize builtin libraries */ +int dst_lib_io(DstArgs args); +int dst_lib_math(DstArgs args); +int dst_lib_array(DstArgs args); +int dst_lib_buffer(DstArgs args); +int dst_lib_parse(DstArgs args); + +#endif /* DST_MATH_H_defined */ diff --git a/src/include/dst/dsttypes.h b/src/include/dst/dsttypes.h new file mode 100644 index 00000000..4bfc62b2 --- /dev/null +++ b/src/include/dst/dsttypes.h @@ -0,0 +1,422 @@ +/* +* Copyright (c) 2017 Calvin Rose +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to +* deal in the Software without restriction, including without limitation the +* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +* sell copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +* IN THE SOFTWARE. +*/ + +#ifndef DST_TYPES_H_defined +#define DST_TYPES_H_defined + +#include "dstconfig.h" + +#ifdef DST_NANBOX +typedef union Dst Dst; +#else +typedef struct Dst Dst; +#endif + +/* All of the dst types */ +typedef struct DstFunction DstFunction; +typedef struct DstArray DstArray; +typedef struct DstBuffer DstBuffer; +typedef struct DstTable DstTable; +typedef struct DstFiber DstFiber; + +/* Other structs */ +typedef struct DstAbstractHeader DstAbstractHeader; +typedef struct DstFuncDef DstFuncDef; +typedef struct DstFuncEnv DstFuncEnv; +typedef struct DstKV DstKV; +typedef struct DstStackFrame DstStackFrame; +typedef struct DstAbstractType DstAbstractType; +typedef struct DstArgs DstArgs; +typedef struct DstAst DstAst; +typedef struct DstReg DstReg; +typedef int (*DstCFunction)(DstArgs args); + +/* Basic types for all Dst Values */ +typedef enum DstType { + DST_NIL, + DST_FALSE, + DST_TRUE, + DST_FIBER, + DST_INTEGER, + DST_REAL, + DST_STRING, + DST_SYMBOL, + DST_ARRAY, + DST_TUPLE, + DST_TABLE, + DST_STRUCT, + DST_BUFFER, + DST_FUNCTION, + DST_CFUNCTION, + DST_ABSTRACT +} DstType; + +/* We provide two possible implemenations of Dsts. The preferred + * nanboxing approach, and the standard C version. Code in the rest of the + * application must interact through exposed interface. */ + +/* Required interface for Dst */ +/* wrap and unwrap for all types */ +/* Get type quickly */ +/* Check against type quickly */ +/* Small footprint */ +/* 32 bit integer support */ + +/* dst_type(x) + * dst_checktype(x, t) + * dst_wrap_##TYPE(x) + * dst_unwrap_##TYPE(x) + * dst_truthy(x) + * dst_memclear(p, n) - clear memory for hash tables to nils + * dst_u64(x) - get 64 bits of payload for hashing + */ + +#ifdef DST_NANBOX + +#include + +union Dst { + uint64_t u64; + int64_t i64; + void *pointer; + const void *cpointer; + double real; +}; + +#define dst_u64(x) ((x).u64) + +/* This representation uses 48 bit pointers. The trade off vs. the LuaJIT style + * 47 bit payload representaion is that the type bits are no long contiguous. Type + * checking can still be fast, but typewise polymorphism takes a bit longer. However, + * hopefully we can avoid some annoying problems that occur when trying to use 47 bit pointers + * in a 48 bit address space (Linux on ARM). If DST_NANBOX_47 is set, use 47 bit tagged pointers. */ + +/* |.......Tag.......|.......................Payload..................| */ +/* Non-double: t|11111111111|1ttt|xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx */ +/* Types of NIL, TRUE, and FALSE must have payload set to all 1s. */ + +/* Double (no NaNs): x xxxxxxxxxxx xxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx */ + +#if defined (DST_NANBOX_47) || defined (DST_32) + +#define DST_NANBOX_TAGBITS 0xFFFF800000000000lu +#define DST_NANBOX_PAYLOADBITS 0x00007FFFFFFFFFFFlu + + +#define dst_nanbox_lowtag(type) \ + ((uint64_t)(type) | 0x1FFF0) + +#define dst_nanbox_tag(type) \ + (dst_nanbox_lowtag(type) << 47) + +#define dst_type(x) \ + (isnan((x).real) \ + ? (((x).u64 >> 47) & 0xF) \ + : DST_REAL) + +#else /* defined (DST_NANBOX_47) || defined (DST_32) */ + +#define DST_NANBOX_TAGBITS 0xFFFF000000000000lu +#define DST_NANBOX_PAYLOADBITS 0x0000FFFFFFFFFFFFlu + +#define dst_nanbox_lowtag(type) \ + ((((uint64_t)(type) & 0x1) << 15) | 0x7FF8 | ((type) >> 1)) + +#define dst_nanbox_tag(type) \ + (dst_nanbox_lowtag(type) << 48) + +#define dst_type(x) \ + (isnan((x).real) \ + ? (((x).u64 >> 47) & 0xE) | ((x).u64 >> 63) \ + : DST_REAL) + +#endif /* defined (DST_NANBOX_47) || defined (DST_32) */ + +/* 32 bit mode will not use the full payload for pointers. */ +#ifdef DST_32 +#define DST_NANBOX_POINTERBITS 0xFFFFFFFFlu +#else +#define DST_NANBOX_POINTERBITS DST_NANBOX_PAYLOADBITS +#endif + +#define dst_nanbox_checkauxtype(x, type) \ + (((x).u64 & DST_NANBOX_TAGBITS) == dst_nanbox_tag((type))) + +#define dst_nanbox_isreal(x) \ + (!isnan((x).real) || dst_nanbox_checkauxtype((x), DST_REAL)) + +#define dst_checktype(x, t) \ + (((t) == DST_REAL) \ + ? dst_nanbox_isreal(x) \ + : dst_nanbox_checkauxtype((x), (t))) + +void *dst_nanbox_to_pointer(Dst x); +void dst_nanbox_memempty(DstKV *mem, int32_t count); +void *dst_nanbox_memalloc_empty(int32_t count); +Dst dst_nanbox_from_pointer(void *p, uint64_t tagmask); +Dst dst_nanbox_from_cpointer(const void *p, uint64_t tagmask); +Dst dst_nanbox_from_double(double d); +Dst dst_nanbox_from_bits(uint64_t bits); + +#define dst_memempty(mem, len) dst_nanbox_memempty((mem), (len)) +#define dst_memalloc_empty(count) dst_nanbox_memalloc_empty(count) + +/* Todo - check for single mask operation */ +#define dst_truthy(x) \ + (!(dst_checktype((x), DST_NIL) || dst_checktype((x), DST_FALSE))) + +#define dst_nanbox_from_payload(t, p) \ + dst_nanbox_from_bits(dst_nanbox_tag(t) | (p)) + +#define dst_nanbox_wrap_(p, t) \ + dst_nanbox_from_pointer((p), dst_nanbox_tag(t)) + +#define dst_nanbox_wrap_c(p, t) \ + dst_nanbox_from_cpointer((p), dst_nanbox_tag(t)) + +/* Wrap the simple types */ +#define dst_wrap_nil() dst_nanbox_from_payload(DST_NIL, 1) +#define dst_wrap_true() dst_nanbox_from_payload(DST_TRUE, 1) +#define dst_wrap_false() dst_nanbox_from_payload(DST_FALSE, 1) +#define dst_wrap_boolean(b) dst_nanbox_from_payload((b) ? DST_TRUE : DST_FALSE, 1) +#define dst_wrap_integer(i) dst_nanbox_from_payload(DST_INTEGER, (uint32_t)(i)) +#define dst_wrap_real(r) dst_nanbox_from_double(r) + +/* Unwrap the simple types */ +#define dst_unwrap_boolean(x) \ + (dst_checktype(x, DST_TRUE)) +#define dst_unwrap_integer(x) \ + ((int32_t)((x).u64 & 0xFFFFFFFFlu)) +#define dst_unwrap_real(x) ((x).real) + +/* Wrap the pointer types */ +#define dst_wrap_struct(s) dst_nanbox_wrap_c((s), DST_STRUCT) +#define dst_wrap_tuple(s) dst_nanbox_wrap_c((s), DST_TUPLE) +#define dst_wrap_fiber(s) dst_nanbox_wrap_((s), DST_FIBER) +#define dst_wrap_array(s) dst_nanbox_wrap_((s), DST_ARRAY) +#define dst_wrap_table(s) dst_nanbox_wrap_((s), DST_TABLE) +#define dst_wrap_buffer(s) dst_nanbox_wrap_((s), DST_BUFFER) +#define dst_wrap_string(s) dst_nanbox_wrap_c((s), DST_STRING) +#define dst_wrap_symbol(s) dst_nanbox_wrap_c((s), DST_SYMBOL) +#define dst_wrap_abstract(s) dst_nanbox_wrap_((s), DST_ABSTRACT) +#define dst_wrap_function(s) dst_nanbox_wrap_((s), DST_FUNCTION) +#define dst_wrap_cfunction(s) dst_nanbox_wrap_((s), DST_CFUNCTION) + +/* Unwrap the pointer types */ +#define dst_unwrap_struct(x) ((const DstKV *)dst_nanbox_to_pointer(x)) +#define dst_unwrap_tuple(x) ((const Dst *)dst_nanbox_to_pointer(x)) +#define dst_unwrap_fiber(x) ((DstFiber *)dst_nanbox_to_pointer(x)) +#define dst_unwrap_array(x) ((DstArray *)dst_nanbox_to_pointer(x)) +#define dst_unwrap_table(x) ((DstTable *)dst_nanbox_to_pointer(x)) +#define dst_unwrap_buffer(x) ((DstBuffer *)dst_nanbox_to_pointer(x)) +#define dst_unwrap_string(x) ((const uint8_t *)dst_nanbox_to_pointer(x)) +#define dst_unwrap_symbol(x) ((const uint8_t *)dst_nanbox_to_pointer(x)) +#define dst_unwrap_abstract(x) (dst_nanbox_to_pointer(x)) +#define dst_unwrap_pointer(x) (dst_nanbox_to_pointer(x)) +#define dst_unwrap_function(x) ((DstFunction *)dst_nanbox_to_pointer(x)) +#define dst_unwrap_cfunction(x) ((DstCFunction)dst_nanbox_to_pointer(x)) + +/* End of [#ifdef DST_NANBOX] */ +#else + +/* A general dst value type */ +struct Dst { + union { + uint64_t u64; + double real; + int32_t integer; + void *pointer; + const void *cpointer; + } as; + DstType type; +}; + +#define dst_u64(x) ((x).as.u64) +#define dst_memempty(mem, count) memset((mem), 0, sizeof(DstKV) * (count)) +#define dst_memalloc_empty(count) calloc((count), sizeof(DstKV)) +#define dst_type(x) ((x).type) +#define dst_checktype(x, t) ((x).type == (t)) +#define dst_truthy(x) \ + ((x).type != DST_NIL && (x).type != DST_FALSE) + +#define dst_unwrap_struct(x) ((const DstKV *)(x).as.pointer) +#define dst_unwrap_tuple(x) ((const Dst *)(x).as.pointer) +#define dst_unwrap_fiber(x) ((DstFiber *)(x).as.pointer) +#define dst_unwrap_array(x) ((DstArray *)(x).as.pointer) +#define dst_unwrap_table(x) ((DstTable *)(x).as.pointer) +#define dst_unwrap_buffer(x) ((DstBuffer *)(x).as.pointer) +#define dst_unwrap_string(x) ((const uint8_t *)(x).as.pointer) +#define dst_unwrap_symbol(x) ((const uint8_t *)(x).as.pointer) +#define dst_unwrap_abstract(x) ((x).as.pointer) +#define dst_unwrap_pointer(x) ((x).as.pointer) +#define dst_unwrap_function(x) ((DstFunction *)(x).as.pointer) +#define dst_unwrap_cfunction(x) ((DstCFunction)(x).as.pointer) +#define dst_unwrap_boolean(x) ((x).type == DST_TRUE) +#define dst_unwrap_integer(x) ((x).as.integer) +#define dst_unwrap_real(x) ((x).as.real) + +Dst dst_wrap_nil(); +Dst dst_wrap_real(double x); +Dst dst_wrap_integer(int32_t x); +Dst dst_wrap_true(); +Dst dst_wrap_false(); +Dst dst_wrap_boolean(int x); +Dst dst_wrap_string(const uint8_t *x); +Dst dst_wrap_symbol(const uint8_t *x); +Dst dst_wrap_array(DstArray *x); +Dst dst_wrap_tuple(const Dst *x); +Dst dst_wrap_struct(const DstKV *x); +Dst dst_wrap_fiber(DstFiber *x); +Dst dst_wrap_buffer(DstBuffer *x); +Dst dst_wrap_function(DstFunction *x); +Dst dst_wrap_cfunction(DstCFunction x); +Dst dst_wrap_table(DstTable *x); +Dst dst_wrap_abstract(void *x); + +/* End of tagged union implementation */ +#endif + +/* Hold components of arguments passed to DstCFunction. */ +struct DstArgs { + int32_t n; + Dst *v; + Dst *ret; +}; + +/* A lightweight green thread in dst. Does not correspond to + * operating system threads. */ +struct DstFiber { + Dst *data; + DstFiber *parent; + int32_t frame; /* Index of the stack frame */ + int32_t stackstart; /* Beginning of next args */ + int32_t stacktop; /* Top of stack. Where values are pushed and popped from. */ + int32_t capacity; + enum { + DST_FIBER_PENDING, + DST_FIBER_NEW, + DST_FIBER_ALIVE, + DST_FIBER_DEAD, + DST_FIBER_ERROR + } status; +}; + +/* A stack frame on the fiber. Is stored along with the stack values. */ +struct DstStackFrame { + DstFunction *func; + uint32_t *pc; + int32_t prevframe; +}; + +/* Number of Dsts a frame takes up in the stack */ +#define DST_FRAME_SIZE ((sizeof(DstStackFrame) + sizeof(Dst) - 1)/ sizeof(Dst)) + +/* A dynamic array type. */ +struct DstArray { + Dst *data; + int32_t count; + int32_t capacity; +}; + +/* A bytebuffer type. Used as a mutable string or string builder. */ +struct DstBuffer { + uint8_t *data; + int32_t count; + int32_t capacity; +}; + +/* A mutable associative data type. Backed by a hashtable. */ +struct DstTable { + DstKV *data; + int32_t count; + int32_t capacity; + int32_t deleted; +}; + +/* A key value pair in a struct or table */ +struct DstKV { + Dst key; + Dst value; +}; + +/* Some function defintion flags */ +#define DST_FUNCDEF_FLAG_VARARG 1 +#define DST_FUNCDEF_FLAG_NEEDSENV 4 + +/* A function definition. Contains information needed to instantiate closures. */ +struct DstFuncDef { + int32_t *environments; /* Which environments to capture from parent. */ + Dst *constants; + DstFuncDef **defs; + uint32_t *bytecode; + + /* Various debug information */ + int32_t *sourcemap; + const uint8_t *source; + const uint8_t *sourcepath; + + uint32_t flags; + int32_t slotcount; /* The amount of stack space required for the function */ + int32_t arity; /* Not including varargs */ + int32_t constants_length; + int32_t bytecode_length; + int32_t environments_length; + int32_t defs_length; +}; + +/* A fuction environment */ +struct DstFuncEnv { + union { + DstFiber *fiber; + Dst *values; + } as; + int32_t length; /* Size of environment */ + int32_t offset; /* Stack offset when values still on stack. If offset is <= 0, then + environment is no longer on the stack. */ +}; + +/* A function */ +struct DstFunction { + DstFuncDef *def; + /* Consider allocating envs with entire function struct */ + DstFuncEnv **envs; +}; + +/* Defines an abstract type */ +struct DstAbstractType { + const char *name; + int (*gc)(void *data, size_t len); + int (*gcmark)(void *data, size_t len); +}; + +/* Contains information about userdata */ +struct DstAbstractHeader { + const DstAbstractType *type; + size_t size; +}; + +struct DstReg { + const char *name; + DstCFunction cfun; +}; + +#endif /* DST_TYPES_H_defined */