From 30f62ca4540ac5e52690ca3dbd834ec925ae867b Mon Sep 17 00:00:00 2001 From: bakpakin Date: Fri, 19 Jan 2018 16:43:19 -0500 Subject: [PATCH] Major refactor and restructure. Add CMake for anticipated windows support. --- .gitignore | 2 +- CMakeLists.txt | 104 ++ Makefile | 53 +- core/opcodes.h | 90 -- include/dst/dst.h | 284 ---- include/dst/dstconfig.h | 129 -- include/dst/dststl.h | 55 - include/dst/dsttypes.h | 427 ------ junkyard/array_test.c | 20 - junkyard/asm_test.c | 55 - junkyard/bootstrap.dst | 78 - junkyard/buffer_test.c | 20 - junkyard/client.c | 65 - junkyard/compile.c | 1343 ----------------- junkyard/compile_test.c | 77 - junkyard/fiber_test.c | 91 -- junkyard/nanbox_test.c | 265 ---- junkyard/parse_test.c | 19 - junkyard/serialize.c | 60 - junkyard/stl.c | 981 ------------ junkyard/strtod_test.c | 122 -- junkyard/table_test.c | 19 - junkyard/xxd.c | 98 -- libs/testlib.c | 14 - packages/test.c | 1 - {core => src/assembler}/asm.c | 35 +- {core => src/compiler}/compile.c | 34 +- {core => src/compiler}/compile.h | 3 +- {core => src/compiler}/compile_specials.c | 6 +- {core => src/compiler}/context.c | 5 +- {core => src/core}/abstract.c | 0 {core => src/core}/array.c | 0 {core => src/core}/buffer.c | 0 {core => src/core}/fiber.c | 0 {core => src/core}/gc.c | 0 {core => src/core}/gc.h | 0 {core => src/core}/io.c | 15 +- {core => src/core}/math.c | 75 +- {core => src/core}/native.c | 1 + {core => src/core}/stl.c | 55 +- {core => src/core}/string.c | 0 {core => src/core}/struct.c | 0 {core => src/core}/symcache.c | 0 {core => src/core}/symcache.h | 0 {core => src/core}/table.c | 0 {core => src/core}/tuple.c | 0 {core => src/core}/util.c | 138 +- junkyard/unit.h => src/core/util.h | 16 +- {core => src/core}/value.c | 0 {core => src/core}/vm.c | 22 +- {core => src/core}/wrap.c | 0 .../include/headerlibs/strbinsearch.h | 59 +- .../util.h => src/include/headerlibs/vector.h | 88 +- {client => src/mainclient}/main.c | 2 +- {core => src/parser}/ast.c | 1 + {core => src/parser}/parse.c | 4 +- {core => src/parser}/strtod.c | 0 src/testlib/testlib.c | 7 + {dsttest => test}/example.dsts | 0 {dsttest => test}/minimal.dsts | 0 {dsttest => test}/suite0.dst | 0 61 files changed, 400 insertions(+), 4638 deletions(-) create mode 100644 CMakeLists.txt delete mode 100644 core/opcodes.h delete mode 100644 include/dst/dst.h delete mode 100644 include/dst/dstconfig.h delete mode 100644 include/dst/dststl.h delete mode 100644 include/dst/dsttypes.h delete mode 100644 junkyard/array_test.c delete mode 100644 junkyard/asm_test.c delete mode 100644 junkyard/bootstrap.dst delete mode 100644 junkyard/buffer_test.c delete mode 100644 junkyard/client.c delete mode 100644 junkyard/compile.c delete mode 100644 junkyard/compile_test.c delete mode 100644 junkyard/fiber_test.c delete mode 100644 junkyard/nanbox_test.c delete mode 100644 junkyard/parse_test.c delete mode 100644 junkyard/serialize.c delete mode 100644 junkyard/stl.c delete mode 100644 junkyard/strtod_test.c delete mode 100644 junkyard/table_test.c delete mode 100644 junkyard/xxd.c delete mode 100644 libs/testlib.c delete mode 100644 packages/test.c rename {core => src/assembler}/asm.c (97%) rename {core => src/compiler}/compile.c (97%) rename {core => src/compiler}/compile.h (99%) rename {core => src/compiler}/compile_specials.c (99%) rename {core => src/compiler}/context.c (97%) rename {core => src/core}/abstract.c (100%) rename {core => src/core}/array.c (100%) rename {core => src/core}/buffer.c (100%) rename {core => src/core}/fiber.c (100%) rename {core => src/core}/gc.c (100%) rename {core => src/core}/gc.h (100%) rename {core => src/core}/io.c (95%) rename {core => src/core}/math.c (84%) rename {core => src/core}/native.c (99%) rename {core => src/core}/stl.c (83%) rename {core => src/core}/string.c (100%) rename {core => src/core}/struct.c (100%) rename {core => src/core}/symcache.c (100%) rename {core => src/core}/symcache.h (100%) rename {core => src/core}/table.c (100%) rename {core => src/core}/tuple.c (100%) rename {core => src/core}/util.c (74%) rename junkyard/unit.h => src/core/util.h (78%) rename {core => src/core}/value.c (100%) rename {core => src/core}/vm.c (96%) rename {core => src/core}/wrap.c (100%) rename include/dst/dststate.h => src/include/headerlibs/strbinsearch.h (56%) rename core/util.h => src/include/headerlibs/vector.h (58%) rename {client => src/mainclient}/main.c (99%) rename {core => src/parser}/ast.c (99%) rename {core => src/parser}/parse.c (99%) rename {core => src/parser}/strtod.c (100%) create mode 100644 src/testlib/testlib.c rename {dsttest => test}/example.dsts (100%) rename {dsttest => test}/minimal.dsts (100%) rename {dsttest => test}/suite0.dst (100%) diff --git a/.gitignore b/.gitignore index ceb1a868..61f5c4f4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ # Target -/client/dst dst +build # Generated files *.gen.h diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..3dc906ba --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,104 @@ +# 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. + +cmake_minimum_required(VERSION 2.8) +project(dst) + +# Set Some Variables +set(TARGET_NAME ${PROJECT_NAME}) +if (CMAKE_VERSION VERSION_LESS "3.1") + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + set (CMAKE_C_FLAGS "--std=gnu99 ${CMAKE_C_FLAGS}") + endif () +else () + set (CMAKE_C_STANDARD 99) +endif () + +include_directories(src/include) + +set(ASSEMBLER_SOURCES +src/assembler/asm.c +) + +set(COMPILER_SOURCES +src/compiler/compile.c +src/compiler/compile_specials.c +src/compiler/context.c + +src/compiler/compile.h +) + +set(CORE_SOURCES +src/core/abstract.c +src/core/array.c +src/core/buffer.c +src/core/fiber.c +src/core/gc.c +src/core/io.c +src/core/math.c +src/core/native.c +src/core/stl.c +src/core/string.c +src/core/struct.c +src/core/symcache.c +src/core/table.c +src/core/tuple.c +src/core/util.c +src/core/value.c +src/core/vm.c +src/core/wrap.c + +src/core/gc.h +src/core/symcache.h +src/core/util.h +) + +set(MAINCLIENT_SOURCES +src/mainclient/main.c +) + +set(PARSER_SOURCES +src/parser/ast.c +src/parser/parse.c +src/parser/strtod.c +) + +set(TESTLIB_SOURCES +src/testlib/testlib.c +) + +set(SOURCES +${ASSEMBLER_SOURCES} +${COMPILER_SOURCES} +${CORE_SOURCES} +${MAINCLIENT_SOURCES} +${PARSER_SOURCES} +) + +# Build the executable +add_executable(${TARGET_NAME} ${SOURCES}) +target_link_libraries(${TARGET_NAME} m) + +# Build some modules +add_library(testlib MODULE ${TESTLIB_SOURCES}) + +# TODO dont do this on windows +target_link_libraries(${TARGET_NAME} dl) + diff --git a/Makefile b/Makefile index 0ae4210a..2c3486c7 100644 --- a/Makefile +++ b/Makefile @@ -24,40 +24,41 @@ PREFIX?=/usr/local BINDIR=$(PREFIX)/bin -VERSION=0.0.0-beta -CFLAGS=-std=c99 -Wall -Wextra -I./include -I./libs -g -DDST_VERSION=\"$(VERSION)\" +CFLAGS=-std=c99 -Wall -Wextra -I./src/include -g CLIBS=-lm -ldl PREFIX=/usr/local DST_TARGET=dst DEBUGGER=lldb -DST_INTERNAL_HEADERS=$(addprefix core/,symcache.h opcodes.h compile.h gc.h util.h) -DST_HEADERS=$(addprefix include/dst/,dst.h dstconfig.h dstcontext.h dsttypes.h dststate.h dststl.h) + DST_C_LIBS=$(addprefix libs/,testlib.so) -############################# -##### Generated headers ##### -############################# +DST_HEADERS=$(sort $(wildcard src/include/dst/*.h)) +DST_LIBHEADERS=$(sort $(wildcard src/include/headerlibs/*.h)) +DST_ALL_HEADERS=$(DST_HEADERS) $(DST_LIB_HEADERS) -DST_ALL_HEADERS=$(DST_HEADERS) $(DST_INTERNAL_HEADERS) +DST_ASM_SOURCES=$(sort $(wildcard src/assembler/*.c)) +DST_COMPILER_SOURCES=$(sort $(wildcard src/compiler/*.c)) +DST_CONTEXT_SOURCES=$(sort $(wildcard src/context/*.c)) +DST_CORE_SOURCES=$(sort $(wildcard src/core/*.c)) +DST_MAINCLIENT_SOURCES=$(sort $(wildcard src/mainclient/*.c)) +DST_PARSER_SOURCES=$(sort $(wildcard src/parser/*.c)) all: $(DST_TARGET) -################################### -##### The core vm and runtime ##### -################################### +######################################## +##### The main interpreter program ##### +######################################## -DST_CORE_SOURCES=$(addprefix core/,\ - abstract.c array.c asm.c ast.c buffer.c compile.c compile_specials.c\ - context.c fiber.c gc.c io.c math.c native.c parse.c string.c\ - stl.c strtod.c struct.c symcache.c table.c tuple.c util.c\ - value.c vm.c wrap.c) +DST_ALL_SOURCES=$(DST_ASM_SOURCES) \ + $(DST_COMPILER_SOURCES) \ + $(DST_CONTEXT_SOURCES) \ + $(DST_CORE_SOURCES) \ + $(DST_MAINCLIENT_SOURCES) \ + $(DST_PARSER_SOURCES) -DST_CLIENT_SOURCES=$(addprefix client/,\ - main.c) - -$(DST_TARGET): $(DST_CORE_SOURCES) $(DST_CLIENT_SOURCES) $(DST_ALL_HEADERS) - $(CC) $(CFLAGS) -o $(DST_TARGET) $(DST_CORE_SOURCES) $(DST_CLIENT_SOURCES) $(CLIBS) +$(DST_TARGET): $(DST_ALL_SOURCES) $(DST_ALL_HEADERS) + $(CC) $(CFLAGS) -o $(DST_TARGET) $(DST_ALL_SOURCES) $(CLIBS) ####################### ##### C Libraries ##### @@ -66,7 +67,6 @@ $(DST_TARGET): $(DST_CORE_SOURCES) $(DST_CLIENT_SOURCES) $(DST_ALL_HEADERS) %.so: %.c $(DST_HEADERS) $(CC) $(CFLAGS) -DDST_LIB -shared -undefined dynamic_lookup -o $@ $< - ################### ##### Testing ##### ################### @@ -81,7 +81,7 @@ valgrind: $(DST_TARGET) @ valgrind --leak-check=full -v ./$(DST_TARGET) test: $(DST_TARGET) - @ ./$(DST_TARGET) --gcinterval=0x10000 dsttest/suite0.dst + @ ./$(DST_TARGET) --gcinterval=0x10000 test/suite0.dst valtest: $(DST_TARGET) valgrind --leak-check=full -v ./$(DST_TARGET) dsttests/basic.dst @@ -92,13 +92,8 @@ valtest: $(DST_TARGET) clean: rm $(DST_TARGET) || true - rm *.o || true - rm client/*.o || true - rm core/*.o || true - rm $(DST_LANG_HEADERS) || true + rm src/**/*.o || true rm vgcore.* || true - rm unittests/*.out || true - rm $(DST_XXD) || true install: $(DST_TARGET) cp $(DST_TARGET) $(BINDIR)/dst diff --git a/core/opcodes.h b/core/opcodes.h deleted file mode 100644 index 298af8a5..00000000 --- a/core/opcodes.h +++ /dev/null @@ -1,90 +0,0 @@ -/* -* 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/include/dst/dst.h b/include/dst/dst.h deleted file mode 100644 index 157a382a..00000000 --- a/include/dst/dst.h +++ /dev/null @@ -1,284 +0,0 @@ -/* -* 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); - -/* Value functions */ -int dst_equals(Dst x, Dst y); -int32_t dst_hash(Dst x); -int dst_compare(Dst x, Dst y); - -/* 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) - -/* Data structure functions */ -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); - -/* 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); - -/* Native */ -DstCFunction dst_native(const char *name, const uint8_t **error); -int dst_load_native(DstArgs args); - -/* VM functions */ -int dst_init(); -void dst_deinit(); -int dst_run(Dst callee, Dst *returnreg); - -/* 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); - -/* Module helpers */ -void dst_env_def(DstTable *env, const char *name, Dst val); -void dst_env_var(DstTable *env, const char *name, Dst val); -Dst dst_env_resolve(DstTable *env, const char *name); -DstTable *dst_env_arg(DstArgs args); - -/* 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) - -/* Parsing */ -typedef enum DstParserStatus DstParserStatus; -typedef struct DstParseState DstParseState; -typedef struct DstParser DstParser; -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; -}; -#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); - -/* Compile */ -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); -DstFunction *dst_compile_func(DstCompileResult result); -int dst_compile_cfun(DstArgs args); - -/* 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); -DstFunction *dst_asm_func(DstAssembleResult result); -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); - -/* STL */ -DstTable *dst_stl_env(); -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_H_defined */ diff --git a/include/dst/dstconfig.h b/include/dst/dstconfig.h deleted file mode 100644 index 64dbc30a..00000000 --- a/include/dst/dstconfig.h +++ /dev/null @@ -1,129 +0,0 @@ -/* -* 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 - -/* - * 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/include/dst/dststl.h b/include/dst/dststl.h deleted file mode 100644 index 4fcc9c45..00000000 --- a/include/dst/dststl.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -* 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 */ -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_io_init(DstArgs args); -int dst_cmath_init(DstArgs args); - -#endif /* DST_MATH_H_defined */ diff --git a/include/dst/dsttypes.h b/include/dst/dsttypes.h deleted file mode 100644 index 888ce116..00000000 --- a/include/dst/dsttypes.h +++ /dev/null @@ -1,427 +0,0 @@ -/* -* 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 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; -}; - -/* Compile structs */ - -/* 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; -}; - -#endif /* DST_TYPES_H_defined */ diff --git a/junkyard/array_test.c b/junkyard/array_test.c deleted file mode 100644 index 03a8d7c9..00000000 --- a/junkyard/array_test.c +++ /dev/null @@ -1,20 +0,0 @@ -#include "unit.h" -#include - - -int main() { - int32_t i; - dst_init(); - DstArray *array = dst_array(10); - assert(array->capacity == 10); - assert(array->count == 0); - for (i = 0; i < 500; ++i) - dst_array_push(array, dst_wrap_integer(i)); - for (i = 0; i < 500; ++i) - assert(dst_checktype(array->data[i], DST_INTEGER) && - dst_unwrap_integer(array->data[i]) == i); - for (i = 0; i < 200; ++i) - dst_array_pop(array); - assert(array->count == 300); - return 0; -} diff --git a/junkyard/asm_test.c b/junkyard/asm_test.c deleted file mode 100644 index 49064569..00000000 --- a/junkyard/asm_test.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "unit.h" -#include - -int main() { - DstParseResult pres; - DstAssembleOptions opts; - DstAssembleResult ares; - DstFunction *func; - - FILE *f = fopen("./dsttest/minimal.dsts", "rb"); - fseek(f, 0, SEEK_END); - long fsize = ftell(f); - fseek(f, 0, SEEK_SET); //same as rewind(f); - - char *string = malloc(fsize + 1); - fread(string, fsize, 1, f); - fclose(f); - - string[fsize] = 0; - - dst_init(); - - pres = dst_parsec(string); - free(string); - - if (pres.status == DST_PARSE_ERROR) { - dst_puts(dst_formatc("parse error at %d: %S\n", pres.bytes_read, pres.error)); - return 1; - } - assert(pres.status == DST_PARSE_OK); - dst_puts(dst_formatc("\nparse result: %v\n\n", pres.value)); - - opts.flags = 0; - opts.source = pres.value; - opts.sourcemap = pres.map; - - ares = dst_asm(opts); - if (ares.status == DST_ASSEMBLE_ERROR) { - dst_puts(dst_formatc("assembly error: %S\n", ares.error)); - dst_puts(dst_formatc("error location: %d, %d\n", ares.error_start, ares.error_end)); - return 1; - } - assert(ares.status == DST_ASSEMBLE_OK); - - func = dst_asm_func(ares); - - dst_puts(dst_formatc("\nfuncdef: %v\n\n", dst_disasm(ares.funcdef))); - - dst_run(dst_wrap_function(func)); - dst_puts(dst_formatc("result: %v\n", dst_vm_fiber->ret)); - - dst_deinit(); - - return 0; -} diff --git a/junkyard/bootstrap.dst b/junkyard/bootstrap.dst deleted file mode 100644 index ddf7321a..00000000 --- a/junkyard/bootstrap.dst +++ /dev/null @@ -1,78 +0,0 @@ - -# This file is executed without any macro expansion (macros are not -# yet defined). Cannot use macros or anything outside the stl. - -# Helper for macro expansion -(def macroexpander (fn [x env f] - (if (= (type x) :tuple) - (if (> (length x) 0) - (do - (def first (get x 0)) - (def macros (get env :macros)) - (if macros - (do - (def macro (get macros first)) - (if macro - (f (apply macro (slice x 1))) - x)) - x) - x) - x) - x))) - -# Macro expansion -(def macroexpand (fn [x env] - (macroexpander x (if env env (getenv)) macroexpander))) - -# Function to create macros -(def global-macro (fn [name f] - (def env (getenv)) - (def env-macros (get env :macros)) - (def macros (if env-macros env-macros {})) - (set! env :macros macros) - (set! macros (symbol name) f) - f)) - -# Make defn -(global-macro "defn" (fn [name &] - (tuple 'def name (apply tuple 'fn &)))) - -# Make defmacro -(global-macro "defmacro" (fn [name &] - (tuple global-macro (string name) (apply tuple 'fn &)))) - -# Comment returns nil -(global-macro "comment" (fn [] nil)) - -# The source file to read from -(var *sourcefile* stdin) - -# The *read* macro gets the next form from the source file, and -# returns it. It is a var and therefor can be overwritten. -(var *read* (fn [] - (def b (buffer)) - (def p (parser)) - (while (not (parse-hasvalue p)) - (read *sourcefile* 1 b) - (if (= (length b) 0) - (error "parse error: unexpected end of source")) - (parse-charseq p b) - (if (= (parse-status p) :error) - (error (string "parse error: " (parse-consume p)))) - (clear b)) - (parse-consume p))) - -# Evaluates a form by macro-expanding it, compiling it, and -# then executing it. -(def eval (fn [x] - (def func (compile (macroexpand x))) - (if (= :function (type func)) - (func) - (error (string "compiler error: " func))))) - -# A simple repl for testing. -(while true - (def t (thread (fn [] - (while true - (print (eval (*read*))))))) - (print (tran t))) diff --git a/junkyard/buffer_test.c b/junkyard/buffer_test.c deleted file mode 100644 index 7e4ef90d..00000000 --- a/junkyard/buffer_test.c +++ /dev/null @@ -1,20 +0,0 @@ -#include "unit.h" -#include - -int main() { - dst_init(); - DstBuffer *buffer = dst_buffer(100); - assert(buffer->count == 0); - assert(buffer->capacity == 100); - dst_buffer_push_u8(buffer, 'h'); - dst_buffer_push_u8(buffer, 'e'); - dst_buffer_push_u8(buffer, 'l'); - dst_buffer_push_u8(buffer, 'l'); - dst_buffer_push_u8(buffer, 'o'); - dst_buffer_push_cstring(buffer, " world!"); - assert(dst_equals( - dst_wrap_string(dst_cstring("hello world!")), - dst_wrap_string(dst_string(buffer->data, buffer->count)) - )); - return 0; -} diff --git a/junkyard/client.c b/junkyard/client.c deleted file mode 100644 index c5b11f42..00000000 --- a/junkyard/client.c +++ /dev/null @@ -1,65 +0,0 @@ -/* -* 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. -*/ - -#include -#include -#include -#include "bootstrap.h" - -void teststr(Dst *vm, const char *src) { - uint32_t len = 0; - const uint8_t *bytes; - const char *ns = NULL; - int status = dst_parsec(vm, src, &ns); - if (status) { - printf("Parse failed: "); - bytes = dst_bytes(vm, -1, &len); - for (uint32_t i = 0; i < len; i++) - putc(bytes[i], stdout); - putc('\n', stdout); - printf("%s\n", src); - for (const char *scan = src + 1; scan < ns; ++scan) - putc(' ', stdout); - putc('^', stdout); - putc('\n', stdout); - return; - } - dst_description(vm); - bytes = dst_bytes(vm, -1, &len); - for (uint32_t i = 0; i < len; i++) - putc(bytes[i], stdout); - putc('\n', stdout); -} - -int main() { - - Dst *vm = dst_init(); - - teststr(vm, "[+ 1 2 3 \"porkpie\" ]"); - teststr(vm, "(+ 1 2 \t asdajs 1035.89 3)"); - teststr(vm, "[+ 1 2 :bokr]"); - teststr(vm, "{+ 1 2 3}"); - - dst_deinit(vm); - - return 0; -} diff --git a/junkyard/compile.c b/junkyard/compile.c deleted file mode 100644 index cab7f2c2..00000000 --- a/junkyard/compile.c +++ /dev/null @@ -1,1343 +0,0 @@ -/* -* 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. -*/ - -#include "internal.h" - -#define DST_LOCAL_FLAG_MUTABLE 1 - -/* Compiler typedefs */ -typedef struct DstCompiler DstCompiler; -typedef struct FormOptions FormOptions; -typedef struct SlotTracker SlotTracker; -typedef struct DstScope DstScope; - -/* Compilation state */ -struct DstCompiler { - Dst *vm; - DstValue error; - jmp_buf onError; - DstScope *tail; - DstBuffer *buffer; - DstTable *env; - int recursionGuard; -}; - -/* During compilation, FormOptions are passed to ASTs - * as configuration options to allow for some optimizations. */ -struct FormOptions { - /* The location the returned Slot must be in. Can be ignored - * if either canDrop or canChoose is true */ - uint16_t target; - /* If the result of the value being compiled is not going to - * be used, some forms can simply return a nil slot and save - * co,putation */ - uint16_t resultUnused : 1; - /* Allows the sub expression to evaluate into a - * temporary slot of it's choice. A temporary Slot - * can be allocated with DstCompilerGetLocal. */ - uint16_t canChoose : 1; - /* True if the form is in the tail position. This allows - * for tail call optimization. If a helper receives this - * flag, it is free to return a returned slot and generate bytecode - * for a return, including tail calls. */ - uint16_t isTail : 1; -}; - -/* A Slot represent a location of a local variable - * on the stack. Also contains some meta information. */ -typedef struct Slot Slot; -struct Slot { - /* The index of the Slot on the stack. */ - uint16_t index; - /* A nil Slot should not be expected to contain real data. (ignore index). - * Forms that have side effects but don't evaulate to - * anything will try to return nil slots. */ - uint16_t isNil : 1; - /* A temp Slot is a Slot on the stack that does not - * belong to a named local. They can be freed whenever, - * and so are used in intermediate calculations. */ - uint16_t isTemp : 1; - /* Flag indicating if byteCode for returning this slot - * has been written to the buffer. Should only ever be true - * when the isTail option is passed */ - uint16_t hasReturned : 1; -}; - -/* A SlotTracker provides a handy way to keep track of - * Slots on the stack and free them in bulk. */ -struct SlotTracker { - Slot *slots; - uint32_t count; - uint32_t capacity; -}; - -/* A DstScope is a lexical scope in the program. It is - * responsible for aliasing programmer facing names to - * Slots and for keeping track of literals. It also - * points to the parent DstScope, and its current child - * DstScope. */ -struct DstScope { - uint32_t level; - uint16_t nextLocal; - uint16_t frameSize; - uint32_t heapCapacity; - uint32_t heapSize; - uint16_t touchParent; - uint16_t touchEnv; - uint16_t *freeHeap; - DstTable *literals; - DstArray *literalsArray; - DstTable *locals; - DstScope *parent; -}; - -/* Provides default FormOptions */ -static FormOptions form_options_default() { - FormOptions opts; - opts.canChoose = 1; - opts.isTail = 0; - opts.resultUnused = 0; - opts.target = 0; - return opts; -} - -/* Create some helpers that allows us to push more than just raw bytes - * to the byte buffer. This helps us create the byte code for the compiled - * functions. */ -BUFFER_DEFINE(i32, int32_t) -BUFFER_DEFINE(i64, int64_t) -BUFFER_DEFINE(real, DstReal) -BUFFER_DEFINE(u16, uint16_t) -BUFFER_DEFINE(i16, int16_t) - -/* If there is an error during compilation, - * jump back to start */ -static void c_error(DstCompiler *c, const char *e) { - c->error = dst_string_cv(c->vm, e); - longjmp(c->onError, 1); -} - -static void c_error1(DstCompiler *c, DstValue e) { - c->error = e; - longjmp(c->onError, 1); -} - -/* Push a new scope in the compiler and return - * a pointer to it for configuration. There is - * more configuration that needs to be done if - * the new scope is a function declaration. */ -static DstScope *compiler_push_scope(DstCompiler *c, int sameFunction) { - DstScope *scope = dst_alloc(c->vm, sizeof(DstScope)); - scope->locals = dst_table(c->vm, 4); - scope->freeHeap = dst_alloc(c->vm, 4 * sizeof(uint16_t)); - scope->heapSize = 0; - scope->heapCapacity = 4; - scope->parent = c->tail; - scope->frameSize = 0; - scope->touchParent = 0; - scope->touchEnv = 0; - if (c->tail) { - scope->level = c->tail->level + (sameFunction ? 0 : 1); - } else { - scope->level = 0; - } - if (sameFunction) { - if (!c->tail) { - c_error(c, "cannot inherit scope when root scope"); - } - scope->nextLocal = c->tail->nextLocal; - scope->literals = c->tail->literals; - scope->literalsArray = c->tail->literalsArray; - } else { - scope->nextLocal = 0; - scope->literals = dst_table(c->vm, 4); - scope->literalsArray = dst_array(c->vm, 4); - } - c->tail = scope; - return scope; -} - -/* Remove the inner most scope from the compiler stack */ -static void compiler_pop_scope(DstCompiler *c) { - DstScope *last = c->tail; - if (last == NULL) { - c_error(c, "no scope to pop"); - } else { - if (last->nextLocal > last->frameSize) { - last->frameSize = last->nextLocal; - } - c->tail = last->parent; - if (c->tail) { - if (last->frameSize > c->tail->frameSize) { - c->tail->frameSize = last->frameSize; - } - } - } -} - -/* Get the next stack position that is open for - * a variable */ -static uint16_t compiler_get_local(DstCompiler *c, DstScope *scope) { - if (scope->heapSize == 0) { - if (scope->nextLocal + 1 == 0) { - c_error(c, "too many local variables"); - } - return scope->nextLocal++; - } else { - return scope->freeHeap[--scope->heapSize]; - } -} - -/* Free a slot on the stack for other locals and/or - * intermediate values */ -static void compiler_free_local(DstCompiler *c, DstScope *scope, uint16_t slot) { - /* Ensure heap has space */ - if (scope->heapSize >= scope->heapCapacity) { - uint32_t newCap = 2 * scope->heapSize; - uint16_t *newData = dst_alloc(c->vm, newCap * sizeof(uint16_t)); - dst_memcpy(newData, scope->freeHeap, scope->heapSize * sizeof(uint16_t)); - scope->freeHeap = newData; - scope->heapCapacity = newCap; - } - scope->freeHeap[scope->heapSize++] = slot; -} - -/* Initializes a SlotTracker. SlotTrackers - * are used during compilation to free up slots on the stack - * after they are no longer needed. */ -static void tracker_init(DstCompiler *c, SlotTracker *tracker) { - tracker->slots = dst_alloc(c->vm, 10 * sizeof(Slot)); - tracker->count = 0; - tracker->capacity = 10; -} - -/* Free up a slot if it is a temporary slot (does not - * belong to a named local). If the slot does belong - * to a named variable, does nothing. */ -static void compiler_drop_slot(DstCompiler *c, DstScope *scope, Slot slot) { - if (!slot.isNil && slot.isTemp) { - compiler_free_local(c, scope, slot.index); - } -} - -/* Helper function to return a slot. Useful for compiling things that return - * nil. (set, while, etc.). Use this to wrap compilation calls that need - * to return things. */ -static Slot compiler_return(DstCompiler *c, Slot slot) { - Slot ret; - ret.hasReturned = 1; - ret.isNil = 1; - if (slot.hasReturned) { - /* Do nothing */ - } else if (slot.isNil) { - /* Return nil */ - dst_buffer_push_u16(c->vm, c->buffer, DST_OP_RTN); - } else { - /* Return normal value */ - dst_buffer_push_u16(c->vm, c->buffer, DST_OP_RET); - dst_buffer_push_u16(c->vm, c->buffer, slot.index); - } - return ret; -} - -/* Gets a temporary slot for the bottom-most scope. */ -static Slot compiler_get_temp(DstCompiler *c) { - DstScope *scope = c->tail; - Slot ret; - ret.isTemp = 1; - ret.isNil = 0; - ret.hasReturned = 0; - ret.index = compiler_get_local(c, scope); - return ret; -} - -/* Return a slot that is the target Slot given some FormOptions. Will - * Create a temporary slot if needed, so be sure to drop the slot after use. */ -static Slot compiler_get_target(DstCompiler *c, FormOptions opts) { - if (opts.canChoose) { - return compiler_get_temp(c); - } else { - Slot ret; - ret.isTemp = 0; - ret.isNil = 0; - ret.hasReturned = 0; - ret.index = opts.target; - return ret; - } -} - -/* If a slot is a nil slot, create a slot that has - * an actual location on the stack. */ -static Slot compiler_realize_slot(DstCompiler *c, Slot slot) { - if (slot.isNil) { - slot = compiler_get_temp(c); - dst_buffer_push_u16(c->vm, c->buffer, DST_OP_NIL); - dst_buffer_push_u16(c->vm, c->buffer, slot.index); - } - return slot; -} - -/* Coerce a slot to match form options. Can write to buffer. */ -static Slot compiler_coerce_slot(DstCompiler *c, FormOptions opts, Slot slot) { - DstScope *scope = c->tail; - if (opts.resultUnused) { - compiler_drop_slot(c, scope, slot); - slot.isNil = 1; - return slot; - } else { - slot = compiler_realize_slot(c, slot); - } - if (opts.canChoose) { - - } else { - if (slot.index != opts.target) { - /* We need to move the variable. This - * would occur in a simple assignment like a = b. */ - DstBuffer *buffer = c->buffer; - dst_buffer_push_u16(c->vm, buffer, DST_OP_MOV); - dst_buffer_push_u16(c->vm, buffer, opts.target); - dst_buffer_push_u16(c->vm, buffer, slot.index); - slot.index = opts.target; - slot.isTemp = 0; /* We don't own the slot anymore */ - } - } - return slot; -} - -/* Helper to get a nil slot */ -static Slot nil_slot() { Slot ret; ret.isNil = 1; ret.hasReturned = 0; return ret; } - -/* Writes all of the slots in the tracker to the compiler */ -static void compiler_tracker_write(DstCompiler *c, SlotTracker *tracker, int reverse) { - uint32_t i; - DstBuffer *buffer = c->buffer; - for (i = 0; i < tracker->count; ++i) { - Slot s; - if (reverse) - s = tracker->slots[tracker->count - 1 - i]; - else - s = tracker->slots[i]; - if (s.isNil) - c_error(c, "trying to write nil slot"); - dst_buffer_push_u16(c->vm, buffer, s.index); - } -} - -/* Free the tracker after creation. This unlocks the memory - * that was allocated by the GC an allows it to be collected. Also - * frees slots that were tracked by this tracker in the given scope. */ -static void compiler_tracker_free(DstCompiler *c, DstScope *scope, SlotTracker *tracker) { - uint32_t i; - /* Free in reverse order */ - for (i = tracker->count - 1; i < tracker->count; --i) { - compiler_drop_slot(c, scope, tracker->slots[i]); - } -} - -/* Add a new Slot to a slot tracker. */ -static void compiler_tracker_push(DstCompiler *c, SlotTracker *tracker, Slot slot) { - if (tracker->count >= tracker->capacity) { - uint32_t newCap = 2 * tracker->count; - Slot *newData = dst_alloc(c->vm, newCap * sizeof(Slot)); - dst_memcpy(newData, tracker->slots, tracker->count * sizeof(Slot)); - tracker->slots = newData; - tracker->capacity = newCap; - } - tracker->slots[tracker->count++] = slot; -} - -/* Registers a literal in the given scope. If an equal literal is found, uses - * that one instead of creating a new literal. This allows for some reuse - * of things like string constants.*/ -static uint16_t compiler_add_literal(DstCompiler *c, DstScope *scope, DstValue x) { - DstValue checkDup = dst_table_get(scope->literals, x); - uint16_t literalIndex = 0; - if (checkDup.type != DST_NIL) { - /* An equal literal is already registered in the current scope */ - return (uint16_t) checkDup.as.integer; - } else { - /* Add our literal for tracking */ - DstValue valIndex; - valIndex.type = DST_INTEGER; - literalIndex = scope->literalsArray->count; - valIndex.as.integer = literalIndex; - dst_table_put(c->vm, scope->literals, x, valIndex); - dst_array_push(c->vm, scope->literalsArray, x); - } - return literalIndex; -} - -/* Declare a symbol in a given scope. */ -static uint16_t compiler_declare_symbol(DstCompiler *c, DstScope *scope, DstValue sym, uint16_t flags) { - DstValue x; - uint16_t target; - if (sym.type != DST_SYMBOL) - c_error(c, "expected symbol"); - target = compiler_get_local(c, scope); - x.type = DST_INTEGER; - x.as.integer = target + (flags << 16); - dst_table_put(c->vm, scope->locals, sym, x); - return target; -} - -/* Try to resolve a symbol. If the symbol can be resolved, return true and - * pass back the level and index by reference. */ -static int symbol_resolve(DstCompiler *c, DstValue x, uint16_t *level, uint16_t *index, uint16_t *flags, DstValue *out) { - DstScope *scope = c->tail; - DstValue check; - uint32_t currentLevel = scope->level; - while (scope) { - check = dst_table_get(scope->locals, x); - if (check.type != DST_NIL) { - *level = currentLevel - scope->level; - *index = (uint16_t) (check.as.integer & 0xFFFF); - if (flags) *flags = check.as.integer >> 16; - return 1; - } - scope = scope->parent; - } - /* Check for named literals */ - check = dst_table_get(c->env, x); - if (check.type != DST_NIL) { - /* Check metadata for var (mutable) */ - DstTable *metas = dst_env_meta(c->vm, c->env); - DstValue maybeMeta = dst_table_get(metas, x); - if (maybeMeta.type == DST_TABLE) { - DstValue isMutable = dst_table_get(maybeMeta.as.table, dst_string_cv(c->vm, "mutable")); - if (dst_truthy(isMutable)) { - if (flags) *flags = DST_LOCAL_FLAG_MUTABLE; - *out = check; - return 3; - } - } - if (flags) *flags = 0; - *out = check; - return 2; - } - /* Check for nil named literal */ - check = dst_table_get(dst_env_nils(c->vm, c->env), x); - if (check.type != DST_NIL) { - if (flags) *flags = 0; - *out = dst_wrap_nil(); - return 2; - } - return 0; -} - -/* Forward declaration */ -/* Compile a value and return it stack location after loading. - * If a target > 0 is passed, the returned value must be equal - * to the targtet. If target < 0, the DstCompiler can choose whatever - * slot location it likes. If, for example, a symbol resolves to - * whatever is in a given slot, it makes sense to use that location - * to 'return' the value. For other expressions, like function - * calls, the compiler will just pick the lowest free slot - * as the location on the stack. */ -static Slot compile_value(DstCompiler *c, FormOptions opts, DstValue x); - -/* Compile boolean, nil, and number values. */ -static Slot compile_nonref_type(DstCompiler *c, FormOptions opts, DstValue x) { - DstBuffer *buffer = c->buffer; - Slot ret; - if (opts.resultUnused) return nil_slot(); - ret = compiler_get_target(c, opts); - if (x.type == DST_NIL) { - dst_buffer_push_u16(c->vm, buffer, DST_OP_NIL); - dst_buffer_push_u16(c->vm, buffer, ret.index); - } else if (x.type == DST_BOOLEAN) { - dst_buffer_push_u16(c->vm, buffer, x.as.boolean ? DST_OP_TRU : DST_OP_FLS); - dst_buffer_push_u16(c->vm, buffer, ret.index); - } else if (x.type == DST_REAL) { - dst_buffer_push_u16(c->vm, buffer, DST_OP_F64); - dst_buffer_push_u16(c->vm, buffer, ret.index); - dst_buffer_push_real(c->vm, buffer, x.as.real); - } else if (x.type == DST_INTEGER) { - if (x.as.integer <= 32767 && x.as.integer >= -32768) { - dst_buffer_push_u16(c->vm, buffer, DST_OP_I16); - dst_buffer_push_u16(c->vm, buffer, ret.index); - dst_buffer_push_i16(c->vm, buffer, x.as.integer); - } else if (x.as.integer <= 2147483647 && x.as.integer >= -2147483648) { - dst_buffer_push_u16(c->vm, buffer, DST_OP_I32); - dst_buffer_push_u16(c->vm, buffer, ret.index); - dst_buffer_push_i32(c->vm, buffer, x.as.integer); - } else { - dst_buffer_push_u16(c->vm, buffer, DST_OP_I64); - dst_buffer_push_u16(c->vm, buffer, ret.index); - dst_buffer_push_i64(c->vm, buffer, x.as.integer); - } - } else { - c_error(c, "expected boolean, nil, or number type"); - } - return ret; -} - -/* Compile a structure that evaluates to a literal value. Useful - * for objects like strings, or anything else that cannot be instantiated - * from bytecode and doesn't do anything in the AST. */ -static Slot compile_literal(DstCompiler *c, FormOptions opts, DstValue x) { - DstScope *scope = c->tail; - DstBuffer *buffer = c->buffer; - Slot ret; - uint16_t literalIndex; - if (opts.resultUnused) return nil_slot(); - switch (x.type) { - case DST_INTEGER: - case DST_REAL: - case DST_BOOLEAN: - case DST_NIL: - return compile_nonref_type(c, opts, x); - default: - break; - } - ret = compiler_get_target(c, opts); - literalIndex = compiler_add_literal(c, scope, x); - dst_buffer_push_u16(c->vm, buffer, DST_OP_CST); - dst_buffer_push_u16(c->vm, buffer, ret.index); - dst_buffer_push_u16(c->vm, buffer, literalIndex); - return ret; -} - -/* Quote a value */ -static DstValue quote(Dst *vm, DstValue x) { - DstValue *tuple = dst_tuple_begin(vm, 2); - tuple[0] = dst_string_cvs(vm, "quote"); - tuple[1] = x; - return dst_wrap_tuple(dst_tuple_end(vm, tuple)); -} - -/* Compile a symbol. Resolves any kind of symbol. */ -static Slot compile_symbol(DstCompiler *c, FormOptions opts, DstValue sym) { - DstValue lit = dst_wrap_nil(); - DstBuffer * buffer = c->buffer; - uint16_t index = 0; - uint16_t level = 0; - Slot ret; - int status = symbol_resolve(c, sym, &level, &index, NULL, &lit); - if (!status) { - c_error1(c, sym); - } - if (opts.resultUnused) return nil_slot(); - if (status == 2) { - /* We have a named literal */ - return compile_literal(c, opts, lit); - } else if (status == 3) { - /* We have a global variable */ - const DstValue *tup; - Dst *vm= c->vm; - DstValue *t = dst_tuple_begin(vm, 3); - t[0] = dst_string_cvs(vm, "get"); /* Todo - replace with actual cfunc or bytecode */ - t[1] = quote(vm, lit); - t[2] = dst_wrap_integer(0); - tup = dst_tuple_end(vm, t); - return compile_value(c, opts, dst_wrap_tuple(tup)); - } else if (level > 0) { - /* We have an upvalue from a parent function. Make - * sure that the chain of functions up to the upvalue keep - * their parent references */ - uint32_t i = level; - DstScope *scope = c->tail; - for (i = level; i > 1; --i) { - scope->touchParent = 1; - scope = scope->parent; - } - scope->touchEnv = 1; - ret = compiler_get_target(c, opts); - dst_buffer_push_u16(c->vm, buffer, DST_OP_UPV); - dst_buffer_push_u16(c->vm, buffer, ret.index); - dst_buffer_push_u16(c->vm, buffer, level); - dst_buffer_push_u16(c->vm, buffer, index); - } else { - /* Local variable on stack */ - ret.isTemp = 0; - ret.isNil = 0; - ret.hasReturned = 0; - if (opts.canChoose) { - ret.index = index; - } else { - /* We need to move the variable. This - * would occur in a simple assignment like a = b. */ - ret.index = opts.target; - dst_buffer_push_u16(c->vm, buffer, DST_OP_MOV); - dst_buffer_push_u16(c->vm, buffer, ret.index); - dst_buffer_push_u16(c->vm, buffer, index); - } - } - return ret; -} - -/* Compile an assignment operation */ -static Slot compile_assign(DstCompiler *c, FormOptions opts, DstValue left, DstValue right) { - DstValue lit = dst_wrap_nil(); - DstScope *scope = c->tail; - DstBuffer *buffer = c->buffer; - FormOptions subOpts = form_options_default(); - uint16_t target = 0; - uint16_t level = 0; - uint16_t flags = 0; - Slot slot; - int status; - subOpts.isTail = 0; - subOpts.resultUnused = 0; - status = symbol_resolve(c, left, &level, &target, &flags, &lit); - if (status == 1) { - if (!(flags & DST_LOCAL_FLAG_MUTABLE)) - c_error(c, "cannot varset immutable binding"); - /* Check if we have an up value. Otherwise, it's just a normal - * local variable */ - if (level != 0) { - subOpts.canChoose = 1; - /* Evaluate the right hand side */ - slot = compiler_realize_slot(c, compile_value(c, subOpts, right)); - /* Set the up value */ - dst_buffer_push_u16(c->vm, buffer, DST_OP_SUV); - dst_buffer_push_u16(c->vm, buffer, slot.index); - dst_buffer_push_u16(c->vm, buffer, level); - dst_buffer_push_u16(c->vm, buffer, target); - } else { - /* Local variable */ - subOpts.canChoose = 0; - subOpts.target = target; - slot = compile_value(c, subOpts, right); - } - } else if (status == 3) { - /* Global var */ - const DstValue *tup; - Dst *vm= c->vm; - DstValue *t = dst_tuple_begin(vm, 4); - t[0] = dst_string_cvs(vm, "set!"); /* Todo - replace with ref ro actual cfunc */ - t[1] = quote(c->vm, lit); - t[2] = dst_wrap_integer(0); - t[3] = right; - tup = dst_tuple_end(vm, t); - subOpts.resultUnused = 1; - compile_value(c, subOpts, dst_wrap_tuple(tup)); - return compile_value(c, opts, left); - } else { - c_error(c, "cannot varset immutable binding"); - } - if (opts.resultUnused) { - compiler_drop_slot(c, scope, slot); - return nil_slot(); - } else { - return slot; - } -} - -/* Set a var */ -static Slot compile_varset(DstCompiler *c, FormOptions opts, const DstValue *form) { - if (dst_tuple_length(form) != 3) - c_error(c, "expected 2 arguments to varset"); - if (DST_SYMBOL != form[1].type) - c_error(c, "expected symbol as first argument"); - return compile_assign(c, opts, form[1], form[2]); -} - -/* Global var */ -static Slot compile_global_var(DstCompiler *c, FormOptions opts, const DstValue *form) { - const DstValue *tup; - Dst *vm= c->vm; - DstValue *t = dst_tuple_begin(vm, 3); - t[0] = dst_string_cvs(vm, "global-var"); /* Todo - replace with ref ro actual cfunc */ - t[1] = form[1]; - t[1].type = DST_STRING; - t[2] = form[2]; - tup = dst_tuple_end(vm, t); - return compile_value(c, opts, dst_wrap_tuple(tup)); -} - -/* Global define */ -static Slot compile_global_def(DstCompiler *c, FormOptions opts, const DstValue *form) { - const DstValue *tup; - Dst *vm= c->vm; - DstValue *t = dst_tuple_begin(vm, 3); - t[0] = dst_string_cvs(vm, "global-def"); /* Todo - replace with ref ro actual cfunc */ - t[1] = form[1]; - t[1].type = DST_STRING; - t[2] = form[2]; - tup = dst_tuple_end(vm, t); - return compile_value(c, opts, dst_wrap_tuple(tup)); -} - -/* Compile def */ -static Slot compile_def(DstCompiler *c, FormOptions opts, const DstValue *form) { - DstScope *scope = c->tail; - if (dst_tuple_length(form) != 3) - c_error(c, "expected 2 arguments to def"); - if (DST_SYMBOL != form[1].type) - c_error(c, "expected symbol as first argument"); - if (scope->parent) { - FormOptions subOpts; - Slot slot; - subOpts.isTail = opts.isTail; - subOpts.resultUnused = 0; - subOpts.canChoose = 0; - subOpts.target = compiler_declare_symbol(c, scope, form[1], 0); - slot = compile_value(c, subOpts, form[2]); - return compiler_coerce_slot(c, opts, slot); - } else { - return compile_global_def(c, opts, form); - } -} - -/* Compile var */ -static Slot compile_var(DstCompiler *c, FormOptions opts, const DstValue *form) { - DstScope *scope = c->tail; - if (dst_tuple_length(form) != 3) - c_error(c, "expected 2 arguments to var"); - if (DST_SYMBOL != form[1].type) - c_error(c, "expected symbol as first argument"); - if (scope->parent) { - FormOptions subOpts; - Slot slot; - subOpts.isTail = opts.isTail; - subOpts.resultUnused = 0; - subOpts.canChoose = 0; - subOpts.target = compiler_declare_symbol(c, scope, form[1], DST_LOCAL_FLAG_MUTABLE); - slot = compile_value(c, subOpts, form[2]); - return compiler_coerce_slot(c, opts, slot); - } else { - return compile_global_var(c, opts, form); - } -} - -/* Compile series of expressions. This compiles the meat of - * function definitions and the inside of do forms. */ -static Slot compile_block(DstCompiler *c, FormOptions opts, const DstValue *form, uint32_t startIndex) { - DstScope *scope = c->tail; - FormOptions subOpts = form_options_default(); - uint32_t current = startIndex; - /* Check for empty body */ - if (dst_tuple_length(form) <= startIndex) return nil_slot(); - /* Compile the body */ - subOpts.resultUnused = 1; - subOpts.isTail = 0; - subOpts.canChoose = 1; - while (current < dst_tuple_length(form) - 1) { - compiler_drop_slot(c, scope, compile_value(c, subOpts, form[current])); - ++current; - } - /* Compile the last expression in the body */ - return compile_value(c, opts, form[dst_tuple_length(form) - 1]); -} - -/* Extract the last n bytes from the buffer and use them to construct - * a function definition. */ -static DstFuncDef *compiler_gen_funcdef(DstCompiler *c, uint32_t lastNBytes, uint32_t arity, int varargs) { - DstScope *scope = c->tail; - DstBuffer *buffer = c->buffer; - DstFuncDef *def = dst_alloc(c->vm, sizeof(DstFuncDef)); - /* Create enough space for the new byteCode */ - if (lastNBytes > buffer->count) - c_error(c, "trying to extract more bytes from buffer than in buffer"); - uint8_t * byteCode = dst_alloc(c->vm, lastNBytes); - def->byteCode = (uint16_t *)byteCode; - def->byteCodeLen = lastNBytes / 2; - /* Copy the last chunk of bytes in the buffer into the new - * memory for the function's byteCOde */ - dst_memcpy(byteCode, buffer->data + buffer->count - lastNBytes, lastNBytes); - /* Remove the byteCode from the end of the buffer */ - buffer->count -= lastNBytes; - /* Create the literals used by this function */ - if (scope->literalsArray->count) { - def->literals = dst_alloc(c->vm, scope->literalsArray->count * sizeof(DstValue)); - dst_memcpy(def->literals, scope->literalsArray->data, - scope->literalsArray->count * sizeof(DstValue)); - } else { - def->literals = NULL; - } - def->literalsLen = scope->literalsArray->count; - /* Delete the sub scope */ - compiler_pop_scope(c); - /* Initialize the new FuncDef */ - def->locals = scope->frameSize; - def->arity = arity; - def->flags = (varargs ? DST_FUNCDEF_FLAG_VARARG : 0) | - (scope->touchParent ? DST_FUNCDEF_FLAG_NEEDSPARENT : 0) | - (scope->touchEnv ? DST_FUNCDEF_FLAG_NEEDSENV : 0); - return def; -} - -/* Check if a string a cstring are equal */ -static int equal_cstr(const uint8_t *str, const char *cstr) { - uint32_t i; - for (i = 0; i < dst_string_length(str); ++i) { - if (cstr[i] == 0) return 0; - if (str[i] != ((const uint8_t *)cstr)[i]) return 0; - } - return cstr[i] == 0; -} - -/* Compile a function from a function literal source form */ -static Slot compile_function(DstCompiler *c, FormOptions opts, const DstValue *form) { - DstScope *scope = c->tail; - DstBuffer *buffer = c->buffer; - uint32_t current = 1; - uint32_t i; - uint32_t sizeBefore; /* Size of buffer before compiling function */ - DstScope *subDstScope; - DstArray *params; - FormOptions subOpts = form_options_default(); - Slot ret; - int varargs = 0; - uint32_t arity; - if (opts.resultUnused) return nil_slot(); - ret = compiler_get_target(c, opts); - subDstScope = compiler_push_scope(c, 0); - /* Define the function parameters */ - if (form[current].type != DST_ARRAY) - c_error(c, "expected function arguments array"); - params = form[current++].as.array; - arity = params->count; - for (i = 0; i < params->count; ++i) { - DstValue param = params->data[i]; - if (param.type != DST_SYMBOL) - c_error(c, "function parameters should be symbols"); - /* Check for varargs */ - if (equal_cstr(param.as.string, "&")) { - if (i != params->count - 1) { - c_error(c, "& is reserved for vararg argument in function"); - } - varargs = 1; - arity--; - } - /* The compiler puts the parameter locals - * in the right place by default - at the beginning - * of the stack frame. */ - compiler_declare_symbol(c, subDstScope, param, 0); - } - /* Mark where we are on the stack so we can - * return to it later. */ - sizeBefore = buffer->count; - /* Compile the body in the subscope */ - subOpts.isTail = 1; - compiler_return(c, compile_block(c, subOpts, form, current)); - /* Create a new FuncDef as a constant in original scope by splicing - * out the relevant code from the buffer. */ - { - DstValue newVal; - uint16_t literalIndex; - DstFuncDef *def = compiler_gen_funcdef(c, buffer->count - sizeBefore, arity, varargs); - /* Add this FuncDef as a literal in the outer scope */ - newVal.type = DST_FUNCDEF; - newVal.as.def = def; - literalIndex = compiler_add_literal(c, scope, newVal); - dst_buffer_push_u16(c->vm, buffer, DST_OP_CLN); - dst_buffer_push_u16(c->vm, buffer, ret.index); - dst_buffer_push_u16(c->vm, buffer, literalIndex); - } - return ret; -} - -/* Branching special */ -static Slot compile_if(DstCompiler *c, FormOptions opts, const DstValue *form) { - DstScope *scope = c->tail; - DstBuffer *buffer = c->buffer; - FormOptions condOpts = opts; - FormOptions branchOpts = opts; - Slot left, right, condition; - uint32_t countAtJumpIf = 0; - uint32_t countAtJump = 0; - uint32_t countAfterFirstBranch = 0; - /* Check argument count */ - if (dst_tuple_length(form) < 3 || dst_tuple_length(form) > 4) - c_error(c, "if takes either 2 or 3 arguments"); - /* Compile the condition */ - condOpts.isTail = 0; - condOpts.resultUnused = 0; - condition = compile_value(c, condOpts, form[1]); - /* If the condition is nil, just compile false path */ - if (condition.isNil) { - if (dst_tuple_length(form) == 4) { - return compile_value(c, opts, form[3]); - } - return condition; - } - /* Mark where the buffer is now so we can write the jump - * length later */ - countAtJumpIf = buffer->count; - buffer->count += sizeof(int32_t) + 2 * sizeof(uint16_t); - /* Configure branch form options */ - branchOpts.canChoose = 0; - branchOpts.target = condition.index; - /* Compile true path */ - left = compile_value(c, branchOpts, form[2]); - if (opts.isTail) { - compiler_return(c, left); - } else { - /* If we need to jump again, do so */ - if (dst_tuple_length(form) == 4) { - countAtJump = buffer->count; - buffer->count += sizeof(int32_t) + sizeof(uint16_t); - } - } - compiler_drop_slot(c, scope, left); - /* Reinsert jump with correct index */ - countAfterFirstBranch = buffer->count; - buffer->count = countAtJumpIf; - dst_buffer_push_u16(c->vm, buffer, DST_OP_JIF); - dst_buffer_push_u16(c->vm, buffer, condition.index); - dst_buffer_push_i32(c->vm, buffer, (countAfterFirstBranch - countAtJumpIf) / 2); - buffer->count = countAfterFirstBranch; - /* Compile false path */ - if (dst_tuple_length(form) == 4) { - right = compile_value(c, branchOpts, form[3]); - if (opts.isTail) compiler_return(c, right); - compiler_drop_slot(c, scope, right); - } else if (opts.isTail) { - compiler_return(c, condition); - } - /* Reset the second jump length */ - if (!opts.isTail && dst_tuple_length(form) == 4) { - countAfterFirstBranch = buffer->count; - buffer->count = countAtJump; - dst_buffer_push_u16(c->vm, buffer, DST_OP_JMP); - dst_buffer_push_i32(c->vm, buffer, (countAfterFirstBranch - countAtJump) / 2); - buffer->count = countAfterFirstBranch; - } - if (opts.isTail) - condition.hasReturned = 1; - return condition; -} - -/* While special */ -static Slot compile_while(DstCompiler *c, FormOptions opts, const DstValue *form) { - Slot cond; - uint32_t countAtStart = c->buffer->count; - uint32_t countAtJumpDelta; - uint32_t countAtFinish; - FormOptions defaultOpts = form_options_default(); - compiler_push_scope(c, 1); - /* Compile condition */ - cond = compile_value(c, defaultOpts, form[1]); - /* Assert that cond is a real value - otherwise do nothing (nil is false, - * so loop never runs.) */ - if (cond.isNil) return cond; - /* Leave space for jump later */ - countAtJumpDelta = c->buffer->count; - c->buffer->count += sizeof(uint16_t) * 2 + sizeof(int32_t); - /* Compile loop body */ - defaultOpts.resultUnused = 1; - compiler_drop_slot(c, c->tail, compile_block(c, defaultOpts, form, 2)); - /* Jump back to the loop start */ - countAtFinish = c->buffer->count; - dst_buffer_push_u16(c->vm, c->buffer, DST_OP_JMP); - dst_buffer_push_i32(c->vm, c->buffer, (int32_t)(countAtFinish - countAtStart) / -2); - countAtFinish = c->buffer->count; - /* Set the jump to the correct length */ - c->buffer->count = countAtJumpDelta; - dst_buffer_push_u16(c->vm, c->buffer, DST_OP_JIF); - dst_buffer_push_u16(c->vm, c->buffer, cond.index); - dst_buffer_push_i32(c->vm, c->buffer, (int32_t)(countAtFinish - countAtJumpDelta) / 2); - /* Pop scope */ - c->buffer->count = countAtFinish; - compiler_pop_scope(c); - /* Return nil */ - if (opts.resultUnused) - return nil_slot(); - else - return cond; -} - -/* Do special */ -static Slot compile_do(DstCompiler *c, FormOptions opts, const DstValue *form) { - Slot ret; - compiler_push_scope(c, 1); - ret = compile_block(c, opts, form, 1); - compiler_pop_scope(c); - return ret; -} - -/* Quote special - returns its argument as is. */ -static Slot compile_quote(DstCompiler *c, FormOptions opts, const DstValue *form) { - DstScope *scope = c->tail; - DstBuffer *buffer = c->buffer; - Slot ret; - uint16_t literalIndex; - if (dst_tuple_length(form) != 2) - c_error(c, "quote takes exactly 1 argument"); - DstValue x = form[1]; - if (x.type == DST_NIL || - x.type == DST_BOOLEAN || - x.type == DST_REAL || - x.type == DST_INTEGER) { - return compile_nonref_type(c, opts, x); - } - if (opts.resultUnused) return nil_slot(); - ret = compiler_get_target(c, opts); - literalIndex = compiler_add_literal(c, scope, x); - dst_buffer_push_u16(c->vm, buffer, DST_OP_CST); - dst_buffer_push_u16(c->vm, buffer, ret.index); - dst_buffer_push_u16(c->vm, buffer, literalIndex); - return ret; -} - -/* Apply special */ -static Slot compile_apply(DstCompiler *c, FormOptions opts, const DstValue *form) { - DstScope *scope = c->tail; - DstBuffer *buffer = c->buffer; - /* Empty forms evaluate to nil. */ - if (dst_tuple_length(form) < 3) - c_error(c, "apply expects at least 2 arguments"); - { - Slot ret, callee; - SlotTracker tracker; - FormOptions subOpts = form_options_default(); - uint32_t i; - tracker_init(c, &tracker); - /* Compile function to be called */ - callee = compiler_realize_slot(c, compile_value(c, subOpts, form[1])); - /* Compile all of the arguments */ - for (i = 2; i < dst_tuple_length(form) - 1; ++i) { - Slot slot = compile_value(c, subOpts, form[i]); - compiler_tracker_push(c, &tracker, slot); - } - /* Write last item */ - { - Slot slot = compile_value(c, subOpts, form[dst_tuple_length(form) - 1]); - slot = compiler_realize_slot(c, slot); - /* Free up some slots */ - compiler_drop_slot(c, scope, callee); - compiler_drop_slot(c, scope, slot); - compiler_tracker_free(c, scope, &tracker); - /* Write first arguments */ - dst_buffer_push_u16(c->vm, buffer, DST_OP_PSK); - dst_buffer_push_u16(c->vm, buffer, tracker.count); - /* Write the location of all of the arguments */ - compiler_tracker_write(c, &tracker, 0); - /* Write last arguments */ - dst_buffer_push_u16(c->vm, buffer, DST_OP_PAR); - dst_buffer_push_u16(c->vm, buffer, slot.index); - } - /* If this is in tail position do a tail call. */ - if (opts.isTail) { - dst_buffer_push_u16(c->vm, buffer, DST_OP_TCL); - dst_buffer_push_u16(c->vm, buffer, callee.index); - ret.hasReturned = 1; - ret.isNil = 1; - } else { - ret = compiler_get_target(c, opts); - dst_buffer_push_u16(c->vm, buffer, DST_OP_CAL); - dst_buffer_push_u16(c->vm, buffer, callee.index); - dst_buffer_push_u16(c->vm, buffer, ret.index); - } - return ret; - } -} - -/* Transfer special */ -static Slot compile_tran(DstCompiler *c, FormOptions opts, const DstValue *form) { - DstBuffer *buffer = c->buffer; - Slot t, v, r; - if (dst_tuple_length(form) != 3 && dst_tuple_length(form) != 2) - c_error(c, "tran expects 2 or 3 arguments"); - t = compiler_realize_slot(c, compile_value(c, form_options_default(), form[1])); - if (dst_tuple_length(form) == 3) - v = compiler_realize_slot(c, compile_value(c, form_options_default(), form[2])); - else - v = compile_value(c, form_options_default(), dst_wrap_nil()); - r = compiler_get_target(c, opts); - dst_buffer_push_u16(c->vm, buffer, DST_OP_TRN); - dst_buffer_push_u16(c->vm, buffer, r.index); - dst_buffer_push_u16(c->vm, buffer, t.index); - dst_buffer_push_u16(c->vm, buffer, v.index); - return r; -} - -/* Define a function type for Special Form helpers */ -typedef Slot (*SpecialFormHelper) (DstCompiler *c, FormOptions opts, const DstValue *form); - -/* Dispatch to a special form */ -static SpecialFormHelper get_special(const DstValue *form) { - const uint8_t *name; - if (dst_tuple_length(form) < 1 || form[0].type != DST_SYMBOL) - return NULL; - name = form[0].as.string; - /* If we have a symbol with a zero length name, we have other - * problems. */ - if (dst_string_length(name) == 0) - return NULL; - /* Specials */ - switch (name[0]) { - case 'a': - { - if (dst_string_length(name) == 5 && - name[1] == 'p' && - name[2] == 'p' && - name[3] == 'l' && - name[4] == 'y') { - return compile_apply; - } - } - break; - case 'd': - { - if (dst_string_length(name) == 2 && - name[1] == 'o') { - return compile_do; - } else if (dst_string_length(name) == 3 && - name[1] == 'e' && - name[2] == 'f') { - return compile_def; - } - } - break; - case 'i': - { - if (dst_string_length(name) == 2 && - name[1] == 'f') { - return compile_if; - } - } - break; - case 'f': - { - if (dst_string_length(name) == 2 && - name[1] == 'n') { - return compile_function; - } - } - break; - case 'q': - { - if (dst_string_length(name) == 5 && - name[1] == 'u' && - name[2] == 'o' && - name[3] == 't' && - name[4] == 'e') { - return compile_quote; - } - } - break; - case 't': - { - if (dst_string_length(name) == 4 && - name[1] == 'r' && - name[2] == 'a' && - name[3] == 'n') { - return compile_tran; - } - } - break; - case 'v': - { - if (dst_string_length(name) == 3 && - name[1] == 'a' && - name[2] == 'r') { - return compile_var; - } - if (dst_string_length(name) == 7 && - name[1] == 'a' && - name[2] == 'r' && - name[3] == 's' && - name[4] == 'e' && - name[5] == 't' && - name[6] == '!') { - return compile_varset; - } - } - break; - case 'w': - { - if (dst_string_length(name) == 5 && - name[1] == 'h' && - name[2] == 'i' && - name[3] == 'l' && - name[4] == 'e') { - return compile_while; - } - } - break; - default: - break; - } - return NULL; -} - -/* Compile an array */ -static Slot compile_array(DstCompiler *c, FormOptions opts, DstArray *array) { - DstScope *scope = c->tail; - FormOptions subOpts = form_options_default(); - DstBuffer *buffer = c->buffer; - Slot ret; - SlotTracker tracker; - uint32_t i, count; - count = array->count; - ret = compiler_get_target(c, opts); - tracker_init(c, &tracker); - for (i = 0; i < count; ++i) { - Slot slot = compile_value(c, subOpts, array->data[i]); - compiler_tracker_push(c, &tracker, compiler_realize_slot(c, slot)); - } - compiler_tracker_free(c, scope, &tracker); - dst_buffer_push_u16(c->vm, buffer, DST_OP_ARR); - dst_buffer_push_u16(c->vm, buffer, ret.index); - dst_buffer_push_u16(c->vm, buffer, count); - compiler_tracker_write(c, &tracker, 0); - return ret; -} - -/* Compile an object literal */ -static Slot compile_table(DstCompiler *c, FormOptions opts, DstTable *tab) { - DstScope *scope = c->tail; - FormOptions subOpts = form_options_default(); - DstBuffer *buffer = c->buffer; - Slot ret; - SlotTracker tracker; - uint32_t i, cap; - cap = tab->capacity; - ret = compiler_get_target(c, opts); - tracker_init(c, &tracker); - for (i = 0; i < cap; i += 2) { - if (tab->data[i].type != DST_NIL) { - Slot slot = compile_value(c, subOpts, tab->data[i]); - compiler_tracker_push(c, &tracker, compiler_realize_slot(c, slot)); - slot = compile_value(c, subOpts, tab->data[i + 1]); - compiler_tracker_push(c, &tracker, compiler_realize_slot(c, slot)); - } - } - compiler_tracker_free(c, scope, &tracker); - dst_buffer_push_u16(c->vm, buffer, DST_OP_DIC); - dst_buffer_push_u16(c->vm, buffer, ret.index); - dst_buffer_push_u16(c->vm, buffer, tab->count * 2); - compiler_tracker_write(c, &tracker, 0); - return ret; -} - -/* Compile a form. Checks for special forms. */ -static Slot compile_form(DstCompiler *c, FormOptions opts, const DstValue *form) { - DstScope *scope = c->tail; - DstBuffer *buffer = c->buffer; - SpecialFormHelper helper; - /* Empty forms evaluate to nil. */ - if (dst_tuple_length(form) == 0) { - DstValue temp; - temp.type = DST_NIL; - return compile_nonref_type(c, opts, temp); - } - /* Check and handle special forms */ - helper = get_special(form); - if (helper != NULL) { - return helper(c, opts, form); - } else { - Slot ret, callee; - SlotTracker tracker; - FormOptions subOpts = form_options_default(); - uint32_t i; - tracker_init(c, &tracker); - /* Compile function to be called */ - callee = compiler_realize_slot(c, compile_value(c, subOpts, form[0])); - /* Compile all of the arguments */ - for (i = 1; i < dst_tuple_length(form); ++i) { - Slot slot = compile_value(c, subOpts, form[i]); - compiler_tracker_push(c, &tracker, slot); - } - /* Free up some slots */ - compiler_drop_slot(c, scope, callee); - compiler_tracker_free(c, scope, &tracker); - /* Prepare next stack frame */ - dst_buffer_push_u16(c->vm, buffer, DST_OP_PSK); - dst_buffer_push_u16(c->vm, buffer, dst_tuple_length(form) - 1); - /* Write the location of all of the arguments */ - compiler_tracker_write(c, &tracker, 0); - /* If this is in tail position do a tail call. */ - if (opts.isTail) { - dst_buffer_push_u16(c->vm, buffer, DST_OP_TCL); - dst_buffer_push_u16(c->vm, buffer, callee.index); - ret.hasReturned = 1; - ret.isNil = 1; - } else { - ret = compiler_get_target(c, opts); - dst_buffer_push_u16(c->vm, buffer, DST_OP_CAL); - dst_buffer_push_u16(c->vm, buffer, callee.index); - dst_buffer_push_u16(c->vm, buffer, ret.index); - } - return ret; - } -} - -/* Recursively compile any value or form */ -static Slot compile_value(DstCompiler *c, FormOptions opts, DstValue x) { - Slot ret; - /* Check if recursion is too deep */ - if (--c->recursionGuard == 0) { - c_error(c, "recursed too deeply"); - } - switch (x.type) { - case DST_NIL: - case DST_BOOLEAN: - case DST_REAL: - case DST_INTEGER: - ret = compile_nonref_type(c, opts, x); - break; - case DST_SYMBOL: - ret = compile_symbol(c, opts, x); - break; - case DST_TUPLE: - ret = compile_form(c, opts, x.as.tuple); - break; - case DST_ARRAY: - ret = compile_array(c, opts, x.as.array); - break; - case DST_TABLE: - ret = compile_table(c, opts, x.as.table); - break; - default: - ret = compile_literal(c, opts, x); - break; - } - c->recursionGuard++; - return ret; -} - -/* Compile interface. Returns a function that evaluates the - * given AST. Returns NULL if there was an error during compilation. */ -DstValue dst_compile(Dst *vm, DstTable *env, DstValue form) { - DstCompiler c; - FormOptions opts = form_options_default(); - DstFuncDef *def; - if (setjmp(c.onError)) { - if (c.error.type == DST_NIL) - return dst_string_cv(vm, "unknown error"); - return c.error; - } - c.error.type = DST_NIL; - c.env = env; - c.vm = vm; - c.tail = NULL; - c.buffer = dst_buffer(vm, 24); - c.recursionGuard = DST_RECURSION_GUARD; - compiler_push_scope(&c, 0); - opts.isTail = 1; - compiler_return(&c, compile_value(&c, opts, form)); - def = compiler_gen_funcdef(&c, c.buffer->count, 0, 0); - { - DstFuncEnv *env = dst_alloc(vm, sizeof(DstFuncEnv)); - DstFunction *func = dst_alloc(vm, sizeof(DstFunction)); - env->values = NULL; - env->stackOffset = 0; - env->thread = NULL; - func->parent = NULL; - func->def = def; - func->env = env; - return dst_wrap_function(func); - } -} diff --git a/junkyard/compile_test.c b/junkyard/compile_test.c deleted file mode 100644 index eb4a58bb..00000000 --- a/junkyard/compile_test.c +++ /dev/null @@ -1,77 +0,0 @@ -#include "unit.h" -#include -#include - -int testprint(DstValue *argv, int32_t argn) { - int32_t i; - for (i = 0; i < argn; i++) { - dst_puts(dst_formatc("%v\n", argv[i])); - } - return 0; -} - -DstReg testreg[] = { - {"print", testprint}, - {"+", dst_add}, - {"-", dst_subtract}, - {"*", dst_multiply}, - {"/", dst_divide}, - {"%", dst_modulo}, - {"acos", dst_acos}, - {"asin", dst_asin} -}; - -int main() { - DstParseResult pres; - DstCompileOptions opts; - DstCompileResult cres; - DstFunction *func; - - FILE *f = fopen("./dsttest/basic.dst", "rb"); - fseek(f, 0, SEEK_END); - long fsize = ftell(f); - fseek(f, 0, SEEK_SET); //same as rewind(f); - - char *string = malloc(fsize + 1); - fread(string, fsize, 1, f); - fclose(f); - - string[fsize] = 0; - - dst_init(); - - pres = dst_parsec(string); - free(string); - - if (pres.status == DST_PARSE_ERROR) { - dst_puts(dst_formatc("parse error at %d: %S\n", pres.bytes_read, pres.error)); - return 1; - } - assert(pres.status == DST_PARSE_OK); - dst_puts(dst_formatc("\nparse result: %v\n\n", pres.value)); - - opts.flags = 0; - opts.source = pres.value; - opts.sourcemap = pres.map; - opts.env = dst_loadreg(testreg, sizeof(testreg)/sizeof(DstReg)); - dst_puts(dst_formatc("initial compile env: %v\n", opts.env)); - - cres = dst_compile(opts); - if (cres.status == DST_COMPILE_ERROR) { - dst_puts(dst_formatc("compilation error: %S\n", cres.error)); - dst_puts(dst_formatc("error location: %d, %d\n", cres.error_start, cres.error_end)); - return 1; - } - assert(cres.status == DST_COMPILE_OK); - - dst_puts(dst_formatc("\nfuncdef: %v\n\n", dst_disasm(cres.funcdef))); - - func = dst_compile_func(cres); - - dst_run(dst_wrap_function(func)); - dst_puts(dst_formatc("result: %v\n", dst_vm_fiber->ret)); - - dst_deinit(); - - return 0; -} diff --git a/junkyard/fiber_test.c b/junkyard/fiber_test.c deleted file mode 100644 index e23ad5cc..00000000 --- a/junkyard/fiber_test.c +++ /dev/null @@ -1,91 +0,0 @@ -#include "unit.h" -#include "../core/gc.h" -#include -#include - -/* Create dud funcdef and function */ -static DstFunction *dud_func(uint32_t slotcount, uint32_t arity, int varargs) { - DstFuncDef *def = dst_gcalloc(DST_MEMORY_FUNCDEF, sizeof(DstFuncDef)); - def->environments_length = 0; - def->constants_length = 0; - def->bytecode_length = 0; - def->environments = NULL; - def->constants = NULL; - def->bytecode = NULL; - def->flags = varargs ? DST_FUNCDEF_FLAG_VARARG : 0; - def->arity = arity; - def->slotcount = slotcount; - DstFunction *f = dst_gcalloc(DST_MEMORY_FUNCTION, sizeof(DstFunction)); - f->envs = NULL; - f->def = def; - return f; -} - -/* Print debug information for a fiber */ -static void debug_print_fiber(DstFiber *fiber, int showslots) { - uint32_t frameindex = fiber->frame; - uint32_t frametopindex = fiber->frametop; - const char *statusname = - fiber->status == DST_FIBER_ALIVE ? "alive" : - fiber->status == DST_FIBER_PENDING ? "pending" : - fiber->status == DST_FIBER_ERROR ? "error" : - "dead"; - - printf("fiber at %p\n", fiber); - printf(" frame = %d\n", fiber->frame); - printf(" frametop = %d\n", fiber->frametop); - printf(" stacktop = %d\n", fiber->stacktop); - printf(" capacity = %d\n", fiber->capacity); - printf(" status = %s\n -----\n", statusname); - - while (frameindex > 0) { - DstValue *stack = fiber->data + frameindex; - DstStackFrame *frame = dst_stack_frame(stack); - uint32_t slots = frametopindex - frameindex; - const uint8_t *str; - /* Print the stack frame */ - if (frame->func != NULL) - str = dst_to_string(dst_wrap_function(frame->func)); - else - str = dst_cstring(""); - printf(" at %.*s (slots: %d)\n", - dst_string_length(str), - (const char *)str, - slots); - /* Optionally print all values in the stack */ - if (showslots) { - for (uint32_t j = 0; j < slots; j++) { - const uint8_t *vstr = dst_to_string(stack[j]); - printf(" [%d]: %.*s\n", - j, - dst_string_length(vstr), - (const char *)vstr); - } - } - frametopindex = frameindex - DST_FRAME_SIZE; - frameindex = frame->prevframe; - } - -} - -int main() { - dst_init(); - - DstFunction *f1 = dud_func(5, 0, 1); - DstFiber *fiber1 = dst_fiber(10); - for (int i = 0; i < 2; i++) { - dst_fiber_funcframe(fiber1, f1); - } - for (int i = 0; i < 13; i++) { - dst_fiber_push(fiber1, dst_wrap_integer(i)); - } - for (int i = 0; i < 10; i++) { - dst_fiber_popvalue(fiber1); - } - dst_fiber_funcframe_tail(fiber1, dud_func(20, 0, 0)); - debug_print_fiber(fiber1, 1); - - //dst_deinit(); - - return 0; -} diff --git a/junkyard/nanbox_test.c b/junkyard/nanbox_test.c deleted file mode 100644 index 0506cce9..00000000 --- a/junkyard/nanbox_test.c +++ /dev/null @@ -1,265 +0,0 @@ -#include -#include -#include -#include "unit.h" - -/* Required interface for DstValue */ -/* wrap and unwrap for all types */ -/* Get type quickly */ -/* Check against type quickly */ -/* Small footprint */ -/* 64 bit integer support undecided */ - -/* 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_isnan(x) - check if value is nan - */ - -typedef union dst_t dst_t; -union dst_t { - uint64_t u64; - int64_t i64; - void *pointer; - double real; -}; - -/* dst_t */ - -/* 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), or when generating Signaling NaNs. */ - -/* |.......Tag.......|.......................Payload..................| */ -/* Non-double: t|11111111111|1ttt|xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx */ -/* Types of NIL, TRUE, and FALSE must have payload set to all 1s. */ - -/* Other possible representations: */ - -/* Common Style */ -/* Non-double: 1|11111111111|tttt|xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx */ - -/* LuaJIT style */ -/* Non-double: 1|11111111111|1ttt|txxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx */ - -/* Double (no NaNs): x xxxxxxxxxxx xxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx */ - -/* A simple scheme for nan boxed values */ -/* normal doubles, denormalized doubles, and infinities are doubles */ -/* Quiet nan is nil. Sign bit should be 0. */ - -#define DST_NANBOX_TYPEBITS 0x0007000000000000lu -#define DST_NANBOX_TAGBITS 0xFFFF000000000000lu - -#ifdef DST_64 -#define DST_NANBOX_POINTERBITS 0x0000FFFFFFFFFFFFlu -#else -#define DST_NANBOX_POINTERBITS 0x00000000FFFFFFFFlu -#endif - -#define DST_NANBOX_QUIET_BIT 0x0008000000000000lu - -#define dst_nanbox_tag(type) \ - ((((uint64_t)(type) & 0x8) << 12) | 0x7FF8 | (type)) - -#define dst_nanbox_checkauxtype(x, type) \ - (((x).u64 & DST_NANBOX_TAGBITS) == (dst_nanbox_tag((type)) << 48)) - -/* Check if number is nan or if number is real double */ -#define dst_nanbox_isreal(x) \ - (!isnan((x).real) || dst_nanbox_checkauxtype((x), DST_REAL)) - -#define dst_nanbox_tagbits(x) \ - ((x).u64 & 0xFFFF000000000000lu) - -#define dst_nanbox_payloadbits(x) \ - ((x).u64 & 0x0000FFFFFFFFFFFFlu) - -#define dst_nanbox_type(x) \ - (isnan((x).real) \ - ? (((x).u64 & DST_NANBOX_TYPEBITS) >> 48) | (((x).u64 >> 60) & 0x8) \ - : DST_REAL) - -#define dst_nanbox_checktype(x, t) \ - (((t) == DST_REAL) \ - ? dst_nanbox_isreal(x) \ - : dst_nanbox_checkauxtype((x), (t))) - -static inline void *dst_nanbox_to_pointer(dst_t x) { - /* We need to do this shift to keep the higher bits of the pointer - * the same as bit 47 as required by the x86 architecture. We may save - * an instruction if we do x.u64 & DST_NANBOX_POINTERBITS, but this 0s - * th high bits. */ - x.i64 = (x.i64 << 16) >> 16; - return x.pointer; -} - -static inline dst_t dst_nanbox_from_pointer(void *p, uint64_t tagmask) { - dst_t ret; - ret.pointer = p; - ret.u64 &= DST_NANBOX_POINTERBITS; - ret.u64 |= tagmask; - return ret; -} - -static inline dst_t dst_nanbox_from_double(double d) { - dst_t ret; - ret.real = d; - /* Normalize NaNs */ - if (d != d) - ret.u64 = dst_nanbox_tag(DST_REAL) << 48; - return ret; -} - -static inline dst_t dst_nanbox_from_bits(uint64_t bits) { - dst_t ret; - ret.u64 = bits; - return ret; -} - -#define dst_nanbox_truthy(x) \ - (~(dst_nanbox_checktype((x), DST_NIL) || dst_nanbox_checktype((x), DST_FALSE))) - -#define dst_nanbox_from_payload(t, p) \ - dst_nanbox_from_bits((dst_nanbox_tag(t) << 48) | (p)) - -#define dst_nanbox_wrap_(p, t) \ - dst_nanbox_from_pointer((p), (dst_nanbox_tag(t) << 48) | 0x7FF8000000000000lu) - -/* Wrap the simple types */ -#define dst_nanbox_wrap_nil() dst_nanbox_from_payload(DST_NIL, 1) -#define dst_nanbox_wrap_true() dst_nanbox_from_payload(DST_TRUE, 1) -#define dst_nanbox_wrap_false() dst_nanbox_from_payload(DST_FALSE, 1) -#define dst_nanbox_wrap_boolean(b) dst_nanbox_from_payload((b) ? DST_TRUE : DST_FALSE, 1) -#define dst_nanbox_wrap_integer(i) dst_nanbox_from_payload(DST_INTEGER, (uint32_t)(i)) -#define dst_nanbox_wrap_real(r) dst_nanbox_from_double(r) - -#define dst_nanbox_unwrap_boolean(x) \ - (((x).u64 >> 48) == dst_nanbox_tag(DST_TRUE)) - -#define dst_nanbox_unwrap_integer(x) \ - ((int32_t)((x).u64 & 0xFFFFFFFFlu)) - -#define dst_nanbox_unwrap_real(x) ((x).real) - -/* Wrap the pointer types */ -#define dst_nanbox_wrap_struct(s) dst_nanbox_wrap_((s), DST_STRUCT) -#define dst_nanbox_wrap_tuple(s) dst_nanbox_wrap_((s), DST_TUPLE) -#define dst_nanbox_wrap_fiber(s) dst_nanbox_wrap_((s), DST_FIBER) -#define dst_nanbox_wrap_array(s) dst_nanbox_wrap_((s), DST_ARRAY) -#define dst_nanbox_wrap_table(s) dst_nanbox_wrap_((s), DST_TABLE) -#define dst_nanbox_wrap_buffer(s) dst_nanbox_wrap_((s), DST_BUFFER) -#define dst_nanbox_wrap_string(s) dst_nanbox_wrap_((s), DST_STRING) -#define dst_nanbox_wrap_symbol(s) dst_nanbox_wrap_((s), DST_SYMBOL) -#define dst_nanbox_wrap_userdata(s) dst_nanbox_wrap_((s), DST_USERDATA) -#define dst_nanbox_wrap_function(s) dst_nanbox_wrap_((s), DST_FUNCTION) -#define dst_nanbox_wrap_cfunction(s) dst_nanbox_wrap_((s), DST_CFUNCTION) - -/* Unwrap the pointer types */ -#define dst_nanbox_unwrap_struct(x) ((const DstValue *)dst_nanbox_to_pointer(x)) -#define dst_nanbox_unwrap_tuple(x) ((const DstValue *)dst_nanbox_to_pointer(x)) -#define dst_nanbox_unwrap_fiber(x) ((DstFiber *)dst_nanbox_to_pointer(x)) -#define dst_nanbox_unwrap_array(x) ((DstArray *)dst_nanbox_to_pointer(x)) -#define dst_nanbox_unwrap_table(x) ((DstTable *)dst_nanbox_to_pointer(x)) -#define dst_nanbox_unwrap_buffer(x) ((DstBuffer *)dst_nanbox_to_pointer(x)) -#define dst_nanbox_unwrap_string(x) ((const uint8_t *)dst_nanbox_to_pointer(x)) -#define dst_nanbox_unwrap_symbol(x) ((const uint8_t *)dst_nanbox_to_pointer(x)) -#define dst_nanbox_unwrap_userdata(x) (dst_nanbox_to_pointer(x)) -#define dst_nanbox_unwrap_function(x) ((DstFunction *)dst_nanbox_to_pointer(x)) -#define dst_nanbox_unwrap_cfunction(x) ((DstCFunction)dst_nanbox_to_pointer(x)) - -void dst_nanbox_print(dst_t x) { - printf("hex: 0x%lx, " - "description: ", x.u64); - switch (dst_nanbox_type(x)) { - case DST_NIL: - printf("nil\n"); - break; - case DST_TRUE: - printf("true\n"); - break; - case DST_FALSE: - printf("false\n"); - break; - case DST_INTEGER: - printf("%dI\n", dst_nanbox_unwrap_integer(x)); - break; - case DST_STRUCT: - printf("\n", dst_nanbox_unwrap_struct(x)); - break; - case DST_TUPLE: - printf("\n", dst_nanbox_unwrap_tuple(x)); - break; - case DST_FIBER: - printf("\n", dst_nanbox_unwrap_fiber(x)); - break; - case DST_ARRAY: - printf("\n", dst_nanbox_unwrap_array(x)); - break; - case DST_TABLE: - printf("\n", dst_nanbox_unwrap_table(x)); - break; - case DST_STRING: - printf("\n", dst_nanbox_unwrap_string(x)); - break; - case DST_SYMBOL: - printf("\n", dst_nanbox_unwrap_symbol(x)); - break; - case DST_USERDATA: - printf("\n", dst_nanbox_unwrap_userdata(x)); - break; - case DST_FUNCTION: - printf("\n", dst_nanbox_unwrap_function(x)); - break; - case DST_CFUNCTION: - printf("\n", dst_nanbox_unwrap_cfunction(x)); - break; - case DST_BUFFER: - printf("\n", dst_nanbox_unwrap_buffer(x)); - break; - default: - printf("unknown type 0x%lu\n", dst_nanbox_type(x)); - case DST_REAL: - printf("%.21g\n", dst_nanbox_unwrap_real(x)); - break; - } - assert(dst_nanbox_checktype(x, dst_nanbox_type(x))); -} - -int main() { - printf("--- nan box test ---\n"); - printf("sizeof(dst_t) = %lu\n", sizeof(dst_t)); - - DstArray array; - - dst_t a = dst_nanbox_wrap_real(0.123); - dst_t b = dst_nanbox_wrap_nil(); - dst_nanbox_print(dst_nanbox_wrap_real(dst_nanbox_unwrap_real(a) + dst_nanbox_unwrap_real(b))); - - dst_nanbox_print(dst_nanbox_wrap_real(0.125)); - dst_nanbox_print(dst_nanbox_wrap_real(19236910.125)); - dst_nanbox_print(dst_nanbox_wrap_real(123120.125)); - dst_nanbox_print(dst_nanbox_wrap_real(0.0)); - dst_nanbox_print(dst_nanbox_wrap_real(1.0/0.0)); - dst_nanbox_print(dst_nanbox_wrap_real(1.0/-0.0)); - dst_nanbox_print(dst_nanbox_wrap_real(0.0/-0.0)); - dst_nanbox_print(dst_nanbox_wrap_real(0.0/0.0)); - dst_nanbox_print(dst_nanbox_wrap_true()); - dst_nanbox_print(dst_nanbox_wrap_false()); - dst_nanbox_print(dst_nanbox_wrap_nil()); - dst_nanbox_print(dst_nanbox_wrap_integer(123)); - dst_nanbox_print(dst_nanbox_wrap_integer(-123)); - dst_nanbox_print(dst_nanbox_wrap_integer(0)); - - dst_nanbox_print(dst_nanbox_wrap_array(&array)); - dst_nanbox_print(dst_nanbox_wrap_table(&array)); - dst_nanbox_print(dst_nanbox_wrap_string(&array)); - dst_nanbox_print(dst_nanbox_wrap_buffer(&array)); - - printf("--- nan box test end ---\n"); -} diff --git a/junkyard/parse_test.c b/junkyard/parse_test.c deleted file mode 100644 index 818ee971..00000000 --- a/junkyard/parse_test.c +++ /dev/null @@ -1,19 +0,0 @@ -#include "unit.h" -#include - -int main() { - DstParseResult pres; - const uint8_t *str; - - dst_init(); - - pres = dst_parsec("'(+ 1 () [] 3 5 :hello \"hi\\h41\")"); - - assert(pres.status == DST_PARSE_OK); - assert(dst_checktype(pres.value, DST_TUPLE)); - - str = dst_to_string(pres.value); - printf("%.*s\n", dst_string_length(str), (const char *) str); - - return 0; -} diff --git a/junkyard/serialize.c b/junkyard/serialize.c deleted file mode 100644 index 9490ceff..00000000 --- a/junkyard/serialize.c +++ /dev/null @@ -1,60 +0,0 @@ -/* -* 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. -*/ - -#include -#include "internal.h" - -/** - * Data format v1 - * - * Types: - * - * Byte 0 to 200: small integer with value (byte - 100) - * Byte 201: Nil - * Byte 202: True - * Byte 203: False - * Byte 204: Number - IEEE 754 double format - * Byte 205: String - [u32 length]*[u8... characters] - * Byte 206: Struct - [u32 length]*2*[value... kvs] - * Byte 207: Buffer - [u32 capacity][u32 length]*[u8... characters] - * Byte 208: Array - [u32 length]*[value... elements] - * Byte 209: Tuple - [u32 length]*[value... elements] - * Byte 210: Thread - [value parent][u8 state][u32 frames]*[[value callee][value env] - * [u32 pcoffset][u32 ret][u32 args][u32 size]*[value ...stack]] - * Byte 211: Table - [u32 length]*2*[value... kvs] - * Byte 212: FuncDef - [u32 locals][u32 arity][u32 flags][u32 literallen]*[value... - * literals][u32 bytecodelen]*[u16... bytecode] - * Byte 213: FuncEnv - [value thread][u32 length]*[value ...upvalues] - * (upvalues is not read if thread is a thread object) - * Byte 214: Func - [value parent][value def][value env] - * (nil values indicate empty) - * Byte 215: LUdata - [value meta][u32 length]*[u8... bytes] - * Byte 216: CFunc - [u32 length]*[u8... idstring] - * Byte 217: Ref - [u32 id] - * Byte 218: Integer - [i64 value] - * Byte 219: Symbol - [u32 length]*[u8... characters] - * - * This data format needs both a serialization function and deserialization function - * written in C, as this will load embeded and precompiled programs into the VM, including - * the self hosted parser abd compiler. It is therefor important that it is correct, - * does not leak memory, and is fast. - */ diff --git a/junkyard/stl.c b/junkyard/stl.c deleted file mode 100644 index dae64883..00000000 --- a/junkyard/stl.c +++ /dev/null @@ -1,981 +0,0 @@ -/* -* 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. -*/ - -#include "internal.h" - -static const char DST_EXPECTED_INTEGER[] = "expected integer"; -static const char DST_EXPECTED_STRING[] = "expected string"; - -static const char *types[] = { - "nil", - "real", - "integer", - "boolean", - "string", - "symbol", - "array", - "tuple", - "table", - "struct", - "thread", - "buffer", - "function", - "cfunction", - "userdata", - "funcenv", - "funcdef" -}; - -static DstValue nil() { - DstValue n; - n.type = DST_NIL; - n.as.integer = 0; - return n; -} - -static DstValue integer(DstInteger i) { - DstValue n; - n.type = DST_INTEGER; - n.as.integer = i; - return n; -} - -static DstValue real(DstReal r) { - DstValue n; - n.type = DST_REAL; - n.as.real = r; - return n; -} - -static DstValue boolean(int b) { - DstValue n; - n.type = DST_BOOLEAN; - n.as.boolean = b; - return n; -} - -/***/ -/* Arithmetic */ -/***/ - -#define MAKE_BINOP(name, op)\ -static DstValue dst_stl_binop_##name(DstValue lhs, DstValue rhs) {\ - if (lhs.type == DST_INTEGER)\ - if (rhs.type == DST_INTEGER)\ - return integer(lhs.as.integer op rhs.as.integer);\ - else if (rhs.type == DST_REAL)\ - return real(lhs.as.integer op rhs.as.real);\ - else\ - return nil();\ - else if (lhs.type == DST_REAL)\ - if (rhs.type == DST_INTEGER)\ - return real(lhs.as.real op rhs.as.integer);\ - else if (rhs.type == DST_REAL)\ - return real(lhs.as.real op rhs.as.real);\ - else\ - return nil();\ - else\ - return nil();\ -} - -#define SIMPLE_ACCUM_FUNCTION(name, op)\ -MAKE_BINOP(name, op)\ -int dst_stl_##name(Dst* vm) {\ - DstValue lhs, rhs;\ - uint32_t j, count;\ - count = dst_args(vm);\ - lhs = dst_arg(vm, 0);\ - for (j = 1; j < count; ++j) {\ - rhs = dst_arg(vm, j);\ - lhs = dst_stl_binop_##name(lhs, rhs);\ - }\ - if (lhs.type == DST_NIL)\ - dst_c_throwc(vm, "expected integer/real");\ - dst_c_return(vm, lhs);\ -} - -SIMPLE_ACCUM_FUNCTION(add, +) -SIMPLE_ACCUM_FUNCTION(mul, *) -SIMPLE_ACCUM_FUNCTION(sub, -) - -/* Detect division by zero */ -MAKE_BINOP(div, /) -int dst_stl_div(Dst *vm) { - DstValue lhs, rhs; - uint32_t j, count; - count = dst_args(vm); - lhs = dst_arg(vm, 0); - for (j = 1; j < count; ++j) { - rhs = dst_arg(vm, j); - if (lhs.type == DST_INTEGER && rhs.type == DST_INTEGER && rhs.as.integer == 0) - dst_c_throwc(vm, "cannot integer divide by 0"); - lhs = dst_stl_binop_div(lhs, rhs); - } - if (lhs.type == DST_NIL) - dst_c_throwc(vm, "expected integer/real"); - dst_c_return(vm, lhs); -} - -#undef SIMPLE_ACCUM_FUNCTION - -#define BITWISE_FUNCTION(name, op) \ -int dst_stl_##name(Dst *vm) {\ - DstValue ret;\ - uint32_t i, count;\ - count = dst_args(vm);\ - ret = dst_arg(vm, 0);\ - if (ret.type != DST_INTEGER) {\ - dst_c_throwc(vm, "expected integer");\ - }\ - if (count < 2) {\ - dst_c_return(vm, ret);\ - }\ - for (i = 1; i < count; ++i) {\ - DstValue next = dst_arg(vm, i);\ - if (next.type != DST_INTEGER) {\ - dst_c_throwc(vm, "expected integer");\ - }\ - ret.as.integer = ret.as.integer op next.as.integer;\ - }\ - dst_c_return(vm, ret);\ -} - -BITWISE_FUNCTION(band, &) -BITWISE_FUNCTION(bor, |) -BITWISE_FUNCTION(bxor, ^) -BITWISE_FUNCTION(blshift, <<) -BITWISE_FUNCTION(brshift, >>) - -#undef BITWISE_FUNCTION - -int dst_stl_bnot(Dst *vm) { - DstValue in = dst_arg(vm, 0); - uint32_t count = dst_args(vm); - if (count != 1 || in.type != DST_INTEGER) { - dst_c_throwc(vm, "expected 1 integer argument"); - } - in.as.integer = ~in.as.integer; - dst_c_return(vm, in); -} - -#define COMPARE_FUNCTION(name, check)\ -int dst_stl_##name(Dst *vm) {\ - DstValue ret;\ - uint32_t i, count;\ - count = dst_args(vm);\ - ret.as.boolean = 1;\ - ret.type = DST_BOOLEAN;\ - if (count < 2) {\ - dst_c_return(vm, ret);\ - }\ - for (i = 1; i < count; ++i) {\ - DstValue lhs = dst_arg(vm, i - 1);\ - DstValue rhs = dst_arg(vm, i);\ - if (!(check)) {\ - ret.as.boolean = 0;\ - break;\ - }\ - }\ - dst_c_return(vm, ret);\ -} - -COMPARE_FUNCTION(lessthan, dst_compare(lhs, rhs) < 0) -COMPARE_FUNCTION(greaterthan, dst_compare(lhs, rhs) > 0) -COMPARE_FUNCTION(equal, dst_equals(lhs, rhs)) -COMPARE_FUNCTION(notequal, !dst_equals(lhs, rhs)) -COMPARE_FUNCTION(lessthaneq, dst_compare(lhs, rhs) <= 0) -COMPARE_FUNCTION(greaterthaneq, dst_compare(lhs, rhs) >= 0) - -#undef COMPARE_FUNCTION - -/* Boolean not */ -int dst_stl_not(Dst *vm) { - dst_c_return(vm, boolean(!dst_truthy(dst_arg(vm, 0)))); -} - -/****/ -/* Core */ -/****/ - -/* Empty a mutable datastructure */ -int dst_stl_clear(Dst *vm) { - DstValue x = dst_arg(vm, 0); - switch (x.type) { - default: - dst_c_throwc(vm, "cannot clear"); - case DST_ARRAY: - x.as.array->count = 0; - break; - case DST_BUFFER: - x.as.buffer->count = 0; - break; - case DST_TABLE: - dst_table_clear(x.as.table); - break; - } - dst_c_return(vm, x); -} - -/* Get length of object */ -int dst_stl_length(Dst *vm) { - dst_set_integer(vm, 0, dst_length(vm, 0)); - dst_return(vm, 0); - return 0; -} - -/* Get hash of a value */ -int dst_stl_hash(Dst *vm) { - dst_set_integer(vm, 0, dst_hash(vm, 0);); - dst_return(vm, 0); - return 0; -} - -/* Convert to integer */ -int dst_stl_to_int(Dst *vm) { - DstValue x = dst_arg(vm, 0); - if (x.type == DST_INTEGER) dst_c_return(vm, x); - if (x.type == DST_REAL) - dst_c_return(vm, integer((DstInteger) x.as.real)); - else - dst_c_throwc(vm, "expected number"); -} - -/* Convert to integer */ -int dst_stl_to_real(Dst *vm) { - DstValue x = dst_arg(vm, 0); - if (x.type == DST_REAL) dst_c_return(vm, x); - if (x.type == DST_INTEGER) - dst_c_return(vm, dst_wrap_real((DstReal) x.as.integer)); - else - dst_c_throwc(vm, "expected number"); -} - -/* Get a slice of a sequence */ -int dst_stl_slice(Dst *vm) { - uint32_t count = dst_args(vm); - int32_t from, to; - DstValue x; - const DstValue *data; - const uint8_t *cdata; - uint32_t length; - uint32_t newlength; - DstInteger num; - - /* Get data */ - x = dst_arg(vm, 0); - if (!dst_seq_view(x, &data, &length) && - !dst_chararray_view(x, &cdata, &length)) { - dst_c_throwc(vm, "expected array/tuple/buffer/symbol/string"); - } - - /* Get from index */ - if (count < 2) { - from = 0; - } else { - if (!dst_check_integer(vm, 1, &num)) - dst_c_throwc(vm, DST_EXPECTED_INTEGER); - from = dst_startrange(num, length); - } - - /* Get to index */ - if (count < 3) { - to = length; - } else { - if (!dst_check_integer(vm, 2, &num)) - dst_c_throwc(vm, DST_EXPECTED_INTEGER); - to = dst_endrange(num, length); - } - - /* Check from bad bounds */ - if (from < 0 || to < 0 || to < from) - dst_c_throwc(vm, "index out of bounds"); - - /* Build slice */ - newlength = to - from; - if (x.type == DST_TUPLE) { - DstValue *tup = dst_tuple_begin(vm, newlength); - dst_memcpy(tup, data + from, newlength * sizeof(DstValue)); - dst_c_return(vm, dst_wrap_tuple(dst_tuple_end(vm, tup))); - } else if (x.type == DST_ARRAY) { - DstArray *arr = dst_array(vm, newlength); - arr->count = newlength; - dst_memcpy(arr->data, data + from, newlength * sizeof(DstValue)); - dst_c_return(vm, dst_wrap_array(arr)); - } else if (x.type == DST_STRING) { - dst_c_return(vm, dst_wrap_string(dst_string_b(vm, x.as.string + from, newlength))); - } else if (x.type == DST_SYMBOL) { - dst_c_return(vm, dst_wrap_symbol(dst_string_b(vm, x.as.string + from, newlength))); - } else { /* buffer */ - DstBuffer *b = dst_buffer(vm, newlength); - dst_memcpy(b->data, x.as.buffer->data, newlength); - b->count = newlength; - dst_c_return(vm, dst_wrap_buffer(b)); - } -} - -/* Get type of object */ -int dst_stl_type(Dst *vm) { - DstValue x; - const char *typestr = "nil"; - uint32_t count = dst_args(vm); - if (count == 0) - dst_c_throwc(vm, "expected at least 1 argument"); - x = dst_arg(vm, 0); - switch (x.type) { - default: - break; - case DST_REAL: - typestr = "real"; - break; - case DST_INTEGER: - typestr = "integer"; - break; - case DST_BOOLEAN: - typestr = "boolean"; - break; - case DST_STRING: - typestr = "string"; - break; - case DST_SYMBOL: - typestr = "symbol"; - break; - case DST_ARRAY: - typestr = "array"; - break; - case DST_TUPLE: - typestr = "tuple"; - break; - case DST_THREAD: - typestr = "thread"; - break; - case DST_BUFFER: - typestr = "buffer"; - break; - case DST_FUNCTION: - typestr = "function"; - break; - case DST_CFUNCTION: - typestr = "cfunction"; - break; - case DST_TABLE: - typestr = "table"; - break; - case DST_USERDATA: - typestr = "userdata"; - break; - case DST_FUNCENV: - typestr = "funcenv"; - break; - case DST_FUNCDEF: - typestr = "funcdef"; - break; - } - dst_c_return(vm, dst_string_cv(vm, typestr)); -} - -/* Create array */ -int dst_stl_array(Dst *vm) { - uint32_t i; - uint32_t count = dst_args(vm); - DstArray *array = dst_array(vm, count); - for (i = 0; i < count; ++i) - array->data[i] = dst_arg(vm, i); - dst_c_return(vm, dst_wrap_array(array)); -} - -/* Create tuple */ -int dst_stl_tuple(Dst *vm) { - uint32_t i; - uint32_t count = dst_args(vm); - DstValue *tuple= dst_tuple_begin(vm, count); - for (i = 0; i < count; ++i) - tuple[i] = dst_arg(vm, i); - dst_c_return(vm, dst_wrap_tuple(dst_tuple_end(vm, tuple))); -} - -/* Create object */ -int dst_stl_table(Dst *vm) { - uint32_t i; - uint32_t count = dst_args(vm); - DstTable *table; - if (count % 2 != 0) - dst_c_throwc(vm, "expected even number of arguments"); - table = dst_table(vm, 4 * count); - for (i = 0; i < count; i += 2) - dst_table_put(vm, table, dst_arg(vm, i), dst_arg(vm, i + 1)); - dst_c_return(vm, dst_wrap_table(table)); -} - -/* Create struct */ -int dst_stl_struct(Dst *vm) { - uint32_t i; - uint32_t count = dst_args(vm); - DstValue *st; - if (count % 2 != 0) - dst_c_throwc(vm, "expected even number of arguments"); - st = dst_struct_begin(vm, count / 2); - for (i = 0; i < count; i += 2) - dst_struct_put(st, dst_arg(vm, i), dst_arg(vm, i + 1)); - dst_c_return(vm, dst_wrap_struct(dst_struct_end(vm, st))); -} - -/* Create a buffer */ -int dst_stl_buffer(Dst *vm) { - uint32_t i, count; - const uint8_t *dat; - uint32_t slen; - DstBuffer *buf = dst_buffer(vm, 10); - count = dst_args(vm); - for (i = 0; i < count; ++i) { - if (dst_chararray_view(dst_arg(vm, i), &dat, &slen)) - dst_buffer_append(vm, buf, dat, slen); - else - dst_c_throwc(vm, DST_EXPECTED_STRING); - } - dst_c_return(vm, dst_wrap_buffer(buf)); -} - -/* Create a string */ -int dst_stl_string(Dst *vm) { - uint32_t j; - uint32_t count = dst_args(vm); - uint32_t length = 0; - uint32_t index = 0; - uint8_t *str; - const uint8_t *dat; - uint32_t slen; - /* Find length and assert string arguments */ - for (j = 0; j < count; ++j) { - if (!dst_chararray_view(dst_arg(vm, j), &dat, &slen)) { - DstValue newarg; - dat = dst_to_string(vm, dst_arg(vm, j)); - slen = dst_string_length(dat); - newarg.type = DST_STRING; - newarg.as.string = dat; - dst_set_arg(vm, j, newarg); - } - length += slen; - } - /* Make string */ - str = dst_string_begin(vm, length); - for (j = 0; j < count; ++j) { - dst_chararray_view(dst_arg(vm, j), &dat, &slen); - dst_memcpy(str + index, dat, slen); - index += slen; - } - dst_c_return(vm, dst_wrap_string(dst_string_end(vm, str))); -} - -/* Create a symbol */ -int dst_stl_symbol(Dst *vm) { - int ret = dst_stl_string(vm); - if (ret == DST_RETURN_OK) { - vm->ret.type = DST_SYMBOL; - } - return ret; -} - -/* Create a thread */ -int dst_stl_thread(Dst *vm) { - DstThread *t; - DstValue callee = dst_arg(vm, 0); - DstValue parent = dst_arg(vm, 1); - DstValue errorParent = dst_arg(vm, 2); - t = dst_thread(vm, callee, 10); - if (callee.type != DST_FUNCTION && callee.type != DST_CFUNCTION) - dst_c_throwc(vm, "expected function in thread constructor"); - if (parent.type == DST_THREAD) { - t->parent = parent.as.thread; - } else if (parent.type != DST_NIL) { - dst_c_throwc(vm, "expected thread/nil as parent"); - } else { - t->parent = vm->thread; - } - dst_c_return(vm, dst_wrap_thread(t)); -} - -/* Get current thread */ -int dst_stl_current(Dst *vm) { - dst_c_return(vm, dst_wrap_thread(vm->thread)); -} - -/* Get parent of a thread */ -/* TODO - consider implications of this function - * for sandboxing */ -int dst_stl_parent(Dst *vm) { - DstThread *t; - if (!dst_check_thread(vm, 0, &t)) - dst_c_throwc(vm, "expected thread"); - if (t->parent == NULL) - dst_c_return(vm, dst_wrap_nil()); - dst_c_return(vm, dst_wrap_thread(t->parent)); -} - -/* Get the status of a thread */ -int dst_stl_status(Dst *vm) { - DstThread *t; - const char *cstr; - if (!dst_check_thread(vm, 0, &t)) - dst_c_throwc(vm, "expected thread"); - switch (t->status) { - case DST_THREAD_PENDING: - cstr = "pending"; - break; - case DST_THREAD_ALIVE: - cstr = "alive"; - break; - case DST_THREAD_DEAD: - cstr = "dead"; - break; - case DST_THREAD_ERROR: - cstr = "error"; - break; - } - dst_c_return(vm, dst_string_cv(vm, cstr)); -} - -/* Associative get */ -int dst_stl_get(Dst *vm) { - DstValue ret; - uint32_t count; - const char *err; - count = dst_args(vm); - if (count != 2) - dst_c_throwc(vm, "expects 2 arguments"); - err = dst_get(dst_arg(vm, 0), dst_arg(vm, 1), &ret); - if (err != NULL) - dst_c_throwc(vm, err); - else - dst_c_return(vm, ret); -} - -/* Associative set */ -int dst_stl_set(Dst *vm) { - uint32_t count; - const char *err; - count = dst_args(vm); - if (count != 3) - dst_c_throwc(vm, "expects 3 arguments"); - err = dst_set(vm, dst_arg(vm, 0), dst_arg(vm, 1), dst_arg(vm, 2)); - if (err != NULL) - dst_c_throwc(vm, err); - else - dst_c_return(vm, dst_arg(vm, 0)); -} - -/* Push to end of array */ -int dst_stl_push(Dst *vm) { - DstValue ds = dst_arg(vm, 0); - if (ds.type != DST_ARRAY) - dst_c_throwc(vm, "expected array"); - dst_array_push(vm, ds.as.array, dst_arg(vm, 1)); - dst_c_return(vm, ds); -} - -/* Pop from end of array */ -int dst_stl_pop(Dst *vm) { - DstValue ds = dst_arg(vm, 0); - if (ds.type != DST_ARRAY) - dst_c_throwc(vm, "expected array"); - dst_c_return(vm, dst_array_pop(ds.as.array)); -} - -/* Peek at end of array */ -int dst_stl_peek(Dst *vm) { - DstValue ds = dst_arg(vm, 0); - if (ds.type != DST_ARRAY) - dst_c_throwc(vm, "expected array"); - dst_c_return(vm, dst_array_peek(ds.as.array)); -} - -/* Ensure array capacity */ -int dst_stl_ensure(Dst *vm) { - DstValue ds = dst_arg(vm, 0); - DstValue cap = dst_arg(vm, 1); - if (ds.type != DST_ARRAY) - dst_c_throwc(vm, "expected array"); - if (cap.type != DST_INTEGER) - dst_c_throwc(vm, DST_EXPECTED_INTEGER); - dst_array_ensure(vm, ds.as.array, (uint32_t) cap.as.integer); - dst_c_return(vm, ds); -} - -/* Get next key in struct or table */ -int dst_stl_next(Dst *vm) { - DstValue ds = dst_arg(vm, 0); - DstValue key = dst_arg(vm, 1); - if (ds.type == DST_TABLE) { - dst_c_return(vm, dst_table_next(ds.as.table, key)); - } else if (ds.type == DST_STRUCT) { - dst_c_return(vm, dst_struct_next(ds.as.st, key)); - } else { - dst_c_throwc(vm, "expected table or struct"); - } -} - -/* Print values for inspection */ -int dst_stl_print(Dst *vm) { - uint32_t j, count; - count = dst_args(vm); - for (j = 0; j < count; ++j) { - uint32_t i; - const uint8_t *string = dst_to_string(vm, dst_arg(vm, j)); - uint32_t len = dst_string_length(string); - for (i = 0; i < len; ++i) - fputc(string[i], stdout); - } - fputc('\n', stdout); - return DST_RETURN_OK; -} - -/* Long description */ -int dst_stl_description(Dst *vm) { - DstValue x = dst_arg(vm, 0); - const uint8_t *buf = dst_description(vm, x); - dst_c_return(vm, dst_wrap_string(buf)); -} - -/* Short description */ -int dst_stl_short_description(Dst *vm) { - DstValue x = dst_arg(vm, 0); - const uint8_t *buf = dst_short_description(vm, x); - dst_c_return(vm, dst_wrap_string(buf)); -} - -/* Exit */ -int dst_stl_exit(Dst *vm) { - int ret; - DstValue x = dst_arg(vm, 0); - ret = x.type == DST_INTEGER ? x.as.integer : (x.type == DST_REAL ? x.as.real : 0); - exit(ret); - return DST_RETURN_OK; -} - -/* Throw error */ -int dst_stl_error(Dst *vm) { - dst_c_throw(vm, dst_arg(vm, 0)); -} - -/***/ -/* Function reflection */ -/***/ - -int dst_stl_funcenv(Dst *vm) { - DstFunction *fn; - if (!dst_check_function(vm, 0, &fn)) - dst_c_throwc(vm, "expected function"); - if (fn->env) - dst_c_return(vm, dst_wrap_funcenv(fn->env)); - else - return DST_RETURN_OK; -} - -int dst_stl_funcdef(Dst *vm) { - DstFunction *fn; - if (!dst_check_function(vm, 0, &fn)) - dst_c_throwc(vm, "expected function"); - dst_c_return(vm, dst_wrap_funcdef(fn->def)); -} - -int dst_stl_funcparent(Dst *vm) { - DstFunction *fn; - if (!dst_check_function(vm, 0, &fn)) - dst_c_throwc(vm, "expected function"); - if (fn->parent) - dst_c_return(vm, dst_wrap_function(fn->parent)); - else - return DST_RETURN_OK; -} - -int dst_stl_def(Dst *vm) { - DstValue key = dst_arg(vm, 0); - if (dst_args(vm) != 2) { - dst_c_throwc(vm, "expected 2 arguments to global-def"); - } - if (key.type != DST_STRING && key.type != DST_SYMBOL) { - dst_c_throwc(vm, "expected string/symbol as first argument"); - } - key.type = DST_SYMBOL; - dst_env_put(vm, vm->env, key, dst_arg(vm, 1)); - dst_c_return(vm, dst_arg(vm, 1)); -} - -int dst_stl_var(Dst *vm) { - DstValue key = dst_arg(vm, 0); - if (dst_args(vm) != 2) { - dst_c_throwc(vm, "expected 2 arguments to global-var"); - } - if (key.type != DST_STRING && key.type != DST_SYMBOL) { - dst_c_throwc(vm, "expected string as first argument"); - } - key.type = DST_SYMBOL; - dst_env_putvar(vm, vm->env, key, dst_arg(vm, 1)); - dst_c_return(vm, dst_arg(vm, 1)); -} - -/****/ -/* IO */ -/****/ - -/* File type definition */ -static DstUserType dst_stl_filetype = { - "std.file", - NULL, - NULL, - NULL, - NULL -}; - -/* Open a a file and return a userdata wrapper arounf the C file API. */ -int dst_stl_open(Dst *vm) { - const uint8_t *fname = dst_to_string(vm, dst_arg(vm, 0)); - const uint8_t *fmode = dst_to_string(vm, dst_arg(vm, 1)); - FILE *f; - FILE **fp; - if (dst_args(vm) < 2 || dst_arg(vm, 0).type != DST_STRING - || dst_arg(vm, 1).type != DST_STRING) - dst_c_throwc(vm, "expected filename and filemode"); - f = fopen((const char *)fname, (const char *)fmode); - if (!f) - dst_c_throwc(vm, "could not open file"); - fp = dst_userdata(vm, sizeof(FILE *), &dst_stl_filetype); - *fp = f; - dst_c_return(vm, dst_wrap_userdata(fp)); -} - -/* Read an entire file into memory */ -int dst_stl_slurp(Dst *vm) { - DstBuffer *b; - long fsize; - FILE *f; - FILE **fp = dst_check_userdata(vm, 0, &dst_stl_filetype); - if (fp == NULL) dst_c_throwc(vm, "expected file"); - if (!dst_check_buffer(vm, 1, &b)) b = dst_buffer(vm, 10); - f = *fp; - /* Read whole file */ - fseek(f, 0, SEEK_END); - fsize = ftell(f); - fseek(f, 0, SEEK_SET); - /* Ensure buffer size */ - dst_buffer_ensure(vm, b, b->count + fsize); - fread((char *)(b->data + b->count), fsize, 1, f); - b->count += fsize; - dst_c_return(vm, dst_wrap_buffer(b)); -} - -/* Read a certain number of bytes into memory */ -int dst_stl_read(Dst *vm) { - DstBuffer *b; - FILE *f; - int64_t len; - FILE **fp = dst_check_userdata(vm, 0, &dst_stl_filetype); - if (fp == NULL) dst_c_throwc(vm, "expected file"); - if (!(dst_check_integer(vm, 1, &len))) dst_c_throwc(vm, "expected integer"); - if (!dst_check_buffer(vm, 2, &b)) b = dst_buffer(vm, 10); - f = *fp; - /* Ensure buffer size */ - dst_buffer_ensure(vm, b, b->count + len); - b->count += fread((char *)(b->data + b->count), len, 1, f) * len; - dst_c_return(vm, dst_wrap_buffer(b)); -} - -/* Write bytes to a file */ -int dst_stl_write(Dst *vm) { - FILE *f; - const uint8_t *data; - uint32_t len; - FILE **fp = dst_check_userdata(vm, 0, &dst_stl_filetype); - if (fp == NULL) dst_c_throwc(vm, "expected file"); - if (!dst_chararray_view(dst_arg(vm, 1), &data, &len)) dst_c_throwc(vm, "expected string|buffer"); - f = *fp; - fwrite(data, len, 1, f); - return DST_RETURN_OK; -} - -/* Close a file */ -int dst_stl_close(Dst *vm) { - FILE **fp = dst_check_userdata(vm, 0, &dst_stl_filetype); - if (fp == NULL) dst_c_throwc(vm, "expected file"); - fclose(*fp); - dst_c_return(vm, dst_wrap_nil()); -} - -/****/ -/* Temporary */ -/****/ - -/* Force garbage collection */ -int dst_stl_gcollect(Dst *vm) { - dst_collect(vm); - return DST_RETURN_OK; -} - -/***/ -/* Compilation */ -/***/ - -/* Generate a unique symbol */ -static int dst_stl_gensym(Dst *vm) { - DstValue source = dst_arg(vm, 0); - const uint8_t *sym = NULL; - uint32_t len; - const uint8_t *data; - if (source.type == DST_NIL) { - sym = dst_string_cu(vm, ""); - } else if (dst_chararray_view(source, &data, &len)) { - sym = dst_string_bu(vm, data, len); - } else { - dst_c_throwc(vm, "exepcted string/buffer/symbol/nil"); - } - dst_c_return(vm, dst_wrap_symbol(sym)); -} - -/* Compile a value */ -static int dst_stl_compile(Dst *vm) { - DstTable *env = vm->env; - if (dst_arg(vm, 1).type == DST_TABLE) { - env = dst_arg(vm, 1).as.table; - } - dst_c_return(vm, dst_compile(vm, env, dst_arg(vm, 0))); -} - -/* Get vm->env */ -static int dst_stl_getenv(Dst *vm) { - dst_c_return(vm, dst_wrap_table(vm->env)); -} - -/* Set vm->env */ -static int dst_stl_setenv(Dst *vm) { - DstValue newEnv = dst_arg(vm, 0); - if (newEnv.type != DST_TABLE) { - dst_c_throwc(vm, "expected table"); - } - vm->env = newEnv.as.table; - return DST_RETURN_OK; -} - -/****/ -/* Bootstraping */ -/****/ - -static const DstModuleItem std_module[] = { - /* Arithmetic */ - {"+", dst_stl_add}, - {"*", dst_stl_mul}, - {"-", dst_stl_sub}, - {"/", dst_stl_div}, - /* Comparisons */ - {"<", dst_stl_lessthan}, - {">", dst_stl_greaterthan}, - {"=", dst_stl_equal}, - {"not=", dst_stl_notequal}, - {"<=", dst_stl_lessthaneq}, - {">=", dst_stl_greaterthaneq}, - /* Bitwise arithmetic */ - {"band", dst_stl_band}, - {"bor", dst_stl_bor}, - {"bxor", dst_stl_bxor}, - {"blshift", dst_stl_blshift}, - {"brshift", dst_stl_brshift}, - {"bnot", dst_stl_bnot}, - /* IO */ - {"open", dst_stl_open}, - {"slurp", dst_stl_slurp}, - {"read", dst_stl_read}, - {"write", dst_stl_write}, - /* Compile */ - {"gensym", dst_stl_gensym}, - {"getenv", dst_stl_getenv}, - {"setenv", dst_stl_setenv}, - {"compile", dst_stl_compile}, - /* Other */ - {"not", dst_stl_not}, - {"clear", dst_stl_clear}, - {"length", dst_stl_length}, - {"hash", dst_stl_hash}, - {"integer", dst_stl_to_int}, - {"real", dst_stl_to_real}, - {"type", dst_stl_type}, - {"slice", dst_stl_slice}, - {"array", dst_stl_array}, - {"tuple", dst_stl_tuple}, - {"table", dst_stl_table}, - {"struct", dst_stl_struct}, - {"buffer", dst_stl_buffer}, - {"string", dst_stl_string}, - {"symbol", dst_stl_symbol}, - {"thread", dst_stl_thread}, - {"status", dst_stl_status}, - {"current", dst_stl_current}, - {"parent", dst_stl_parent}, - {"print", dst_stl_print}, - {"description", dst_stl_description}, - {"short-description", dst_stl_short_description}, - {"exit!", dst_stl_exit}, - {"get", dst_stl_get}, - {"set!", dst_stl_set}, - {"next", dst_stl_next}, - {"error", dst_stl_error}, - {"push!", dst_stl_push}, - {"pop!", dst_stl_pop}, - {"peek", dst_stl_peek}, - {"ensure!", dst_stl_ensure}, - {"open", dst_stl_open}, - {"slurp", dst_stl_slurp}, - {"read", dst_stl_read}, - {"write", dst_stl_write}, - {"close", dst_stl_close}, - {"funcenv", dst_stl_funcenv}, - {"funcdef", dst_stl_funcdef}, - {"funcparent", dst_stl_funcparent}, - {"gcollect", dst_stl_gcollect}, - {"global-def", dst_stl_def}, - {"global-var", dst_stl_var}, - {NULL, NULL} -}; - -/* Load stl library into the current environment. Create stl module object - * only if it is not yet created. */ -void dst_stl_load(Dst *vm) { - DstValue maybeEnv = dst_table_get(vm->modules, dst_string_cvs(vm, "std")); - if (maybeEnv.type == DST_TABLE) { - /* Module already created, so merge into main vm. */ - dst_env_merge(vm, vm->env, maybeEnv.as.table); - } else { - /* Module not yet created */ - /* Load the normal c functions */ - dst_module_mutable(vm, "std", std_module); - /* Wrap stdin and stdout */ - FILE **inp = dst_userdata(vm, sizeof(FILE *), &dst_stl_filetype); - FILE **outp = dst_userdata(vm, sizeof(FILE *), &dst_stl_filetype); - FILE **errp = dst_userdata(vm, sizeof(FILE *), &dst_stl_filetype); - *inp = stdin; - *outp = stdout; - *errp = stderr; - dst_module_put(vm, "std", "stdin", dst_wrap_userdata(inp)); - dst_module_put(vm, "std", "stdout", dst_wrap_userdata(outp)); - dst_module_put(vm, "std", "stderr", dst_wrap_userdata(outp)); - /* Now merge */ - maybeEnv = dst_table_get(vm->modules, dst_string_cvs(vm, "std")); - dst_env_merge(vm, vm->env, maybeEnv.as.table); - } -} diff --git a/junkyard/strtod_test.c b/junkyard/strtod_test.c deleted file mode 100644 index 6c4b364e..00000000 --- a/junkyard/strtod_test.c +++ /dev/null @@ -1,122 +0,0 @@ -/* -* 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. -*/ - -/* Use a custom double parser instead of libc's strtod for better portability - * and control. Also, uses a less strict rounding method than ieee to not incur - * the cost of 4000 loc and dependence on arbitary precision arithmetic. There - * is no plan to use arbitrary precision arithmetic for parsing numbers, and a - * formal rounding mode has yet to be chosen (round towards 0 seems - * reasonable). - * - * This version has been modified for much greater flexibility in parsing, such - * as choosing the radix, supporting integer output, and returning DstValues - * directly. - * - * Numbers are of the form [-+]R[rR]I.F[eE&][-+]X where R is the radix, I is - * the integer part, F is the fractional part, and X is the exponent. All - * signs, radix, decimal point, fractional part, and exponent can be ommited. - * The number will be considered and integer if the there is no decimal point - * and no exponent. Any number greater the 2^32-1 or less than -(2^32) will be - * coerced to a double. If there is an error, the function dst_scan_number will - * return a dst nil. The radix is assumed to be 10 if omitted, and the E - * separator for the exponent can only be used when the radix is 10. This is - * because E is a vaid digit in bases 15 or greater. For bases greater than 10, - * the letters are used as digitis. A through Z correspond to the digits 10 - * through 35, and the lowercase letters have the same values. The radix number - * is always in base 10. For example, a hexidecimal number could be written - * '16rdeadbeef'. dst_scan_number also supports some c style syntax for - * hexidecimal literals. The previous number could also be written - * '0xdeadbeef'. Note that in this case, the number will actually be a double - * as it will not fit in the range for a signed 32 bit integer. The string - * '0xbeef' would parse to an integer as it is in the range of an int32_t. */ - -#include "unit.h" -#include -#include - -DstValue dst_scan_number(const uint8_t *str, int32_t len); - -const char *valid_test_strs[] = { - "0", - "-0.0", - "+0", - "123", - "-123", - "aaaaaa", - "+a123", - "0.12312", - "89.12312", - "-123.01231", - "123e10", - "1203412347981232379183.13013248723478932478923478e12", - "120341234798123237918313013248723478932478923478", - "999_999_999_999", - "8r777", - "", - "----", - " ", - "--123", - "0xff", - "0xff.f", - "0xff&-1", - "0xfefefe", - "1926.4823e11", - "0xff_ff_ff_ff", - "0xff_ff_ff_ff_ff_ff", - "2r1010", - "2r10101010001101", - "123a", - "0.1e510", - "4.123123e-308", - "4.123123e-320", - "1e-308", - "1e-309", - "9e-308", - "9e-309", - "919283691283e-309", - "9999e302", - "123.12312.123", - "90.e0.1", - "90.e1", - ".e1" -}; - -int main() { - dst_init(); - unsigned i; - for (i = 0; i < (sizeof(valid_test_strs) / sizeof(void *)); i++) { - DstValue out; - double refout; - const uint8_t *str = (const uint8_t *) valid_test_strs[i]; - int32_t len = 0; while (str[len]) len++; - - refout = strtod(valid_test_strs[i], NULL); - out = dst_scan_number(str, len); - dst_puts(dst_formatc("literal: %s, out: %v, refout: %v\n", - valid_test_strs[i], out, dst_wrap_real(refout))); - - } - uint64_t x = 0x07FFFFFFFFFFFFFF; - uint64_t y = 36; - - printf("%llu, %llu\n", x, (x * y) / y); -} diff --git a/junkyard/table_test.c b/junkyard/table_test.c deleted file mode 100644 index 8acccba4..00000000 --- a/junkyard/table_test.c +++ /dev/null @@ -1,19 +0,0 @@ -#include "unit.h" -#include - -int main() { - dst_init(); - DstTable *table = dst_table(10); - assert(table->count == 0); - dst_table_put(table, dst_cstringv("a"), dst_cstringv("b")); - dst_table_put(table, dst_cstringv("b"), dst_cstringv("a")); - dst_table_put(table, dst_cstringv("a"), dst_cstringv("c")); - assert(table->count == 2); - dst_table_remove(table, dst_cstringv("a")); - assert(table->count == 1); - assert(dst_equals( - dst_table_get(table, dst_cstringv("b")), - dst_cstringv("a") - )); - return 0; -} diff --git a/junkyard/xxd.c b/junkyard/xxd.c deleted file mode 100644 index fde020ec..00000000 --- a/junkyard/xxd.c +++ /dev/null @@ -1,98 +0,0 @@ -/* -* 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. -*/ - -/* Simple clone of the xxd tool used at build time. Used to - * create headers out of source files. Only used for core libraries - * like the bootstrapping code and the stl. */ - -#include -#include -#include - -#define BUFSIZE 1024 -#define PERLINE 10 - -int main(int argc, const char **argv) { - - static const char hex[] = "0123456789ABCDEF"; - char buf[BUFSIZE]; - size_t bytesRead = 0; - int lineIndex = 0; - int line = 0; - - if (argc != 4) { - fprintf(stderr, "Usage: %s infile outfile symbol\n", argv[0]); - return 1; - } - - /* Open the files */ - FILE *in = fopen(argv[1], "rb"); - FILE *out = fopen(argv[2], "wb"); - - /* Check if files open successfully */ - if (in == NULL) { - fprintf(stderr, "Could not open input file %s\n", argv[1]); - return 1; - } else if (out == NULL) { - fprintf(stderr, "Could not open output file %s\n", argv[2]); - return 1; - } - - /* Write the header */ - fprintf(out, "/* Auto generated - DO NOT EDIT */\n\n"); - fprintf(out, "#include \n\n"); - fprintf(out, "const uint8_t dst_gen_%s[] = {", argv[3]); - - /* Read in chunks from buffer */ - while ((bytesRead = fread(buf, 1, sizeof(buf), in)) > 0) { - int i; - for (i = 0; i < bytesRead; ++i) { - int byte = ((uint8_t *)buf) [i]; - - /* Write the byte */ - if (lineIndex++ == 0) { - if (line++) - fputc(',', out); - fputs("\n\t", out); - } else { - fputs(", ", out); - } - fputs("0x", out); - fputc(hex[byte & 0xF], out); - fputc(hex[byte >> 4], out); - - /* Make line index wrap */ - if (lineIndex >= PERLINE) - lineIndex = 0; - - } - } - - /* Write the tail */ - fputs("\n};\n", out); - - /* Close the file handles */ - fclose(in); - fclose(out); - - return 0; -} \ No newline at end of file diff --git a/libs/testlib.c b/libs/testlib.c deleted file mode 100644 index 4b608370..00000000 --- a/libs/testlib.c +++ /dev/null @@ -1,14 +0,0 @@ -#include - -#ifdef DST_LIB -#define dst_entry _dst_init -#else -#define dst_entry dst_testlib_init -#endif - -int dst_entry(DstArgs args) { - DstTable *module = dst_get_module(args); - dst_module_def(module, "pi", dst_wrap_real(M_PI)); - *args.ret = dst_wrap_table(module); - return 0; -} diff --git a/packages/test.c b/packages/test.c deleted file mode 100644 index 928be974..00000000 --- a/packages/test.c +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/core/asm.c b/src/assembler/asm.c similarity index 97% rename from core/asm.c rename to src/assembler/asm.c index bb8d77e7..d0886499 100644 --- a/core/asm.c +++ b/src/assembler/asm.c @@ -23,9 +23,9 @@ #include #include -#include "opcodes.h" -#include "gc.h" -#include "util.h" +#include +#include +#include /* Bytecode op argument types */ @@ -492,21 +492,7 @@ static DstAssembleResult dst_asm1(DstAssembler *parent, Dst source, int flags) { (void) flags; /* Initialize funcdef */ - def = dst_gcalloc(DST_MEMORY_FUNCDEF, sizeof(DstFuncDef)); - def->environments = NULL; - def->constants = NULL; - def->bytecode = NULL; - def->flags = 0; - def->slotcount = 0; - def->arity = 0; - def->source = NULL; - def->sourcepath = NULL; - def->sourcemap = NULL; - def->defs = NULL; - def->defs_length = 0; - def->constants_length = 0; - def->bytecode_length = 0; - def->environments_length = 1; + def = dst_funcdef_alloc(); /* Initialize Assembler */ a.def = def; @@ -732,17 +718,6 @@ DstAssembleResult dst_asm(Dst source, int flags) { return dst_asm1(NULL, source, flags); } -/* Build a function from the result */ -DstFunction *dst_asm_func(DstAssembleResult result) { - if (result.status != DST_ASSEMBLE_OK) { - return NULL; - } - DstFunction *func = dst_gcalloc(DST_MEMORY_FUNCTION, sizeof(DstFunction)); - func->def = result.funcdef; - func->envs = NULL; - return func; -} - /* Disassembly */ /* Find the deinfintion of an instruction given the instruction word. Return @@ -917,7 +892,7 @@ int dst_asm_cfun(DstArgs args) { if (args.n < 1) return dst_throw(args, "expected assembly source"); res = dst_asm(args.v[0], 0); if (res.status == DST_ASSEMBLE_OK) { - return dst_return(args, dst_wrap_function(dst_asm_func(res))); + return dst_return(args, dst_wrap_function(dst_function(res.funcdef, NULL))); } else { return dst_throwv(args, dst_wrap_string(res.error)); } diff --git a/core/compile.c b/src/compiler/compile.c similarity index 97% rename from core/compile.c rename to src/compiler/compile.c index 185eb985..94d23cde 100644 --- a/core/compile.c +++ b/src/compiler/compile.c @@ -23,8 +23,12 @@ #include #include #include "compile.h" -#include "gc.h" -#include "util.h" + +#define DST_V_DEF_COPYMEM +#define DST_V_DEF_FLATTENMEM +#include +#undef DST_V_DEF_COPYMEM +#undef DST_V_DEF_FLATTENMEM DstFopts dstc_fopts_default(DstCompiler *c) { DstFopts ret; @@ -792,15 +796,11 @@ DstSlot dstc_value(DstFopts opts, Dst x) { /* Compile a funcdef */ DstFuncDef *dstc_pop_funcdef(DstCompiler *c) { DstScope scope = dst_v_last(c->scopes); - DstFuncDef *def = dst_gcalloc(DST_MEMORY_FUNCDEF, sizeof(DstFuncDef)); - def->source = NULL; - def->sourcepath = NULL; - def->sourcemap = NULL; + DstFuncDef *def = dst_funcdef_alloc(); def->slotcount = scope.smax + 1; /* Copy envs */ def->environments_length = dst_v_count(scope.envs); - def->environments = NULL; if (def->environments_length > 1) def->environments = dst_v_flatten(scope.envs); def->constants_length = dst_v_count(scope.consts); @@ -897,24 +897,6 @@ DstCompileResult dst_compile(Dst source, DstTable *env, int flags) { return c.result; } -DstFunction *dst_compile_func(DstCompileResult res) { - if (res.status != DST_COMPILE_OK) { - return NULL; - } - DstFunction *func = dst_gcalloc(DST_MEMORY_FUNCTION, sizeof(DstFunction)); - func->def = res.funcdef; - if (res.funcdef->flags & DST_FUNCDEF_FLAG_NEEDSENV) { - func->envs = malloc(sizeof(DstFuncEnv *)); - if (NULL == func->envs) { - DST_OUT_OF_MEMORY; - } - func->envs[0] = NULL; - } else { - func->envs = NULL; - } - return func; -} - /* C Function for compiling */ int dst_compile_cfun(DstArgs args) { DstCompileResult res; @@ -930,7 +912,7 @@ int dst_compile_cfun(DstArgs args) { } res = dst_compile(args.v[0], env, 0); if (res.status == DST_COMPILE_OK) { - DstFunction *fun = dst_compile_func(res); + DstFunction *fun = dst_function(res.funcdef, NULL); return dst_return(args, dst_wrap_function(fun)); } else { t = dst_table(2); diff --git a/core/compile.h b/src/compiler/compile.h similarity index 99% rename from core/compile.h rename to src/compiler/compile.h index 85c92005..a3ad2862 100644 --- a/core/compile.h +++ b/src/compiler/compile.h @@ -25,7 +25,8 @@ #include #include -#include "opcodes.h" +#include +#include /* Compiler typedefs */ typedef struct DstCompiler DstCompiler; diff --git a/core/compile_specials.c b/src/compiler/compile_specials.c similarity index 99% rename from core/compile_specials.c rename to src/compiler/compile_specials.c index d0dce7dd..3f00a584 100644 --- a/core/compile_specials.c +++ b/src/compiler/compile_specials.c @@ -22,9 +22,11 @@ #include #include +#include +#include #include "compile.h" -#include "gc.h" -#include "util.h" +#include +#include DstSlot dstc_quote(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) { if (argn != 1) { diff --git a/core/context.c b/src/compiler/context.c similarity index 97% rename from core/context.c rename to src/compiler/context.c index da6d9301..ba29ca21 100644 --- a/core/context.c +++ b/src/compiler/context.c @@ -21,7 +21,8 @@ */ #include -#include +#include +#include #define CHUNKSIZE 1024 @@ -158,7 +159,7 @@ int dst_context_run(DstContext *c, int flags) { { DstCompileResult cres = dst_compile(dst_parser_produce(&parser), c->env, flags); if (cres.status == DST_COMPILE_OK) { - DstFunction *f = dst_compile_func(cres); + DstFunction *f = dst_function(cres.funcdef, NULL); Dst ret; if (dst_run(dst_wrap_function(f), &ret)) { /* Get location from stacktrace? */ diff --git a/core/abstract.c b/src/core/abstract.c similarity index 100% rename from core/abstract.c rename to src/core/abstract.c diff --git a/core/array.c b/src/core/array.c similarity index 100% rename from core/array.c rename to src/core/array.c diff --git a/core/buffer.c b/src/core/buffer.c similarity index 100% rename from core/buffer.c rename to src/core/buffer.c diff --git a/core/fiber.c b/src/core/fiber.c similarity index 100% rename from core/fiber.c rename to src/core/fiber.c diff --git a/core/gc.c b/src/core/gc.c similarity index 100% rename from core/gc.c rename to src/core/gc.c diff --git a/core/gc.h b/src/core/gc.h similarity index 100% rename from core/gc.h rename to src/core/gc.h diff --git a/core/io.c b/src/core/io.c similarity index 95% rename from core/io.c rename to src/core/io.c index abc887b6..317e27af 100644 --- a/core/io.c +++ b/src/core/io.c @@ -230,14 +230,19 @@ static int dst_io_fclose(DstArgs args) { #define dst_lib_io _dst_init #endif +static const DstReg cfuns[] = { + {"fopen", dst_io_fopen}, + {"fclose", dst_io_fclose}, + {"fread", dst_io_fread}, + {"fwrite", dst_io_fwrite}, + {"fflush", dst_io_fflush}, + {NULL, NULL} +}; + /* Module entry point */ int dst_lib_io(DstArgs args) { DstTable *env = dst_env_arg(args); - dst_env_def(env, "fopen", dst_wrap_cfunction(dst_io_fopen)); - dst_env_def(env, "fclose", dst_wrap_cfunction(dst_io_fclose)); - dst_env_def(env, "fread", dst_wrap_cfunction(dst_io_fread)); - dst_env_def(env, "fwrite", dst_wrap_cfunction(dst_io_fwrite)); - dst_env_def(env, "fflush", dst_wrap_cfunction(dst_io_fflush)); + dst_env_cfuns(env, cfuns); /* stdout */ dst_env_def(env, "stdout", diff --git a/core/math.c b/src/core/math.c similarity index 84% rename from core/math.c rename to src/core/math.c index e21d79ed..ead2e44f 100644 --- a/core/math.c +++ b/src/core/math.c @@ -343,45 +343,50 @@ static int dst_math_not(DstArgs args) { return 0; } +static const DstReg cfuns[] = { + {"int", dst_int}, + {"real", dst_real}, + {"+", dst_add}, + {"-", dst_subtract}, + {"*", dst_multiply}, + {"/", dst_divide}, + {"%", dst_modulo}, + {"=", dst_math_equal}, + {"not=", dst_math_notequal}, + {"<", dst_math_ascending}, + {">", dst_math_descending}, + {"<=", dst_math_notdescending}, + {">=", dst_math_notascending}, + {"|", dst_bor}, + {"&", dst_band}, + {"^", dst_bxor}, + {"~", dst_bnot}, + {">>", dst_lshift}, + {"<<", dst_rshift}, + {">>>", dst_lshiftu}, + {"not", dst_math_not}, + {"cos", dst_cos}, + {"sin", dst_sin}, + {"tan", dst_tan}, + {"acos", dst_acos}, + {"asin", dst_asin}, + {"atan", dst_atan}, + {"exp", dst_exp}, + {"log", dst_log}, + {"log10", dst_log10}, + {"sqrt", dst_sqrt}, + {"floor", dst_floor}, + {"ceil", dst_ceil}, + {"pow", dst_pow}, + {NULL, NULL} +}; + /* Module entry point */ int dst_lib_math(DstArgs args) { DstTable *env = dst_env_arg(args); - dst_env_def(env, "int", dst_wrap_cfunction(dst_int)); - dst_env_def(env, "real", dst_wrap_cfunction(dst_real)); - dst_env_def(env, "+", dst_wrap_cfunction(dst_add)); - dst_env_def(env, "-", dst_wrap_cfunction(dst_subtract)); - dst_env_def(env, "*", dst_wrap_cfunction(dst_multiply)); - dst_env_def(env, "/", dst_wrap_cfunction(dst_divide)); - dst_env_def(env, "%", dst_wrap_cfunction(dst_modulo)); - dst_env_def(env, "=", dst_wrap_cfunction(dst_math_equal)); - dst_env_def(env, "not=", dst_wrap_cfunction(dst_math_notequal)); - dst_env_def(env, "<", dst_wrap_cfunction(dst_math_ascending)); - dst_env_def(env, ">", dst_wrap_cfunction(dst_math_descending)); - dst_env_def(env, "<=", dst_wrap_cfunction(dst_math_notdescending)); - dst_env_def(env, ">=", dst_wrap_cfunction(dst_math_notascending)); - dst_env_def(env, "|", dst_wrap_cfunction(dst_bor)); - dst_env_def(env, "&", dst_wrap_cfunction(dst_band)); - dst_env_def(env, "^", dst_wrap_cfunction(dst_bxor)); - dst_env_def(env, "~", dst_wrap_cfunction(dst_bnot)); - dst_env_def(env, ">>", dst_wrap_cfunction(dst_lshift)); - dst_env_def(env, "<<", dst_wrap_cfunction(dst_rshift)); - dst_env_def(env, ">>>", dst_wrap_cfunction(dst_lshiftu)); - dst_env_def(env, "not", dst_wrap_cfunction(dst_math_not)); - dst_env_def(env, "cos", dst_wrap_cfunction(dst_cos)); - dst_env_def(env, "sin", dst_wrap_cfunction(dst_sin)); - dst_env_def(env, "tan", dst_wrap_cfunction(dst_tan)); - dst_env_def(env, "acos", dst_wrap_cfunction(dst_acos)); - dst_env_def(env, "asin", dst_wrap_cfunction(dst_asin)); - dst_env_def(env, "atan", dst_wrap_cfunction(dst_atan)); - dst_env_def(env, "exp", dst_wrap_cfunction(dst_exp)); - dst_env_def(env, "log", dst_wrap_cfunction(dst_log)); - dst_env_def(env, "log10", dst_wrap_cfunction(dst_log10)); - dst_env_def(env, "sqrt", dst_wrap_cfunction(dst_sqrt)); - dst_env_def(env, "floor", dst_wrap_cfunction(dst_floor)); - dst_env_def(env, "ceil", dst_wrap_cfunction(dst_ceil)); - dst_env_def(env, "pow", dst_wrap_cfunction(dst_pow)); + dst_env_cfuns(env, cfuns); + dst_env_def(env, "pi", dst_wrap_real(3.1415926535897931)); - dst_env_def(env, "\xCF\x80", dst_wrap_real(3.1415926535897931)); dst_env_def(env, "e", dst_wrap_real(2.7182818284590451)); return 0; } diff --git a/core/native.c b/src/core/native.c similarity index 99% rename from core/native.c rename to src/core/native.c index 2be2527c..c956cdee 100644 --- a/core/native.c +++ b/src/core/native.c @@ -21,6 +21,7 @@ */ #include +#include /* Use LoadLibrary on windows or dlopen on posix to load dynamic libaries * with native code. */ diff --git a/core/stl.c b/src/core/stl.c similarity index 83% rename from core/stl.c rename to src/core/stl.c index 8e7ddf3f..2d4441a3 100644 --- a/core/stl.c +++ b/src/core/stl.c @@ -22,6 +22,7 @@ #include #include +#include int dst_stl_exit(DstArgs args) { int32_t exitcode = 0; @@ -245,35 +246,39 @@ int dst_stl_hash(DstArgs args) { return dst_return(args, dst_wrap_integer(dst_hash(args.v[0]))); } +static const DstReg cfuns[] = { + {"native", dst_load_native}, + {"print", dst_stl_print}, + {"describe", dst_stl_describe}, + {"string", dst_stl_string}, + {"buffer-string", dst_stl_buffer_to_string}, + {"table", dst_cfun_table}, + {"array", dst_cfun_array}, + {"tuple", dst_cfun_tuple}, + {"struct", dst_cfun_struct}, + {"fiber", dst_stl_fiber}, + {"status", dst_stl_status}, + {"buffer", dst_stl_buffer}, + {"gensym", dst_stl_gensym}, + {"get", dst_stl_get}, + {"put", dst_stl_put}, + {"length", dst_stl_length}, + {"gccollect", dst_stl_gccollect}, + {"type", dst_stl_type}, + {"next", dst_stl_next}, + {"hash", dst_stl_hash}, + {"exit", dst_stl_exit}, + {"asm", dst_asm_cfun}, + {"disasm", dst_disasm_cfun}, + {NULL, NULL} +}; + DstTable *dst_stl_env() { DstTable *env = dst_table(0); Dst ret = dst_wrap_table(env); - dst_env_def(env, "native", dst_wrap_cfunction(dst_load_native)); - dst_env_def(env, "print", dst_wrap_cfunction(dst_stl_print)); - dst_env_def(env, "describe", dst_wrap_cfunction(dst_stl_describe)); - dst_env_def(env, "string", dst_wrap_cfunction(dst_stl_string)); - dst_env_def(env, "buffer-to-string", dst_wrap_cfunction(dst_stl_buffer_to_string)); - dst_env_def(env, "table", dst_wrap_cfunction(dst_cfun_table)); - dst_env_def(env, "array", dst_wrap_cfunction(dst_cfun_array)); - dst_env_def(env, "tuple", dst_wrap_cfunction(dst_cfun_tuple)); - dst_env_def(env, "struct", dst_wrap_cfunction(dst_cfun_struct)); - dst_env_def(env, "fiber", dst_wrap_cfunction(dst_stl_fiber)); - dst_env_def(env, "status", dst_wrap_cfunction(dst_stl_status)); - dst_env_def(env, "buffer", dst_wrap_cfunction(dst_stl_buffer)); - dst_env_def(env, "gensym", dst_wrap_cfunction(dst_stl_gensym)); - dst_env_def(env, "get", dst_wrap_cfunction(dst_stl_get)); - dst_env_def(env, "put", dst_wrap_cfunction(dst_stl_put)); - dst_env_def(env, "length", dst_wrap_cfunction(dst_stl_length)); - dst_env_def(env, "gccollect", dst_wrap_cfunction(dst_stl_gccollect)); - dst_env_def(env, "type", dst_wrap_cfunction(dst_stl_type)); - dst_env_def(env, "next", dst_wrap_cfunction(dst_stl_next)); - dst_env_def(env, "hash", dst_wrap_cfunction(dst_stl_hash)); - dst_env_def(env, "exit", dst_wrap_cfunction(dst_stl_exit)); - - dst_env_def(env, "compile", dst_wrap_cfunction(dst_compile_cfun)); - dst_env_def(env, "asm", dst_wrap_cfunction(dst_asm_cfun)); - dst_env_def(env, "disasm", dst_wrap_cfunction(dst_disasm_cfun)); + /* Load main functions */ + dst_env_cfuns(env, cfuns); /* Allow references to the environment */ dst_env_def(env, "_env", ret); diff --git a/core/string.c b/src/core/string.c similarity index 100% rename from core/string.c rename to src/core/string.c diff --git a/core/struct.c b/src/core/struct.c similarity index 100% rename from core/struct.c rename to src/core/struct.c diff --git a/core/symcache.c b/src/core/symcache.c similarity index 100% rename from core/symcache.c rename to src/core/symcache.c diff --git a/core/symcache.h b/src/core/symcache.h similarity index 100% rename from core/symcache.h rename to src/core/symcache.h diff --git a/core/table.c b/src/core/table.c similarity index 100% rename from core/table.c rename to src/core/table.c diff --git a/core/tuple.c b/src/core/tuple.c similarity index 100% rename from core/tuple.c rename to src/core/tuple.c diff --git a/core/util.c b/src/core/util.c similarity index 74% rename from core/util.c rename to src/core/util.c index a58e7b24..19f50a21 100644 --- a/core/util.c +++ b/src/core/util.c @@ -22,6 +22,7 @@ #include #include "util.h" +#include "gc.h" /* Base 64 lookup table for digits */ const char dst_base64[65] = @@ -51,6 +52,16 @@ const char *dst_type_names[16] = { "abstract" }; +/* Calculate hash for string */ + +int32_t dst_string_calchash(const uint8_t *str, int32_t len) { + const uint8_t *end = str + len; + uint32_t hash = 5381; + while (str < end) + hash = (hash << 5) + hash + *str++; + return (int32_t) hash; +} + /* Computes hash of an array of values */ int32_t dst_array_calchash(const Dst *array, int32_t len) { const Dst *end = array + len; @@ -72,15 +83,6 @@ int32_t dst_kv_calchash(const DstKV *kvs, int32_t len) { return (int32_t) hash; } -/* Calculate hash for string */ -int32_t dst_string_calchash(const uint8_t *str, int32_t len) { - const uint8_t *end = str + len; - uint32_t hash = 5381; - while (str < end) - hash = (hash << 5) + hash + *str++; - return (int32_t) hash; -} - /* Calculate next power of 2. May overflow. If n is 0, * will return 0. */ int32_t dst_tablen(int32_t n) { @@ -123,6 +125,14 @@ void dst_env_var(DstTable *env, const char *name, Dst val) { dst_table_put(env, dst_csymbolv(name), dst_wrap_table(subt)); } +/* Load many cfunctions at once */ +void dst_env_cfuns(DstTable *env, const DstReg *cfuns) { + while (cfuns->name) { + dst_env_def(env, cfuns->name, dst_wrap_cfunction(cfuns->cfun)); + cfuns++; + } +} + /* Resolve a symbol in the environment. Undefined symbols will * resolve to nil */ Dst dst_env_resolve(DstTable *env, const char *name) { @@ -148,32 +158,6 @@ DstTable *dst_env_arg(DstArgs args) { return module; } -/* Do a binary search on a static array of structs. Each struct must - * have a string as its first element, and the struct must be sorted - * lexogrpahically by that element. */ -const void *dst_strbinsearch( - const void *tab, - size_t tabcount, - size_t itemsize, - const uint8_t *key) { - size_t low = 0; - size_t hi = tabcount; - while (low < hi) { - size_t mid = low + ((hi - low) / 2); - const char **item = (const char **)(tab + mid * itemsize); - const char *name = *item; - int comp = dst_cstrcmp(key, name); - if (comp < 0) { - hi = mid; - } else if (comp > 0) { - low = mid + 1; - } else { - return (const void *)item; - } - } - return NULL; -} - /* Read both tuples and arrays as c pointers + int32_t length. Return 1 if the * view can be constructed, 0 if an invalid type. */ int dst_seq_view(Dst seq, const Dst **data, int32_t *len) { @@ -222,56 +206,46 @@ int dst_hashtable_view(Dst tab, const DstKV **data, int32_t *len, int32_t *cap) return 0; } -/* Vector code */ - -/* Grow the buffer dynamically. Used for push operations. */ -void *dst_v_grow(void *v, int32_t increment, int32_t itemsize) { - int32_t dbl_cur = (NULL != v) ? 2 * dst_v__cap(v) : 0; - int32_t min_needed = dst_v_count(v) + increment; - int32_t m = dbl_cur > min_needed ? dbl_cur : min_needed; - int32_t *p = (int32_t *) realloc(v ? dst_v__raw(v) : 0, itemsize * m + sizeof(int32_t)*2); - if (NULL != p) { - if (!v) p[1] = 0; - p[0] = m; - return p + 2; - } else { - { - DST_OUT_OF_MEMORY; - } - return (void *) (2 * sizeof(int32_t)); // try to force a NULL pointer exception later - } +/* Allocate an empty funcdef. This function may have added functionality + * as commonalities between asm and compile arise. */ +DstFuncDef *dst_funcdef_alloc() { + DstFuncDef *def = dst_gcalloc(DST_MEMORY_FUNCDEF, sizeof(DstFuncDef)); + def->environments = NULL; + def->constants = NULL; + def->bytecode = NULL; + def->flags = 0; + def->slotcount = 0; + def->arity = 0; + def->source = NULL; + def->sourcepath = NULL; + def->sourcemap = NULL; + def->defs = NULL; + def->defs_length = 0; + def->constants_length = 0; + def->bytecode_length = 0; + def->environments_length = 1; + return def; } -/* Clone a buffer. */ -void *dst_v_copymem(void *v, int32_t itemsize) { - int32_t *p; - if (NULL == v) return NULL; - p = malloc(2 * sizeof(int32_t) + itemsize * dst_v__cap(v)); - if (NULL != p) { - memcpy(p, dst_v__raw(v), 2 * sizeof(int32_t) + itemsize * dst_v__cnt(v)); - return p + 2; +/* Create a closure from a funcdef and a parent function */ +DstFunction *dst_function(DstFuncDef *def, DstFunction *parent) { + int32_t i; + DstFunction *func = dst_gcalloc(DST_MEMORY_FUNCTION, sizeof(DstFunction)); + int32_t elen = def->environments_length; + func->def = def; + if (elen) { + func->envs = malloc(sizeof(DstFuncEnv *) * elen); + if (elen > 1 && !parent) return NULL; + if (NULL == func->envs) { + DST_OUT_OF_MEMORY; + } + func->envs[0] = NULL; } else { - { - DST_OUT_OF_MEMORY; - } - return (void *) (2 * sizeof(int32_t)); // try to force a NULL pointer exception later + func->envs = NULL; } -} - -/* Convert a buffer to normal allocated memory (forget capacity) */ -void *dst_v_flattenmem(void *v, int32_t itemsize) { - int32_t *p; - int32_t sizen; - if (NULL == v) return NULL; - sizen = itemsize * dst_v__cnt(v); - p = malloc(sizen); - if (NULL != p) { - memcpy(p, v, sizen); - return p; - } else { - { - DST_OUT_OF_MEMORY; - } - return NULL; + for (i = 1; i < def->environments_length; ++i) { + int32_t inherit = def->environments[i]; + func->envs[i] = parent->envs[inherit]; } + return func; } diff --git a/junkyard/unit.h b/src/core/util.h similarity index 78% rename from junkyard/unit.h rename to src/core/util.h index ba402027..5677d016 100644 --- a/junkyard/unit.h +++ b/src/core/util.h @@ -20,12 +20,16 @@ * IN THE SOFTWARE. */ -/* Header for unit testing of dst components */ - -#ifndef UNIT_H_U09UBW3V -#define UNIT_H_U09UBW3V +#ifndef DST_UTIL_H_defined +#define DST_UTIL_H_defined #include -#include -#endif /* end of include guard: UNIT_H_U09UBW3V */ +/* Utils */ +extern const char dst_base64[65]; +int32_t dst_array_calchash(const Dst *array, int32_t len); +int32_t dst_kv_calchash(const DstKV *kvs, int32_t len); +int32_t dst_string_calchash(const uint8_t *str, int32_t len); +int32_t dst_tablen(int32_t n); + +#endif diff --git a/core/value.c b/src/core/value.c similarity index 100% rename from core/value.c rename to src/core/value.c diff --git a/core/vm.c b/src/core/vm.c similarity index 96% rename from core/vm.c rename to src/core/vm.c index 26746d72..14609d1a 100644 --- a/core/vm.c +++ b/src/core/vm.c @@ -21,7 +21,7 @@ */ #include -#include "opcodes.h" +#include #include "symcache.h" #include "gc.h" @@ -422,28 +422,10 @@ static int dst_continue(Dst *returnreg) { case DOP_CLOSURE: { - int32_t i, elen; - DstFunction *fn; DstFuncDef *fd; vm_assert((int32_t)oparg(2, 0xFFFF) < func->def->defs_length, "invalid funcdef"); fd = func->def->defs[(int32_t)oparg(2, 0xFFFF)]; - fn = dst_gcalloc(DST_MEMORY_FUNCTION, sizeof(DstFunction)); - fn->def = fd; - elen = fd->environments_length; - if (elen) { - fn->envs = malloc(sizeof(DstFuncEnv *) * elen); - if (NULL == fn->envs) { - DST_OUT_OF_MEMORY; - } - fn->envs[0] = NULL; - } else { - fn->envs = NULL; - } - for (i = 1; i < fd->environments_length; ++i) { - int32_t inherit = fd->environments[i]; - fn->envs[i] = func->envs[inherit]; - } - stack[oparg(1, 0xFF)] = dst_wrap_function(fn); + stack[oparg(1, 0xFF)] = dst_wrap_function(dst_function(fd, func)); pc++; vm_checkgc_next(); } diff --git a/core/wrap.c b/src/core/wrap.c similarity index 100% rename from core/wrap.c rename to src/core/wrap.c diff --git a/include/dst/dststate.h b/src/include/headerlibs/strbinsearch.h similarity index 56% rename from include/dst/dststate.h rename to src/include/headerlibs/strbinsearch.h index 9b36ea4a..de14d5f9 100644 --- a/include/dst/dststate.h +++ b/src/include/headerlibs/strbinsearch.h @@ -20,36 +20,33 @@ * IN THE SOFTWARE. */ -#ifndef DST_STATE_H_defined -#define DST_STATE_H_defined +#ifndef DST_STRBINSEARCH_H_defined +#define DST_STRBINSEARCH_H_defined -#include -#include "dstconfig.h" -#include "dsttypes.h" +/* Do a binary search on a static array of structs. Each struct must + * have a string as its first element, and the struct must be sorted + * lexogrpahically by that element. */ +static const void *dst_strbinsearch( + const void *tab, + size_t tabcount, + size_t itemsize, + const uint8_t *key) { + size_t low = 0; + size_t hi = tabcount; + while (low < hi) { + size_t mid = low + ((hi - low) / 2); + const char **item = (const char **)(tab + mid * itemsize); + const char *name = *item; + int comp = dst_cstrcmp(key, name); + if (comp < 0) { + hi = mid; + } else if (comp > 0) { + low = mid + 1; + } else { + return (const void *)item; + } + } + return NULL; +} -/* 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 */ +#endif diff --git a/core/util.h b/src/include/headerlibs/vector.h similarity index 58% rename from core/util.h rename to src/include/headerlibs/vector.h index cdd60be2..9389f4ff 100644 --- a/core/util.h +++ b/src/include/headerlibs/vector.h @@ -20,31 +20,8 @@ * IN THE SOFTWARE. */ -#ifndef DST_UTIL_H_defined -#define DST_UTIL_H_defined - -#include - -/* Utils internal to dst. */ - -/* Type check Dst C Function arguments */ -typedef struct DstCSig { - int32_t flags; - DstAbstractType abs; -} DstCSig; - -/* Utils */ -extern const char dst_base64[65]; -int32_t dst_array_calchash(const Dst *array, int32_t len); -int32_t dst_kv_calchash(const DstKV *kvs, int32_t len); -int32_t dst_string_calchash(const uint8_t *str, int32_t len); -int32_t dst_tablen(int32_t n); -int dst_cstrcmp(const uint8_t *str, const char *other); -const void *dst_strbinsearch( - const void *tab, - size_t tabcount, - size_t itemsize, - const uint8_t *key); +#ifndef DST_VECTOR_H_defined +#define DST_VECTOR_H_defined /* * vector code modified from @@ -73,8 +50,63 @@ const void *dst_strbinsearch( #define dst_v__maybegrow(v, n) (dst_v__needgrow((v), (n)) ? dst_v__grow((v), (n)) : 0) #define dst_v__grow(v, n) ((v) = dst_v_grow((v), (n), sizeof(*(v)))) -void *dst_v_grow(void *v, int32_t increment, int32_t itemsize); -void *dst_v_copymem(void *v, int32_t itemsize); -void *dst_v_flattenmem(void *v, int32_t itemsize); + +/* Vector code */ + +/* Grow the buffer dynamically. Used for push operations. */ +static void *dst_v_grow(void *v, int32_t increment, int32_t itemsize) { + int32_t dbl_cur = (NULL != v) ? 2 * dst_v__cap(v) : 0; + int32_t min_needed = dst_v_count(v) + increment; + int32_t m = dbl_cur > min_needed ? dbl_cur : min_needed; + int32_t *p = (int32_t *) realloc(v ? dst_v__raw(v) : 0, itemsize * m + sizeof(int32_t)*2); + if (NULL != p) { + if (!v) p[1] = 0; + p[0] = m; + return p + 2; + } else { + { + DST_OUT_OF_MEMORY; + } + return (void *) (2 * sizeof(int32_t)); // try to force a NULL pointer exception later + } +} + +/* Clone a buffer. */ +#ifdef DST_V_DEF_COPYMEM +static void *dst_v_copymem(void *v, int32_t itemsize) { + int32_t *p; + if (NULL == v) return NULL; + p = malloc(2 * sizeof(int32_t) + itemsize * dst_v__cap(v)); + if (NULL != p) { + memcpy(p, dst_v__raw(v), 2 * sizeof(int32_t) + itemsize * dst_v__cnt(v)); + return p + 2; + } else { + { + DST_OUT_OF_MEMORY; + } + return (void *) (2 * sizeof(int32_t)); // try to force a NULL pointer exception later + } +} +#endif + +/* Convert a buffer to normal allocated memory (forget capacity) */ +#ifdef DST_V_DEF_FLATTENMEM +static void *dst_v_flattenmem(void *v, int32_t itemsize) { + int32_t *p; + int32_t sizen; + if (NULL == v) return NULL; + sizen = itemsize * dst_v__cnt(v); + p = malloc(sizen); + if (NULL != p) { + memcpy(p, v, sizen); + return p; + } else { + { + DST_OUT_OF_MEMORY; + } + return NULL; + } +} +#endif #endif diff --git a/client/main.c b/src/mainclient/main.c similarity index 99% rename from client/main.c rename to src/mainclient/main.c index 1a32b503..eca5b5c0 100644 --- a/client/main.c +++ b/src/mainclient/main.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #define DST_CLIENT_HELP 1 #define DST_CLIENT_VERBOSE 2 diff --git a/core/ast.c b/src/parser/ast.c similarity index 99% rename from core/ast.c rename to src/parser/ast.c index 2dc2eb41..530ad78a 100644 --- a/core/ast.c +++ b/src/parser/ast.c @@ -21,6 +21,7 @@ */ #include +#include /* Mark an ast node */ static int dst_ast_gcmark(void *p, size_t size) { diff --git a/core/parse.c b/src/parser/parse.c similarity index 99% rename from core/parse.c rename to src/parser/parse.c index 67e1a83d..6ade38ff 100644 --- a/core/parse.c +++ b/src/parser/parse.c @@ -21,7 +21,8 @@ */ #include -#include "util.h" +#include +#include /* Quote a value */ static Dst quote(Dst x) { @@ -450,6 +451,7 @@ int dst_parser_consume(DstParser *parser, uint8_t c) { consumed = state->consumer(parser, state, c); } parser->lookback = c; + parser->index++; return 1; } diff --git a/core/strtod.c b/src/parser/strtod.c similarity index 100% rename from core/strtod.c rename to src/parser/strtod.c diff --git a/src/testlib/testlib.c b/src/testlib/testlib.c new file mode 100644 index 00000000..6d408501 --- /dev/null +++ b/src/testlib/testlib.c @@ -0,0 +1,7 @@ +#include + +int dst_init_(DstArgs args) { + DstTable *env = dst_env_arg(args); + dst_env_def(env, "pi", dst_wrap_real(M_PI)); + return 0; +} diff --git a/dsttest/example.dsts b/test/example.dsts similarity index 100% rename from dsttest/example.dsts rename to test/example.dsts diff --git a/dsttest/minimal.dsts b/test/minimal.dsts similarity index 100% rename from dsttest/minimal.dsts rename to test/minimal.dsts diff --git a/dsttest/suite0.dst b/test/suite0.dst similarity index 100% rename from dsttest/suite0.dst rename to test/suite0.dst