mirror of
https://github.com/janet-lang/janet
synced 2025-01-10 23:50:26 +00:00
Major refactor. Move files around, merge compiler into
core and other changes, work on inlining many c functions.
This commit is contained in:
parent
17685bd789
commit
a018f9f54a
31
Makefile
31
Makefile
@ -32,7 +32,7 @@ BINDIR=$(PREFIX)/bin
|
||||
# TODO - when api is finalized, only export public symbols instead of using rdynamic
|
||||
# which exports all symbols. Saves a few KB in binary.
|
||||
|
||||
CFLAGS=-std=c99 -Wall -Wextra -Isrc/include -fpic -O2
|
||||
CFLAGS=-std=c99 -Wall -Wextra -Isrc/include -fpic -Os -s
|
||||
CLIBS=-lm -ldl
|
||||
PREFIX=/usr/local
|
||||
DST_TARGET=dst
|
||||
@ -49,18 +49,11 @@ else
|
||||
endif
|
||||
|
||||
# Source headers
|
||||
DST_GENERATED_HEADERS=$(sort $(wildcard src/include/generated/*.h))
|
||||
DST_HEADERS=$(sort $(wildcard src/include/dst/*.h))
|
||||
DST_LOCAL_HEADERS=$(sort $(wildcard src/*/*.h))
|
||||
DST_LIBHEADERS=$(sort $(wildcard src/include/headerlibs/*.h))
|
||||
DST_GENERATED_HEADERS=src/mainclient/clientinit.gen.h \
|
||||
src/compiler/dststlbootstrap.gen.h
|
||||
DST_ALL_HEADERS=$(DST_LOCAL_HEADERS) \
|
||||
$(DST_HEADERS) \
|
||||
$(DST_LIB_HEADERS) \
|
||||
$(DST_GENERATED_HEADERS)
|
||||
|
||||
# Source files
|
||||
DST_COMPILER_SOURCES=$(sort $(wildcard src/compiler/*.c))
|
||||
DST_CORE_SOURCES=$(sort $(wildcard src/core/*.c))
|
||||
DST_MAINCLIENT_SOURCES=$(sort $(wildcard src/mainclient/*.c))
|
||||
|
||||
@ -77,33 +70,33 @@ xxd: src/tools/xxd.c
|
||||
##### Generated Headers #####
|
||||
#############################
|
||||
|
||||
src/mainclient/clientinit.gen.h: src/mainclient/init.dst xxd
|
||||
src/include/generated/init.h: src/mainclient/init.dst xxd
|
||||
./xxd $< $@ dst_mainclient_init
|
||||
|
||||
src/compiler/dststlbootstrap.gen.h: src/compiler/boot.dst xxd
|
||||
src/include/generated/boot.h: src/core/boot.dst xxd
|
||||
./xxd $< $@ dst_stl_bootstrap_gen
|
||||
|
||||
# Only a few files depend on the generated headers
|
||||
src/core/corelib.o: src/include/generated/boot.h
|
||||
src/mainclient/main.o: src/include/generated/init.h
|
||||
|
||||
##########################################################
|
||||
##### The main interpreter program and shared object #####
|
||||
##########################################################
|
||||
|
||||
DST_LIB_SOURCES=$(DST_COMPILER_SOURCES) \
|
||||
$(DST_CONTEXT_SOURCES) \
|
||||
$(DST_CORE_SOURCES)
|
||||
|
||||
DST_ALL_SOURCES=$(DST_LIB_SOURCES) \
|
||||
DST_ALL_SOURCES=$(DST_CORE_SOURCES) \
|
||||
$(DST_MAINCLIENT_SOURCES)
|
||||
|
||||
DST_LIB_OBJECTS=$(patsubst %.c,%.o,$(DST_LIB_SOURCES))
|
||||
DST_CORE_OBJECTS=$(patsubst %.c,%.o,$(DST_CORE_SOURCES))
|
||||
DST_ALL_OBJECTS=$(patsubst %.c,%.o,$(DST_ALL_SOURCES))
|
||||
|
||||
%.o: %.c $(DST_ALL_HEADERS)
|
||||
%.o: %.c $(DST_HEADERS) $(DST_LOCAL_HEADERS)
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
$(DST_TARGET): $(DST_ALL_OBJECTS)
|
||||
$(CC) $(CFLAGS) -o $(DST_TARGET) $^ $(CLIBS)
|
||||
|
||||
$(DST_LIBRARY): $(DST_LIB_OBJECTS)
|
||||
$(DST_LIBRARY): $(DST_CORE_OBJECTS)
|
||||
$(CC) $(CFLAGS) -shared -o $(DST_LIBRARY) $^ $(CLIBS)
|
||||
|
||||
###################
|
||||
|
@ -1,246 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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 <dst/dst.h>
|
||||
#include <dst/dstopcodes.h>
|
||||
#include <dst/dstcorelib.h>
|
||||
#include <dst/dstcompile.h>
|
||||
#include "compile.h"
|
||||
|
||||
/* Generated header */
|
||||
#include "dststlbootstrap.gen.h"
|
||||
|
||||
static const DstReg cfuns[] = {
|
||||
{"native", dst_core_native},
|
||||
{"print", dst_core_print},
|
||||
{"describe", dst_core_describe},
|
||||
{"string", dst_core_string},
|
||||
{"symbol", dst_core_symbol},
|
||||
{"buffer", dst_core_buffer},
|
||||
{"table", dst_core_table},
|
||||
{"array", dst_core_array},
|
||||
{"scan-number", dst_core_scannumber},
|
||||
{"scan-integer", dst_core_scaninteger},
|
||||
{"scan-real", dst_core_scanreal},
|
||||
{"tuple", dst_core_tuple},
|
||||
{"struct", dst_core_struct},
|
||||
{"buffer", dst_core_buffer},
|
||||
{"gensym", dst_core_gensym},
|
||||
{"gccollect", dst_core_gccollect},
|
||||
{"gcsetinterval", dst_core_gcsetinterval},
|
||||
{"gcinterval", dst_core_gcinterval},
|
||||
{"type", dst_core_type},
|
||||
{"next", dst_core_next},
|
||||
{"hash", dst_core_hash},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/* Utility for inline assembly */
|
||||
static void dst_quick_asm(
|
||||
DstTable *env,
|
||||
int32_t flags,
|
||||
const char *name,
|
||||
int32_t arity,
|
||||
int32_t slots,
|
||||
const uint32_t *bytecode,
|
||||
size_t bytecode_size) {
|
||||
DstFuncDef *def = dst_funcdef_alloc();
|
||||
def->arity = arity;
|
||||
def->flags = flags;
|
||||
def->slotcount = slots;
|
||||
def->bytecode = malloc(bytecode_size);
|
||||
def->bytecode_length = bytecode_size / sizeof(uint32_t);
|
||||
def->name = dst_cstring(name);
|
||||
if (!def->bytecode) {
|
||||
DST_OUT_OF_MEMORY;
|
||||
}
|
||||
memcpy(def->bytecode, bytecode, bytecode_size);
|
||||
dst_env_def(env, name, dst_wrap_function(dst_thunk(def)));
|
||||
}
|
||||
|
||||
#define SSS(op, a, b, c) (op | (a << 8) | (b << 16) | (c << 24))
|
||||
#define SS(op, a, b) SSS(op, a, b, 0)
|
||||
#define S(op, a) SSS(op, a, 0, 0)
|
||||
/* Variadic operator assembly. Must be templatized for each different opcode. */
|
||||
/* Reg 0: Argument tuple (args) */
|
||||
/* Reg 1: Argument count (argn) */
|
||||
/* Reg 2: Jump flag (jump?) */
|
||||
/* Reg 3: Accumulator (accum) */
|
||||
/* Reg 4: Next operand (operand) */
|
||||
/* Reg 5: Loop iterator (i) */
|
||||
static DST_THREAD_LOCAL uint32_t varop_asm[] = {
|
||||
DOP_LENGTH | (1 << 8), /* Put number of arguments in register 1 -> argn = count(args) */
|
||||
|
||||
/* Cheack nullary */
|
||||
DOP_EQUALS_IMMEDIATE | (2 << 8) | (1 << 16) | (0 << 24), /* Check if numargs equal to 0 */
|
||||
DOP_JUMP_IF_NOT | (2 << 8) | (3 << 16), /* If not 0, jump to next check */
|
||||
/* Nullary */
|
||||
DOP_LOAD_INTEGER | (3 << 8), /* accum = nullary value */
|
||||
DOP_RETURN | (3 << 8), /* return accum */
|
||||
|
||||
/* Check unary */
|
||||
DOP_EQUALS_IMMEDIATE | (2 << 8) | (1 << 16) | (1 << 24), /* Check if numargs equal to 1 */
|
||||
DOP_JUMP_IF_NOT | (2 << 8) | (5 << 16), /* If not 1, jump to next check */
|
||||
/* Unary */
|
||||
DOP_LOAD_INTEGER | (3 << 8), /* accum = unary value */
|
||||
DOP_GET_INDEX | (4 << 8) | (0 << 16) | (0 << 24), /* operand = args[0] */
|
||||
DOP_NOOP | (3 << 8) | (3 << 16) | (4 << 24), /* accum = accum op operand */
|
||||
DOP_RETURN | (3 << 8), /* return accum */
|
||||
|
||||
/* Mutli (2 or more) arity */
|
||||
/* Prime loop */
|
||||
DOP_GET_INDEX | (3 << 8) | (0 << 16) | (0 << 24), /* accum = args[0] */
|
||||
DOP_LOAD_INTEGER | (5 << 8) | (1 << 16), /* i = 1 */
|
||||
/* Main loop */
|
||||
DOP_GET | (4 << 8) | (0 << 16) | (5 << 24), /* operand = args[i] */
|
||||
DOP_NOOP | (3 << 8) | (3 << 16) | (4 << 24), /* accum = accum op operand */
|
||||
DOP_ADD_IMMEDIATE | (5 << 8) | (5 << 16) | (1 << 24), /* i++ */
|
||||
DOP_EQUALS_INTEGER | (2 << 8) | (5 << 16) | (1 << 24), /* jump? = (i == argn) */
|
||||
DOP_JUMP_IF_NOT | (2 << 8) | ((uint32_t)(-4) << 16), /* if not jump? go back 4 */
|
||||
/* Done, do last and return accumulator */
|
||||
DOP_RETURN | (3 << 8) /* return accum */
|
||||
};
|
||||
|
||||
#define VAROP_NULLARY_LOC 3
|
||||
#define VAROP_UNARY_LOC 7
|
||||
#define VAROP_OP_LOC1 9
|
||||
#define VAROP_OP_LOC2 14
|
||||
|
||||
/* Templatize a varop */
|
||||
static void templatize_varop(
|
||||
DstTable *env,
|
||||
int32_t flags,
|
||||
const char *name,
|
||||
int32_t nullary,
|
||||
int32_t unary,
|
||||
uint32_t op) {
|
||||
varop_asm[VAROP_NULLARY_LOC] = SS(DOP_LOAD_INTEGER, 3, nullary);
|
||||
varop_asm[VAROP_UNARY_LOC] = SS(DOP_LOAD_INTEGER, 3, unary);
|
||||
varop_asm[VAROP_OP_LOC1] = SSS(op, 3, 3, 4);
|
||||
varop_asm[VAROP_OP_LOC2] = SSS(op, 3, 3, 4);
|
||||
dst_quick_asm(
|
||||
env,
|
||||
flags | DST_FUNCDEF_FLAG_VARARG,
|
||||
name,
|
||||
0,
|
||||
6,
|
||||
varop_asm,
|
||||
sizeof(varop_asm));
|
||||
}
|
||||
|
||||
DstTable *dst_stl_env(int flags) {
|
||||
static uint32_t error_asm[] = {
|
||||
DOP_ERROR
|
||||
};
|
||||
static uint32_t apply_asm[] = {
|
||||
DOP_PUSH_ARRAY | (1 << 8),
|
||||
DOP_TAILCALL
|
||||
};
|
||||
static uint32_t debug_asm[] = {
|
||||
DOP_SIGNAL | (2 << 24),
|
||||
DOP_RETURN_NIL
|
||||
};
|
||||
static uint32_t yield_asm[] = {
|
||||
DOP_SIGNAL | (3 << 24),
|
||||
DOP_RETURN
|
||||
};
|
||||
static uint32_t resume_asm[] = {
|
||||
DOP_RESUME | (1 << 24),
|
||||
DOP_RETURN
|
||||
};
|
||||
static uint32_t get_asm[] = {
|
||||
DOP_GET | (1 << 24),
|
||||
DOP_RETURN
|
||||
};
|
||||
static uint32_t put_asm[] = {
|
||||
DOP_PUT | (1 << 16) | (2 << 24),
|
||||
DOP_RETURN
|
||||
};
|
||||
static uint32_t length_asm[] = {
|
||||
DOP_LENGTH,
|
||||
DOP_RETURN
|
||||
};
|
||||
|
||||
DstTable *env = dst_table(0);
|
||||
Dst ret = dst_wrap_table(env);
|
||||
|
||||
/* Load main functions */
|
||||
dst_env_cfuns(env, cfuns);
|
||||
|
||||
dst_quick_asm(env, DST_FUN_YIELD, "debug", 0, 1, debug_asm, sizeof(debug_asm));
|
||||
dst_quick_asm(env, DST_FUN_ERROR, "error", 1, 1, error_asm, sizeof(error_asm));
|
||||
dst_quick_asm(env, DST_FUN_APPLY1, "apply1", 2, 2, apply_asm, sizeof(apply_asm));
|
||||
dst_quick_asm(env, DST_FUN_YIELD, "yield", 1, 2, yield_asm, sizeof(yield_asm));
|
||||
dst_quick_asm(env, DST_FUN_RESUME, "resume", 2, 2, resume_asm, sizeof(resume_asm));
|
||||
dst_quick_asm(env, DST_FUN_GET, "get", 2, 2, get_asm, sizeof(get_asm));
|
||||
dst_quick_asm(env, DST_FUN_PUT, "put", 3, 3, put_asm, sizeof(put_asm));
|
||||
dst_quick_asm(env, DST_FUN_LENGTH, "length", 1, 1, length_asm, sizeof(length_asm));
|
||||
|
||||
/* Variadic ops */
|
||||
templatize_varop(env, DST_FUN_ADD, "+", 0, 0, DOP_ADD);
|
||||
templatize_varop(env, DST_FUN_SUBTRACT, "-", 0, 0, DOP_SUBTRACT);
|
||||
templatize_varop(env, DST_FUN_MULTIPLY, "*", 1, 1, DOP_MULTIPLY);
|
||||
templatize_varop(env, DST_FUN_DIVIDE, "/", 1, 1, DOP_DIVIDE);
|
||||
templatize_varop(env, DST_FUN_BAND, "&", -1, -1, DOP_BAND);
|
||||
templatize_varop(env, DST_FUN_BOR, "|", 0, 0, DOP_BOR);
|
||||
templatize_varop(env, DST_FUN_BXOR, "^", 0, 0, DOP_BXOR);
|
||||
templatize_varop(env, DST_FUN_LSHIFT, "<<", 1, 1, DOP_SHIFT_LEFT);
|
||||
templatize_varop(env, DST_FUN_RSHIFT, ">>", 1, 1, DOP_SHIFT_RIGHT);
|
||||
templatize_varop(env, DST_FUN_RSHIFTU, ">>>", 1, 1, DOP_SHIFT_RIGHT_UNSIGNED);
|
||||
|
||||
dst_env_def(env, "VERSION", dst_cstringv(DST_VERSION));
|
||||
|
||||
/* Set as gc root */
|
||||
dst_gcroot(dst_wrap_table(env));
|
||||
|
||||
/* Load auxiliary envs */
|
||||
{
|
||||
DstArgs args;
|
||||
args.n = 1;
|
||||
args.v = &ret;
|
||||
args.ret = &ret;
|
||||
dst_lib_io(args);
|
||||
dst_lib_math(args);
|
||||
dst_lib_array(args);
|
||||
dst_lib_tuple(args);
|
||||
dst_lib_buffer(args);
|
||||
dst_lib_table(args);
|
||||
dst_lib_fiber(args);
|
||||
dst_lib_os(args);
|
||||
dst_lib_parse(args);
|
||||
dst_lib_compile(args);
|
||||
dst_lib_asm(args);
|
||||
dst_lib_string(args);
|
||||
dst_lib_marsh(args);
|
||||
}
|
||||
|
||||
/* Allow references to the environment */
|
||||
dst_env_def(env, "_env", ret);
|
||||
|
||||
/* Run bootstrap source */
|
||||
dst_dobytes(env, dst_stl_bootstrap_gen, sizeof(dst_stl_bootstrap_gen), "boot.dst");
|
||||
|
||||
if (flags & DST_STL_NOGCROOT)
|
||||
dst_gcunroot(dst_wrap_table(env));
|
||||
|
||||
return env;
|
||||
}
|
@ -21,8 +21,8 @@
|
||||
*/
|
||||
|
||||
#include <dst/dst.h>
|
||||
#include <dst/dstcorelib.h>
|
||||
#include "gc.h"
|
||||
#include <string.h>
|
||||
|
||||
/* Initializes an array */
|
||||
DstArray *dst_array_init(DstArray *array, int32_t capacity) {
|
||||
@ -49,6 +49,19 @@ DstArray *dst_array(int32_t capacity) {
|
||||
return dst_array_init(array, capacity);
|
||||
}
|
||||
|
||||
/* Creates a new array from n elements. */
|
||||
DstArray *dst_array_n(const Dst *elements, int32_t n) {
|
||||
DstArray *array = dst_gcalloc(DST_MEMORY_ARRAY, sizeof(DstArray));
|
||||
array->capacity = n;
|
||||
array->count = n;
|
||||
array->data = malloc(sizeof(Dst) * n);
|
||||
if (!array->data) {
|
||||
DST_OUT_OF_MEMORY;
|
||||
}
|
||||
memcpy(array->data, elements, sizeof(Dst) * n);
|
||||
return array;
|
||||
}
|
||||
|
||||
/* Ensure the array has enough capacity for elements */
|
||||
void dst_array_ensure(DstArray *array, int32_t capacity) {
|
||||
Dst *newData;
|
||||
|
@ -21,10 +21,8 @@
|
||||
*/
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
#include <dst/dst.h>
|
||||
#include <dst/dstopcodes.h>
|
||||
#include <headerlibs/strbinsearch.h>
|
||||
#include "util.h"
|
||||
|
||||
/* Convert a slot to to an integer for bytecode */
|
||||
|
||||
@ -118,6 +116,12 @@ static const DstInstructionDef dst_ops[] = {
|
||||
{"ltim", DOP_LESS_THAN_IMMEDIATE},
|
||||
{"ltr", DOP_LESS_THAN_REAL},
|
||||
{"lter", DOP_LESS_THAN_EQUAL_REAL},
|
||||
{"mkarr", DOP_MAKE_ARRAY},
|
||||
{"mkbuf", DOP_MAKE_BUFFER},
|
||||
{"mktab", DOP_MAKE_TABLE},
|
||||
{"mktup", DOP_MAKE_TUPLE},
|
||||
{"mkstr", DOP_MAKE_STRING},
|
||||
{"mkstu", DOP_MAKE_STRUCT},
|
||||
{"movf", DOP_MOVE_FAR},
|
||||
{"movn", DOP_MOVE_NEAR},
|
||||
{"mul", DOP_MULTIPLY},
|
||||
@ -376,7 +380,7 @@ static uint32_t read_instruction(
|
||||
{
|
||||
if (dst_tuple_length(argt) != 2)
|
||||
dst_asm_error(a, "expected 1 argument: (op, slot)");
|
||||
instr |= doarg(a, DST_OAT_SLOT, 1, 3, 0, argt[1]);
|
||||
instr |= doarg(a, DST_OAT_SLOT, 1, 2, 0, argt[1]);
|
||||
break;
|
||||
}
|
||||
case DIT_L:
|
||||
|
@ -15,7 +15,7 @@
|
||||
"Define a function. Equivalent to (def name (fn name [args] ...))."
|
||||
(fn defn [name & more]
|
||||
(def len (length more))
|
||||
(def fstart
|
||||
(def fstart
|
||||
(fn recur [i]
|
||||
(def {i ith} more)
|
||||
(def t (type ith))
|
||||
@ -88,9 +88,9 @@
|
||||
(defn true? [x] (= x true))
|
||||
(defn false? [x] (= x false))
|
||||
(defn nil? [x] (= x nil))
|
||||
(def atomic?
|
||||
(def atomic?
|
||||
(do
|
||||
(def non-atomic-types
|
||||
(def non-atomic-types
|
||||
{:array true
|
||||
:tuple true
|
||||
:table true
|
||||
@ -301,8 +301,8 @@
|
||||
evaluates to false."
|
||||
[& forms]
|
||||
(def len (length forms))
|
||||
(if (= len 0)
|
||||
true
|
||||
(if (= len 0)
|
||||
true
|
||||
((fn aux [i]
|
||||
(cond
|
||||
(>= (inc i) len) (get forms i)
|
||||
@ -313,8 +313,8 @@
|
||||
evaluates to true."
|
||||
[& forms]
|
||||
(def len (length forms))
|
||||
(if (= len 0)
|
||||
false
|
||||
(if (= len 0)
|
||||
false
|
||||
((fn aux [i]
|
||||
(def fi (get forms i))
|
||||
(if
|
||||
@ -971,7 +971,7 @@
|
||||
(def p (parser.new))
|
||||
|
||||
# Fiber stream of characters
|
||||
(def chars
|
||||
(def chars
|
||||
(coro
|
||||
(def buf @"")
|
||||
(var len 1)
|
||||
@ -984,7 +984,7 @@
|
||||
0))
|
||||
|
||||
# Fiber stream of values
|
||||
(def vals
|
||||
(def vals
|
||||
(coro
|
||||
(while going
|
||||
(switch (parser.status p)
|
||||
@ -1002,21 +1002,22 @@
|
||||
# Evaluate 1 source form
|
||||
(defn eval1 [source]
|
||||
(var good true)
|
||||
(def f
|
||||
(fiber.new
|
||||
(def f
|
||||
(fiber.new
|
||||
(fn []
|
||||
(def res (compile source env where))
|
||||
(if (= (type res) :function)
|
||||
(res)
|
||||
(do
|
||||
(:= good false)
|
||||
(def {:error err :error-line errl :error-column errc} res)
|
||||
(onerr
|
||||
where
|
||||
(def {:error err :line errl :column errc :fiber errf} res)
|
||||
(onerr
|
||||
where
|
||||
"compile"
|
||||
(if (< 0 errl)
|
||||
(string err " in form at line " errl ", column " errc)
|
||||
err)))))
|
||||
(string err "\n in a form at line " errl ", column " errc)
|
||||
err)
|
||||
errf))))
|
||||
:a))
|
||||
(def res (resume f))
|
||||
(when good
|
||||
@ -1043,7 +1044,7 @@
|
||||
(pp x))
|
||||
(when f
|
||||
(def st (fiber.stack f))
|
||||
(loop
|
||||
(loop
|
||||
[{
|
||||
:function func
|
||||
:tail tail
|
||||
@ -1051,20 +1052,26 @@
|
||||
:c c
|
||||
:name name
|
||||
:source source
|
||||
:source-line source-line
|
||||
:source-column source-col
|
||||
:line source-line
|
||||
:column source-col
|
||||
} :in st]
|
||||
(file.write stdout " in")
|
||||
(when c (file.write stdout " cfunction"))
|
||||
(if name
|
||||
(file.write stdout " " name)
|
||||
(when func (file.write stdout " " (string func))))
|
||||
(if source
|
||||
(if source
|
||||
(do
|
||||
(file.write stdout " [" source "]")
|
||||
(if source-line (file.write stdout " on line "
|
||||
(string source-line) ", column " (string source-col)))))
|
||||
(if pc (file.write stdout " (pc=" (string pc) ")"))
|
||||
(if source-line
|
||||
(file.write
|
||||
stdout
|
||||
" on line "
|
||||
(string source-line)
|
||||
", column "
|
||||
(string source-col)))))
|
||||
(if (and (not source-line) pc)
|
||||
(file.write stdout " (pc=" (string pc) ")"))
|
||||
(when tail (file.write stdout " (tailcall)"))
|
||||
(file.write stdout "\n"))))
|
||||
|
||||
@ -1082,7 +1089,7 @@
|
||||
(run-context *env* chunks (fn [x] (:= returnval x)) default-error-handler "eval")
|
||||
returnval)
|
||||
|
||||
(def module.paths
|
||||
(def module.paths
|
||||
@["./?.dst"
|
||||
"./?/init.dst"
|
||||
"./dst_modules/?.dst"
|
||||
@ -1090,7 +1097,7 @@
|
||||
"/usr/local/dst/0.0.0/?.dst"
|
||||
"/usr/local/dst/0.0.0/?/init.dst"])
|
||||
|
||||
(def module.native-paths
|
||||
(def module.native-paths
|
||||
@["./?.so"
|
||||
"./?/??.so"
|
||||
"./dst_modules/?.so"
|
||||
@ -1143,8 +1150,8 @@
|
||||
(error (string "circular dependency: module " path " is loading")))
|
||||
(def {:exit exit-on-error} (or args {}))
|
||||
(def check (get cache path))
|
||||
(if check
|
||||
check
|
||||
(if check
|
||||
check
|
||||
(do
|
||||
(def newenv (make-env))
|
||||
(put cache path newenv)
|
@ -21,7 +21,6 @@
|
||||
*/
|
||||
|
||||
#include <dst/dst.h>
|
||||
#include <dst/dstcorelib.h>
|
||||
#include "gc.h"
|
||||
|
||||
/* Initialize a buffer */
|
||||
|
@ -20,8 +20,7 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <dst/dsttypes.h>
|
||||
#include <dst/dstopcodes.h>
|
||||
#include <dst/dst.h>
|
||||
#include "gc.h"
|
||||
|
||||
/* Look up table for instructions */
|
||||
@ -97,7 +96,13 @@ enum DstInstructionType dst_instructions[DOP_INSTRUCTION_COUNT] = {
|
||||
DIT_SSS, /* DOP_PUT, */
|
||||
DIT_SSU, /* DOP_GET_INDEX, */
|
||||
DIT_SSU, /* DOP_PUT_INDEX, */
|
||||
DIT_SS /* DOP_LENGTH */
|
||||
DIT_SS, /* DOP_LENGTH */
|
||||
DIT_S, /* DOP_MAKE_ARRAY */
|
||||
DIT_S, /* DOP_MAKE_BUFFER */
|
||||
DIT_S, /* DOP_MAKE_TUPLE */
|
||||
DIT_S, /* DOP_MAKE_STRUCT */
|
||||
DIT_S, /* DOP_MAKE_TABLE */
|
||||
DIT_S /* DOP_MAKE_STRING */
|
||||
};
|
||||
|
||||
/* Verify some bytecode */
|
||||
|
@ -21,12 +21,9 @@
|
||||
*/
|
||||
|
||||
#include <dst/dst.h>
|
||||
#include <dst/dstcorelib.h>
|
||||
#include "compile.h"
|
||||
#define DST_V_NODEF_GROW
|
||||
#include <headerlibs/vector.h>
|
||||
#undef DST_V_NODEF_GROW
|
||||
#include "emit.h"
|
||||
#include "vector.h"
|
||||
|
||||
static int fixarity0(DstFopts opts, DstSlot *args) {
|
||||
(void) opts;
|
||||
@ -41,41 +38,17 @@ static int fixarity2(DstFopts opts, DstSlot *args) {
|
||||
return dst_v_count(args) == 2;
|
||||
}
|
||||
|
||||
/* Generic hanldling for $A = B op $C */
|
||||
static DstSlot genericSSS(DstFopts opts, int op, Dst leftval, DstSlot s) {
|
||||
DstSlot target = dstc_gettarget(opts);
|
||||
DstSlot zero = dstc_cslot(leftval);
|
||||
int32_t lhs = dstc_regnear(opts.compiler, zero, DSTC_REGTEMP_0);
|
||||
int32_t rhs = dstc_regnear(opts.compiler, s, DSTC_REGTEMP_1);
|
||||
dstc_emit(opts.compiler, op |
|
||||
(target.index << 8) |
|
||||
(lhs << 16) |
|
||||
(rhs << 24));
|
||||
dstc_free_reg(opts.compiler, zero, lhs);
|
||||
dstc_free_reg(opts.compiler, s, rhs);
|
||||
return target;
|
||||
}
|
||||
|
||||
/* Generic hanldling for $A = op $B */
|
||||
static DstSlot genericSS(DstFopts opts, int op, DstSlot s) {
|
||||
DstSlot target = dstc_gettarget(opts);
|
||||
int32_t rhs = dstc_regfar(opts.compiler, s, DSTC_REGTEMP_0);
|
||||
dstc_emit(opts.compiler, op |
|
||||
(target.index << 8) |
|
||||
(rhs << 16));
|
||||
dstc_free_reg(opts.compiler, s, rhs);
|
||||
dstc_emit_ss(opts.compiler, op, target, s, 1);
|
||||
return target;
|
||||
}
|
||||
|
||||
/* Generic hanldling for $A = $B op I */
|
||||
static DstSlot genericSSI(DstFopts opts, int op, DstSlot s, int32_t imm) {
|
||||
DstSlot target = dstc_gettarget(opts);
|
||||
int32_t rhs = dstc_regnear(opts.compiler, s, DSTC_REGTEMP_0);
|
||||
dstc_emit(opts.compiler, op |
|
||||
(target.index << 8) |
|
||||
(rhs << 16) |
|
||||
(imm << 24));
|
||||
dstc_free_reg(opts.compiler, s, rhs);
|
||||
dstc_emit_ssi(opts.compiler, op, target, s, imm, 1);
|
||||
return target;
|
||||
}
|
||||
|
||||
@ -92,29 +65,21 @@ static DstSlot opreduce(
|
||||
if (len == 0) {
|
||||
return dstc_cslot(nullary);
|
||||
} else if (len == 1) {
|
||||
return genericSSS(opts, op, nullary, args[0]);
|
||||
t = dstc_gettarget(opts);
|
||||
dstc_emit_sss(c, op, t, dstc_cslot(nullary), args[0], 1);
|
||||
return t;
|
||||
}
|
||||
t = dstc_gettarget(opts);
|
||||
/* Compile initial two arguments */
|
||||
int32_t lhs = dstc_regnear(c, args[0], DSTC_REGTEMP_0);
|
||||
int32_t rhs = dstc_regnear(c, args[1], DSTC_REGTEMP_1);
|
||||
dstc_emit(c, op | (t.index << 8) | (lhs << 16) | (rhs << 24));
|
||||
dstc_free_reg(c, args[0], lhs);
|
||||
dstc_free_reg(c, args[1], rhs);
|
||||
/* Don't release t */
|
||||
/* Compile the rest of the arguments */
|
||||
for (i = 2; i < len; i++) {
|
||||
rhs = dstc_regnear(c, args[i], DSTC_REGTEMP_0);
|
||||
dstc_emit(c, op | (t.index << 8) | (t.index << 16) | (rhs << 24));
|
||||
dstc_free_reg(c, args[i], rhs);
|
||||
}
|
||||
dstc_emit_sss(c, op, t, args[0], args[1], 1);
|
||||
for (i = 2; i < len; i++)
|
||||
dstc_emit_sss(c, op, t, t, args[i], 1);
|
||||
return t;
|
||||
}
|
||||
|
||||
/* Function optimizers */
|
||||
|
||||
static DstSlot do_error(DstFopts opts, DstSlot *args) {
|
||||
dstc_emit_s(opts.compiler, DOP_ERROR, args[0]);
|
||||
dstc_emit_s(opts.compiler, DOP_ERROR, args[0], 0);
|
||||
return dstc_cslot(dst_wrap_nil());
|
||||
}
|
||||
static DstSlot do_debug(DstFopts opts, DstSlot *args) {
|
||||
@ -139,23 +104,17 @@ static DstSlot do_resume(DstFopts opts, DstSlot *args) {
|
||||
}
|
||||
static DstSlot do_apply1(DstFopts opts, DstSlot *args) {
|
||||
/* Push phase */
|
||||
int32_t array_reg = dstc_regfar(opts.compiler, args[1], DSTC_REGTEMP_1);
|
||||
dstc_emit(opts.compiler, DOP_PUSH_ARRAY | (array_reg << 8));
|
||||
dstc_free_reg(opts.compiler, args[1], array_reg);
|
||||
dstc_emit_s(opts.compiler, DOP_PUSH_ARRAY, args[1], 0);
|
||||
/* Call phase */
|
||||
int32_t fun_reg = dstc_regnear(opts.compiler, args[0], DSTC_REGTEMP_0);
|
||||
DstSlot target;
|
||||
if (opts.flags & DST_FOPTS_TAIL) {
|
||||
dstc_emit(opts.compiler, DOP_TAILCALL | (fun_reg << 8));
|
||||
dstc_emit_s(opts.compiler, DOP_TAILCALL, args[0], 0);
|
||||
target = dstc_cslot(dst_wrap_nil());
|
||||
target.flags |= DST_SLOT_RETURNED;
|
||||
} else {
|
||||
target = dstc_gettarget(opts);
|
||||
dstc_emit(opts.compiler, DOP_CALL |
|
||||
(target.index << 8) |
|
||||
(fun_reg << 16));
|
||||
dstc_emit_ss(opts.compiler, DOP_CALL, target, args[0], 1);
|
||||
}
|
||||
dstc_free_reg(opts.compiler, args[0], fun_reg);
|
||||
return target;
|
||||
}
|
||||
|
@ -21,13 +21,9 @@
|
||||
*/
|
||||
|
||||
#include <dst/dst.h>
|
||||
#include <dst/dstcorelib.h>
|
||||
#include "compile.h"
|
||||
#include "emit.h"
|
||||
|
||||
#define DST_V_DEF_FLATTENMEM
|
||||
#include <headerlibs/vector.h>
|
||||
#undef DST_V_DEF_FLATTENMEM
|
||||
#include "vector.h"
|
||||
|
||||
DstFopts dstc_fopts_default(DstCompiler *c) {
|
||||
DstFopts ret;
|
||||
@ -97,17 +93,7 @@ DstSlot dstc_cslot(Dst x) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Get a temp near slot */
|
||||
DstSlot dstc_nearslot(DstCompiler *c, DstcRegisterTemp tag) {
|
||||
DstSlot ret;
|
||||
ret.flags = DST_SLOTTYPE_ANY;
|
||||
ret.index = dstc_allocnear(c, tag);
|
||||
ret.constant = dst_wrap_nil();
|
||||
ret.envindex = -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Get a temp near slot */
|
||||
/* Get a local slot */
|
||||
DstSlot dstc_farslot(DstCompiler *c) {
|
||||
DstSlot ret;
|
||||
ret.flags = DST_SLOTTYPE_ANY;
|
||||
@ -296,14 +282,13 @@ DstSlot dstc_return(DstCompiler *c, DstSlot s) {
|
||||
if (s.flags & DST_SLOT_CONSTANT && dst_checktype(s.constant, DST_NIL))
|
||||
dstc_emit(c, DOP_RETURN_NIL);
|
||||
else
|
||||
dstc_emit_s(c, DOP_RETURN, s);
|
||||
dstc_emit_s(c, DOP_RETURN, s, 0);
|
||||
s.flags |= DST_SLOT_RETURNED;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/* Get a target slot for emitting an instruction. Will always return
|
||||
* a local slot. */
|
||||
/* Get a target slot for emitting an instruction. */
|
||||
DstSlot dstc_gettarget(DstFopts opts) {
|
||||
DstSlot slot;
|
||||
if ((opts.flags & DST_FOPTS_HINT) &&
|
||||
@ -314,7 +299,7 @@ DstSlot dstc_gettarget(DstFopts opts) {
|
||||
slot.envindex = -1;
|
||||
slot.constant = dst_wrap_nil();
|
||||
slot.flags = 0;
|
||||
slot.index = dstc_allocnear(opts.compiler, DSTC_REGTEMP_TARGET);
|
||||
slot.index = dstc_allocfar(opts.compiler);
|
||||
}
|
||||
return slot;
|
||||
}
|
||||
@ -346,11 +331,11 @@ DstSlot *dstc_toslotskv(DstCompiler *c, Dst ds) {
|
||||
void dstc_pushslots(DstCompiler *c, DstSlot *slots) {
|
||||
int32_t i;
|
||||
for (i = 0; i < dst_v_count(slots) - 2; i += 3)
|
||||
dstc_emit_sss(c, DOP_PUSH_3, slots[i], slots[i+1], slots[i+2]);
|
||||
dstc_emit_sss(c, DOP_PUSH_3, slots[i], slots[i+1], slots[i+2], 0);
|
||||
if (i == dst_v_count(slots) - 2)
|
||||
dstc_emit_ss(c, DOP_PUSH_2, slots[i], slots[i+1]);
|
||||
dstc_emit_ss(c, DOP_PUSH_2, slots[i], slots[i+1], 0);
|
||||
else if (i == dst_v_count(slots) - 1)
|
||||
dstc_emit_s(c, DOP_PUSH, slots[i]);
|
||||
dstc_emit_s(c, DOP_PUSH, slots[i], 0);
|
||||
}
|
||||
|
||||
/* Free slots loaded via dstc_toslots */
|
||||
@ -399,159 +384,185 @@ static DstSlot dstc_call(DstFopts opts, DstSlot *slots, DstSlot fun) {
|
||||
if (!specialized) {
|
||||
dstc_pushslots(c, slots);
|
||||
if (opts.flags & DST_FOPTS_TAIL) {
|
||||
dstc_emit_s(c, DOP_TAILCALL, fun);
|
||||
dstc_emit_s(c, DOP_TAILCALL, fun, 0);
|
||||
retslot = dstc_cslot(dst_wrap_nil());
|
||||
retslot.flags = DST_SLOT_RETURNED;
|
||||
} else {
|
||||
retslot = dstc_gettarget(opts);
|
||||
int32_t fun_register = dstc_regnear(c, fun, DSTC_REGTEMP_0);
|
||||
dstc_emit(c, DOP_CALL |
|
||||
(retslot.index << 8) |
|
||||
(fun_register << 16));
|
||||
/* Don't free ret register */
|
||||
dstc_free_reg(c, fun, fun_register);
|
||||
dstc_emit_ss(c, DOP_CALL, retslot, fun, 1);
|
||||
}
|
||||
}
|
||||
dstc_freeslots(c, slots);
|
||||
return retslot;
|
||||
}
|
||||
|
||||
static DstSlot dstc_maker(DstFopts opts, DstSlot *slots, int op) {
|
||||
DstCompiler *c = opts.compiler;
|
||||
DstSlot retslot;
|
||||
dstc_pushslots(c, slots);
|
||||
dstc_freeslots(c, slots);
|
||||
retslot = dstc_gettarget(opts);
|
||||
dstc_emit_s(c, op, retslot, 1);
|
||||
return retslot;
|
||||
}
|
||||
|
||||
static DstSlot dstc_array(DstFopts opts, Dst x) {
|
||||
DstCompiler *c = opts.compiler;
|
||||
DstArray *a = dst_unwrap_array(x);
|
||||
return dstc_call(opts,
|
||||
return dstc_maker(opts,
|
||||
dstc_toslots(c, a->data, a->count),
|
||||
dstc_cslot(dst_wrap_cfunction(dst_core_array)));
|
||||
DOP_MAKE_ARRAY);
|
||||
}
|
||||
|
||||
static DstSlot dstc_tablector(DstFopts opts, Dst x, DstCFunction cfun) {
|
||||
static DstSlot dstc_tablector(DstFopts opts, Dst x, int op) {
|
||||
DstCompiler *c = opts.compiler;
|
||||
return dstc_call(opts, dstc_toslotskv(c, x), dstc_cslot(dst_wrap_cfunction(cfun)));
|
||||
return dstc_maker(opts,
|
||||
dstc_toslotskv(c, x),
|
||||
op);
|
||||
}
|
||||
|
||||
static DstSlot dstc_bufferctor(DstFopts opts, Dst x) {
|
||||
DstCompiler *c = opts.compiler;
|
||||
DstBuffer *b = dst_unwrap_buffer(x);
|
||||
Dst onearg = dst_stringv(b->data, b->count);
|
||||
return dstc_call(opts,
|
||||
return dstc_maker(opts,
|
||||
dstc_toslots(c, &onearg, 1),
|
||||
dstc_cslot(dst_wrap_cfunction(dst_core_buffer)));
|
||||
DOP_MAKE_BUFFER);
|
||||
}
|
||||
|
||||
/* Compile a symbol */
|
||||
DstSlot dstc_symbol(DstFopts opts, const uint8_t *sym) {
|
||||
static DstSlot dstc_symbol(DstFopts opts, const uint8_t *sym) {
|
||||
if (dst_string_length(sym) && sym[0] != ':') {
|
||||
/* Non keyword */
|
||||
return dstc_resolve(opts.compiler, sym);
|
||||
} else {
|
||||
/* Keyword */
|
||||
return dstc_cslot(dst_wrap_symbol(sym));
|
||||
}
|
||||
}
|
||||
|
||||
/* Expand a macro one time. Also get the special form compiler if we
|
||||
* find that instead. */
|
||||
static int macroexpand1(
|
||||
DstCompiler *c,
|
||||
Dst x,
|
||||
Dst *out,
|
||||
const DstSpecial **spec) {
|
||||
if (!dst_checktype(x, DST_TUPLE))
|
||||
return 0;
|
||||
const Dst *form = dst_unwrap_tuple(x);
|
||||
if (dst_tuple_length(form) == 0)
|
||||
return 0;
|
||||
/* Source map - only set when we get a tuple */
|
||||
if (dst_tuple_sm_line(form) > 0) {
|
||||
c->current_mapping.line = dst_tuple_sm_line(form);
|
||||
c->current_mapping.column = dst_tuple_sm_col(form);
|
||||
}
|
||||
if (!dst_checktype(form[0], DST_SYMBOL))
|
||||
return 0;
|
||||
const uint8_t *name = dst_unwrap_symbol(form[0]);
|
||||
const DstSpecial *s = dstc_special(name);
|
||||
if (s) {
|
||||
*spec = s;
|
||||
return 0;
|
||||
}
|
||||
Dst macroval;
|
||||
DstBindingType btype = dst_env_resolve(c->env, name, ¯oval);
|
||||
if (btype != DST_BINDING_MACRO ||
|
||||
!dst_checktype(macroval, DST_FUNCTION))
|
||||
return 0;
|
||||
|
||||
|
||||
/* Evaluate macro */
|
||||
DstFiber *fiberp;
|
||||
DstFunction *macro = dst_unwrap_function(macroval);
|
||||
int lock = dst_gclock();
|
||||
DstSignal status = dst_call(
|
||||
macro,
|
||||
dst_tuple_length(form) - 1,
|
||||
form + 1,
|
||||
&x,
|
||||
&fiberp);
|
||||
dst_gcunlock(lock);
|
||||
if (status != DST_SIGNAL_OK) {
|
||||
const uint8_t *es = dst_formatc("(macro) %V", x);
|
||||
c->result.macrofiber = fiberp;
|
||||
dstc_error(c, es);
|
||||
} else {
|
||||
*out = x;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Compile a single value */
|
||||
DstSlot dstc_value(DstFopts opts, Dst x) {
|
||||
DstSlot ret;
|
||||
DstCompiler *c = opts.compiler;
|
||||
int macrorecur = 0;
|
||||
DstSourceMapping last_mapping = c->current_mapping;
|
||||
opts.compiler->recursion_guard--;
|
||||
recur:
|
||||
if (dstc_iserr(&opts)) {
|
||||
c->recursion_guard--;
|
||||
|
||||
/* Guard against previous errors and unbounded recursion */
|
||||
if (dstc_iserr(&opts)) return dstc_cslot(dst_wrap_nil());
|
||||
if (c->recursion_guard <= 0) {
|
||||
dstc_cerror(c, "recursed too deeply");
|
||||
return dstc_cslot(dst_wrap_nil());
|
||||
}
|
||||
if (opts.compiler->recursion_guard <= 0) {
|
||||
dstc_cerror(opts.compiler, "recursed too deeply");
|
||||
|
||||
/* Macro expand. Also gets possible special form and
|
||||
* refines source mapping cursor if possible. */
|
||||
const DstSpecial *spec = NULL;
|
||||
int macroi = DST_RECURSION_GUARD;
|
||||
while (macroi && !dstc_iserr(&opts) && macroexpand1(c, x, &x, &spec))
|
||||
macroi--;
|
||||
if (macroi == 0) {
|
||||
dstc_cerror(c, "recursed too deeply in macro expansion");
|
||||
return dstc_cslot(dst_wrap_nil());
|
||||
}
|
||||
switch (dst_type(x)) {
|
||||
default:
|
||||
ret = dstc_cslot(x);
|
||||
break;
|
||||
case DST_SYMBOL:
|
||||
{
|
||||
const uint8_t *sym = dst_unwrap_symbol(x);
|
||||
ret = dstc_symbol(opts, sym);
|
||||
break;
|
||||
}
|
||||
case DST_TUPLE:
|
||||
{
|
||||
int compiled = 0;
|
||||
Dst headval;
|
||||
DstSlot head;
|
||||
DstFopts subopts = dstc_fopts_default(c);
|
||||
const Dst *tup = dst_unwrap_tuple(x);
|
||||
/* Get ast mapping */
|
||||
if (dst_tuple_sm_line(tup) > 0) {
|
||||
c->current_mapping.line = dst_tuple_sm_line(tup);
|
||||
c->current_mapping.column = dst_tuple_sm_col(tup);
|
||||
}
|
||||
/* Empty tuple is tuple literal */
|
||||
if (dst_tuple_length(tup) == 0) {
|
||||
compiled = 1;
|
||||
ret = dstc_cslot(x);
|
||||
} else {
|
||||
/* Symbols could be specials */
|
||||
headval = tup[0];
|
||||
if (dst_checktype(headval, DST_SYMBOL)) {
|
||||
const uint8_t *headsym = dst_unwrap_symbol(headval);
|
||||
const DstSpecial *s = dstc_special(headsym);
|
||||
if (NULL != s) {
|
||||
ret = s->compile(opts, dst_tuple_length(tup) - 1, tup + 1);
|
||||
compiled = 1;
|
||||
} else {
|
||||
/* Check macro */
|
||||
Dst macVal;
|
||||
DstBindingType btype = dst_env_resolve(c->env, headsym, &macVal);
|
||||
if (btype == DST_BINDING_MACRO &&
|
||||
dst_checktype(macVal, DST_FUNCTION)) {
|
||||
if (macrorecur++ > DST_RECURSION_GUARD) {
|
||||
dstc_cerror(c, "macro expansion recursed too deeply");
|
||||
return dstc_cslot(dst_wrap_nil());
|
||||
} else {
|
||||
DstFunction *f = dst_unwrap_function(macVal);
|
||||
int lock = dst_gclock();
|
||||
DstSignal status = dst_call(f, dst_tuple_length(tup) - 1, tup + 1, &x);
|
||||
dst_gcunlock(lock);
|
||||
if (status != DST_SIGNAL_OK) {
|
||||
const uint8_t *es = dst_formatc("error in macro expansion: %V", x);
|
||||
dstc_error(c, es);
|
||||
}
|
||||
/* Tail recur on the value */
|
||||
goto recur;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!compiled) {
|
||||
/* Compile the head of the tuple */
|
||||
|
||||
/* Special forms */
|
||||
if (spec) {
|
||||
const Dst *tup = dst_unwrap_tuple(x);
|
||||
ret = spec->compile(opts, dst_tuple_length(tup) - 1, tup + 1);
|
||||
} else {
|
||||
switch (dst_type(x)) {
|
||||
case DST_TUPLE:
|
||||
{
|
||||
DstFopts subopts = dstc_fopts_default(c);
|
||||
const Dst *tup = dst_unwrap_tuple(x);
|
||||
/* Empty tuple is tuple literal */
|
||||
if (dst_tuple_length(tup) == 0) {
|
||||
ret = dstc_cslot(x);
|
||||
} else {
|
||||
DstSlot head = dstc_value(subopts, tup[0]);
|
||||
subopts.flags = DST_FUNCTION | DST_CFUNCTION;
|
||||
head = dstc_value(subopts, tup[0]);
|
||||
/* Add compile function call */
|
||||
ret = dstc_call(opts, dstc_toslots(c, tup + 1, dst_tuple_length(tup) - 1), head);
|
||||
dstc_freeslot(c, head);
|
||||
}
|
||||
}
|
||||
/* Pop source mapping */
|
||||
if (c->result.status != DST_COMPILE_ERROR)
|
||||
c->current_mapping = last_mapping;
|
||||
}
|
||||
break;
|
||||
case DST_ARRAY:
|
||||
ret = dstc_array(opts, x);
|
||||
break;
|
||||
case DST_STRUCT:
|
||||
ret = dstc_tablector(opts, x, dst_core_struct);
|
||||
break;
|
||||
case DST_TABLE:
|
||||
ret = dstc_tablector(opts, x, dst_core_table);
|
||||
break;
|
||||
case DST_BUFFER:
|
||||
ret = dstc_bufferctor(opts, x);
|
||||
break;
|
||||
break;
|
||||
case DST_SYMBOL:
|
||||
ret = dstc_symbol(opts, dst_unwrap_symbol(x));
|
||||
break;
|
||||
case DST_ARRAY:
|
||||
ret = dstc_array(opts, x);
|
||||
break;
|
||||
case DST_STRUCT:
|
||||
ret = dstc_tablector(opts, x, DOP_MAKE_STRUCT);
|
||||
break;
|
||||
case DST_TABLE:
|
||||
ret = dstc_tablector(opts, x, DOP_MAKE_TABLE);
|
||||
break;
|
||||
case DST_BUFFER:
|
||||
ret = dstc_bufferctor(opts, x);
|
||||
break;
|
||||
default:
|
||||
ret = dstc_cslot(x);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dstc_iserr(&opts)) {
|
||||
return dstc_cslot(dst_wrap_nil());
|
||||
}
|
||||
c->current_mapping = last_mapping;
|
||||
if (opts.flags & DST_FOPTS_TAIL) {
|
||||
ret = dstc_return(opts.compiler, ret);
|
||||
}
|
||||
@ -631,6 +642,7 @@ static void dstc_init(DstCompiler *c, DstTable *env, const uint8_t *where) {
|
||||
c->result.error = NULL;
|
||||
c->result.status = DST_COMPILE_OK;
|
||||
c->result.funcdef = NULL;
|
||||
c->result.macrofiber = NULL;
|
||||
c->result.error_mapping.line = 0;
|
||||
c->result.error_mapping.column = 0;
|
||||
}
|
||||
@ -691,10 +703,13 @@ static int cfun(DstArgs args) {
|
||||
if (res.status == DST_COMPILE_OK) {
|
||||
DST_RETURN_FUNCTION(args, dst_thunk(res.funcdef));
|
||||
} else {
|
||||
t = dst_table(2);
|
||||
t = dst_table(4);
|
||||
dst_table_put(t, dst_csymbolv(":error"), dst_wrap_string(res.error));
|
||||
dst_table_put(t, dst_csymbolv(":error-line"), dst_wrap_integer(res.error_mapping.line));
|
||||
dst_table_put(t, dst_csymbolv(":error-column"), dst_wrap_integer(res.error_mapping.column));
|
||||
dst_table_put(t, dst_csymbolv(":line"), dst_wrap_integer(res.error_mapping.line));
|
||||
dst_table_put(t, dst_csymbolv(":column"), dst_wrap_integer(res.error_mapping.column));
|
||||
if (res.macrofiber) {
|
||||
dst_table_put(t, dst_csymbolv(":fiber"), dst_wrap_fiber(res.macrofiber));
|
||||
}
|
||||
DST_RETURN_TABLE(args, t);
|
||||
}
|
||||
}
|
@ -24,8 +24,6 @@
|
||||
#define DST_COMPILE_H
|
||||
|
||||
#include <dst/dst.h>
|
||||
#include <dst/dstcompile.h>
|
||||
#include <dst/dstopcodes.h>
|
||||
#include "regalloc.h"
|
||||
|
||||
/* Tags for some functions for the prepared inliner */
|
||||
@ -185,7 +183,6 @@ const DstKV *dstc_next(Dst ds, const DstKV *kv);
|
||||
|
||||
void dstc_freeslot(DstCompiler *c, DstSlot s);
|
||||
void dstc_nameslot(DstCompiler *c, const uint8_t *sym, DstSlot s);
|
||||
DstSlot dstc_nearslot(DstCompiler *c, DstcRegisterTemp tag);
|
||||
DstSlot dstc_farslot(DstCompiler *c);
|
||||
|
||||
/* Throw away some code after checking that it is well formed. */
|
@ -21,9 +21,64 @@
|
||||
*/
|
||||
|
||||
#include <dst/dst.h>
|
||||
#include <dst/dstcorelib.h>
|
||||
#include "corelib.h"
|
||||
#include "compile.h"
|
||||
#include "state.h"
|
||||
|
||||
/* Generated header */
|
||||
#include <generated/boot.h>
|
||||
|
||||
/* Use LoadLibrary on windows or dlopen on posix to load dynamic libaries
|
||||
* with native code. */
|
||||
#ifdef DST_WINDOWS
|
||||
#include <windows.h>
|
||||
typedef HINSTANCE Clib;
|
||||
#define load_clib(name) LoadLibrary((name))
|
||||
#define symbol_clib(lib, sym) GetProcAddress((lib), (sym))
|
||||
#define error_clib() "could not load dynamic library"
|
||||
#elif defined(DST_WEB)
|
||||
#include <emscripten.h>
|
||||
/* TODO - figure out how loading modules will work in JS */
|
||||
typedef int Clib;
|
||||
#define load_clib(name) 0
|
||||
#define symbol_clib(lib, sym) 0
|
||||
#define error_clib() "dynamic libraries not supported"
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
typedef void *Clib;
|
||||
#define load_clib(name) dlopen((name), RTLD_NOW)
|
||||
#define symbol_clib(lib, sym) dlsym((lib), (sym))
|
||||
#define error_clib() dlerror()
|
||||
#endif
|
||||
|
||||
DstCFunction dst_native(const char *name, const uint8_t **error) {
|
||||
Clib lib = load_clib(name);
|
||||
DstCFunction init;
|
||||
if (!lib) {
|
||||
*error = dst_cstring(error_clib());
|
||||
return NULL;
|
||||
}
|
||||
init = (DstCFunction) symbol_clib(lib, "_dst_init");
|
||||
if (!init) {
|
||||
*error = dst_cstring("could not find _dst_init symbol");
|
||||
return NULL;
|
||||
}
|
||||
return init;
|
||||
}
|
||||
|
||||
int dst_core_native(DstArgs args) {
|
||||
DstCFunction init;
|
||||
const uint8_t *error = NULL;
|
||||
const uint8_t *path = NULL;
|
||||
DST_FIXARITY(args, 1);
|
||||
DST_ARG_STRING(path, args, 0);
|
||||
init = dst_native((const char *)path, &error);
|
||||
if (!init) {
|
||||
DST_THROWV(args, dst_wrap_string(error));
|
||||
}
|
||||
DST_RETURN_CFUNCTION(args, init);
|
||||
}
|
||||
|
||||
int dst_core_print(DstArgs args) {
|
||||
int32_t i;
|
||||
for (i = 0; i < args.n; ++i) {
|
||||
@ -232,3 +287,219 @@ int dst_core_hash(DstArgs args) {
|
||||
DST_FIXARITY(args, 1);
|
||||
DST_RETURN_INTEGER(args, dst_hash(args.v[0]));
|
||||
}
|
||||
|
||||
static const DstReg cfuns[] = {
|
||||
{"native", dst_core_native},
|
||||
{"print", dst_core_print},
|
||||
{"describe", dst_core_describe},
|
||||
{"string", dst_core_string},
|
||||
{"symbol", dst_core_symbol},
|
||||
{"buffer", dst_core_buffer},
|
||||
{"table", dst_core_table},
|
||||
{"array", dst_core_array},
|
||||
{"scan-number", dst_core_scannumber},
|
||||
{"scan-integer", dst_core_scaninteger},
|
||||
{"scan-real", dst_core_scanreal},
|
||||
{"tuple", dst_core_tuple},
|
||||
{"struct", dst_core_struct},
|
||||
{"buffer", dst_core_buffer},
|
||||
{"gensym", dst_core_gensym},
|
||||
{"gccollect", dst_core_gccollect},
|
||||
{"gcsetinterval", dst_core_gcsetinterval},
|
||||
{"gcinterval", dst_core_gcinterval},
|
||||
{"type", dst_core_type},
|
||||
{"next", dst_core_next},
|
||||
{"hash", dst_core_hash},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/* Utility for inline assembly */
|
||||
static void dst_quick_asm(
|
||||
DstTable *env,
|
||||
int32_t flags,
|
||||
const char *name,
|
||||
int32_t arity,
|
||||
int32_t slots,
|
||||
const uint32_t *bytecode,
|
||||
size_t bytecode_size) {
|
||||
DstFuncDef *def = dst_funcdef_alloc();
|
||||
def->arity = arity;
|
||||
def->flags = flags;
|
||||
def->slotcount = slots;
|
||||
def->bytecode = malloc(bytecode_size);
|
||||
def->bytecode_length = bytecode_size / sizeof(uint32_t);
|
||||
def->name = dst_cstring(name);
|
||||
if (!def->bytecode) {
|
||||
DST_OUT_OF_MEMORY;
|
||||
}
|
||||
memcpy(def->bytecode, bytecode, bytecode_size);
|
||||
dst_env_def(env, name, dst_wrap_function(dst_thunk(def)));
|
||||
}
|
||||
|
||||
#define SSS(op, a, b, c) (op | (a << 8) | (b << 16) | (c << 24))
|
||||
#define SS(op, a, b) SSS(op, a, b, 0)
|
||||
#define S(op, a) SSS(op, a, 0, 0)
|
||||
/* Variadic operator assembly. Must be templatized for each different opcode. */
|
||||
/* Reg 0: Argument tuple (args) */
|
||||
/* Reg 1: Argument count (argn) */
|
||||
/* Reg 2: Jump flag (jump?) */
|
||||
/* Reg 3: Accumulator (accum) */
|
||||
/* Reg 4: Next operand (operand) */
|
||||
/* Reg 5: Loop iterator (i) */
|
||||
static DST_THREAD_LOCAL uint32_t varop_asm[] = {
|
||||
DOP_LENGTH | (1 << 8), /* Put number of arguments in register 1 -> argn = count(args) */
|
||||
|
||||
/* Cheack nullary */
|
||||
DOP_EQUALS_IMMEDIATE | (2 << 8) | (1 << 16) | (0 << 24), /* Check if numargs equal to 0 */
|
||||
DOP_JUMP_IF_NOT | (2 << 8) | (3 << 16), /* If not 0, jump to next check */
|
||||
/* Nullary */
|
||||
DOP_LOAD_INTEGER | (3 << 8), /* accum = nullary value */
|
||||
DOP_RETURN | (3 << 8), /* return accum */
|
||||
|
||||
/* Check unary */
|
||||
DOP_EQUALS_IMMEDIATE | (2 << 8) | (1 << 16) | (1 << 24), /* Check if numargs equal to 1 */
|
||||
DOP_JUMP_IF_NOT | (2 << 8) | (5 << 16), /* If not 1, jump to next check */
|
||||
/* Unary */
|
||||
DOP_LOAD_INTEGER | (3 << 8), /* accum = unary value */
|
||||
DOP_GET_INDEX | (4 << 8) | (0 << 16) | (0 << 24), /* operand = args[0] */
|
||||
DOP_NOOP | (3 << 8) | (3 << 16) | (4 << 24), /* accum = accum op operand */
|
||||
DOP_RETURN | (3 << 8), /* return accum */
|
||||
|
||||
/* Mutli (2 or more) arity */
|
||||
/* Prime loop */
|
||||
DOP_GET_INDEX | (3 << 8) | (0 << 16) | (0 << 24), /* accum = args[0] */
|
||||
DOP_LOAD_INTEGER | (5 << 8) | (1 << 16), /* i = 1 */
|
||||
/* Main loop */
|
||||
DOP_GET | (4 << 8) | (0 << 16) | (5 << 24), /* operand = args[i] */
|
||||
DOP_NOOP | (3 << 8) | (3 << 16) | (4 << 24), /* accum = accum op operand */
|
||||
DOP_ADD_IMMEDIATE | (5 << 8) | (5 << 16) | (1 << 24), /* i++ */
|
||||
DOP_EQUALS_INTEGER | (2 << 8) | (5 << 16) | (1 << 24), /* jump? = (i == argn) */
|
||||
DOP_JUMP_IF_NOT | (2 << 8) | ((uint32_t)(-4) << 16), /* if not jump? go back 4 */
|
||||
/* Done, do last and return accumulator */
|
||||
DOP_RETURN | (3 << 8) /* return accum */
|
||||
};
|
||||
|
||||
#define VAROP_NULLARY_LOC 3
|
||||
#define VAROP_UNARY_LOC 7
|
||||
#define VAROP_OP_LOC1 9
|
||||
#define VAROP_OP_LOC2 14
|
||||
|
||||
/* Templatize a varop */
|
||||
static void templatize_varop(
|
||||
DstTable *env,
|
||||
int32_t flags,
|
||||
const char *name,
|
||||
int32_t nullary,
|
||||
int32_t unary,
|
||||
uint32_t op) {
|
||||
varop_asm[VAROP_NULLARY_LOC] = SS(DOP_LOAD_INTEGER, 3, nullary);
|
||||
varop_asm[VAROP_UNARY_LOC] = SS(DOP_LOAD_INTEGER, 3, unary);
|
||||
varop_asm[VAROP_OP_LOC1] = SSS(op, 3, 3, 4);
|
||||
varop_asm[VAROP_OP_LOC2] = SSS(op, 3, 3, 4);
|
||||
dst_quick_asm(
|
||||
env,
|
||||
flags | DST_FUNCDEF_FLAG_VARARG,
|
||||
name,
|
||||
0,
|
||||
6,
|
||||
varop_asm,
|
||||
sizeof(varop_asm));
|
||||
}
|
||||
|
||||
DstTable *dst_stl_env(int flags) {
|
||||
static uint32_t error_asm[] = {
|
||||
DOP_ERROR
|
||||
};
|
||||
static uint32_t apply_asm[] = {
|
||||
DOP_PUSH_ARRAY | (1 << 8),
|
||||
DOP_TAILCALL
|
||||
};
|
||||
static uint32_t debug_asm[] = {
|
||||
DOP_SIGNAL | (2 << 24),
|
||||
DOP_RETURN_NIL
|
||||
};
|
||||
static uint32_t yield_asm[] = {
|
||||
DOP_SIGNAL | (3 << 24),
|
||||
DOP_RETURN
|
||||
};
|
||||
static uint32_t resume_asm[] = {
|
||||
DOP_RESUME | (1 << 24),
|
||||
DOP_RETURN
|
||||
};
|
||||
static uint32_t get_asm[] = {
|
||||
DOP_GET | (1 << 24),
|
||||
DOP_RETURN
|
||||
};
|
||||
static uint32_t put_asm[] = {
|
||||
DOP_PUT | (1 << 16) | (2 << 24),
|
||||
DOP_RETURN
|
||||
};
|
||||
static uint32_t length_asm[] = {
|
||||
DOP_LENGTH,
|
||||
DOP_RETURN
|
||||
};
|
||||
|
||||
DstTable *env = dst_table(0);
|
||||
Dst ret = dst_wrap_table(env);
|
||||
|
||||
/* Load main functions */
|
||||
dst_env_cfuns(env, cfuns);
|
||||
|
||||
dst_quick_asm(env, DST_FUN_YIELD, "debug", 0, 1, debug_asm, sizeof(debug_asm));
|
||||
dst_quick_asm(env, DST_FUN_ERROR, "error", 1, 1, error_asm, sizeof(error_asm));
|
||||
dst_quick_asm(env, DST_FUN_APPLY1, "apply1", 2, 2, apply_asm, sizeof(apply_asm));
|
||||
dst_quick_asm(env, DST_FUN_YIELD, "yield", 1, 2, yield_asm, sizeof(yield_asm));
|
||||
dst_quick_asm(env, DST_FUN_RESUME, "resume", 2, 2, resume_asm, sizeof(resume_asm));
|
||||
dst_quick_asm(env, DST_FUN_GET, "get", 2, 2, get_asm, sizeof(get_asm));
|
||||
dst_quick_asm(env, DST_FUN_PUT, "put", 3, 3, put_asm, sizeof(put_asm));
|
||||
dst_quick_asm(env, DST_FUN_LENGTH, "length", 1, 1, length_asm, sizeof(length_asm));
|
||||
|
||||
/* Variadic ops */
|
||||
templatize_varop(env, DST_FUN_ADD, "+", 0, 0, DOP_ADD);
|
||||
templatize_varop(env, DST_FUN_SUBTRACT, "-", 0, 0, DOP_SUBTRACT);
|
||||
templatize_varop(env, DST_FUN_MULTIPLY, "*", 1, 1, DOP_MULTIPLY);
|
||||
templatize_varop(env, DST_FUN_DIVIDE, "/", 1, 1, DOP_DIVIDE);
|
||||
templatize_varop(env, DST_FUN_BAND, "&", -1, -1, DOP_BAND);
|
||||
templatize_varop(env, DST_FUN_BOR, "|", 0, 0, DOP_BOR);
|
||||
templatize_varop(env, DST_FUN_BXOR, "^", 0, 0, DOP_BXOR);
|
||||
templatize_varop(env, DST_FUN_LSHIFT, "<<", 1, 1, DOP_SHIFT_LEFT);
|
||||
templatize_varop(env, DST_FUN_RSHIFT, ">>", 1, 1, DOP_SHIFT_RIGHT);
|
||||
templatize_varop(env, DST_FUN_RSHIFTU, ">>>", 1, 1, DOP_SHIFT_RIGHT_UNSIGNED);
|
||||
|
||||
dst_env_def(env, "VERSION", dst_cstringv(DST_VERSION));
|
||||
|
||||
/* Set as gc root */
|
||||
dst_gcroot(dst_wrap_table(env));
|
||||
|
||||
/* Load auxiliary envs */
|
||||
{
|
||||
DstArgs args;
|
||||
args.n = 1;
|
||||
args.v = &ret;
|
||||
args.ret = &ret;
|
||||
dst_lib_io(args);
|
||||
dst_lib_math(args);
|
||||
dst_lib_array(args);
|
||||
dst_lib_tuple(args);
|
||||
dst_lib_buffer(args);
|
||||
dst_lib_table(args);
|
||||
dst_lib_fiber(args);
|
||||
dst_lib_os(args);
|
||||
dst_lib_parse(args);
|
||||
dst_lib_compile(args);
|
||||
dst_lib_asm(args);
|
||||
dst_lib_string(args);
|
||||
dst_lib_marsh(args);
|
||||
}
|
||||
|
||||
/* Allow references to the environment */
|
||||
dst_env_def(env, "_env", ret);
|
||||
|
||||
/* Run bootstrap source */
|
||||
dst_dobytes(env, dst_stl_bootstrap_gen, sizeof(dst_stl_bootstrap_gen), "boot.dst");
|
||||
|
||||
if (flags & DST_STL_NOGCROOT)
|
||||
dst_gcunroot(dst_wrap_table(env));
|
||||
|
||||
return env;
|
||||
}
|
||||
|
@ -20,39 +20,7 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef DST_COMPILE_H_defined
|
||||
#define DST_COMPILE_H_defined
|
||||
#ifndef DST_CORELIB_H
|
||||
#define DST_CORELIB_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "dsttypes.h"
|
||||
|
||||
typedef struct DstCompileOptions DstCompileOptions;
|
||||
typedef struct DstCompileResult DstCompileResult;
|
||||
enum DstCompileStatus {
|
||||
DST_COMPILE_OK,
|
||||
DST_COMPILE_ERROR
|
||||
};
|
||||
struct DstCompileResult {
|
||||
enum DstCompileStatus status;
|
||||
DstFuncDef *funcdef;
|
||||
const uint8_t *error;
|
||||
DstSourceMapping error_mapping;
|
||||
};
|
||||
DstCompileResult dst_compile(Dst source, DstTable *env, const uint8_t *where);
|
||||
int dst_compile_cfun(DstArgs args);
|
||||
int dst_lib_compile(DstArgs args);
|
||||
|
||||
/* Get the default environment for dst */
|
||||
DstTable *dst_stl_env();
|
||||
|
||||
int dst_dobytes(DstTable *env, const uint8_t *bytes, int32_t len, const char *sourcePath);
|
||||
int dst_dostring(DstTable *env, const char *str, const char *sourcePath);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -20,9 +20,10 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <dst/dstcompile.h>
|
||||
#include <headerlibs/vector.h>
|
||||
#include <dst/dst.h>
|
||||
#include "emit.h"
|
||||
#include "vector.h"
|
||||
#include "regalloc.h"
|
||||
|
||||
/* Get a register */
|
||||
int32_t dstc_allocfar(DstCompiler *c) {
|
||||
@ -106,77 +107,104 @@ static void dstc_loadconst(DstCompiler *c, Dst k, int32_t reg) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert a slot to a two byte register */
|
||||
int32_t dstc_regfar(DstCompiler *c, DstSlot s, DstcRegisterTemp tag) {
|
||||
int32_t reg;
|
||||
if (s.flags & (DST_SLOT_CONSTANT | DST_SLOT_REF)) {
|
||||
reg = dstc_allocnear(c, tag);
|
||||
dstc_loadconst(c, s.constant, reg);
|
||||
/* Move a slot to a near register */
|
||||
static void dstc_movenear(DstCompiler *c,
|
||||
int32_t dest,
|
||||
DstSlot src) {
|
||||
if (src.flags & (DST_SLOT_CONSTANT | DST_SLOT_REF)) {
|
||||
dstc_loadconst(c, src.constant, dest);
|
||||
/* If we also are a reference, deref the one element array */
|
||||
if (s.flags & DST_SLOT_REF) {
|
||||
if (src.flags & DST_SLOT_REF) {
|
||||
dstc_emit(c,
|
||||
(reg << 16) |
|
||||
(reg << 8) |
|
||||
(dest << 16) |
|
||||
(dest << 8) |
|
||||
DOP_GET_INDEX);
|
||||
}
|
||||
} else if (s.envindex >= 0) {
|
||||
reg = dstc_allocnear(c, tag);
|
||||
} else if (src.envindex >= 0) {
|
||||
dstc_emit(c,
|
||||
((uint32_t)(s.index) << 24) |
|
||||
((uint32_t)(s.envindex) << 16) |
|
||||
((uint32_t)(reg) << 8) |
|
||||
((uint32_t)(src.index) << 24) |
|
||||
((uint32_t)(src.envindex) << 16) |
|
||||
((uint32_t)(dest) << 8) |
|
||||
DOP_LOAD_UPVALUE);
|
||||
} else if (src.index > 0xFF || src.index != dest) {
|
||||
dstc_emit(c,
|
||||
((uint32_t)(src.index) << 16) |
|
||||
((uint32_t)(dest) << 8) |
|
||||
DOP_MOVE_NEAR);
|
||||
}
|
||||
}
|
||||
|
||||
/* Move a near register to a Slot. */
|
||||
static void dstc_moveback(DstCompiler *c,
|
||||
DstSlot dest,
|
||||
int32_t src) {
|
||||
if (dest.flags & DST_SLOT_REF) {
|
||||
int32_t refreg = dstc_regalloc_temp(&c->scope->ra, DSTC_REGTEMP_5);
|
||||
dstc_loadconst(c, dest.constant, refreg);
|
||||
dstc_emit(c,
|
||||
(src << 16) |
|
||||
(refreg << 8) |
|
||||
DOP_PUT_INDEX);
|
||||
dstc_regalloc_freetemp(&c->scope->ra, refreg, DSTC_REGTEMP_5);
|
||||
} else if (dest.envindex >= 0) {
|
||||
dstc_emit(c,
|
||||
((uint32_t)(dest.index) << 24) |
|
||||
((uint32_t)(dest.envindex) << 16) |
|
||||
((uint32_t)(src) << 8) |
|
||||
DOP_SET_UPVALUE);
|
||||
} else if (dest.index != src) {
|
||||
dstc_emit(c,
|
||||
((uint32_t)(dest.index) << 16) |
|
||||
((uint32_t)(src) << 8) |
|
||||
DOP_MOVE_FAR);
|
||||
}
|
||||
}
|
||||
|
||||
/* Call this to release a register after emitting the instruction. */
|
||||
static void dstc_free_regnear(DstCompiler *c, DstSlot s, int32_t reg, DstcRegisterTemp tag) {
|
||||
if (reg != s.index ||
|
||||
s.envindex >= 0 ||
|
||||
s.flags & (DST_SLOT_CONSTANT | DST_SLOT_REF)) {
|
||||
/* We need to free the temporary slot */
|
||||
dstc_regalloc_freetemp(&c->scope->ra, reg, tag);
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert a slot to a two byte register */
|
||||
static int32_t dstc_regfar(DstCompiler *c, DstSlot s, DstcRegisterTemp tag) {
|
||||
/* check if already near register */
|
||||
if (s.envindex < 0 && s.index >= 0) {
|
||||
return s.index;
|
||||
}
|
||||
int32_t reg;
|
||||
int32_t nearreg = dstc_regalloc_temp(&c->scope->ra, tag);
|
||||
dstc_movenear(c, nearreg, s);
|
||||
if (nearreg >= 0xF0) {
|
||||
reg = dstc_allocfar(c);
|
||||
dstc_emit(c, DOP_MOVE_FAR | (nearreg << 8) | (reg << 16));
|
||||
dstc_regalloc_freetemp(&c->scope->ra, nearreg, tag);
|
||||
} else {
|
||||
/* We have a normal slot that fits in the required bit width */
|
||||
reg = s.index;
|
||||
reg = nearreg;
|
||||
dstc_regalloc_freetemp(&c->scope->ra, nearreg, tag);
|
||||
dstc_regalloc_touch(&c->scope->ra, reg);
|
||||
}
|
||||
return reg;
|
||||
}
|
||||
|
||||
/* Convert a slot to a temporary 1 byte register */
|
||||
int32_t dstc_regnear(DstCompiler *c, DstSlot s, DstcRegisterTemp tag) {
|
||||
int32_t reg;
|
||||
if (s.flags & (DST_SLOT_CONSTANT | DST_SLOT_REF)) {
|
||||
reg = dstc_allocnear(c, tag);
|
||||
dstc_loadconst(c, s.constant, reg);
|
||||
/* If we also are a reference, deref the one element array */
|
||||
if (s.flags & DST_SLOT_REF) {
|
||||
dstc_emit(c,
|
||||
(reg << 16) |
|
||||
(reg << 8) |
|
||||
DOP_GET_INDEX);
|
||||
}
|
||||
} else if (s.envindex >= 0) {
|
||||
reg = dstc_allocnear(c, tag);
|
||||
dstc_emit(c,
|
||||
((uint32_t)(s.index) << 24) |
|
||||
((uint32_t)(s.envindex) << 16) |
|
||||
((uint32_t)(reg) << 8) |
|
||||
DOP_LOAD_UPVALUE);
|
||||
} else if (s.index > 0xFF) {
|
||||
reg = dstc_allocnear(c, tag);
|
||||
dstc_emit(c,
|
||||
((uint32_t)(s.index) << 16) |
|
||||
((uint32_t)(reg) << 8) |
|
||||
DOP_MOVE_NEAR);
|
||||
} else {
|
||||
/* We have a normal slot that fits in the required bit width */
|
||||
reg = s.index;
|
||||
static int32_t dstc_regnear(DstCompiler *c, DstSlot s, DstcRegisterTemp tag) {
|
||||
/* check if already near register */
|
||||
if (s.envindex < 0 && s.index >= 0 && s.index <= 0xFF) {
|
||||
return s.index;
|
||||
}
|
||||
int32_t reg = dstc_regalloc_temp(&c->scope->ra, tag);
|
||||
dstc_movenear(c, reg, s);
|
||||
return reg;
|
||||
}
|
||||
|
||||
/* Call this to release a register after emitting the instruction. */
|
||||
void dstc_free_reg(DstCompiler *c, DstSlot s, int32_t reg) {
|
||||
if (reg != s.index || s.envindex >= 0 || s.flags & DST_SLOT_CONSTANT) {
|
||||
/* We need to free the temporary slot */
|
||||
dstc_regalloc_free(&c->scope->ra, reg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if two slots are equal */
|
||||
static int dstc_sequal(DstSlot lhs, DstSlot rhs) {
|
||||
if (lhs.flags == rhs.flags &&
|
||||
if ((lhs.flags & ~DST_SLOTTYPE_ANY) == (rhs.flags & ~DST_SLOTTYPE_ANY) &&
|
||||
lhs.index == rhs.index &&
|
||||
lhs.envindex == rhs.envindex) {
|
||||
if (lhs.flags & (DST_SLOT_REF | DST_SLOT_CONSTANT)) {
|
||||
@ -194,131 +222,48 @@ void dstc_copy(
|
||||
DstCompiler *c,
|
||||
DstSlot dest,
|
||||
DstSlot src) {
|
||||
int writeback = 0;
|
||||
int32_t destlocal = -1;
|
||||
int32_t srclocal = -1;
|
||||
int32_t reflocal = -1;
|
||||
|
||||
/* Can't write to constants */
|
||||
if (dest.flags & DST_SLOT_CONSTANT) {
|
||||
dstc_cerror(c, "cannot write to constant");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Short circuit if dest and source are equal */
|
||||
if (dstc_sequal(dest, src)) return;
|
||||
|
||||
/* Types of slots - src */
|
||||
/* constants */
|
||||
/* upvalues */
|
||||
/* refs */
|
||||
/* near index */
|
||||
/* far index */
|
||||
|
||||
/* Types of slots - dest */
|
||||
/* upvalues */
|
||||
/* refs */
|
||||
/* near index */
|
||||
/* far index */
|
||||
|
||||
/* If dest is a near index, do some optimization */
|
||||
/* If dest is a near register */
|
||||
if (dest.envindex < 0 && dest.index >= 0 && dest.index <= 0xFF) {
|
||||
if (src.flags & DST_SLOT_CONSTANT) {
|
||||
dstc_loadconst(c, src.constant, dest.index);
|
||||
} else if (src.flags & DST_SLOT_REF) {
|
||||
dstc_loadconst(c, src.constant, dest.index);
|
||||
dstc_emit(c,
|
||||
(dest.index << 16) |
|
||||
(dest.index << 8) |
|
||||
DOP_GET_INDEX);
|
||||
} else if (src.envindex >= 0) {
|
||||
dstc_emit(c,
|
||||
(src.index << 24) |
|
||||
(src.envindex << 16) |
|
||||
(dest.index << 8) |
|
||||
DOP_LOAD_UPVALUE);
|
||||
} else {
|
||||
dstc_emit(c,
|
||||
(src.index << 16) |
|
||||
(dest.index << 8) |
|
||||
DOP_MOVE_NEAR);
|
||||
}
|
||||
dstc_movenear(c, dest.index, src);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Process: src -> srclocal -> destlocal -> dest */
|
||||
|
||||
/* src -> srclocal */
|
||||
srclocal = dstc_regnear(c, src, DSTC_REGTEMP_0);
|
||||
|
||||
/* Pull down dest (find destlocal) */
|
||||
if (dest.flags & DST_SLOT_REF) {
|
||||
writeback = 1;
|
||||
destlocal = srclocal;
|
||||
reflocal = dstc_allocnear(c, DSTC_REGTEMP_1);
|
||||
dstc_emit(c,
|
||||
(dstc_const(c, dest.constant) << 16) |
|
||||
(reflocal << 8) |
|
||||
DOP_LOAD_CONSTANT);
|
||||
} else if (dest.envindex >= 0) {
|
||||
writeback = 2;
|
||||
destlocal = srclocal;
|
||||
} else if (dest.index > 0xFF) {
|
||||
writeback = 3;
|
||||
destlocal = srclocal;
|
||||
} else {
|
||||
destlocal = dest.index;
|
||||
/* If src is a near register */
|
||||
if (src.envindex < 0 && src.index >= 0 && src.index <= 0xFF) {
|
||||
dstc_moveback(c, dest, src.index);
|
||||
return;
|
||||
}
|
||||
|
||||
/* srclocal -> destlocal */
|
||||
if (srclocal != destlocal) {
|
||||
dstc_emit(c,
|
||||
((uint32_t)(srclocal) << 16) |
|
||||
((uint32_t)(destlocal) << 8) |
|
||||
DOP_MOVE_NEAR);
|
||||
}
|
||||
|
||||
/* destlocal -> dest */
|
||||
if (writeback == 1) {
|
||||
dstc_emit(c,
|
||||
(destlocal << 16) |
|
||||
(reflocal << 8) |
|
||||
DOP_PUT_INDEX);
|
||||
} else if (writeback == 2) {
|
||||
dstc_emit(c,
|
||||
((uint32_t)(dest.index) << 24) |
|
||||
((uint32_t)(dest.envindex) << 16) |
|
||||
((uint32_t)(destlocal) << 8) |
|
||||
DOP_SET_UPVALUE);
|
||||
} else if (writeback == 3) {
|
||||
dstc_emit(c,
|
||||
((uint32_t)(dest.index) << 16) |
|
||||
((uint32_t)(destlocal) << 8) |
|
||||
DOP_MOVE_FAR);
|
||||
}
|
||||
|
||||
/* Process: src -> near -> dest */
|
||||
int32_t near = dstc_allocnear(c, DSTC_REGTEMP_3);
|
||||
dstc_movenear(c, near, src);
|
||||
dstc_moveback(c, dest, near);
|
||||
/* Cleanup */
|
||||
if (reflocal >= 0) {
|
||||
dstc_regalloc_free(&c->scope->ra, reflocal);
|
||||
}
|
||||
dstc_free_reg(c, src, srclocal);
|
||||
}
|
||||
dstc_regalloc_freetemp(&c->scope->ra, near, DSTC_REGTEMP_3);
|
||||
|
||||
}
|
||||
/* Instruction templated emitters */
|
||||
|
||||
static int32_t emit1s(DstCompiler *c, uint8_t op, DstSlot s, int32_t rest) {
|
||||
static int32_t emit1s(DstCompiler *c, uint8_t op, DstSlot s, int32_t rest, int wr) {
|
||||
int32_t reg = dstc_regnear(c, s, DSTC_REGTEMP_0);
|
||||
int32_t label = dst_v_count(c->buffer);
|
||||
dstc_emit(c, op | (reg << 8) | (rest << 16));
|
||||
dstc_free_reg(c, s, reg);
|
||||
if (wr)
|
||||
dstc_moveback(c, s, reg);
|
||||
dstc_free_regnear(c, s, reg, DSTC_REGTEMP_0);
|
||||
return label;
|
||||
}
|
||||
|
||||
int32_t dstc_emit_s(DstCompiler *c, uint8_t op, DstSlot s) {
|
||||
int32_t dstc_emit_s(DstCompiler *c, uint8_t op, DstSlot s, int wr) {
|
||||
int32_t reg = dstc_regfar(c, s, DSTC_REGTEMP_0);
|
||||
int32_t label = dst_v_count(c->buffer);
|
||||
dstc_emit(c, op | (reg << 8));
|
||||
dstc_free_reg(c, s, reg);
|
||||
if (wr)
|
||||
dstc_moveback(c, s, reg);
|
||||
dstc_free_regnear(c, s, reg, DSTC_REGTEMP_0);
|
||||
return label;
|
||||
}
|
||||
|
||||
@ -328,57 +273,63 @@ int32_t dstc_emit_sl(DstCompiler *c, uint8_t op, DstSlot s, int32_t label) {
|
||||
if (jump < INT16_MIN || jump > INT16_MAX) {
|
||||
dstc_cerror(c, "jump is too far");
|
||||
}
|
||||
return emit1s(c, op, s, jump);
|
||||
return emit1s(c, op, s, jump, 0);
|
||||
}
|
||||
|
||||
int32_t dstc_emit_st(DstCompiler *c, uint8_t op, DstSlot s, int32_t tflags) {
|
||||
return emit1s(c, op, s, tflags);
|
||||
return emit1s(c, op, s, tflags, 0);
|
||||
}
|
||||
|
||||
int32_t dstc_emit_si(DstCompiler *c, uint8_t op, DstSlot s, int16_t immediate) {
|
||||
return emit1s(c, op, s, immediate);
|
||||
int32_t dstc_emit_si(DstCompiler *c, uint8_t op, DstSlot s, int16_t immediate, int wr) {
|
||||
return emit1s(c, op, s, immediate, wr);
|
||||
}
|
||||
|
||||
int32_t dstc_emit_su(DstCompiler *c, uint8_t op, DstSlot s, uint16_t immediate) {
|
||||
return emit1s(c, op, s, (int32_t) immediate);
|
||||
int32_t dstc_emit_su(DstCompiler *c, uint8_t op, DstSlot s, uint16_t immediate, int wr) {
|
||||
return emit1s(c, op, s, (int32_t) immediate, wr);
|
||||
}
|
||||
|
||||
static int32_t emit2s(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, int32_t rest) {
|
||||
static int32_t emit2s(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, int32_t rest, int wr) {
|
||||
int32_t reg1 = dstc_regnear(c, s1, DSTC_REGTEMP_0);
|
||||
int32_t reg2 = dstc_regnear(c, s2, DSTC_REGTEMP_1);
|
||||
int32_t label = dst_v_count(c->buffer);
|
||||
dstc_emit(c, op | (reg1 << 8) | (reg2 << 16) | (rest << 24));
|
||||
dstc_free_reg(c, s1, reg1);
|
||||
dstc_free_reg(c, s2, reg2);
|
||||
dstc_free_regnear(c, s2, reg2, DSTC_REGTEMP_1);
|
||||
if (wr)
|
||||
dstc_moveback(c, s1, reg1);
|
||||
dstc_free_regnear(c, s1, reg1, DSTC_REGTEMP_0);
|
||||
return label;
|
||||
}
|
||||
|
||||
int32_t dstc_emit_ss(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2) {
|
||||
int32_t dstc_emit_ss(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, int wr) {
|
||||
int32_t reg1 = dstc_regnear(c, s1, DSTC_REGTEMP_0);
|
||||
int32_t reg2 = dstc_regfar(c, s2, DSTC_REGTEMP_1);
|
||||
int32_t label = dst_v_count(c->buffer);
|
||||
dstc_emit(c, op | (reg1 << 8) | (reg2 << 16));
|
||||
dstc_free_reg(c, s1, reg1);
|
||||
dstc_free_reg(c, s2, reg2);
|
||||
dstc_free_regnear(c, s2, reg2, DSTC_REGTEMP_1);
|
||||
if (wr)
|
||||
dstc_moveback(c, s1, reg1);
|
||||
dstc_free_regnear(c, s1, reg1, DSTC_REGTEMP_0);
|
||||
return label;
|
||||
}
|
||||
|
||||
int32_t dstc_emit_ssi(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, int8_t immediate) {
|
||||
return emit2s(c, op, s1, s2, immediate);
|
||||
int32_t dstc_emit_ssi(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, int8_t immediate, int wr) {
|
||||
return emit2s(c, op, s1, s2, immediate, wr);
|
||||
}
|
||||
|
||||
int32_t dstc_emit_ssu(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, uint8_t immediate) {
|
||||
return emit2s(c, op, s1, s2, (int32_t) immediate);
|
||||
int32_t dstc_emit_ssu(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, uint8_t immediate, int wr) {
|
||||
return emit2s(c, op, s1, s2, (int32_t) immediate, wr);
|
||||
}
|
||||
|
||||
int32_t dstc_emit_sss(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, DstSlot s3) {
|
||||
int32_t dstc_emit_sss(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, DstSlot s3, int wr) {
|
||||
int32_t reg1 = dstc_regnear(c, s1, DSTC_REGTEMP_0);
|
||||
int32_t reg2 = dstc_regnear(c, s2, DSTC_REGTEMP_1);
|
||||
int32_t reg3 = dstc_regnear(c, s3, DSTC_REGTEMP_2);
|
||||
int32_t label = dst_v_count(c->buffer);
|
||||
dstc_emit(c, op | (reg1 << 8) | (reg2 << 16) | (reg3 << 24));
|
||||
dstc_free_reg(c, s1, reg1);
|
||||
dstc_free_reg(c, s2, reg2);
|
||||
dstc_free_reg(c, s3, reg3);
|
||||
dstc_free_regnear(c, s2, reg2, DSTC_REGTEMP_1);
|
||||
dstc_free_regnear(c, s3, reg3, DSTC_REGTEMP_2);
|
||||
if (wr)
|
||||
dstc_moveback(c, s1, reg1);
|
||||
dstc_free_regnear(c, s1, reg1, DSTC_REGTEMP_0);
|
||||
return label;
|
||||
}
|
@ -30,19 +30,15 @@ void dstc_emit(DstCompiler *c, uint32_t instr);
|
||||
int32_t dstc_allocfar(DstCompiler *c);
|
||||
int32_t dstc_allocnear(DstCompiler *c, DstcRegisterTemp);
|
||||
|
||||
int32_t dstc_regfar(DstCompiler *c, DstSlot s, DstcRegisterTemp tag);
|
||||
int32_t dstc_regnear(DstCompiler *c, DstSlot s, DstcRegisterTemp tag);
|
||||
void dstc_free_reg(DstCompiler *c, DstSlot s, int32_t reg);
|
||||
|
||||
int32_t dstc_emit_s(DstCompiler *c, uint8_t op, DstSlot s);
|
||||
int32_t dstc_emit_s(DstCompiler *c, uint8_t op, DstSlot s, int wr);
|
||||
int32_t dstc_emit_sl(DstCompiler *c, uint8_t op, DstSlot s, int32_t label);
|
||||
int32_t dstc_emit_st(DstCompiler *c, uint8_t op, DstSlot s, int32_t tflags);
|
||||
int32_t dstc_emit_si(DstCompiler *c, uint8_t op, DstSlot s, int16_t immediate);
|
||||
int32_t dstc_emit_su(DstCompiler *c, uint8_t op, DstSlot s, uint16_t immediate);
|
||||
int32_t dstc_emit_ss(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2);
|
||||
int32_t dstc_emit_ssi(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, int8_t immediate);
|
||||
int32_t dstc_emit_ssu(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, uint8_t immediate);
|
||||
int32_t dstc_emit_sss(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, DstSlot s3);
|
||||
int32_t dstc_emit_si(DstCompiler *c, uint8_t op, DstSlot s, int16_t immediate, int wr);
|
||||
int32_t dstc_emit_su(DstCompiler *c, uint8_t op, DstSlot s, uint16_t immediate, int wr);
|
||||
int32_t dstc_emit_ss(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, int wr);
|
||||
int32_t dstc_emit_ssi(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, int8_t immediate, int wr);
|
||||
int32_t dstc_emit_ssu(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, uint8_t immediate, int wr);
|
||||
int32_t dstc_emit_sss(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, DstSlot s3, int wr);
|
||||
|
||||
/* Move value from one slot to another. Cannot copy to constant slots. */
|
||||
void dstc_copy(DstCompiler *c, DstSlot dest, DstSlot src);
|
@ -21,8 +21,6 @@
|
||||
*/
|
||||
|
||||
#include <dst/dst.h>
|
||||
#include <dst/dstopcodes.h>
|
||||
#include <dst/dstcorelib.h>
|
||||
#include "fiber.h"
|
||||
#include "state.h"
|
||||
#include "gc.h"
|
||||
@ -365,8 +363,8 @@ static Dst doframe(DstStackFrame *frame) {
|
||||
dst_table_put(t, dst_csymbolv(":pc"), dst_wrap_integer(off));
|
||||
if (def->sourcemap) {
|
||||
DstSourceMapping mapping = def->sourcemap[off];
|
||||
dst_table_put(t, dst_csymbolv(":source-line"), dst_wrap_integer(mapping.line));
|
||||
dst_table_put(t, dst_csymbolv(":source-column"), dst_wrap_integer(mapping.column));
|
||||
dst_table_put(t, dst_csymbolv(":line"), dst_wrap_integer(mapping.line));
|
||||
dst_table_put(t, dst_csymbolv(":column"), dst_wrap_integer(mapping.column));
|
||||
}
|
||||
if (def->source) {
|
||||
dst_table_put(t, dst_csymbolv(":source"), dst_wrap_string(def->source));
|
||||
|
@ -20,8 +20,9 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define _DEFAULT_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <dst/dst.h>
|
||||
#include <dst/dstcorelib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define IO_WRITE 1
|
||||
|
@ -21,7 +21,6 @@
|
||||
*/
|
||||
|
||||
#include <dst/dst.h>
|
||||
#include <dst/dstcorelib.h>
|
||||
#include <math.h>
|
||||
|
||||
/* Get a random number */
|
||||
|
@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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 <dst/dst.h>
|
||||
#include <dst/dstcorelib.h>
|
||||
|
||||
/* Use LoadLibrary on windows or dlopen on posix to load dynamic libaries
|
||||
* with native code. */
|
||||
#ifdef DST_WINDOWS
|
||||
#include <windows.h>
|
||||
typedef HINSTANCE Clib;
|
||||
#define load_clib(name) LoadLibrary((name))
|
||||
#define symbol_clib(lib, sym) GetProcAddress((lib), (sym))
|
||||
#define error_clib() "could not load dynamic library"
|
||||
#elif defined(DST_WEB)
|
||||
#include <emscripten.h>
|
||||
/* TODO - figure out how loading modules will work in JS */
|
||||
typedef int Clib;
|
||||
#define load_clib(name) 0
|
||||
#define symbol_clib(lib, sym) 0
|
||||
#define error_clib() "dynamic libraries not supported"
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
typedef void *Clib;
|
||||
#define load_clib(name) dlopen((name), RTLD_NOW)
|
||||
#define symbol_clib(lib, sym) dlsym((lib), (sym))
|
||||
#define error_clib() dlerror()
|
||||
#endif
|
||||
|
||||
DstCFunction dst_native(const char *name, const uint8_t **error) {
|
||||
Clib lib = load_clib(name);
|
||||
DstCFunction init;
|
||||
if (!lib) {
|
||||
*error = dst_cstring(error_clib());
|
||||
return NULL;
|
||||
}
|
||||
init = (DstCFunction) symbol_clib(lib, "_dst_init");
|
||||
if (!init) {
|
||||
*error = dst_cstring("could not find _dst_init symbol");
|
||||
return NULL;
|
||||
}
|
||||
return init;
|
||||
}
|
||||
|
||||
int dst_core_native(DstArgs args) {
|
||||
DstCFunction init;
|
||||
const uint8_t *error = NULL;
|
||||
const uint8_t *path = NULL;
|
||||
DST_FIXARITY(args, 1);
|
||||
DST_ARG_STRING(path, args, 0);
|
||||
init = dst_native((const char *)path, &error);
|
||||
if (!init) {
|
||||
DST_THROWV(args, dst_wrap_string(error));
|
||||
}
|
||||
DST_RETURN_CFUNCTION(args, init);
|
||||
}
|
@ -21,8 +21,6 @@
|
||||
*/
|
||||
|
||||
#include <dst/dst.h>
|
||||
#include <dst/dstcorelib.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
|
@ -20,9 +20,8 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "regalloc.h"
|
||||
#include <stdlib.h>
|
||||
#include <dst/dst.h>
|
||||
#include "regalloc.h"
|
||||
|
||||
void dstc_regalloc_init(DstcRegisterAllocator *ra) {
|
||||
ra->chunks = NULL;
|
||||
@ -66,6 +65,7 @@ void dstc_regalloc_clone(DstcRegisterAllocator *dest, DstcRegisterAllocator *src
|
||||
dest->max = src->max;
|
||||
size = sizeof(uint32_t) * dest->capacity;
|
||||
dest->chunks = malloc(size);
|
||||
dest->regtemps = 0;
|
||||
if (!dest->chunks) {
|
||||
DST_OUT_OF_MEMORY;
|
||||
}
|
||||
@ -126,17 +126,7 @@ int32_t dstc_regalloc_1(DstcRegisterAllocator *ra) {
|
||||
/* Free a register. The register must have been previously allocated
|
||||
* without being freed. */
|
||||
void dstc_regalloc_free(DstcRegisterAllocator *ra, int32_t reg) {
|
||||
/* We cannot free reserved slots */
|
||||
if (reg < 0)
|
||||
return;
|
||||
if (reg >= 0xF0 && reg <= 0xFF) {
|
||||
ra->regtemps &= ~(1 << (reg - 0xF0));
|
||||
return;
|
||||
}
|
||||
int32_t chunk = reg >> 5;
|
||||
/* Outside normal chunk range */
|
||||
if (chunk >= ra->count)
|
||||
return;
|
||||
int32_t bit = reg & 0x1F;
|
||||
ra->chunks[chunk] &= ~ithbit(bit);
|
||||
}
|
||||
@ -146,9 +136,11 @@ void dstc_regalloc_free(DstcRegisterAllocator *ra, int32_t reg) {
|
||||
* on the returned register before. */
|
||||
int32_t dstc_regalloc_temp(DstcRegisterAllocator *ra, DstcRegisterTemp nth) {
|
||||
int32_t oldmax = ra->max;
|
||||
int32_t reg = dstc_regalloc_1(ra);
|
||||
dst_assert(~(ra->regtemps & (1 << nth)), "regtemp already allocated");
|
||||
if (ra->regtemps & (1 << nth)) {
|
||||
dst_exit("regtemp already allocated");
|
||||
}
|
||||
ra->regtemps |= 1 << nth;
|
||||
int32_t reg = dstc_regalloc_1(ra);
|
||||
if (reg > 0xFF) {
|
||||
reg = 0xF0 + nth;
|
||||
ra->max = (reg > oldmax) ? reg : oldmax;
|
||||
@ -156,6 +148,12 @@ int32_t dstc_regalloc_temp(DstcRegisterAllocator *ra, DstcRegisterTemp nth) {
|
||||
return reg;
|
||||
}
|
||||
|
||||
void dstc_regalloc_freetemp(DstcRegisterAllocator *ra, int32_t reg, DstcRegisterTemp nth) {
|
||||
ra->regtemps &= ~(1 << nth);
|
||||
if (reg < 0xF0)
|
||||
dstc_regalloc_free(ra, reg);
|
||||
}
|
||||
|
||||
/* Disable multi-slot allocation for now. */
|
||||
|
||||
/*
|
@ -36,7 +36,7 @@ typedef enum {
|
||||
DSTC_REGTEMP_4,
|
||||
DSTC_REGTEMP_5,
|
||||
DSTC_REGTEMP_6,
|
||||
DSTC_REGTEMP_TARGET
|
||||
DSTC_REGTEMP_7
|
||||
} DstcRegisterTemp;
|
||||
|
||||
typedef struct {
|
||||
@ -53,6 +53,7 @@ void dstc_regalloc_deinit(DstcRegisterAllocator *ra);
|
||||
int32_t dstc_regalloc_1(DstcRegisterAllocator *ra);
|
||||
void dstc_regalloc_free(DstcRegisterAllocator *ra, int32_t reg);
|
||||
int32_t dstc_regalloc_temp(DstcRegisterAllocator *ra, DstcRegisterTemp nth);
|
||||
void dstc_regalloc_freetemp(DstcRegisterAllocator *ra, int32_t reg, DstcRegisterTemp nth);
|
||||
void dstc_regalloc_clone(DstcRegisterAllocator *dest, DstcRegisterAllocator *src);
|
||||
void dstc_regalloc_touch(DstcRegisterAllocator *ra, int32_t reg);
|
||||
|
@ -21,8 +21,49 @@
|
||||
*/
|
||||
|
||||
#include <dst/dst.h>
|
||||
#include <dst/dstcorelib.h>
|
||||
#include <dst/dstcompile.h>
|
||||
#include "state.h"
|
||||
|
||||
/* Error reporting */
|
||||
static void print_error_report(DstFiber *fiber, const char *errtype, Dst err) {
|
||||
const char *errstr = (const char *)dst_to_string(err);
|
||||
printf("%s error: %s\n", errtype, errstr);
|
||||
if (!fiber) return;
|
||||
int32_t i = fiber->frame;
|
||||
while (i > 0) {
|
||||
DstStackFrame *frame = (DstStackFrame *)(fiber->data + i - DST_FRAME_SIZE);
|
||||
DstFuncDef *def = NULL;
|
||||
i = frame->prevframe;
|
||||
|
||||
printf(" at");
|
||||
|
||||
if (frame->func) {
|
||||
def = frame->func->def;
|
||||
printf(" %s", def->name ? (const char *)def->name : "<anonymous>");
|
||||
if (def->source) {
|
||||
printf(" %s", (const char *)def->source);
|
||||
}
|
||||
} else {
|
||||
DstCFunction cfun = (DstCFunction)(frame->pc);
|
||||
if (cfun) {
|
||||
Dst name = dst_table_get(dst_vm_registry, dst_wrap_cfunction(cfun));
|
||||
if (!dst_checktype(name, DST_NIL))
|
||||
printf(" [%s]", (const char *)dst_to_string(name));
|
||||
}
|
||||
}
|
||||
if (frame->flags & DST_STACKFRAME_TAILCALL)
|
||||
printf(" (tailcall)");
|
||||
if (frame->func && frame->pc) {
|
||||
int32_t off = (int32_t) (frame->pc - def->bytecode);
|
||||
if (def->sourcemap) {
|
||||
DstSourceMapping mapping = def->sourcemap[off];
|
||||
printf(" on line %d, column %d", mapping.line, mapping.column);
|
||||
} else {
|
||||
printf(" pc=%d", off);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Run a string */
|
||||
int dst_dobytes(DstTable *env, const uint8_t *bytes, int32_t len, const char *sourcePath) {
|
||||
@ -47,18 +88,19 @@ int dst_dobytes(DstTable *env, const uint8_t *bytes, int32_t len, const char *so
|
||||
Dst ret = dst_wrap_nil();
|
||||
DstSignal status = dst_run(fiber, &ret);
|
||||
if (status != DST_SIGNAL_OK) {
|
||||
printf("internal runtime error: %s\n", (const char *) dst_to_string(ret));
|
||||
print_error_report(fiber, "runtime", ret);
|
||||
errflags |= 0x01;
|
||||
}
|
||||
} else {
|
||||
printf("internal compile error: %s\n", (const char *) cres.error);
|
||||
print_error_report(cres.macrofiber, "compile",
|
||||
dst_wrap_string(cres.error));
|
||||
errflags |= 0x02;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DST_PARSE_ERROR:
|
||||
errflags |= 0x04;
|
||||
printf("internal parse error: %s\n", dst_parser_error(&parser));
|
||||
printf("parse error: %s\n", dst_parser_error(&parser));
|
||||
break;
|
||||
case DST_PARSE_PENDING:
|
||||
if (index >= len) {
|
@ -21,11 +21,9 @@
|
||||
*/
|
||||
|
||||
#include <dst/dst.h>
|
||||
#include <dst/dstcorelib.h>
|
||||
#include <dst/dstcompile.h>
|
||||
#include "compile.h"
|
||||
#include <headerlibs/strbinsearch.h>
|
||||
#include <headerlibs/vector.h>
|
||||
#include "util.h"
|
||||
#include "vector.h"
|
||||
#include "emit.h"
|
||||
|
||||
DstSlot dstc_quote(DstFopts opts, int32_t argn, const Dst *argv) {
|
||||
@ -37,11 +35,12 @@ DstSlot dstc_quote(DstFopts opts, int32_t argn, const Dst *argv) {
|
||||
}
|
||||
|
||||
/* Preform destructuring. Be careful to
|
||||
* keep the order registers are freed. */
|
||||
static void destructure(DstCompiler *c,
|
||||
* keep the order registers are freed.
|
||||
* Returns if the slot 'right' can be freed. */
|
||||
static int destructure(DstCompiler *c,
|
||||
Dst left,
|
||||
DstSlot right,
|
||||
void (*leaf)(DstCompiler *c,
|
||||
int (*leaf)(DstCompiler *c,
|
||||
const uint8_t *sym,
|
||||
DstSlot s,
|
||||
DstTable *attr),
|
||||
@ -49,73 +48,43 @@ static void destructure(DstCompiler *c,
|
||||
switch (dst_type(left)) {
|
||||
default:
|
||||
dstc_cerror(c, "unexpected type in destructuring");
|
||||
break;
|
||||
return 1;
|
||||
case DST_SYMBOL:
|
||||
/* Leaf, assign right to left */
|
||||
leaf(c, dst_unwrap_symbol(left), right, attr);
|
||||
break;
|
||||
return leaf(c, dst_unwrap_symbol(left), right, attr);
|
||||
case DST_TUPLE:
|
||||
case DST_ARRAY:
|
||||
{
|
||||
int32_t i, len, right_register, subval_register;
|
||||
int32_t i, len;
|
||||
const Dst *values;
|
||||
dst_seq_view(left, &values, &len);
|
||||
for (i = 0; i < len; i++) {
|
||||
DstSlot nextright;
|
||||
DstSlot nextright = dstc_farslot(c);
|
||||
Dst subval = values[i];
|
||||
right_register = dstc_regnear(c, right, DSTC_REGTEMP_0);
|
||||
subval_register = dstc_allocnear(c, DSTC_REGTEMP_1);
|
||||
if (i < 0x100) {
|
||||
dstc_emit(c, DOP_GET_INDEX |
|
||||
(subval_register << 8) |
|
||||
(right_register << 16) |
|
||||
(i << 24));
|
||||
dstc_emit_ssu(c, DOP_GET_INDEX, nextright, right, (uint8_t) i, 1);
|
||||
} else {
|
||||
DstSlot islot = dstc_cslot(dst_wrap_integer(i));
|
||||
int32_t i_register = dstc_regnear(c, islot, DSTC_REGTEMP_2);
|
||||
dstc_emit(c, DOP_GET_INDEX |
|
||||
(subval_register << 8) |
|
||||
(right_register << 16) |
|
||||
(i_register << 24));
|
||||
dstc_free_reg(c, islot, i_register);
|
||||
DstSlot k = dstc_cslot(dst_wrap_integer(i));
|
||||
dstc_emit_sss(c, DOP_GET, nextright, right, k, 1);
|
||||
}
|
||||
nextright.index = subval_register;
|
||||
nextright.envindex = -1;
|
||||
nextright.constant = dst_wrap_nil();
|
||||
nextright.flags = DST_SLOTTYPE_ANY;
|
||||
destructure(c, subval, nextright, leaf, attr);
|
||||
/* Free right_register AFTER sub destructuring */
|
||||
dstc_free_reg(c, right, right_register);
|
||||
if (destructure(c, subval, nextright, leaf, attr))
|
||||
dstc_freeslot(c, nextright);
|
||||
}
|
||||
}
|
||||
break;
|
||||
return 1;
|
||||
case DST_TABLE:
|
||||
case DST_STRUCT:
|
||||
{
|
||||
int32_t right_register, subval_register, k_register;
|
||||
const DstKV *kv = NULL;
|
||||
while ((kv = dstc_next(left, kv))) {
|
||||
DstSlot nextright;
|
||||
DstSlot kslot = dstc_value(dstc_fopts_default(c), kv->key);
|
||||
|
||||
right_register = dstc_regnear(c, right, DSTC_REGTEMP_0);
|
||||
subval_register = dstc_allocnear(c, DSTC_REGTEMP_1);
|
||||
k_register = dstc_regnear(c, kslot, DSTC_REGTEMP_2);
|
||||
dstc_emit(c, DOP_GET |
|
||||
(subval_register << 8) |
|
||||
(right_register << 16) |
|
||||
(k_register << 24));
|
||||
dstc_free_reg(c, kslot, k_register);
|
||||
nextright.index = subval_register;
|
||||
nextright.envindex = -1;
|
||||
nextright.constant = dst_wrap_nil();
|
||||
nextright.flags = DST_SLOTTYPE_ANY;
|
||||
destructure(c, kv->value, nextright, leaf, attr);
|
||||
/* Free right_register AFTER sub destructuring */
|
||||
dstc_free_reg(c, right, right_register);
|
||||
DstSlot nextright = dstc_farslot(c);
|
||||
DstSlot k = dstc_value(dstc_fopts_default(c), kv->key);
|
||||
dstc_emit_sss(c, DOP_GET, nextright, right, k, 1);
|
||||
if (destructure(c, kv->value, nextright, leaf, attr))
|
||||
dstc_freeslot(c, nextright);
|
||||
}
|
||||
}
|
||||
break;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -180,28 +149,22 @@ static DstSlot dohead(DstCompiler *c, DstFopts opts, Dst *head, int32_t argn, co
|
||||
}
|
||||
|
||||
/* Def or var a symbol in a local scope */
|
||||
static DstSlot namelocal(DstCompiler *c, Dst head, int32_t flags, DstSlot ret) {
|
||||
/* Non root scope, bring to local slot */
|
||||
if (ret.flags & DST_SLOT_NAMED ||
|
||||
ret.envindex >= 0 ||
|
||||
ret.index < 0 ||
|
||||
ret.index > 0xFF) {
|
||||
static int namelocal(DstCompiler *c, const uint8_t *head, int32_t flags, DstSlot ret) {
|
||||
int isUnnamedRegister = !(ret.flags & DST_SLOT_NAMED) &&
|
||||
ret.index > 0 &&
|
||||
ret.envindex >= 0;
|
||||
if (!isUnnamedRegister) {
|
||||
/* Slot is not able to be named */
|
||||
DstSlot localslot;
|
||||
localslot.index = dstc_allocfar(c);
|
||||
/* infer type? */
|
||||
localslot.flags = flags;
|
||||
localslot.envindex = -1;
|
||||
localslot.constant = dst_wrap_nil();
|
||||
DstSlot localslot = dstc_farslot(c);
|
||||
dstc_copy(c, localslot, ret);
|
||||
ret = localslot;
|
||||
}
|
||||
ret.flags |= flags;
|
||||
dstc_nameslot(c, dst_unwrap_symbol(head), ret);
|
||||
return ret;
|
||||
dstc_nameslot(c, head, ret);
|
||||
return !isUnnamedRegister;
|
||||
}
|
||||
|
||||
static void varleaf(
|
||||
static int varleaf(
|
||||
DstCompiler *c,
|
||||
const uint8_t *sym,
|
||||
DstSlot s,
|
||||
@ -216,9 +179,10 @@ static void varleaf(
|
||||
dst_table_put(reftab, dst_csymbolv(":ref"), dst_wrap_array(ref));
|
||||
dst_table_put(c->env, dst_wrap_symbol(sym), dst_wrap_table(reftab));
|
||||
refslot = dstc_cslot(dst_wrap_array(ref));
|
||||
dstc_emit_ssu(c, DOP_PUT_INDEX, refslot, s, 0);
|
||||
dstc_emit_ssu(c, DOP_PUT_INDEX, refslot, s, 0, 0);
|
||||
return 1;
|
||||
} else {
|
||||
namelocal(c, dst_wrap_symbol(sym), DST_SLOT_NAMED | DST_SLOT_MUTABLE, s) ;
|
||||
return namelocal(c, sym, DST_SLOT_MUTABLE, s);
|
||||
}
|
||||
}
|
||||
|
||||
@ -227,11 +191,12 @@ DstSlot dstc_var(DstFopts opts, int32_t argn, const Dst *argv) {
|
||||
Dst head;
|
||||
DstSlot ret = dohead(c, opts, &head, argn, argv);
|
||||
if (dstc_iserr(&opts)) return dstc_cslot(dst_wrap_nil());
|
||||
destructure(c, argv[0], ret, varleaf, handleattr(c, argn, argv));
|
||||
if (destructure(c, argv[0], ret, varleaf, handleattr(c, argn, argv)))
|
||||
dstc_freeslot(c, ret);
|
||||
return dstc_cslot(dst_wrap_nil());
|
||||
}
|
||||
|
||||
static void defleaf(
|
||||
static int defleaf(
|
||||
DstCompiler *c,
|
||||
const uint8_t *sym,
|
||||
DstSlot s,
|
||||
@ -246,9 +211,10 @@ static void defleaf(
|
||||
dst_table_put(c->env, dst_wrap_symbol(sym), dst_wrap_table(tab));
|
||||
|
||||
/* Put value in table when evaulated */
|
||||
dstc_emit_sss(c, DOP_PUT, tabslot, valsym, s);
|
||||
dstc_emit_sss(c, DOP_PUT, tabslot, valsym, s, 0);
|
||||
return 1;
|
||||
} else {
|
||||
namelocal(c, dst_wrap_symbol(sym), DST_SLOT_NAMED, s);
|
||||
return namelocal(c, sym, 0, s);
|
||||
}
|
||||
}
|
||||
|
||||
@ -258,7 +224,8 @@ DstSlot dstc_def(DstFopts opts, int32_t argn, const Dst *argv) {
|
||||
opts.flags &= ~DST_FOPTS_HINT;
|
||||
DstSlot ret = dohead(c, opts, &head, argn, argv);
|
||||
if (dstc_iserr(&opts)) return dstc_cslot(dst_wrap_nil());
|
||||
destructure(c, argv[0], ret, defleaf, handleattr(c, argn, argv));
|
||||
if (destructure(c, argv[0], ret, defleaf, handleattr(c, argn, argv)))
|
||||
dstc_freeslot(c, ret);
|
||||
return dstc_cslot(dst_wrap_nil());
|
||||
}
|
||||
|
||||
@ -321,7 +288,7 @@ DstSlot dstc_if(DstFopts opts, int32_t argn, const Dst *argv) {
|
||||
: dstc_gettarget(opts);
|
||||
|
||||
/* Compile jump to right */
|
||||
labeljr = dstc_emit_si(c, DOP_JUMP_IF_NOT, cond, 0);
|
||||
labeljr = dstc_emit_si(c, DOP_JUMP_IF_NOT, cond, 0, 0);
|
||||
|
||||
/* Condition left body */
|
||||
dstc_scope(&tempscope, c, 0, "if-true");
|
||||
@ -414,7 +381,7 @@ DstSlot dstc_while(DstFopts opts, int32_t argn, const Dst *argv) {
|
||||
|
||||
/* Infinite loop does not need to check condition */
|
||||
if (!infinite) {
|
||||
labelc = dstc_emit_si(c, DOP_JUMP_IF_NOT, cond, 0);
|
||||
labelc = dstc_emit_si(c, DOP_JUMP_IF_NOT, cond, 0, 0);
|
||||
} else {
|
||||
labelc = 0;
|
||||
}
|
||||
@ -459,7 +426,7 @@ DstSlot dstc_fn(DstFopts opts, int32_t argn, const Dst *argv) {
|
||||
DstSlot ret;
|
||||
Dst head, paramv;
|
||||
DstScope fnscope;
|
||||
int32_t paramcount, argi, parami, arity, localslot, defindex;
|
||||
int32_t paramcount, argi, parami, arity, defindex;
|
||||
DstFopts subopts = dstc_fopts_default(c);
|
||||
const Dst *params;
|
||||
const char *errmsg = NULL;
|
||||
@ -517,7 +484,7 @@ DstSlot dstc_fn(DstFopts opts, int32_t argn, const Dst *argv) {
|
||||
if (selfref) {
|
||||
DstSlot slot = dstc_farslot(c);
|
||||
slot.flags = DST_SLOT_NAMED | DST_FUNCTION;
|
||||
dstc_emit_s(c, DOP_LOAD_SELF, slot);
|
||||
dstc_emit_s(c, DOP_LOAD_SELF, slot, 1);
|
||||
dstc_nameslot(c, dst_unwrap_symbol(head), slot);
|
||||
}
|
||||
|
||||
@ -525,10 +492,8 @@ DstSlot dstc_fn(DstFopts opts, int32_t argn, const Dst *argv) {
|
||||
if (parami + 1 == argn) {
|
||||
dstc_emit(c, DOP_RETURN_NIL);
|
||||
} else for (argi = parami + 1; argi < argn; argi++) {
|
||||
DstSlot s;
|
||||
subopts.flags = (argi == (argn - 1)) ? DST_FOPTS_TAIL : DST_FOPTS_DROP;
|
||||
s = dstc_value(subopts, argv[argi]);
|
||||
dstc_freeslot(c, s);
|
||||
dstc_value(subopts, argv[argi]);
|
||||
if (dstc_iserr(&opts))
|
||||
goto error2;
|
||||
}
|
||||
@ -545,20 +510,7 @@ DstSlot dstc_fn(DstFopts opts, int32_t argn, const Dst *argv) {
|
||||
|
||||
/* Instantiate closure */
|
||||
ret = dstc_gettarget(opts);
|
||||
|
||||
localslot = ret.index > 0xF0 ? 0xF1 : ret.index;
|
||||
dstc_emit(c,
|
||||
(defindex << 16) |
|
||||
(localslot << 8) |
|
||||
DOP_CLOSURE);
|
||||
|
||||
if (ret.index != localslot) {
|
||||
dstc_emit(c,
|
||||
(ret.index << 16) |
|
||||
(localslot << 8) |
|
||||
DOP_MOVE_FAR);
|
||||
}
|
||||
|
||||
dstc_emit_su(c, DOP_CLOSURE, ret, defindex, 1);
|
||||
return ret;
|
||||
|
||||
error:
|
@ -23,13 +23,7 @@
|
||||
#ifndef DST_STATE_H_defined
|
||||
#define DST_STATE_H_defined
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <dst/dstconfig.h>
|
||||
#include <dst/dsttypes.h>
|
||||
|
||||
/* The VM state. Rather than a struct that is passed
|
||||
* around, the vm state is global for simplicity. If
|
||||
@ -66,8 +60,4 @@ extern DST_THREAD_LOCAL Dst *dst_vm_roots;
|
||||
extern DST_THREAD_LOCAL uint32_t dst_vm_root_count;
|
||||
extern DST_THREAD_LOCAL uint32_t dst_vm_root_capacity;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DST_STATE_H_defined */
|
||||
|
@ -21,7 +21,6 @@
|
||||
*/
|
||||
|
||||
#include <dst/dst.h>
|
||||
#include <dst/dstcorelib.h>
|
||||
#include "gc.h"
|
||||
#include "util.h"
|
||||
#include "state.h"
|
||||
|
@ -21,7 +21,6 @@
|
||||
*/
|
||||
|
||||
#include <dst/dst.h>
|
||||
#include <dst/dstcorelib.h>
|
||||
#include "gc.h"
|
||||
#include "util.h"
|
||||
|
||||
|
@ -21,7 +21,6 @@
|
||||
*/
|
||||
|
||||
#include <dst/dst.h>
|
||||
#include <dst/dstcorelib.h>
|
||||
#include "symcache.h"
|
||||
#include "gc.h"
|
||||
#include "util.h"
|
||||
|
@ -110,6 +110,33 @@ int dst_cstrcmp(const uint8_t *str, const char *other) {
|
||||
return (other[index] == '\0') ? 0 : -1;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
const char *t = (const char *)tab;
|
||||
while (low < hi) {
|
||||
size_t mid = low + ((hi - low) / 2);
|
||||
const char **item = (const char **)(t + 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;
|
||||
}
|
||||
|
||||
/* Add a module definition */
|
||||
void dst_env_def(DstTable *env, const char *name, Dst val) {
|
||||
DstTable *subt = dst_table(1);
|
||||
@ -238,26 +265,29 @@ int dst_type_err(DstArgs args, int32_t n, DstType expected) {
|
||||
DST_THROWV(args, dst_wrap_string(message));
|
||||
}
|
||||
|
||||
int dst_typemany_err(DstArgs args, int32_t n, int expected) {
|
||||
int i;
|
||||
void dst_buffer_push_types(DstBuffer *buffer, int types) {
|
||||
int first = 1;
|
||||
int i = 0;
|
||||
while (types) {
|
||||
if (1 & types) {
|
||||
if (first) {
|
||||
first = 0;
|
||||
} else {
|
||||
dst_buffer_push_u8(buffer, '|');
|
||||
}
|
||||
dst_buffer_push_cstring(buffer, dst_type_names[i] + 1);
|
||||
}
|
||||
i++;
|
||||
types >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
int dst_typemany_err(DstArgs args, int32_t n, int expected) {
|
||||
const uint8_t *message;
|
||||
DstBuffer buf;
|
||||
dst_buffer_init(&buf, 20);
|
||||
dst_buffer_push_string(&buf, dst_formatc("bad slot #%d, expected ", n));
|
||||
i = 0;
|
||||
while (expected) {
|
||||
if (1 & expected) {
|
||||
if (first) {
|
||||
first = 0;
|
||||
} else {
|
||||
dst_buffer_push_u8(&buf, '|');
|
||||
}
|
||||
dst_buffer_push_cstring(&buf, dst_type_names[i] + 1);
|
||||
}
|
||||
i++;
|
||||
expected >>= 1;
|
||||
}
|
||||
dst_buffer_push_types(&buf, expected);
|
||||
dst_buffer_push_cstring(&buf, ", got ");
|
||||
dst_buffer_push_cstring(&buf, typestr(args, n));
|
||||
message = dst_string(buf.data, buf.count);
|
||||
|
@ -31,5 +31,11 @@ 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);
|
||||
void dst_buffer_push_types(DstBuffer *buffer, int types);
|
||||
const void *dst_strbinsearch(
|
||||
const void *tab,
|
||||
size_t tabcount,
|
||||
size_t itemsize,
|
||||
const uint8_t *key);
|
||||
|
||||
#endif
|
||||
|
76
src/core/vector.c
Normal file
76
src/core/vector.c
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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 "vector.h"
|
||||
|
||||
/* 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));
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
} else {
|
||||
{
|
||||
DST_OUT_OF_MEMORY;
|
||||
}
|
||||
return (void *) (2 * sizeof(int32_t));
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,8 @@
|
||||
#ifndef DST_VECTOR_H_defined
|
||||
#define DST_VECTOR_H_defined
|
||||
|
||||
#include <dst/dst.h>
|
||||
|
||||
/*
|
||||
* vector code modified from
|
||||
* https://github.com/nothings/stb/blob/master/stretchy_buffer.h
|
||||
@ -50,65 +52,9 @@
|
||||
#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))))
|
||||
|
||||
|
||||
/* Vector code */
|
||||
|
||||
/* Grow the buffer dynamically. Used for push operations. */
|
||||
#ifndef DST_V_NODEF_GROW
|
||||
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
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 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
|
||||
/* Actual functions defined in vector.c */
|
||||
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);
|
||||
|
||||
#endif
|
203
src/core/vm.c
203
src/core/vm.c
@ -21,11 +21,11 @@
|
||||
*/
|
||||
|
||||
#include <dst/dst.h>
|
||||
#include <dst/dstopcodes.h>
|
||||
#include "state.h"
|
||||
#include "fiber.h"
|
||||
#include "gc.h"
|
||||
#include "symcache.h"
|
||||
#include "util.h"
|
||||
|
||||
/* VM state */
|
||||
DST_THREAD_LOCAL DstTable *dst_vm_registry;
|
||||
@ -51,6 +51,9 @@ DstSignal dst_continue(DstFiber *fiber, Dst in, Dst *out) {
|
||||
* Values stored here should be used immediately */
|
||||
Dst retreg;
|
||||
|
||||
/* Expected types on type error */
|
||||
uint16_t expected_types;
|
||||
|
||||
/* Signal to return when done */
|
||||
DstSignal signal = DST_SIGNAL_OK;
|
||||
|
||||
@ -181,6 +184,12 @@ static void *op_lookup[255] = {
|
||||
&&label_DOP_GET_INDEX,
|
||||
&&label_DOP_PUT_INDEX,
|
||||
&&label_DOP_LENGTH,
|
||||
&&label_DOP_MAKE_ARRAY,
|
||||
&&label_DOP_MAKE_BUFFER,
|
||||
&&label_DOP_MAKE_STRING,
|
||||
&&label_DOP_MAKE_STRUCT,
|
||||
&&label_DOP_MAKE_TABLE,
|
||||
&&label_DOP_MAKE_TUPLE,
|
||||
&&label_unknown_op
|
||||
};
|
||||
#else
|
||||
@ -195,6 +204,20 @@ static void *op_lookup[255] = {
|
||||
|
||||
#define vm_throw(e) do { retreg = dst_cstringv(e); goto vm_error; } while (0)
|
||||
#define vm_assert(cond, e) do {if (!(cond)) vm_throw((e)); } while (0)
|
||||
#define vm_assert_type(X, T) do { \
|
||||
if (!(dst_checktype((X), (T)))) { \
|
||||
expected_types = 1 << (T); \
|
||||
retreg = (X); \
|
||||
goto vm_type_error; \
|
||||
} \
|
||||
} while (0)
|
||||
#define vm_assert_types(X, TS) do { \
|
||||
if (!((1 << dst_type(X)) & (TS))) { \
|
||||
expected_types = (TS); \
|
||||
retreg = (X); \
|
||||
goto vm_type_error; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define vm_binop_integer(op) \
|
||||
stack[oparg(1, 0xFF)] = dst_wrap_integer(\
|
||||
@ -221,8 +244,8 @@ static void *op_lookup[255] = {
|
||||
{\
|
||||
Dst op1 = stack[oparg(2, 0xFF)];\
|
||||
Dst op2 = stack[oparg(3, 0xFF)];\
|
||||
vm_assert(dst_checktype(op1, DST_INTEGER) || dst_checktype(op1, DST_REAL), "expected number");\
|
||||
vm_assert(dst_checktype(op2, DST_INTEGER) || dst_checktype(op2, DST_REAL), "expected number");\
|
||||
vm_assert_types(op1, DST_TFLAG_NUMBER);\
|
||||
vm_assert_types(op2, DST_TFLAG_NUMBER);\
|
||||
stack[oparg(1, 0xFF)] = dst_checktype(op1, DST_INTEGER)\
|
||||
? (dst_checktype(op2, DST_INTEGER)\
|
||||
? dst_wrap_integer(dst_unwrap_integer(op1) op dst_unwrap_integer(op2))\
|
||||
@ -333,8 +356,8 @@ static void *op_lookup[255] = {
|
||||
{
|
||||
Dst op1 = stack[oparg(2, 0xFF)];
|
||||
Dst op2 = stack[oparg(3, 0xFF)];
|
||||
vm_assert(dst_checktype(op1, DST_INTEGER) || dst_checktype(op1, DST_REAL), "expected number");
|
||||
vm_assert(dst_checktype(op2, DST_INTEGER) || dst_checktype(op2, DST_REAL), "expected number");
|
||||
vm_assert_types(op1, DST_TFLAG_NUMBER);
|
||||
vm_assert_types(op2, DST_TFLAG_NUMBER);
|
||||
if (dst_checktype(op2, DST_INTEGER) && dst_unwrap_integer(op2) == 0)
|
||||
vm_throw("integer divide by zero");
|
||||
if (dst_checktype(op2, DST_INTEGER) && dst_unwrap_integer(op2) == -1 &&
|
||||
@ -688,7 +711,9 @@ static void *op_lookup[255] = {
|
||||
if (dst_seq_view(stack[oparg(1, 0xFFFFFF)], &vals, &len)) {
|
||||
dst_fiber_pushn(fiber, vals, len);
|
||||
} else {
|
||||
vm_throw("expected array/tuple");
|
||||
retreg = stack[oparg(1, 0xFFFFFF)];
|
||||
expected_types = DST_TFLAG_INDEXED;
|
||||
goto vm_type_error;
|
||||
}
|
||||
}
|
||||
pc++;
|
||||
@ -721,7 +746,9 @@ static void *op_lookup[255] = {
|
||||
}
|
||||
goto vm_return_cfunc;
|
||||
}
|
||||
vm_throw("expected function");
|
||||
expected_types = DST_TFLAG_CALLABLE;
|
||||
retreg = callee;
|
||||
goto vm_type_error;
|
||||
}
|
||||
|
||||
VM_OP(DOP_TAILCALL)
|
||||
@ -745,13 +772,15 @@ static void *op_lookup[255] = {
|
||||
}
|
||||
goto vm_return_cfunc_tail;
|
||||
}
|
||||
vm_throw("expected function");
|
||||
expected_types = DST_TFLAG_CALLABLE;
|
||||
retreg = callee;
|
||||
goto vm_type_error;
|
||||
}
|
||||
|
||||
VM_OP(DOP_RESUME)
|
||||
{
|
||||
Dst fiberval = stack[oparg(2, 0xFF)];
|
||||
vm_assert(dst_checktype(fiberval, DST_FIBER), "expected fiber");
|
||||
vm_assert_type(fiberval, DST_FIBER);
|
||||
retreg = stack[oparg(3, 0xFF)];
|
||||
fiber->child = dst_unwrap_fiber(fiberval);
|
||||
goto vm_resume_child;
|
||||
@ -775,12 +804,15 @@ static void *op_lookup[255] = {
|
||||
Dst value = stack[oparg(3, 0xFF)];
|
||||
switch (dst_type(ds)) {
|
||||
default:
|
||||
vm_throw("expected mutable data structure");
|
||||
expected_types = DST_TFLAG_ARRAY | DST_TFLAG_BUFFER | DST_TFLAG_TABLE;
|
||||
retreg = ds;
|
||||
goto vm_type_error;
|
||||
case DST_ARRAY:
|
||||
{
|
||||
int32_t index;
|
||||
DstArray *array = dst_unwrap_array(ds);
|
||||
if (!dst_checktype(key, DST_INTEGER) || dst_unwrap_integer(key) < 0)
|
||||
vm_assert_type(key, DST_INTEGER);
|
||||
if (dst_unwrap_integer(key) < 0)
|
||||
vm_throw("expected non-negative integer key");
|
||||
index = dst_unwrap_integer(key);
|
||||
if (index == INT32_MAX)
|
||||
@ -795,13 +827,13 @@ static void *op_lookup[255] = {
|
||||
{
|
||||
int32_t index;
|
||||
DstBuffer *buffer = dst_unwrap_buffer(ds);
|
||||
if (!dst_checktype(key, DST_INTEGER) || dst_unwrap_integer(key) < 0)
|
||||
vm_assert_type(key, DST_INTEGER);
|
||||
if (dst_unwrap_integer(key) < 0)
|
||||
vm_throw("expected non-negative integer key");
|
||||
index = dst_unwrap_integer(key);
|
||||
if (index == INT32_MAX)
|
||||
vm_throw("key too large");
|
||||
if (!dst_checktype(value, DST_INTEGER))
|
||||
vm_throw("expected integer value");
|
||||
vm_assert_type(value, DST_INTEGER);
|
||||
if (index >= buffer->count) {
|
||||
dst_buffer_setcount(buffer, index + 1);
|
||||
}
|
||||
@ -823,7 +855,9 @@ static void *op_lookup[255] = {
|
||||
int32_t index = oparg(3, 0xFF);
|
||||
switch (dst_type(ds)) {
|
||||
default:
|
||||
vm_throw("expected mutable indexed data structure");
|
||||
expected_types = DST_TFLAG_ARRAY | DST_TFLAG_BUFFER;
|
||||
retreg = ds;
|
||||
goto vm_type_error;
|
||||
case DST_ARRAY:
|
||||
if (index >= dst_unwrap_array(ds)->count) {
|
||||
dst_array_ensure(dst_unwrap_array(ds), 2 * index);
|
||||
@ -832,8 +866,7 @@ static void *op_lookup[255] = {
|
||||
dst_unwrap_array(ds)->data[index] = value;
|
||||
break;
|
||||
case DST_BUFFER:
|
||||
if (!dst_checktype(value, DST_INTEGER))\
|
||||
vm_throw("expected integer to set in buffer");
|
||||
vm_assert_type(value, DST_INTEGER);
|
||||
if (index >= dst_unwrap_buffer(ds)->count) {
|
||||
dst_buffer_ensure(dst_unwrap_buffer(ds), 2 * index);
|
||||
dst_unwrap_buffer(ds)->count = index + 1;
|
||||
@ -852,7 +885,9 @@ static void *op_lookup[255] = {
|
||||
Dst value;
|
||||
switch (dst_type(ds)) {
|
||||
default:
|
||||
vm_throw("expected data structure");
|
||||
expected_types = DST_TFLAG_LENGTHABLE;
|
||||
retreg = ds;
|
||||
goto vm_type_error;
|
||||
case DST_STRUCT:
|
||||
value = dst_struct_get(dst_unwrap_struct(ds), key);
|
||||
break;
|
||||
@ -863,8 +898,7 @@ static void *op_lookup[255] = {
|
||||
{
|
||||
DstArray *array = dst_unwrap_array(ds);
|
||||
int32_t index;
|
||||
if (!dst_checktype(key, DST_INTEGER))
|
||||
vm_throw("expected integer key");
|
||||
vm_assert_type(key, DST_INTEGER);
|
||||
index = dst_unwrap_integer(key);
|
||||
if (index < 0 || index >= array->count) {
|
||||
/*vm_throw("index out of bounds");*/
|
||||
@ -878,8 +912,7 @@ static void *op_lookup[255] = {
|
||||
{
|
||||
const Dst *tuple = dst_unwrap_tuple(ds);
|
||||
int32_t index;
|
||||
if (!dst_checktype(key, DST_INTEGER))
|
||||
vm_throw("expected integer key");
|
||||
vm_assert_type(key, DST_INTEGER);
|
||||
index = dst_unwrap_integer(key);
|
||||
if (index < 0 || index >= dst_tuple_length(tuple)) {
|
||||
/*vm_throw("index out of bounds");*/
|
||||
@ -893,8 +926,7 @@ static void *op_lookup[255] = {
|
||||
{
|
||||
DstBuffer *buffer = dst_unwrap_buffer(ds);
|
||||
int32_t index;
|
||||
if (!dst_checktype(key, DST_INTEGER))
|
||||
vm_throw("expected integer key");
|
||||
vm_assert_type(key, DST_INTEGER);
|
||||
index = dst_unwrap_integer(key);
|
||||
if (index < 0 || index >= buffer->count) {
|
||||
/*vm_throw("index out of bounds");*/
|
||||
@ -909,8 +941,7 @@ static void *op_lookup[255] = {
|
||||
{
|
||||
const uint8_t *str = dst_unwrap_string(ds);
|
||||
int32_t index;
|
||||
if (!dst_checktype(key, DST_INTEGER))
|
||||
vm_throw("expected integer key");
|
||||
vm_assert_type(key, DST_INTEGER);
|
||||
index = dst_unwrap_integer(key);
|
||||
if (index < 0 || index >= dst_string_length(str)) {
|
||||
/*vm_throw("index out of bounds");*/
|
||||
@ -933,7 +964,9 @@ static void *op_lookup[255] = {
|
||||
Dst value;
|
||||
switch (dst_type(ds)) {
|
||||
default:
|
||||
vm_throw("expected indexed data structure");
|
||||
expected_types = DST_TFLAG_LENGTHABLE;
|
||||
retreg = ds;
|
||||
goto vm_type_error;
|
||||
case DST_STRING:
|
||||
case DST_SYMBOL:
|
||||
if (index >= dst_string_length(dst_unwrap_string(ds))) {
|
||||
@ -967,6 +1000,12 @@ static void *op_lookup[255] = {
|
||||
value = dst_unwrap_tuple(ds)[index];
|
||||
}
|
||||
break;
|
||||
case DST_TABLE:
|
||||
value = dst_table_get(dst_unwrap_table(ds), dst_wrap_integer(index));
|
||||
break;
|
||||
case DST_STRUCT:
|
||||
value = dst_struct_get(dst_unwrap_struct(ds), dst_wrap_integer(index));
|
||||
break;
|
||||
}
|
||||
stack[oparg(1, 0xFF)] = value;
|
||||
++pc;
|
||||
@ -979,7 +1018,9 @@ static void *op_lookup[255] = {
|
||||
int32_t len;
|
||||
switch (dst_type(x)) {
|
||||
default:
|
||||
vm_throw("expected data structure");
|
||||
expected_types = DST_TFLAG_LENGTHABLE;
|
||||
retreg = x;
|
||||
goto vm_type_error;
|
||||
case DST_STRING:
|
||||
case DST_SYMBOL:
|
||||
len = dst_string_length(dst_unwrap_string(x));
|
||||
@ -1005,6 +1046,84 @@ static void *op_lookup[255] = {
|
||||
vm_next();
|
||||
}
|
||||
|
||||
VM_OP(DOP_MAKE_ARRAY)
|
||||
{
|
||||
int32_t count = fiber->stacktop - fiber->stackstart;
|
||||
Dst *mem = fiber->data + fiber->stackstart;
|
||||
stack[oparg(1, 0xFFFFFF)] = dst_wrap_array(dst_array_n(mem, count));
|
||||
fiber->stacktop = fiber->stackstart;
|
||||
++pc;
|
||||
vm_checkgc_next();
|
||||
}
|
||||
|
||||
VM_OP(DOP_MAKE_TUPLE)
|
||||
{
|
||||
int32_t count = fiber->stacktop - fiber->stackstart;
|
||||
Dst *mem = fiber->data + fiber->stackstart;
|
||||
stack[oparg(1, 0xFFFFFF)] = dst_wrap_tuple(dst_tuple_n(mem, count));
|
||||
fiber->stacktop = fiber->stackstart;
|
||||
++pc;
|
||||
vm_checkgc_next();
|
||||
}
|
||||
|
||||
VM_OP(DOP_MAKE_TABLE)
|
||||
{
|
||||
int32_t count = fiber->stacktop - fiber->stackstart;
|
||||
Dst *mem = fiber->data + fiber->stackstart;
|
||||
if (count & 1)
|
||||
vm_throw("expected even number of arguments to table constructor");
|
||||
DstTable *table = dst_table(count / 2);
|
||||
for (int32_t i = 0; i < count; i += 2)
|
||||
dst_table_put(table, mem[i], mem[i + 1]);
|
||||
stack[oparg(1, 0xFFFFFF)] = dst_wrap_table(table);
|
||||
fiber->stacktop = fiber->stackstart;
|
||||
++pc;
|
||||
vm_checkgc_next();
|
||||
}
|
||||
|
||||
VM_OP(DOP_MAKE_STRUCT)
|
||||
{
|
||||
int32_t count = fiber->stacktop - fiber->stackstart;
|
||||
Dst *mem = fiber->data + fiber->stackstart;
|
||||
if (count & 1)
|
||||
vm_throw("expected even number of arguments to struct constructor");
|
||||
DstKV *st = dst_struct_begin(count / 2);
|
||||
for (int32_t i = 0; i < count; i += 2)
|
||||
dst_struct_put(st, mem[i], mem[i + 1]);
|
||||
stack[oparg(1, 0xFFFFFF)] = dst_wrap_struct(dst_struct_end(st));
|
||||
fiber->stacktop = fiber->stackstart;
|
||||
++pc;
|
||||
vm_checkgc_next();
|
||||
}
|
||||
|
||||
VM_OP(DOP_MAKE_STRING)
|
||||
{
|
||||
int32_t count = fiber->stacktop - fiber->stackstart;
|
||||
Dst *mem = fiber->data + fiber->stackstart;
|
||||
DstBuffer buffer;
|
||||
dst_buffer_init(&buffer, 10 * count);
|
||||
for (int32_t i = 0; i < count; i++)
|
||||
dst_to_string_b(&buffer, mem[i]);
|
||||
stack[oparg(1, 0xFFFFFF)] = dst_stringv(buffer.data, buffer.count);
|
||||
dst_buffer_deinit(&buffer);
|
||||
fiber->stacktop = fiber->stackstart;
|
||||
++pc;
|
||||
vm_checkgc_next();
|
||||
}
|
||||
|
||||
VM_OP(DOP_MAKE_BUFFER)
|
||||
{
|
||||
int32_t count = fiber->stacktop - fiber->stackstart;
|
||||
Dst *mem = fiber->data + fiber->stackstart;
|
||||
DstBuffer *buffer = dst_buffer(10 * count);
|
||||
for (int32_t i = 0; i < count; i++)
|
||||
dst_to_string_b(buffer, mem[i]);
|
||||
stack[oparg(1, 0xFFFFFF)] = dst_wrap_buffer(buffer);
|
||||
fiber->stacktop = fiber->stackstart;
|
||||
++pc;
|
||||
vm_checkgc_next();
|
||||
}
|
||||
|
||||
/* Return from c function. Simpler than returning from dst function */
|
||||
vm_return_cfunc:
|
||||
{
|
||||
@ -1059,6 +1178,22 @@ static void *op_lookup[255] = {
|
||||
vm_checkgc_next();
|
||||
}
|
||||
|
||||
/* Handle type errors. The found type is the type of retreg,
|
||||
* the expected types are in the expected_types field. */
|
||||
vm_type_error:
|
||||
{
|
||||
DstBuffer errbuf;
|
||||
dst_buffer_init(&errbuf, 10);
|
||||
dst_buffer_push_cstring(&errbuf, "expected ");
|
||||
dst_buffer_push_types(&errbuf, expected_types);
|
||||
dst_buffer_push_cstring(&errbuf, ", got ");
|
||||
dst_buffer_push_cstring(&errbuf, dst_type_names[dst_type(retreg)] + 1);
|
||||
retreg = dst_stringv(errbuf.data, errbuf.count);
|
||||
dst_buffer_deinit(&errbuf);
|
||||
signal = DST_SIGNAL_ERROR;
|
||||
goto vm_exit;
|
||||
}
|
||||
|
||||
/* Handle errors from c functions and vm opcodes */
|
||||
vm_error:
|
||||
{
|
||||
@ -1108,12 +1243,18 @@ static void *op_lookup[255] = {
|
||||
|
||||
}
|
||||
|
||||
DstSignal dst_call(DstFunction *fun, int32_t argn, const Dst *argv, Dst *out) {
|
||||
DstSignal dst_call(
|
||||
DstFunction *fun,
|
||||
int32_t argn,
|
||||
const Dst *argv,
|
||||
Dst *out,
|
||||
DstFiber **f) {
|
||||
int32_t i;
|
||||
DstFiber *fiber = dst_fiber(fun, 64);
|
||||
for (i = 0; i < argn; i++) {
|
||||
if (f)
|
||||
*f = fiber;
|
||||
for (i = 0; i < argn; i++)
|
||||
dst_fiber_push(fiber, argv[i]);
|
||||
}
|
||||
dst_fiber_funcframe(fiber, fiber->root);
|
||||
/* Prevent push an extra value on the stack */
|
||||
dst_fiber_set_status(fiber, DST_STATUS_PENDING);
|
||||
|
@ -27,14 +27,786 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "dstconfig.h"
|
||||
/***** START SECTION CONFIG *****/
|
||||
|
||||
#define DST_VERSION "0.0.0 alpha"
|
||||
|
||||
/*
|
||||
* 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
|
||||
/* Enable certain posix features */
|
||||
#ifndef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
#endif
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
#define DST_WEB 1
|
||||
#elif 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(_WIN64)) /* Windows 64 bit */ \
|
||||
|| (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
|
||||
|
||||
/* Define how global dst state is declared */
|
||||
#ifdef DST_SINGLE_THREADED
|
||||
#define DST_THREAD_LOCAL
|
||||
#elif defined(__GNUC__)
|
||||
#define DST_THREAD_LOCAL __thread
|
||||
#elif defined(_MSC_BUILD)
|
||||
#define DST_THREAD_LOCAL __declspec(thread)
|
||||
#else
|
||||
#define DST_THREAD_LOCAL
|
||||
#endif
|
||||
|
||||
/* Handle runtime errors */
|
||||
#ifndef dst_exit
|
||||
#include <stdio.h>
|
||||
#define dst_exit(m) do { \
|
||||
printf("C runtime error at line %d in file %s: %s\n",\
|
||||
__LINE__,\
|
||||
__FILE__,\
|
||||
(m));\
|
||||
exit(1);\
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define dst_assert(c, m) do { \
|
||||
if (!(c)) dst_exit((m)); \
|
||||
} while (0)
|
||||
|
||||
/* What to do when out of memory */
|
||||
#ifndef DST_OUT_OF_MEMORY
|
||||
#include <stdio.h>
|
||||
#define DST_OUT_OF_MEMORY do { printf("dst 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 1024
|
||||
|
||||
/* Maximum depth to follow table prototypes before giving up and returning nil. */
|
||||
#define DST_MAX_PROTO_DEPTH 200
|
||||
|
||||
/* Define max stack size for stacks before raising a stack overflow error.
|
||||
* If this is not defined, fiber stacks can grow without limit (until memory
|
||||
* runs out) */
|
||||
#define DST_STACK_MAX 8192
|
||||
|
||||
/* 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
|
||||
|
||||
/***** END SECTION CONFIG *****/
|
||||
|
||||
/***** START SECTION TYPES *****/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "dsttypes.h"
|
||||
/* Names of all of the types */
|
||||
extern const char *const dst_type_names[16];
|
||||
|
||||
/* Fiber signals */
|
||||
typedef enum {
|
||||
DST_SIGNAL_OK,
|
||||
DST_SIGNAL_ERROR,
|
||||
DST_SIGNAL_DEBUG,
|
||||
DST_SIGNAL_YIELD,
|
||||
DST_SIGNAL_USER0,
|
||||
DST_SIGNAL_USER1,
|
||||
DST_SIGNAL_USER2,
|
||||
DST_SIGNAL_USER3,
|
||||
DST_SIGNAL_USER4,
|
||||
DST_SIGNAL_USER5,
|
||||
DST_SIGNAL_USER6,
|
||||
DST_SIGNAL_USER7,
|
||||
DST_SIGNAL_USER8,
|
||||
DST_SIGNAL_USER9
|
||||
} DstSignal;
|
||||
|
||||
/* Fiber statuses - mostly corresponds to signals. */
|
||||
typedef enum {
|
||||
DST_STATUS_DEAD,
|
||||
DST_STATUS_ERROR,
|
||||
DST_STATUS_DEBUG,
|
||||
DST_STATUS_PENDING,
|
||||
DST_STATUS_USER0,
|
||||
DST_STATUS_USER1,
|
||||
DST_STATUS_USER2,
|
||||
DST_STATUS_USER3,
|
||||
DST_STATUS_USER4,
|
||||
DST_STATUS_USER5,
|
||||
DST_STATUS_USER6,
|
||||
DST_STATUS_USER7,
|
||||
DST_STATUS_USER8,
|
||||
DST_STATUS_USER9,
|
||||
DST_STATUS_NEW,
|
||||
DST_STATUS_ALIVE
|
||||
} DstFiberStatus;
|
||||
|
||||
#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 DstReg DstReg;
|
||||
typedef struct DstSourceMapping DstSourceMapping;
|
||||
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;
|
||||
|
||||
#define DST_COUNT_TYPES (DST_ABSTRACT + 1)
|
||||
|
||||
/* Type flags */
|
||||
#define DST_TFLAG_NIL (1 << DST_NIL)
|
||||
#define DST_TFLAG_FALSE (1 << DST_FALSE)
|
||||
#define DST_TFLAG_TRUE (1 << DST_TRUE)
|
||||
#define DST_TFLAG_FIBER (1 << DST_FIBER)
|
||||
#define DST_TFLAG_INTEGER (1 << DST_INTEGER)
|
||||
#define DST_TFLAG_REAL (1 << DST_REAL)
|
||||
#define DST_TFLAG_STRING (1 << DST_STRING)
|
||||
#define DST_TFLAG_SYMBOL (1 << DST_SYMBOL)
|
||||
#define DST_TFLAG_ARRAY (1 << DST_ARRAY)
|
||||
#define DST_TFLAG_TUPLE (1 << DST_TUPLE)
|
||||
#define DST_TFLAG_TABLE (1 << DST_TABLE)
|
||||
#define DST_TFLAG_STRUCT (1 << DST_STRUCT)
|
||||
#define DST_TFLAG_BUFFER (1 << DST_BUFFER)
|
||||
#define DST_TFLAG_FUNCTION (1 << DST_FUNCTION)
|
||||
#define DST_TFLAG_CFUNCTION (1 << DST_CFUNCTION)
|
||||
#define DST_TFLAG_ABSTRACT (1 << DST_ABSTRACT)
|
||||
|
||||
/* Some abstractions */
|
||||
#define DST_TFLAG_BOOLEAN (DST_TFLAG_TRUE | DST_TFLAG_FALSE)
|
||||
#define DST_TFLAG_NUMBER (DST_TFLAG_REAL | DST_TFLAG_INTEGER)
|
||||
#define DST_TFLAG_CALLABLE (DST_TFLAG_FUNCTION | DST_TFLAG_CFUNCTION)
|
||||
#define DST_TFLAG_BYTES (DST_TFLAG_STRING | DST_TFLAG_SYMBOL | DST_TFLAG_BUFFER)
|
||||
#define DST_TFLAG_INDEXED (DST_TFLAG_ARRAY | DST_TFLAG_TUPLE)
|
||||
#define DST_TFLAG_DICTIONARY (DST_TFLAG_TABLE | DST_TFLAG_STRUCT)
|
||||
#define DST_TFLAG_LENGTHABLE (DST_TFLAG_BYTES | DST_TFLAG_INDEXED | DST_TFLAG_DICTIONARY)
|
||||
|
||||
/* 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 <math.h>
|
||||
|
||||
union Dst {
|
||||
uint64_t u64;
|
||||
int64_t i64;
|
||||
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 0xFFFF800000000000llu
|
||||
#define DST_NANBOX_PAYLOADBITS 0x00007FFFFFFFFFFFllu
|
||||
|
||||
|
||||
#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 0xFFFF000000000000llu
|
||||
#define DST_NANBOX_PAYLOADBITS 0x0000FFFFFFFFFFFFllu
|
||||
|
||||
#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 0xFFFFFFFFllu
|
||||
#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(void);
|
||||
Dst dst_wrap_real(double x);
|
||||
Dst dst_wrap_integer(int32_t x);
|
||||
Dst dst_wrap_true(void);
|
||||
Dst dst_wrap_false(void);
|
||||
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;
|
||||
};
|
||||
|
||||
/* Fiber flags */
|
||||
#define DST_FIBER_FLAG_SIGNAL_WAITING (1 << 30)
|
||||
|
||||
/* Fiber signal masks. */
|
||||
#define DST_FIBER_MASK_ERROR 2
|
||||
#define DST_FIBER_MASK_DEBUG 4
|
||||
#define DST_FIBER_MASK_YIELD 8
|
||||
|
||||
#define DST_FIBER_MASK_USER0 (16 << 0)
|
||||
#define DST_FIBER_MASK_USER1 (16 << 1)
|
||||
#define DST_FIBER_MASK_USER2 (16 << 2)
|
||||
#define DST_FIBER_MASK_USER3 (16 << 3)
|
||||
#define DST_FIBER_MASK_USER4 (16 << 4)
|
||||
#define DST_FIBER_MASK_USER5 (16 << 5)
|
||||
#define DST_FIBER_MASK_USER6 (16 << 6)
|
||||
#define DST_FIBER_MASK_USER7 (16 << 7)
|
||||
#define DST_FIBER_MASK_USER8 (16 << 8)
|
||||
#define DST_FIBER_MASK_USER9 (16 << 9)
|
||||
|
||||
#define DST_FIBER_MASK_USERN(N) (16 << (N))
|
||||
#define DST_FIBER_MASK_USER 0x3FF0
|
||||
|
||||
#define DST_FIBER_STATUS_MASK 0xFF0000
|
||||
#define DST_FIBER_STATUS_OFFSET 16
|
||||
|
||||
/* A lightweight green thread in dst. Does not correspond to
|
||||
* operating system threads. */
|
||||
struct DstFiber {
|
||||
Dst *data;
|
||||
DstFiber *child; /* Keep linked list of fibers for restarting pending fibers */
|
||||
DstFunction *root; /* First value */
|
||||
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;
|
||||
int32_t maxstack; /* Arbitrary defined limit for stack overflow */
|
||||
uint32_t flags; /* Various flags */
|
||||
};
|
||||
|
||||
/* Mark if a stack frame is a tail call for debugging */
|
||||
#define DST_STACKFRAME_TAILCALL 1
|
||||
|
||||
/* A stack frame on the fiber. Is stored along with the stack values. */
|
||||
struct DstStackFrame {
|
||||
DstFunction *func;
|
||||
uint32_t *pc;
|
||||
DstFuncEnv *env;
|
||||
int32_t prevframe;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
/* 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;
|
||||
DstTable *proto;
|
||||
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 0x10000
|
||||
#define DST_FUNCDEF_FLAG_NEEDSENV 0x20000
|
||||
#define DST_FUNCDEF_FLAG_FIXARITY 0x40000
|
||||
#define DST_FUNCDEF_FLAG_TAG 0xFFFF
|
||||
|
||||
/* Source mapping structure for a bytecode instruction */
|
||||
struct DstSourceMapping {
|
||||
int32_t line;
|
||||
int32_t column;
|
||||
};
|
||||
|
||||
/* 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 */
|
||||
DstSourceMapping *sourcemap;
|
||||
const uint8_t *source;
|
||||
const uint8_t *name;
|
||||
|
||||
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;
|
||||
DstFuncEnv *envs[];
|
||||
};
|
||||
|
||||
typedef struct DstParseState DstParseState;
|
||||
typedef struct DstParser DstParser;
|
||||
|
||||
enum DstParserStatus {
|
||||
DST_PARSE_ROOT,
|
||||
DST_PARSE_ERROR,
|
||||
DST_PARSE_FULL,
|
||||
DST_PARSE_PENDING
|
||||
};
|
||||
|
||||
/* A dst parser */
|
||||
struct DstParser {
|
||||
Dst* args;
|
||||
const char *error;
|
||||
DstParseState *states;
|
||||
uint8_t *buf;
|
||||
size_t argcount;
|
||||
size_t argcap;
|
||||
size_t statecount;
|
||||
size_t statecap;
|
||||
size_t bufcount;
|
||||
size_t bufcap;
|
||||
size_t line;
|
||||
size_t col;
|
||||
int lookback;
|
||||
};
|
||||
|
||||
/* Defines an abstract type */
|
||||
struct DstAbstractType {
|
||||
const char *name;
|
||||
int (*gc)(void *data, size_t len);
|
||||
int (*gcmark)(void *data, size_t len);
|
||||
};
|
||||
|
||||
/* Contains information about userdata */
|
||||
struct DstAbstractHeader {
|
||||
const DstAbstractType *type;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct DstReg {
|
||||
const char *name;
|
||||
DstCFunction cfun;
|
||||
};
|
||||
|
||||
/***** END SECTION TYPES *****/
|
||||
|
||||
/***** START SECTION OPCODES *****/
|
||||
|
||||
/* Bytecode op argument types */
|
||||
enum DstOpArgType {
|
||||
DST_OAT_SLOT,
|
||||
DST_OAT_ENVIRONMENT,
|
||||
DST_OAT_CONSTANT,
|
||||
DST_OAT_INTEGER,
|
||||
DST_OAT_TYPE,
|
||||
DST_OAT_SIMPLETYPE,
|
||||
DST_OAT_LABEL,
|
||||
DST_OAT_FUNCDEF
|
||||
};
|
||||
|
||||
/* Various types of instructions */
|
||||
enum DstInstructionType {
|
||||
DIT_0, /* No args */
|
||||
DIT_S, /* Slot(3) */
|
||||
DIT_L, /* Label(3) */
|
||||
DIT_SS, /* Slot(1), Slot(2) */
|
||||
DIT_SL, /* Slot(1), Label(2) */
|
||||
DIT_ST, /* Slot(1), Slot(2) */
|
||||
DIT_SI, /* Slot(1), Immediate(2) */
|
||||
DIT_SD, /* Slot(1), Closure(2) */
|
||||
DIT_SU, /* Slot(1), Unsigned Immediate(2) */
|
||||
DIT_SSS, /* Slot(1), Slot(1), Slot(1) */
|
||||
DIT_SSI, /* Slot(1), Slot(1), Immediate(1) */
|
||||
DIT_SSU, /* Slot(1), Slot(1), Unsigned Immediate(1) */
|
||||
DIT_SES, /* Slot(1), Environment(1), Far Slot(1) */
|
||||
DIT_SC /* Slot(1), Constant(2) */
|
||||
};
|
||||
|
||||
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_GREATER_THAN_INTEGER,
|
||||
DOP_GREATER_THAN_IMMEDIATE,
|
||||
DOP_GREATER_THAN_REAL,
|
||||
DOP_GREATER_THAN_EQUAL_REAL,
|
||||
DOP_LESS_THAN,
|
||||
DOP_LESS_THAN_INTEGER,
|
||||
DOP_LESS_THAN_IMMEDIATE,
|
||||
DOP_LESS_THAN_REAL,
|
||||
DOP_LESS_THAN_EQUAL_REAL,
|
||||
DOP_EQUALS,
|
||||
DOP_EQUALS_INTEGER,
|
||||
DOP_EQUALS_IMMEDIATE,
|
||||
DOP_EQUALS_REAL,
|
||||
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_RESUME,
|
||||
DOP_SIGNAL,
|
||||
DOP_GET,
|
||||
DOP_PUT,
|
||||
DOP_GET_INDEX,
|
||||
DOP_PUT_INDEX,
|
||||
DOP_LENGTH,
|
||||
DOP_MAKE_ARRAY,
|
||||
DOP_MAKE_BUFFER,
|
||||
DOP_MAKE_STRING,
|
||||
DOP_MAKE_STRUCT,
|
||||
DOP_MAKE_TABLE,
|
||||
DOP_MAKE_TUPLE,
|
||||
DOP_INSTRUCTION_COUNT
|
||||
};
|
||||
|
||||
/* Info about all instructions */
|
||||
extern enum DstInstructionType dst_instructions[DOP_INSTRUCTION_COUNT];
|
||||
|
||||
/***** END SECTION OPCODES *****/
|
||||
|
||||
/***** START SECTION MAIN *****/
|
||||
|
||||
/* Parsing */
|
||||
void dst_parser_init(DstParser *parser);
|
||||
@ -62,6 +834,28 @@ DstAssembleResult dst_asm(Dst source, int flags);
|
||||
Dst dst_disasm(DstFuncDef *def);
|
||||
Dst dst_asm_decode_instruction(uint32_t instr);
|
||||
|
||||
/* Compilation */
|
||||
typedef struct DstCompileOptions DstCompileOptions;
|
||||
typedef struct DstCompileResult DstCompileResult;
|
||||
enum DstCompileStatus {
|
||||
DST_COMPILE_OK,
|
||||
DST_COMPILE_ERROR
|
||||
};
|
||||
struct DstCompileResult {
|
||||
enum DstCompileStatus status;
|
||||
DstFuncDef *funcdef;
|
||||
const uint8_t *error;
|
||||
DstFiber *macrofiber;
|
||||
DstSourceMapping error_mapping;
|
||||
};
|
||||
DstCompileResult dst_compile(Dst source, DstTable *env, const uint8_t *where);
|
||||
|
||||
/* Get the default environment for dst */
|
||||
DstTable *dst_stl_env();
|
||||
|
||||
int dst_dobytes(DstTable *env, const uint8_t *bytes, int32_t len, const char *sourcePath);
|
||||
int dst_dostring(DstTable *env, const char *str, const char *sourcePath);
|
||||
|
||||
/* 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);
|
||||
@ -69,6 +863,7 @@ double dst_scan_real(const uint8_t *str, int32_t len, int *err);
|
||||
|
||||
/* Array functions */
|
||||
DstArray *dst_array(int32_t capacity);
|
||||
DstArray *dst_array_n(const Dst *elements, int32_t n);
|
||||
DstArray *dst_array_init(DstArray *array, int32_t capacity);
|
||||
void dst_array_deinit(DstArray *array);
|
||||
void dst_array_ensure(DstArray *array, int32_t capacity);
|
||||
@ -119,6 +914,8 @@ 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_to_string(Dst x);
|
||||
void dst_to_string_b(DstBuffer *buffer, Dst x);
|
||||
void dst_to_description_b(DstBuffer *buffer, 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)))
|
||||
@ -208,7 +1005,7 @@ int dst_init(void);
|
||||
void dst_deinit(void);
|
||||
DstSignal dst_continue(DstFiber *fiber, Dst in, Dst *out);
|
||||
#define dst_run(F,O) dst_continue(F, dst_wrap_nil(), O)
|
||||
DstSignal dst_call(DstFunction *fun, int32_t argn, const Dst *argv, Dst *out);
|
||||
DstSignal dst_call(DstFunction *fun, int32_t argn, const Dst *argv, Dst *out, DstFiber **f);
|
||||
|
||||
/* Env helpers */
|
||||
typedef enum {
|
||||
@ -233,6 +1030,25 @@ int dst_type_err(DstArgs args, int32_t n, DstType expected);
|
||||
int dst_typemany_err(DstArgs args, int32_t n, int expected);
|
||||
int dst_typeabstract_err(DstArgs args, int32_t n, const DstAbstractType *at);
|
||||
|
||||
/* Initialize builtin libraries */
|
||||
int dst_lib_io(DstArgs args);
|
||||
int dst_lib_math(DstArgs args);
|
||||
int dst_lib_array(DstArgs args);
|
||||
int dst_lib_tuple(DstArgs args);
|
||||
int dst_lib_buffer(DstArgs args);
|
||||
int dst_lib_table(DstArgs args);
|
||||
int dst_lib_fiber(DstArgs args);
|
||||
int dst_lib_os(DstArgs args);
|
||||
int dst_lib_string(DstArgs args);
|
||||
int dst_lib_marsh(DstArgs args);
|
||||
int dst_lib_parse(DstArgs args);
|
||||
int dst_lib_asm(DstArgs args);
|
||||
int dst_lib_compile(DstArgs args);
|
||||
|
||||
/***** END SECTION MAIN *****/
|
||||
|
||||
/***** START SECTION MACROS *****/
|
||||
|
||||
/* Macros */
|
||||
#define DST_THROW(a, e) return (*((a).ret) = dst_cstringv(e), DST_SIGNAL_ERROR)
|
||||
#define DST_THROWV(a, v) return (*((a).ret) = (v), DST_SIGNAL_ERROR)
|
||||
@ -343,6 +1159,8 @@ int dst_typeabstract_err(DstArgs args, int32_t n, const DstAbstractType *at);
|
||||
#define DST_RETURN_CSTRING(A, X) DST_RETURN(A, dst_cstringv(X))
|
||||
#define DST_RETURN_CSYMBOL(A, X) DST_RETURN(A, dst_csymbolv(X))
|
||||
|
||||
/**** END SECTION MACROS *****/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,163 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define DST_VERSION "0.0.0 alpha"
|
||||
|
||||
/*
|
||||
* 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
|
||||
/* Enable certain posix features */
|
||||
#ifndef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
#endif
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
#define DST_WEB 1
|
||||
#elif 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(_WIN64)) /* Windows 64 bit */ \
|
||||
|| (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
|
||||
|
||||
/* Define how global dst state is declared */
|
||||
#ifdef DST_SINGLE_THREADED
|
||||
#define DST_THREAD_LOCAL
|
||||
#else
|
||||
#if defined(__GNUC__)
|
||||
#define DST_THREAD_LOCAL __thread
|
||||
#elif defined(_MSC_BUILD)
|
||||
#define DST_THREAD_LOCAL __declspec(thread)
|
||||
#else
|
||||
#define DST_THREAD_LOCAL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Include default headers */
|
||||
#include <stdint.h>
|
||||
|
||||
/* Handle runtime errors */
|
||||
#ifndef dst_exit
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#define dst_exit(m) do { \
|
||||
printf("runtime error at line %d in file %s: %s\n",\
|
||||
__LINE__,\
|
||||
__FILE__,\
|
||||
(m));\
|
||||
exit(1);\
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define dst_assert(c, m) do { \
|
||||
if (!(c)) dst_exit((m)); \
|
||||
} while (0)
|
||||
|
||||
/* What to do when out of memory */
|
||||
#ifndef DST_OUT_OF_MEMORY
|
||||
#include <stdio.h>
|
||||
#define DST_OUT_OF_MEMORY do { printf("dst 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 1024
|
||||
|
||||
/* Maximum depth to follow table prototypes before giving up and returning nil. */
|
||||
#define DST_MAX_PROTO_DEPTH 200
|
||||
|
||||
/* Define max stack size for stacks before raising a stack overflow error.
|
||||
* If this is not defined, fiber stacks can grow without limit (until memory
|
||||
* runs out) */
|
||||
#define DST_STACK_MAX 8192
|
||||
|
||||
/* 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
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DST_CONFIG_H_defined */
|
@ -1,88 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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_CORELIB_H_defined
|
||||
#define DST_CORELIB_H_defined
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "dsttypes.h"
|
||||
|
||||
/* Native */
|
||||
int dst_core_native(DstArgs args);
|
||||
|
||||
/* Arithmetic */
|
||||
int dst_int(DstArgs args);
|
||||
int dst_real(DstArgs args);
|
||||
int dst_rand(DstArgs args);
|
||||
int dst_srand(DstArgs args);
|
||||
int dst_remainder(DstArgs args);
|
||||
|
||||
/* Misc core functions */
|
||||
int dst_core_print(DstArgs args);
|
||||
int dst_core_describe(DstArgs args);
|
||||
int dst_core_string(DstArgs args);
|
||||
int dst_core_symbol(DstArgs args);
|
||||
int dst_core_buffer(DstArgs args);
|
||||
int dst_core_scannumber(DstArgs args);
|
||||
int dst_core_scaninteger(DstArgs args);
|
||||
int dst_core_scanreal(DstArgs args);
|
||||
int dst_core_tuple(DstArgs args);
|
||||
int dst_core_array(DstArgs args);
|
||||
int dst_core_table(DstArgs args);
|
||||
int dst_core_struct(DstArgs args);
|
||||
int dst_core_buffer(DstArgs args);
|
||||
int dst_core_gensym(DstArgs args);
|
||||
int dst_core_type(DstArgs args);
|
||||
int dst_core_next(DstArgs args);
|
||||
int dst_core_hash(DstArgs args);
|
||||
|
||||
/* GC */
|
||||
int dst_core_gccollect(DstArgs args);
|
||||
int dst_core_gcsetinterval(DstArgs args);
|
||||
int dst_core_gcinterval(DstArgs args);
|
||||
|
||||
/* Initialize builtin libraries */
|
||||
int dst_lib_io(DstArgs args);
|
||||
int dst_lib_math(DstArgs args);
|
||||
int dst_lib_array(DstArgs args);
|
||||
int dst_lib_tuple(DstArgs args);
|
||||
int dst_lib_buffer(DstArgs args);
|
||||
int dst_lib_table(DstArgs args);
|
||||
int dst_lib_fiber(DstArgs args);
|
||||
int dst_lib_os(DstArgs args);
|
||||
int dst_lib_string(DstArgs args);
|
||||
int dst_lib_marsh(DstArgs args);
|
||||
int dst_lib_parse(DstArgs args);
|
||||
int dst_lib_asm(DstArgs args);
|
||||
|
||||
/* Useful for compiler */
|
||||
Dst dst_op_add(Dst lhs, Dst rhs);
|
||||
Dst dst_op_subtract(Dst lhs, Dst rhs);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DST_CORELIB_H_defined */
|
@ -1,143 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Bytecode op argument types */
|
||||
enum DstOpArgType {
|
||||
DST_OAT_SLOT,
|
||||
DST_OAT_ENVIRONMENT,
|
||||
DST_OAT_CONSTANT,
|
||||
DST_OAT_INTEGER,
|
||||
DST_OAT_TYPE,
|
||||
DST_OAT_SIMPLETYPE,
|
||||
DST_OAT_LABEL,
|
||||
DST_OAT_FUNCDEF
|
||||
};
|
||||
|
||||
/* Various types of instructions */
|
||||
enum DstInstructionType {
|
||||
DIT_0, /* No args */
|
||||
DIT_S, /* Slot(3) */
|
||||
DIT_L, /* Label(3) */
|
||||
DIT_SS, /* Slot(1), Slot(2) */
|
||||
DIT_SL, /* Slot(1), Label(2) */
|
||||
DIT_ST, /* Slot(1), Slot(2) */
|
||||
DIT_SI, /* Slot(1), Immediate(2) */
|
||||
DIT_SD, /* Slot(1), Closure(2) */
|
||||
DIT_SU, /* Slot(1), Unsigned Immediate(2) */
|
||||
DIT_SSS, /* Slot(1), Slot(1), Slot(1) */
|
||||
DIT_SSI, /* Slot(1), Slot(1), Immediate(1) */
|
||||
DIT_SSU, /* Slot(1), Slot(1), Unsigned Immediate(1) */
|
||||
DIT_SES, /* Slot(1), Environment(1), Far Slot(1) */
|
||||
DIT_SC /* Slot(1), Constant(2) */
|
||||
};
|
||||
|
||||
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_GREATER_THAN_INTEGER,
|
||||
DOP_GREATER_THAN_IMMEDIATE,
|
||||
DOP_GREATER_THAN_REAL,
|
||||
DOP_GREATER_THAN_EQUAL_REAL,
|
||||
DOP_LESS_THAN,
|
||||
DOP_LESS_THAN_INTEGER,
|
||||
DOP_LESS_THAN_IMMEDIATE,
|
||||
DOP_LESS_THAN_REAL,
|
||||
DOP_LESS_THAN_EQUAL_REAL,
|
||||
DOP_EQUALS,
|
||||
DOP_EQUALS_INTEGER,
|
||||
DOP_EQUALS_IMMEDIATE,
|
||||
DOP_EQUALS_REAL,
|
||||
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_RESUME,
|
||||
DOP_SIGNAL,
|
||||
DOP_GET,
|
||||
DOP_PUT,
|
||||
DOP_GET_INDEX,
|
||||
DOP_PUT_INDEX,
|
||||
DOP_LENGTH,
|
||||
DOP_INSTRUCTION_COUNT
|
||||
};
|
||||
|
||||
/* Info about all instructions */
|
||||
extern enum DstInstructionType dst_instructions[DOP_INSTRUCTION_COUNT];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,562 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "dstconfig.h"
|
||||
|
||||
/* Names of all of the types */
|
||||
extern const char *const dst_type_names[16];
|
||||
|
||||
/* Fiber signals */
|
||||
typedef enum {
|
||||
DST_SIGNAL_OK,
|
||||
DST_SIGNAL_ERROR,
|
||||
DST_SIGNAL_DEBUG,
|
||||
DST_SIGNAL_YIELD,
|
||||
DST_SIGNAL_USER0,
|
||||
DST_SIGNAL_USER1,
|
||||
DST_SIGNAL_USER2,
|
||||
DST_SIGNAL_USER3,
|
||||
DST_SIGNAL_USER4,
|
||||
DST_SIGNAL_USER5,
|
||||
DST_SIGNAL_USER6,
|
||||
DST_SIGNAL_USER7,
|
||||
DST_SIGNAL_USER8,
|
||||
DST_SIGNAL_USER9
|
||||
} DstSignal;
|
||||
|
||||
/* Fiber statuses - mostly corresponds to signals. */
|
||||
typedef enum {
|
||||
DST_STATUS_DEAD,
|
||||
DST_STATUS_ERROR,
|
||||
DST_STATUS_DEBUG,
|
||||
DST_STATUS_PENDING,
|
||||
DST_STATUS_USER0,
|
||||
DST_STATUS_USER1,
|
||||
DST_STATUS_USER2,
|
||||
DST_STATUS_USER3,
|
||||
DST_STATUS_USER4,
|
||||
DST_STATUS_USER5,
|
||||
DST_STATUS_USER6,
|
||||
DST_STATUS_USER7,
|
||||
DST_STATUS_USER8,
|
||||
DST_STATUS_USER9,
|
||||
DST_STATUS_NEW,
|
||||
DST_STATUS_ALIVE
|
||||
} DstFiberStatus;
|
||||
|
||||
#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 DstReg DstReg;
|
||||
typedef struct DstSourceMapping DstSourceMapping;
|
||||
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;
|
||||
|
||||
#define DST_COUNT_TYPES (DST_ABSTRACT + 1)
|
||||
|
||||
/* Type flags */
|
||||
#define DST_TFLAG_NIL (1 << DST_NIL)
|
||||
#define DST_TFLAG_FALSE (1 << DST_FALSE)
|
||||
#define DST_TFLAG_TRUE (1 << DST_TRUE)
|
||||
#define DST_TFLAG_FIBER (1 << DST_FIBER)
|
||||
#define DST_TFLAG_INTEGER (1 << DST_INTEGER)
|
||||
#define DST_TFLAG_REAL (1 << DST_REAL)
|
||||
#define DST_TFLAG_STRING (1 << DST_STRING)
|
||||
#define DST_TFLAG_SYMBOL (1 << DST_SYMBOL)
|
||||
#define DST_TFLAG_ARRAY (1 << DST_ARRAY)
|
||||
#define DST_TFLAG_TUPLE (1 << DST_TUPLE)
|
||||
#define DST_TFLAG_TABLE (1 << DST_TABLE)
|
||||
#define DST_TFLAG_STRUCT (1 << DST_STRUCT)
|
||||
#define DST_TFLAG_BUFFER (1 << DST_BUFFER)
|
||||
#define DST_TFLAG_FUNCTION (1 << DST_FUNCTION)
|
||||
#define DST_TFLAG_CFUNCTION (1 << DST_CFUNCTION)
|
||||
#define DST_TFLAG_ABSTRACT (1 << DST_ABSTRACT)
|
||||
|
||||
/* Some abstractions */
|
||||
#define DST_TFLAG_BOOLEAN (DST_TFLAG_TRUE | DST_TFLAG_FALSE)
|
||||
#define DST_TFLAG_NUMBER (DST_TFLAG_REAL | DST_TFLAG_INTEGER)
|
||||
#define DST_TFLAG_CALLABLE (DST_TFLAG_FUNCTION | DST_TFLAG_CFUNCTION)
|
||||
#define DST_TFLAG_BYTES (DST_TFLAG_STRING | DST_TFLAG_SYMBOL | DST_TFLAG_BUFFER)
|
||||
#define DST_TFLAG_INDEXED (DST_TFLAG_ARRAY | DST_TFLAG_TUPLE)
|
||||
#define DST_TFLAG_DICTIONARY (DST_TFLAG_TABLE | DST_TFLAG_STRUCT)
|
||||
#define DST_TFLAG_LENGTHABLE (DST_TFLAG_CHARS | DST_TFLAG_INDEXED | DST_TFLAG_DICTIONARY)
|
||||
|
||||
/* 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 <math.h>
|
||||
|
||||
union Dst {
|
||||
uint64_t u64;
|
||||
int64_t i64;
|
||||
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 0xFFFF800000000000llu
|
||||
#define DST_NANBOX_PAYLOADBITS 0x00007FFFFFFFFFFFllu
|
||||
|
||||
|
||||
#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 0xFFFF000000000000llu
|
||||
#define DST_NANBOX_PAYLOADBITS 0x0000FFFFFFFFFFFFllu
|
||||
|
||||
#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 0xFFFFFFFFllu
|
||||
#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(void);
|
||||
Dst dst_wrap_real(double x);
|
||||
Dst dst_wrap_integer(int32_t x);
|
||||
Dst dst_wrap_true(void);
|
||||
Dst dst_wrap_false(void);
|
||||
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;
|
||||
};
|
||||
|
||||
/* Fiber flags */
|
||||
#define DST_FIBER_FLAG_SIGNAL_WAITING (1 << 30)
|
||||
|
||||
/* Fiber signal masks. */
|
||||
#define DST_FIBER_MASK_ERROR 2
|
||||
#define DST_FIBER_MASK_DEBUG 4
|
||||
#define DST_FIBER_MASK_YIELD 8
|
||||
|
||||
#define DST_FIBER_MASK_USER0 (16 << 0)
|
||||
#define DST_FIBER_MASK_USER1 (16 << 1)
|
||||
#define DST_FIBER_MASK_USER2 (16 << 2)
|
||||
#define DST_FIBER_MASK_USER3 (16 << 3)
|
||||
#define DST_FIBER_MASK_USER4 (16 << 4)
|
||||
#define DST_FIBER_MASK_USER5 (16 << 5)
|
||||
#define DST_FIBER_MASK_USER6 (16 << 6)
|
||||
#define DST_FIBER_MASK_USER7 (16 << 7)
|
||||
#define DST_FIBER_MASK_USER8 (16 << 8)
|
||||
#define DST_FIBER_MASK_USER9 (16 << 9)
|
||||
|
||||
#define DST_FIBER_MASK_USERN(N) (16 << (N))
|
||||
#define DST_FIBER_MASK_USER 0x3FF0
|
||||
|
||||
#define DST_FIBER_STATUS_MASK 0xFF0000
|
||||
#define DST_FIBER_STATUS_OFFSET 16
|
||||
|
||||
/* A lightweight green thread in dst. Does not correspond to
|
||||
* operating system threads. */
|
||||
struct DstFiber {
|
||||
Dst *data;
|
||||
DstFiber *child; /* Keep linked list of fibers for restarting pending fibers */
|
||||
DstFunction *root; /* First value */
|
||||
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;
|
||||
int32_t maxstack; /* Arbitrary defined limit for stack overflow */
|
||||
uint32_t flags; /* Various flags */
|
||||
};
|
||||
|
||||
/* Mark if a stack frame is a tail call for debugging */
|
||||
#define DST_STACKFRAME_TAILCALL 1
|
||||
|
||||
/* A stack frame on the fiber. Is stored along with the stack values. */
|
||||
struct DstStackFrame {
|
||||
DstFunction *func;
|
||||
uint32_t *pc;
|
||||
DstFuncEnv *env;
|
||||
int32_t prevframe;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
/* 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;
|
||||
DstTable *proto;
|
||||
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 0x10000
|
||||
#define DST_FUNCDEF_FLAG_NEEDSENV 0x20000
|
||||
#define DST_FUNCDEF_FLAG_FIXARITY 0x40000
|
||||
#define DST_FUNCDEF_FLAG_TAG 0xFFFF
|
||||
|
||||
/* Source mapping structure for a bytecode instruction */
|
||||
struct DstSourceMapping {
|
||||
int32_t line;
|
||||
int32_t column;
|
||||
};
|
||||
|
||||
/* 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 */
|
||||
DstSourceMapping *sourcemap;
|
||||
const uint8_t *source;
|
||||
const uint8_t *name;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
#define DST_PARSEFLAG_SOURCEMAP 1
|
||||
|
||||
/* 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;
|
||||
DstFuncEnv *envs[];
|
||||
};
|
||||
|
||||
typedef struct DstParseState DstParseState;
|
||||
typedef struct DstParser DstParser;
|
||||
|
||||
enum DstParserStatus {
|
||||
DST_PARSE_ROOT,
|
||||
DST_PARSE_ERROR,
|
||||
DST_PARSE_FULL,
|
||||
DST_PARSE_PENDING
|
||||
};
|
||||
|
||||
/* A dst parser */
|
||||
struct DstParser {
|
||||
Dst* args;
|
||||
const char *error;
|
||||
DstParseState *states;
|
||||
uint8_t *buf;
|
||||
size_t argcount;
|
||||
size_t argcap;
|
||||
size_t statecount;
|
||||
size_t statecap;
|
||||
size_t bufcount;
|
||||
size_t bufcap;
|
||||
size_t line;
|
||||
size_t col;
|
||||
int lookback;
|
||||
};
|
||||
|
||||
/* Defines an abstract type */
|
||||
struct DstAbstractType {
|
||||
const char *name;
|
||||
int (*gc)(void *data, size_t len);
|
||||
int (*gcmark)(void *data, size_t len);
|
||||
};
|
||||
|
||||
/* Contains information about userdata */
|
||||
struct DstAbstractHeader {
|
||||
const DstAbstractType *type;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct DstReg {
|
||||
const char *name;
|
||||
DstCFunction cfun;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DST_TYPES_H_defined */
|
0
src/include/generated/.gitkeep
Normal file
0
src/include/generated/.gitkeep
Normal file
3636
src/include/generated/boot.h
Normal file
3636
src/include/generated/boot.h
Normal file
File diff suppressed because it is too large
Load Diff
193
src/include/generated/init.h
Normal file
193
src/include/generated/init.h
Normal file
@ -0,0 +1,193 @@
|
||||
/* Auto generated - DO NOT EDIT */
|
||||
|
||||
static const unsigned char dst_mainclient_init[] = {
|
||||
0x23, 0x20, 0x43, 0x6F, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68,
|
||||
0x74, 0x20, 0x32, 0x30, 0x31, 0x37, 0x2D, 0x32, 0x30, 0x31,
|
||||
0x38, 0x20, 0x28, 0x43, 0x29, 0x20, 0x43, 0x61, 0x6C, 0x76,
|
||||
0x69, 0x6E, 0x20, 0x52, 0x6F, 0x73, 0x65, 0x0A, 0x28, 0x74,
|
||||
0x61, 0x62, 0x6C, 0x65, 0x2E, 0x73, 0x65, 0x74, 0x70, 0x72,
|
||||
0x6F, 0x74, 0x6F, 0x20, 0x40, 0x7B, 0x20, 0x31, 0x20, 0x32,
|
||||
0x7D, 0x20, 0x40, 0x7B, 0x7D, 0x29, 0x0A, 0x28, 0x64, 0x6F,
|
||||
0x0A, 0x0A, 0x20, 0x20, 0x28, 0x76, 0x61, 0x72, 0x20, 0x2A,
|
||||
0x73, 0x68, 0x6F, 0x75, 0x6C, 0x64, 0x2D, 0x72, 0x65, 0x70,
|
||||
0x6C, 0x2A, 0x20, 0x3A, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74,
|
||||
0x65, 0x20, 0x66, 0x61, 0x6C, 0x73, 0x65, 0x29, 0x0A, 0x20,
|
||||
0x20, 0x28, 0x76, 0x61, 0x72, 0x20, 0x2A, 0x6E, 0x6F, 0x2D,
|
||||
0x66, 0x69, 0x6C, 0x65, 0x2A, 0x20, 0x3A, 0x70, 0x72, 0x69,
|
||||
0x76, 0x61, 0x74, 0x65, 0x20, 0x74, 0x72, 0x75, 0x65, 0x29,
|
||||
0x0A, 0x20, 0x20, 0x28, 0x76, 0x61, 0x72, 0x20, 0x2A, 0x72,
|
||||
0x61, 0x77, 0x2D, 0x73, 0x74, 0x64, 0x69, 0x6E, 0x2A, 0x20,
|
||||
0x3A, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x20, 0x66,
|
||||
0x61, 0x6C, 0x73, 0x65, 0x29, 0x0A, 0x20, 0x20, 0x28, 0x76,
|
||||
0x61, 0x72, 0x20, 0x2A, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65,
|
||||
0x6F, 0x70, 0x74, 0x73, 0x2A, 0x20, 0x3A, 0x70, 0x72, 0x69,
|
||||
0x76, 0x61, 0x74, 0x65, 0x20, 0x74, 0x72, 0x75, 0x65, 0x29,
|
||||
0x0A, 0x20, 0x20, 0x28, 0x76, 0x61, 0x72, 0x20, 0x2A, 0x65,
|
||||
0x78, 0x69, 0x74, 0x2D, 0x6F, 0x6E, 0x2D, 0x65, 0x72, 0x72,
|
||||
0x6F, 0x72, 0x2A, 0x20, 0x3A, 0x70, 0x72, 0x69, 0x76, 0x61,
|
||||
0x74, 0x65, 0x20, 0x74, 0x72, 0x75, 0x65, 0x29, 0x0A, 0x0A,
|
||||
0x20, 0x20, 0x23, 0x20, 0x46, 0x6C, 0x61, 0x67, 0x20, 0x68,
|
||||
0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x73, 0x0A, 0x20, 0x20,
|
||||
0x28, 0x64, 0x65, 0x66, 0x20, 0x68, 0x61, 0x6E, 0x64, 0x6C,
|
||||
0x65, 0x72, 0x73, 0x20, 0x3A, 0x70, 0x72, 0x69, 0x76, 0x61,
|
||||
0x74, 0x65, 0x20, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x7B, 0x22,
|
||||
0x68, 0x22, 0x20, 0x28, 0x66, 0x6E, 0x20, 0x5B, 0x5D, 0x20,
|
||||
0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x28, 0x70, 0x72, 0x69, 0x6E, 0x74, 0x20, 0x22,
|
||||
0x75, 0x73, 0x61, 0x67, 0x65, 0x3A, 0x20, 0x22, 0x20, 0x28,
|
||||
0x67, 0x65, 0x74, 0x20, 0x61, 0x72, 0x67, 0x73, 0x20, 0x30,
|
||||
0x29, 0x20, 0x22, 0x20, 0x5B, 0x6F, 0x70, 0x74, 0x69, 0x6F,
|
||||
0x6E, 0x73, 0x5D, 0x20, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
|
||||
0x73, 0x2E, 0x2E, 0x2E, 0x22, 0x29, 0x0A, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x70,
|
||||
0x72, 0x69, 0x6E, 0x74, 0x20, 0x0A, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x60,
|
||||
0x4F, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x61, 0x72,
|
||||
0x65, 0x3A, 0x0A, 0x20, 0x20, 0x2D, 0x68, 0x20, 0x53, 0x68,
|
||||
0x6F, 0x77, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x68, 0x65,
|
||||
0x6C, 0x70, 0x0A, 0x20, 0x20, 0x2D, 0x76, 0x20, 0x50, 0x72,
|
||||
0x69, 0x6E, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x65,
|
||||
0x72, 0x73, 0x69, 0x6F, 0x6E, 0x20, 0x73, 0x74, 0x72, 0x69,
|
||||
0x6E, 0x67, 0x0A, 0x20, 0x20, 0x2D, 0x73, 0x20, 0x55, 0x73,
|
||||
0x65, 0x20, 0x72, 0x61, 0x77, 0x20, 0x73, 0x74, 0x64, 0x69,
|
||||
0x6E, 0x20, 0x69, 0x6E, 0x73, 0x74, 0x65, 0x61, 0x64, 0x20,
|
||||
0x6F, 0x66, 0x20, 0x67, 0x65, 0x74, 0x6C, 0x69, 0x6E, 0x65,
|
||||
0x20, 0x6C, 0x69, 0x6B, 0x65, 0x20, 0x66, 0x75, 0x6E, 0x63,
|
||||
0x74, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x69, 0x74, 0x79, 0x0A,
|
||||
0x20, 0x20, 0x2D, 0x65, 0x20, 0x45, 0x78, 0x65, 0x63, 0x75,
|
||||
0x74, 0x65, 0x20, 0x61, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E,
|
||||
0x67, 0x20, 0x6F, 0x66, 0x20, 0x64, 0x73, 0x74, 0x0A, 0x20,
|
||||
0x20, 0x2D, 0x72, 0x20, 0x45, 0x6E, 0x74, 0x65, 0x72, 0x20,
|
||||
0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x70, 0x6C, 0x20, 0x61,
|
||||
0x66, 0x74, 0x65, 0x72, 0x20, 0x72, 0x75, 0x6E, 0x6E, 0x69,
|
||||
0x6E, 0x67, 0x20, 0x61, 0x6C, 0x6C, 0x20, 0x73, 0x63, 0x72,
|
||||
0x69, 0x70, 0x74, 0x73, 0x0A, 0x20, 0x20, 0x2D, 0x70, 0x20,
|
||||
0x4B, 0x65, 0x65, 0x70, 0x20, 0x6F, 0x6E, 0x20, 0x65, 0x78,
|
||||
0x65, 0x63, 0x75, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x66,
|
||||
0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20,
|
||||
0x61, 0x20, 0x74, 0x6F, 0x70, 0x20, 0x6C, 0x65, 0x76, 0x65,
|
||||
0x6C, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x20, 0x28, 0x70,
|
||||
0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6E, 0x74, 0x29,
|
||||
0x0A, 0x20, 0x20, 0x2D, 0x2D, 0x20, 0x53, 0x74, 0x6F, 0x70,
|
||||
0x20, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x69, 0x6E, 0x67, 0x20,
|
||||
0x6F, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x60, 0x29, 0x0A,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x28, 0x6F, 0x73, 0x2E, 0x65, 0x78, 0x69, 0x74, 0x20,
|
||||
0x30, 0x29, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x31, 0x29, 0x0A, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x22, 0x76, 0x22, 0x20, 0x28, 0x66, 0x6E, 0x20,
|
||||
0x5B, 0x5D, 0x20, 0x28, 0x70, 0x72, 0x69, 0x6E, 0x74, 0x20,
|
||||
0x56, 0x45, 0x52, 0x53, 0x49, 0x4F, 0x4E, 0x29, 0x20, 0x28,
|
||||
0x6F, 0x73, 0x2E, 0x65, 0x78, 0x69, 0x74, 0x20, 0x30, 0x29,
|
||||
0x20, 0x31, 0x29, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22,
|
||||
0x73, 0x22, 0x20, 0x28, 0x66, 0x6E, 0x20, 0x5B, 0x5D, 0x20,
|
||||
0x28, 0x3A, 0x3D, 0x20, 0x2A, 0x72, 0x61, 0x77, 0x2D, 0x73,
|
||||
0x74, 0x64, 0x69, 0x6E, 0x2A, 0x20, 0x74, 0x72, 0x75, 0x65,
|
||||
0x29, 0x20, 0x28, 0x3A, 0x3D, 0x20, 0x2A, 0x73, 0x68, 0x6F,
|
||||
0x75, 0x6C, 0x64, 0x2D, 0x72, 0x65, 0x70, 0x6C, 0x2A, 0x20,
|
||||
0x74, 0x72, 0x75, 0x65, 0x29, 0x20, 0x31, 0x29, 0x0A, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x22, 0x72, 0x22, 0x20, 0x28, 0x66,
|
||||
0x6E, 0x20, 0x5B, 0x5D, 0x20, 0x28, 0x3A, 0x3D, 0x20, 0x2A,
|
||||
0x73, 0x68, 0x6F, 0x75, 0x6C, 0x64, 0x2D, 0x72, 0x65, 0x70,
|
||||
0x6C, 0x2A, 0x20, 0x74, 0x72, 0x75, 0x65, 0x29, 0x20, 0x31,
|
||||
0x29, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x70, 0x22,
|
||||
0x20, 0x28, 0x66, 0x6E, 0x20, 0x5B, 0x5D, 0x20, 0x28, 0x3A,
|
||||
0x3D, 0x20, 0x2A, 0x65, 0x78, 0x69, 0x74, 0x2D, 0x6F, 0x6E,
|
||||
0x2D, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x2A, 0x20, 0x66, 0x61,
|
||||
0x6C, 0x73, 0x65, 0x29, 0x20, 0x31, 0x29, 0x0A, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x22, 0x2D, 0x22, 0x20, 0x28, 0x66, 0x6E,
|
||||
0x20, 0x5B, 0x5D, 0x20, 0x28, 0x3A, 0x3D, 0x20, 0x2A, 0x68,
|
||||
0x61, 0x6E, 0x64, 0x6C, 0x65, 0x6F, 0x70, 0x74, 0x73, 0x2A,
|
||||
0x20, 0x66, 0x61, 0x6C, 0x73, 0x65, 0x29, 0x20, 0x31, 0x29,
|
||||
0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x65, 0x22, 0x20,
|
||||
0x28, 0x66, 0x6E, 0x20, 0x5B, 0x69, 0x5D, 0x20, 0x0A, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x28, 0x3A, 0x3D, 0x20, 0x2A, 0x6E, 0x6F, 0x2D, 0x66, 0x69,
|
||||
0x6C, 0x65, 0x2A, 0x20, 0x66, 0x61, 0x6C, 0x73, 0x65, 0x29,
|
||||
0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x28, 0x65, 0x76, 0x61, 0x6C, 0x20, 0x28, 0x67,
|
||||
0x65, 0x74, 0x20, 0x61, 0x72, 0x67, 0x73, 0x20, 0x28, 0x2B,
|
||||
0x20, 0x69, 0x20, 0x31, 0x29, 0x29, 0x29, 0x0A, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x32,
|
||||
0x29, 0x7D, 0x29, 0x0A, 0x0A, 0x20, 0x20, 0x28, 0x64, 0x65,
|
||||
0x66, 0x6E, 0x2D, 0x20, 0x64, 0x6F, 0x68, 0x61, 0x6E, 0x64,
|
||||
0x6C, 0x65, 0x72, 0x20, 0x5B, 0x6E, 0x20, 0x69, 0x5D, 0x0A,
|
||||
0x20, 0x20, 0x20, 0x20, 0x28, 0x64, 0x65, 0x66, 0x20, 0x68,
|
||||
0x20, 0x28, 0x67, 0x65, 0x74, 0x20, 0x68, 0x61, 0x6E, 0x64,
|
||||
0x6C, 0x65, 0x72, 0x73, 0x20, 0x6E, 0x29, 0x29, 0x0A, 0x20,
|
||||
0x20, 0x20, 0x20, 0x28, 0x69, 0x66, 0x20, 0x68, 0x20, 0x28,
|
||||
0x68, 0x20, 0x69, 0x29, 0x20, 0x28, 0x70, 0x72, 0x69, 0x6E,
|
||||
0x74, 0x20, 0x22, 0x75, 0x6E, 0x6B, 0x6E, 0x6F, 0x77, 0x6E,
|
||||
0x20, 0x66, 0x6C, 0x61, 0x67, 0x20, 0x2D, 0x22, 0x20, 0x6E,
|
||||
0x29, 0x29, 0x29, 0x0A, 0x0A, 0x20, 0x20, 0x23, 0x20, 0x50,
|
||||
0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 0x20, 0x61, 0x72, 0x67,
|
||||
0x75, 0x6D, 0x65, 0x6E, 0x74, 0x73, 0x0A, 0x20, 0x20, 0x28,
|
||||
0x76, 0x61, 0x72, 0x20, 0x69, 0x20, 0x31, 0x29, 0x0A, 0x20,
|
||||
0x20, 0x28, 0x64, 0x65, 0x66, 0x20, 0x6C, 0x65, 0x6E, 0x61,
|
||||
0x72, 0x67, 0x73, 0x20, 0x28, 0x6C, 0x65, 0x6E, 0x67, 0x74,
|
||||
0x68, 0x20, 0x61, 0x72, 0x67, 0x73, 0x29, 0x29, 0x0A, 0x20,
|
||||
0x20, 0x28, 0x77, 0x68, 0x69, 0x6C, 0x65, 0x20, 0x28, 0x3C,
|
||||
0x20, 0x69, 0x20, 0x6C, 0x65, 0x6E, 0x61, 0x72, 0x67, 0x73,
|
||||
0x29, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x28, 0x64, 0x65, 0x66,
|
||||
0x20, 0x61, 0x72, 0x67, 0x20, 0x28, 0x67, 0x65, 0x74, 0x20,
|
||||
0x61, 0x72, 0x67, 0x73, 0x20, 0x69, 0x29, 0x29, 0x0A, 0x20,
|
||||
0x20, 0x20, 0x20, 0x28, 0x69, 0x66, 0x20, 0x28, 0x61, 0x6E,
|
||||
0x64, 0x20, 0x2A, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x6F,
|
||||
0x70, 0x74, 0x73, 0x2A, 0x20, 0x28, 0x3D, 0x20, 0x22, 0x2D,
|
||||
0x22, 0x20, 0x28, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x2E,
|
||||
0x73, 0x6C, 0x69, 0x63, 0x65, 0x20, 0x61, 0x72, 0x67, 0x20,
|
||||
0x30, 0x20, 0x31, 0x29, 0x29, 0x29, 0x0A, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x28, 0x2B, 0x3D, 0x20, 0x69, 0x20, 0x28,
|
||||
0x64, 0x6F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x20,
|
||||
0x28, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x2E, 0x73, 0x6C,
|
||||
0x69, 0x63, 0x65, 0x20, 0x61, 0x72, 0x67, 0x20, 0x31, 0x20,
|
||||
0x32, 0x29, 0x20, 0x69, 0x29, 0x29, 0x0A, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x28, 0x64, 0x6F, 0x0A, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x3A, 0x3D, 0x20, 0x2A,
|
||||
0x6E, 0x6F, 0x2D, 0x66, 0x69, 0x6C, 0x65, 0x2A, 0x20, 0x66,
|
||||
0x61, 0x6C, 0x73, 0x65, 0x29, 0x0A, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x28, 0x69, 0x6D, 0x70, 0x6F, 0x72,
|
||||
0x74, 0x2A, 0x20, 0x5F, 0x65, 0x6E, 0x76, 0x20, 0x61, 0x72,
|
||||
0x67, 0x20, 0x3A, 0x65, 0x78, 0x69, 0x74, 0x20, 0x2A, 0x65,
|
||||
0x78, 0x69, 0x74, 0x2D, 0x6F, 0x6E, 0x2D, 0x65, 0x72, 0x72,
|
||||
0x6F, 0x72, 0x2A, 0x29, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x28, 0x2B, 0x2B, 0x20, 0x69, 0x29, 0x29,
|
||||
0x29, 0x29, 0x0A, 0x0A, 0x20, 0x20, 0x28, 0x77, 0x68, 0x65,
|
||||
0x6E, 0x20, 0x28, 0x6F, 0x72, 0x20, 0x2A, 0x73, 0x68, 0x6F,
|
||||
0x75, 0x6C, 0x64, 0x2D, 0x72, 0x65, 0x70, 0x6C, 0x2A, 0x20,
|
||||
0x2A, 0x6E, 0x6F, 0x2D, 0x66, 0x69, 0x6C, 0x65, 0x2A, 0x29,
|
||||
0x20, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x28, 0x69, 0x66, 0x20,
|
||||
0x2A, 0x72, 0x61, 0x77, 0x2D, 0x73, 0x74, 0x64, 0x69, 0x6E,
|
||||
0x2A, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x72,
|
||||
0x65, 0x70, 0x6C, 0x20, 0x6E, 0x69, 0x6C, 0x20, 0x69, 0x64,
|
||||
0x65, 0x6E, 0x74, 0x69, 0x74, 0x79, 0x29, 0x0A, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x28, 0x64, 0x6F, 0x0A, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x70, 0x72, 0x69,
|
||||
0x6E, 0x74, 0x20, 0x28, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67,
|
||||
0x20, 0x22, 0x44, 0x73, 0x74, 0x20, 0x22, 0x20, 0x56, 0x45,
|
||||
0x52, 0x53, 0x49, 0x4F, 0x4E, 0x20, 0x22, 0x20, 0x20, 0x43,
|
||||
0x6F, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28,
|
||||
0x43, 0x29, 0x20, 0x32, 0x30, 0x31, 0x37, 0x2D, 0x32, 0x30,
|
||||
0x31, 0x38, 0x20, 0x43, 0x61, 0x6C, 0x76, 0x69, 0x6E, 0x20,
|
||||
0x52, 0x6F, 0x73, 0x65, 0x22, 0x29, 0x29, 0x0A, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x72, 0x65, 0x70,
|
||||
0x6C, 0x20, 0x28, 0x66, 0x6E, 0x20, 0x5B, 0x62, 0x75, 0x66,
|
||||
0x20, 0x70, 0x5D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x28, 0x64, 0x65, 0x66, 0x20, 0x5B, 0x6C, 0x69, 0x6E, 0x65,
|
||||
0x5D, 0x20, 0x28, 0x70, 0x61, 0x72, 0x73, 0x65, 0x72, 0x2E,
|
||||
0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x70, 0x29, 0x29, 0x0A,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x64, 0x65, 0x66,
|
||||
0x20, 0x70, 0x72, 0x6F, 0x6D, 0x70, 0x74, 0x20, 0x28, 0x73,
|
||||
0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x22, 0x64, 0x73, 0x74,
|
||||
0x3A, 0x22, 0x20, 0x6C, 0x69, 0x6E, 0x65, 0x20, 0x22, 0x3A,
|
||||
0x22, 0x20, 0x28, 0x70, 0x61, 0x72, 0x73, 0x65, 0x72, 0x2E,
|
||||
0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x70, 0x29, 0x20, 0x22,
|
||||
0x3E, 0x20, 0x22, 0x29, 0x29, 0x0A, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x28, 0x67, 0x65, 0x74, 0x6C, 0x69, 0x6E, 0x65,
|
||||
0x20, 0x70, 0x72, 0x6F, 0x6D, 0x70, 0x74, 0x20, 0x62, 0x75,
|
||||
0x66, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x0A
|
||||
};
|
||||
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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_STRBINSEARCH_H_defined
|
||||
#define DST_STRBINSEARCH_H_defined
|
||||
|
||||
/* 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;
|
||||
const char *t = (const char *)tab;
|
||||
while (low < hi) {
|
||||
size_t mid = low + ((hi - low) / 2);
|
||||
const char **item = (const char **)(t + 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;
|
||||
}
|
||||
|
||||
#endif
|
@ -1,4 +1,5 @@
|
||||
# Copyright 2017-2018 (C) Calvin Rose
|
||||
(table.setproto @{ 1 2} @{})
|
||||
(do
|
||||
|
||||
(var *should-repl* :private false)
|
||||
|
@ -83,8 +83,6 @@ https://github.com/antirez/linenoise/blob/master/linenoise.c
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <headerlibs/vector.h>
|
||||
|
||||
/* static state */
|
||||
#define DST_LINE_MAX 1024
|
||||
#define DST_HISTORY_MAX 100
|
||||
@ -95,7 +93,8 @@ static char buf[DST_LINE_MAX];
|
||||
static int len = 0;
|
||||
static int pos = 0;
|
||||
static int cols = 80;
|
||||
static char **history = NULL;
|
||||
static char *history[DST_HISTORY_MAX];
|
||||
static int history_count = 0;
|
||||
static int historyi = 0;
|
||||
static struct termios termios_start;
|
||||
|
||||
@ -238,7 +237,7 @@ static int insert(char c) {
|
||||
}
|
||||
|
||||
static void historymove(int delta) {
|
||||
if (dst_v_count(history) > 1) {
|
||||
if (history_count > 1) {
|
||||
free(history[historyi]);
|
||||
history[historyi] = sdup(buf);
|
||||
|
||||
@ -246,8 +245,8 @@ static void historymove(int delta) {
|
||||
if (historyi < 0) {
|
||||
historyi = 0;
|
||||
return;
|
||||
} else if (historyi >= dst_v_count(history)) {
|
||||
historyi = dst_v_count(history) - 1;
|
||||
} else if (historyi >= history_count) {
|
||||
historyi = history_count - 1;
|
||||
return;
|
||||
}
|
||||
strncpy(buf, history[historyi], DST_LINE_MAX);
|
||||
@ -262,9 +261,9 @@ static void addhistory() {
|
||||
int i, len;
|
||||
char *newline = sdup(buf);
|
||||
if (!newline) return;
|
||||
len = dst_v_count(history);
|
||||
len = history_count;
|
||||
if (len < DST_HISTORY_MAX) {
|
||||
dst_v_push(history, newline);
|
||||
history[history_count++] = newline;
|
||||
len++;
|
||||
} else {
|
||||
free(history[DST_HISTORY_MAX - 1]);
|
||||
@ -429,9 +428,8 @@ void dst_line_init() {
|
||||
void dst_line_deinit() {
|
||||
int i;
|
||||
norawmode();
|
||||
for (i = 0; i < dst_v_count(history); i++)
|
||||
for (i = 0; i < history_count; i++)
|
||||
free(history[i]);
|
||||
dst_v_free(history);
|
||||
historyi = 0;
|
||||
}
|
||||
|
||||
|
@ -21,9 +21,8 @@
|
||||
*/
|
||||
|
||||
#include <dst/dst.h>
|
||||
#include <dst/dstcompile.h>
|
||||
|
||||
#include "clientinit.gen.h"
|
||||
#include <generated/init.h>
|
||||
#include "line.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
Loading…
Reference in New Issue
Block a user