1
0
mirror of https://github.com/janet-lang/janet synced 2024-11-17 14:14:49 +00:00

New sourcemaps v1.

This commit is contained in:
Calvin Rose 2018-06-28 23:36:31 -04:00
parent 23dcfb986e
commit bb406133de
25 changed files with 1118 additions and 677 deletions

574
3 Normal file
View File

@ -0,0 +1,574 @@
/*
* 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 1
#define DST_FUNCDEF_FLAG_NEEDSENV 4
struct DstSourceMapping {
int32_t start;
int32_t end;
};
/* 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 *sourcepath;
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[];
};
/* Parser types */
typedef struct {
Dst key;
int32_t start;
int32_t end;
} DstParseKV;
typedef struct {
DstParseKV *kvs;
int32_t capacity;
int32_t count;
} DstParseMap;
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;
const uint8_t *sourcelink;
DstParseState *states;
uint8_t *buf;
DstParseMap map; /* optional map */
size_t argcount;
size_t argcap;
size_t statecount;
size_t statecap;
size_t bufcount;
size_t bufcap;
size_t index;
int lookback;
int flags;
};
/* 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 */

View File

@ -62,6 +62,7 @@ src/core/marsh.c
src/core/math.c
src/core/native.c
src/core/os.c
src/core/parse.c
src/core/string.c
src/core/strtod.c
src/core/struct.c
@ -87,11 +88,6 @@ src/mainclient/line.c
src/mainclient/line.h
)
set(PARSER_SOURCES
src/parser/ast.c
src/parser/parse.c
)
set(TESTLIB_SOURCES
src/testlib/testlib.c
)
@ -101,7 +97,6 @@ ${ASSEMBLER_SOURCES}
${COMPILER_SOURCES}
${CORE_SOURCES}
${MAINCLIENT_SOURCES}
${PARSER_SOURCES}
)
# Set Public headers
@ -112,7 +107,6 @@ src/include/dst/dstcompile.h
src/include/dst/dstconfig.h
src/include/dst/dstcorelib.h
src/include/dst/dstopcodes.h
src/include/dst/dstparse.h
src/include/dst/dsttypes.h
)

View File

@ -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 -s -O2
CLIBS=-lm -ldl
PREFIX=/usr/local
DST_TARGET=dst
@ -60,7 +60,6 @@ DST_ASM_SOURCES=$(sort $(wildcard src/assembler/*.c))
DST_COMPILER_SOURCES=$(sort $(wildcard src/compiler/*.c))
DST_CORE_SOURCES=$(sort $(wildcard src/core/*.c))
DST_MAINCLIENT_SOURCES=$(sort $(wildcard src/mainclient/*.c))
DST_PARSER_SOURCES=$(sort $(wildcard src/parser/*.c))
all: $(DST_TARGET) $(DST_LIBRARY)
@ -88,8 +87,7 @@ src/compiler/dststlbootstrap.gen.h: src/compiler/boot.dst xxd
DST_LIB_SOURCES=$(DST_ASM_SOURCES) \
$(DST_COMPILER_SOURCES) \
$(DST_CONTEXT_SOURCES) \
$(DST_CORE_SOURCES) \
$(DST_PARSER_SOURCES)
$(DST_CORE_SOURCES)
DST_ALL_SOURCES=$(DST_LIB_SOURCES) \
$(DST_MAINCLIENT_SOURCES)
@ -140,22 +138,22 @@ natives: $(DST_TARGET)
#################
clean:
rm $(DST_TARGET) || true
rm src/**/*.o || true
rm vgcore.* || true
rm $(DST_GENERATED_HEADERS) || true
-rm $(DST_TARGET)
-rm src/**/*.o
-rm vgcore.*
-rm $(DST_GENERATED_HEADERS)
install: $(DST_TARGET)
cp $(DST_TARGET) $(BINDIR)/$(DST_TARGET)
mkdir -p $(INCLUDEDIR)
cp $(DST_HEADERS) $(INCLUDEDIR)
cp $(DST_LIBRARY) $(LIBDIR)/$(DST_LIBRARY)
ldconfig
-ldconfig
uninstall:
rm $(BINDIR)/$(DST_TARGET)
rm $(LIBDIR)/$(DST_LIBRARY)
rm -rf $(INCLUDEDIR)
ldconfig
-rm $(BINDIR)/$(DST_TARGET)
-rm $(LIBDIR)/$(DST_LIBRARY)
-rm -rf $(INCLUDEDIR)
-ldconfig
.PHONY: clean install repl debug valgrind test valtest install uninstall

View File

@ -548,10 +548,6 @@ static DstAssembleResult dst_asm1(DstAssembler *parent, Dst source, int flags) {
x = dst_get(s, dst_csymbolv("source"));
if (dst_checktype(x, DST_STRING)) def->source = dst_unwrap_string(x);
/* Check source path */
x = dst_get(s, dst_csymbolv("sourcepath"));
if (dst_checktype(x, DST_STRING)) def->sourcepath = dst_unwrap_string(x);
/* Create slot aliases */
x = dst_get(s, dst_csymbolv("slots"));
if (dst_seq_view(x, &arr, &count)) {
@ -836,10 +832,6 @@ Dst dst_disasm(DstFuncDef *def) {
DstTable *ret = dst_table(10);
dst_table_put(ret, dst_csymbolv("arity"), dst_wrap_integer(def->arity));
dst_table_put(ret, dst_csymbolv("bytecode"), dst_wrap_array(bcode));
if (NULL != def->sourcepath) {
dst_table_put(ret, dst_csymbolv("sourcepath"),
dst_wrap_string(def->sourcepath));
}
if (NULL != def->source) {
dst_table_put(ret, dst_csymbolv("source"), dst_wrap_string(def->source));
}

View File

@ -16,7 +16,7 @@
(fn [name & more]
(def len (length more))
(def fstart (fn recur [i]
(def ith (ast.unwrap1 (get more i)))
(def {i ith} more)
(def t (type ith))
(def tuple? (= t :tuple))
(def array? (= t :array))
@ -189,7 +189,7 @@ evaluates to 10."
has an odd number of arguments, the last is the default expression.
If no match is found, returns nil"
[dispatch & pairs]
(def atm (atomic? (ast.unwrap1 dispatch)))
(def atm (atomic? dispatch))
(def sym (if atm dispatch (gensym)))
(defn aux [i]
(def restlen (- (length pairs) i))
@ -209,15 +209,14 @@ If no match is found, returns nil"
assigned as if with def, and the body of the let form returns the last
value."
[bindings & body]
(def head (ast.unwrap1 bindings))
(if (odd? (length head)) (error "expected even number of bindings to let"))
(def len (length head))
(if (odd? (length bindings)) (error "expected even number of bindings to let"))
(def len (length bindings))
(var i 0)
(var accum @['do])
(while (< i len)
(array.push accum (tuple 'def
(get head i)
(get head (+ 1 i))))
(get bindings i)
(get bindings (+ 1 i))))
(+= i 2))
(array.concat accum body)
(apply1 tuple accum))
@ -225,21 +224,19 @@ value."
(defmacro loop
"A general purpose loop macro."
[head & body]
(def head1 (ast.unwrap1 head))
(def len (length head1))
(def len (length head))
(defn doone
[i preds]
(default preds @['and])
(if (>= i len)
(tuple.prepend body 'do)
(do
(def bindings (get head1 i))
(def ubindings (ast.unwrap1 bindings))
(def verb (ast.unwrap1 (get head1 (+ i 1))))
(def object (ast.unwrap1 (get head1 (+ i 2))))
(if (keyword? ubindings)
(def bindings (get head i))
(def verb (get head (+ i 1)))
(def object (get head (+ i 2)))
(if (keyword? bindings)
(switch
ubindings
bindings
:while (do
(array.push preds verb)
(doone (+ i 2) preds))
@ -249,7 +246,7 @@ value."
(switch
verb
:range (do
(def [start end _inc] (ast.unwrap1 object))
(def [start end _inc] object)
(def inc (if _inc _inc 1))
(def endsym (gensym))
(def preds @['and (tuple < bindings endsym)])
@ -318,7 +315,7 @@ evaluates to true."
(if
(>= (inc i) len) fi
(do
(if (atomic? (ast.unwrap1 fi))
(if (atomic? fi)
(tuple 'if fi fi (aux (inc i)))
(do
(def $fi (gensym))
@ -335,7 +332,6 @@ evaluates to true."
all the forms with let and evaluates the first expression else
evaluates the second"
[bindings tru fal]
(def bindings (ast.unwrap1 bindings))
(def len (length bindings))
(if (zero? len) (error "expected at least 1 binding"))
(if (odd? len) (error "expected an even number of bindings"))
@ -345,7 +341,7 @@ evaluates to true."
(if (>= i len)
tru
(do
(def atm (atomic? (ast.unwrap1 bl)))
(def atm (atomic? bl))
(def sym (if atm bl (gensym)))
(if atm
# Simple binding
@ -605,8 +601,7 @@ the predicate, and abort on first failure."
in form, and inserts the modified firsts form into the second form
in the same manner, and so on. Useful for expressing pipelines of data."
[x & forms]
(defn fop [last nextform]
(def n (ast.unwrap1 nextform))
(defn fop [last n]
(def [h t] (if (= :tuple (type n))
[tuple (get n 0) (array.slice n 1)]
[tuple n @[]]))
@ -619,8 +614,7 @@ in the same manner, and so on. Useful for expressing pipelines of data."
in form, and inserts the modified firsts form into the second form
in the same manner, and so on. Useful for expressing pipelines of data."
[x & forms]
(defn fop [last nextform]
(def n (ast.unwrap1 nextform))
(defn fop [last n]
(def [h t] (if (= :tuple (type n))
[tuple (get n 0) (array.slice n 1)]
[tuple n @[]]))
@ -865,7 +859,6 @@ to call on any table. Does not print table prototype information."
(def specs {
':= expandlast
'ast-quote identity
'def expandlast
'do expandall
'fn expandfn
@ -894,13 +887,12 @@ to call on any table. Does not print table prototype information."
(def res (dotable t))
(if (= (table.to-struct res) (table.to-struct t)) t res))
(def ux (ast.unwrap1 x))
(switch (type ux)
:tuple (dotup ux)
:array (doarray* ux)
:struct (table.to-struct (dotable ux))
:table (dotable* ux)
ux))
(switch (type x)
:tuple (dotup x)
:array (doarray* x)
:struct (table.to-struct (dotable x))
:table (dotable* x)
x))
(defn macroexpand
"Expand macros completely."
@ -1013,13 +1005,20 @@ onvalue."
:pc pc
:c c
:name name
:source source
:source-start source-start
:source-end source-end
} :in st]
(file.write stdout " in")
(when c (file.write stdout " cfunction"))
(if name
(file.write stdout (string " " name))
(when func (file.write stdout (string " " func))))
(when pc (file.write stdout (string " (pc=" pc ")")))
(file.write stdout " " name)
(when func (file.write stdout " " func)))
(if source (file.write stdout " [" source "]"))
(cond
source-start (file.write stdout " at byte range ("
(string source-start) ":" (string source-end) ")")
pc (file.write stdout " at (pc=" (string pc) ")"))
(when tail (file.write stdout " (tailcall)"))
(file.write stdout "\n"))))
@ -1145,13 +1144,12 @@ returned from compiling and running the file."
symbols into the current environment, prepending a given prefix as needed.
(use the :as or :prefix option to set a prefix). If no prefix is provided,
use the name of the module as a prefix."
(def upath (string (ast.unwrap path)))
(def argm (map (fn [x]
(if (and (symbol? x) (= (get x 0) 58))
x
(string x)))
(ast.unwrap args)))
(apply tuple import* '_env upath argm))
args))
(apply tuple import* '_env (string path) argm))
(defn repl [getchunk onvalue onerr]
"Run a repl. The first parameter is an optional function to call to

View File

@ -29,13 +29,12 @@
/* This logic needs to be expanded for more types */
/* Check if a function received only numbers */
static int numbers(DstFopts opts, DstAst *ast, DstSM *args) {
static int numbers(DstFopts opts, DstSlot *args) {
int32_t i;
int32_t len = dst_v_count(args);
(void) opts;
(void) ast;
for (i = 0; i < len; i++) {
DstSlot s = args[i].slot;
DstSlot s = args[i];
if (s.flags & DST_SLOT_CONSTANT) {
Dst c = s.constant;
if (!dst_checktype(c, DST_INTEGER) &&
@ -48,34 +47,33 @@ static int numbers(DstFopts opts, DstAst *ast, DstSM *args) {
return 1;
}
/* Fold constants in a DstSM */
static DstSM *foldc(DstSM *sms, DstAst *ast, Dst (*fn)(Dst lhs, Dst rhs)) {
/* Fold constants in a DstSlot [] */
static DstSlot *foldc(DstSlot *slots, Dst (*fn)(Dst lhs, Dst rhs)) {
int32_t ccount;
int32_t i;
DstSM *ret = NULL;
DstSM sm;
DstSlot *ret = NULL;
DstSlot s;
Dst current;
for (ccount = 0; ccount < dst_v_count(sms); ccount++) {
if (sms[ccount].slot.flags & DST_SLOT_CONSTANT) continue;
for (ccount = 0; ccount < dst_v_count(slots); ccount++) {
if (slots[ccount].flags & DST_SLOT_CONSTANT) continue;
break;
}
if (ccount < 2) return sms;
current = fn(sms[0].slot.constant, sms[1].slot.constant);
if (ccount < 2) return slots;
current = fn(slots[0].constant, slots[1].constant);
for (i = 2; i < ccount; i++) {
Dst nextarg = sms[i].slot.constant;
Dst nextarg = slots[i].constant;
current = fn(current, nextarg);
}
sm.slot = dstc_cslot(current);
sm.map = ast;
dst_v_push(ret, sm);
for (; i < dst_v_count(sms); i++) {
dst_v_push(ret, sms[i]);
s = dstc_cslot(current);
dst_v_push(ret, s);
for (; i < dst_v_count(slots); i++) {
dst_v_push(ret, slots[i]);
}
return ret;
}
/* Emit a series of instructions instead of a function call to a math op */
static DstSlot opreduce(DstFopts opts, DstAst *ast, DstSM *args, int op) {
static DstSlot opreduce(DstFopts opts, DstSlot *args, int op) {
DstCompiler *c = opts.compiler;
int32_t i, len;
int32_t op1, op2;
@ -84,42 +82,41 @@ static DstSlot opreduce(DstFopts opts, DstAst *ast, DstSM *args, int op) {
if (len == 0) {
return dstc_cslot(dst_wrap_integer(0));
} else if (len == 1) {
return args[0].slot;
return args[0];
}
t = dstc_gettarget(opts);
/* Compile initial two arguments */
op1 = dstc_preread(c, args[0].map, 0xFF, 1, args[0].slot);
op2 = dstc_preread(c, args[1].map, 0xFF, 2, args[1].slot);
dstc_emit(c, ast, (t.index << 8) | (op1 << 16) | (op2 << 24) | op);
dstc_postread(c, args[0].slot, op1);
dstc_postread(c, args[1].slot, op2);
op1 = dstc_preread(c, 0xFF, 1, args[0]);
op2 = dstc_preread(c, 0xFF, 2, args[1]);
dstc_emit(c, (t.index << 8) | (op1 << 16) | (op2 << 24) | op);
dstc_postread(c, args[0], op1);
dstc_postread(c, args[1], op2);
for (i = 2; i < len; i++) {
op1 = dstc_preread(c, args[i].map, 0xFF, 1, args[i].slot);
dstc_emit(c, ast, (t.index << 8) | (t.index << 16) | (op1 << 24) | op);
dstc_postread(c, args[i].slot, op1);
op1 = dstc_preread(c, 0xFF, 1, args[i]);
dstc_emit(c, (t.index << 8) | (t.index << 16) | (op1 << 24) | op);
dstc_postread(c, args[i], op1);
}
return t;
}
static DstSlot add(DstFopts opts, DstAst *ast, DstSM *args) {
DstSM *newargs = foldc(args, ast, dst_op_add);
DstSlot ret = opreduce(opts, ast, newargs, DOP_ADD);
static DstSlot add(DstFopts opts, DstSlot *args) {
DstSlot *newargs = foldc(args, dst_op_add);
DstSlot ret = opreduce(opts, newargs, DOP_ADD);
if (newargs != args) dstc_freeslots(opts.compiler, newargs);
return ret;
}
static DstSlot sub(DstFopts opts, DstAst *ast, DstSM *args) {
DstSM *newargs;
static DstSlot sub(DstFopts opts, DstSlot *args) {
DstSlot *newargs;
if (dst_v_count(args) == 1) {
newargs = NULL;
dst_v_push(newargs, args[0]);
dst_v_push(newargs, args[0]);
newargs[0].slot = dstc_cslot(dst_wrap_integer(0));
newargs[0].map = ast;
newargs[0] = dstc_cslot(dst_wrap_integer(0));
} else {
newargs = foldc(args, ast, dst_op_subtract);
newargs = foldc(args, dst_op_subtract);
}
DstSlot ret = opreduce(opts, ast, newargs, DOP_SUBTRACT);
DstSlot ret = opreduce(opts, newargs, DOP_SUBTRACT);
if (newargs != args) dstc_freeslots(opts.compiler, newargs);
return ret;
}

View File

@ -21,7 +21,6 @@
*/
#include <dst/dst.h>
#include <dst/dstparse.h>
#include <dst/dstcorelib.h>
#include "compile.h"
@ -31,6 +30,34 @@
#undef DST_V_DEF_COPYMEM
#undef DST_V_DEF_FLATTENMEM
void dstc_ast_push(DstCompiler *c, Dst x) {
DstSourceMapping mapping;
if (c->parser) {
int found = dst_parser_lookup(c->parser, x, &mapping);
if (!found) {
/* Duplicate last value */
if (dst_v_count(c->ast_stack)) {
mapping = dst_v_last(c->ast_stack);
} else {
mapping.start = -1;
mapping.end = -1;
}
}
} else {
mapping.start = -1;
mapping.end = -1;
}
dst_v_push(c->ast_stack, mapping);
}
void dstc_ast_pop(DstCompiler *c) {
dst_v_pop(c->ast_stack);
}
DstSourceMapping dstc_ast(DstCompiler *c) {
return dst_v_last(c->ast_stack);
}
DstFopts dstc_fopts_default(DstCompiler *c) {
DstFopts ret;
ret.compiler = c;
@ -40,25 +67,18 @@ DstFopts dstc_fopts_default(DstCompiler *c) {
}
/* Throw an error with a dst string. */
void dstc_error(DstCompiler *c, DstAst *ast, const uint8_t *m) {
void dstc_error(DstCompiler *c, const uint8_t *m) {
/* Don't override first error */
if (c->result.status == DST_COMPILE_ERROR) {
return;
}
if (NULL != ast) {
c->result.error_start = ast->source_start;
c->result.error_end = ast->source_end;
} else {
c->result.error_start = -1;
c->result.error_end = -1;
}
c->result.status = DST_COMPILE_ERROR;
c->result.error = m;
}
/* Throw an error with a message in a cstring */
void dstc_cerror(DstCompiler *c, DstAst *ast, const char *m) {
dstc_error(c, ast, dst_cstring(m));
void dstc_cerror(DstCompiler *c, const char *m) {
dstc_error(c, dst_cstring(m));
}
/* Check error */
@ -239,7 +259,6 @@ DstSlot dstc_cslot(Dst x) {
/* Allow searching for symbols. Return information about the symbol */
DstSlot dstc_resolve(
DstCompiler *c,
DstAst *ast,
const uint8_t *sym) {
DstSlot ret = dstc_cslot(dst_wrap_nil());
@ -275,7 +294,7 @@ DstSlot dstc_resolve(
switch (btype) {
default:
case DST_BINDING_NONE:
dstc_error(c, ast, dst_formatc("unknown symbol %q", sym));
dstc_error(c, dst_formatc("unknown symbol %q", sym));
return dstc_cslot(dst_wrap_nil());
case DST_BINDING_DEF:
case DST_BINDING_MACRO: /* Macro should function like defs when not in calling pos */
@ -341,13 +360,13 @@ DstSlot dstc_resolve(
}
/* Emit a raw instruction with source mapping. */
void dstc_emit(DstCompiler *c, DstAst *ast, uint32_t instr) {
void dstc_emit(DstCompiler *c, uint32_t instr) {
dst_v_push(c->buffer, instr);
dst_v_push(c->mapbuffer, ast);
dst_v_push(c->mapbuffer, dstc_ast(c));
}
/* Add a constant to the current scope. Return the index of the constant. */
static int32_t dstc_const(DstCompiler *c, DstAst *ast, Dst x) {
static int32_t dstc_const(DstCompiler *c, Dst x) {
DstScope *scope = &dst_v_last(c->scopes);
int32_t i, len;
/* Get the topmost function scope */
@ -364,7 +383,7 @@ static int32_t dstc_const(DstCompiler *c, DstAst *ast, Dst x) {
}
/* Ensure not too many constsants. */
if (len >= 0xFFFF) {
dstc_cerror(c, ast, "too many constants");
dstc_cerror(c, "too many constants");
return 0;
}
dst_v_push(scope->consts, x);
@ -372,22 +391,22 @@ static int32_t dstc_const(DstCompiler *c, DstAst *ast, Dst x) {
}
/* Load a constant into a local slot */
static void dstc_loadconst(DstCompiler *c, DstAst *ast, Dst k, int32_t dest) {
static void dstc_loadconst(DstCompiler *c, Dst k, int32_t dest) {
switch (dst_type(k)) {
case DST_NIL:
dstc_emit(c, ast, (dest << 8) | DOP_LOAD_NIL);
dstc_emit(c, (dest << 8) | DOP_LOAD_NIL);
break;
case DST_TRUE:
dstc_emit(c, ast, (dest << 8) | DOP_LOAD_TRUE);
dstc_emit(c, (dest << 8) | DOP_LOAD_TRUE);
break;
case DST_FALSE:
dstc_emit(c, ast, (dest << 8) | DOP_LOAD_FALSE);
dstc_emit(c, (dest << 8) | DOP_LOAD_FALSE);
break;
case DST_INTEGER:
{
int32_t i = dst_unwrap_integer(k);
if (i <= INT16_MAX && i >= INT16_MIN) {
dstc_emit(c, ast,
dstc_emit(c,
(i << 16) |
(dest << 8) |
DOP_LOAD_INTEGER);
@ -398,8 +417,8 @@ static void dstc_loadconst(DstCompiler *c, DstAst *ast, Dst k, int32_t dest) {
default:
do_constant:
{
int32_t cindex = dstc_const(c, ast, k);
dstc_emit(c, ast,
int32_t cindex = dstc_const(c, k);
dstc_emit(c,
(cindex << 16) |
(dest << 8) |
DOP_LOAD_CONSTANT);
@ -412,7 +431,6 @@ static void dstc_loadconst(DstCompiler *c, DstAst *ast, Dst k, int32_t dest) {
* that can be used in an instruction. */
int32_t dstc_preread(
DstCompiler *c,
DstAst *ast,
int32_t max,
int nth,
DstSlot s) {
@ -424,24 +442,24 @@ int32_t dstc_preread(
if (s.flags & (DST_SLOT_CONSTANT | DST_SLOT_REF)) {
ret = dstc_lslotn(c, 0xFF, nth);
dstc_loadconst(c, ast, s.constant, ret);
dstc_loadconst(c, s.constant, ret);
/* If we also are a reference, deref the one element array */
if (s.flags & DST_SLOT_REF) {
dstc_emit(c, ast,
dstc_emit(c,
(ret << 16) |
(ret << 8) |
DOP_GET_INDEX);
}
} else if (s.envindex >= 0 || s.index > max) {
ret = dstc_lslotn(c, max, nth);
dstc_emit(c, ast,
dstc_emit(c,
((uint32_t)(s.index) << 24) |
((uint32_t)(s.envindex) << 16) |
((uint32_t)(ret) << 8) |
DOP_LOAD_UPVALUE);
} else if (s.index > max) {
ret = dstc_lslotn(c, max, nth);
dstc_emit(c, ast,
dstc_emit(c,
((uint32_t)(s.index) << 16) |
((uint32_t)(ret) << 8) |
DOP_MOVE_NEAR);
@ -478,7 +496,6 @@ int dstc_sequal(DstSlot lhs, DstSlot rhs) {
* be writeable (not a literal). */
void dstc_copy(
DstCompiler *c,
DstAst *ast,
DstSlot dest,
DstSlot src) {
int writeback = 0;
@ -488,7 +505,7 @@ void dstc_copy(
/* Can't write to constants */
if (dest.flags & DST_SLOT_CONSTANT) {
dstc_cerror(c, ast, "cannot write to constant");
dstc_cerror(c, "cannot write to constant");
return;
}
@ -511,21 +528,21 @@ void dstc_copy(
/* If dest is a near index, do some optimization */
if (dest.envindex < 0 && dest.index >= 0 && dest.index <= 0xFF) {
if (src.flags & DST_SLOT_CONSTANT) {
dstc_loadconst(c, ast, src.constant, dest.index);
dstc_loadconst(c, src.constant, dest.index);
} else if (src.flags & DST_SLOT_REF) {
dstc_loadconst(c, ast, src.constant, dest.index);
dstc_emit(c, ast,
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, ast,
dstc_emit(c,
(src.index << 24) |
(src.envindex << 16) |
(dest.index << 8) |
DOP_LOAD_UPVALUE);
} else {
dstc_emit(c, ast,
dstc_emit(c,
(src.index << 16) |
(dest.index << 8) |
DOP_MOVE_NEAR);
@ -536,15 +553,15 @@ void dstc_copy(
/* Process: src -> srclocal -> destlocal -> dest */
/* src -> srclocal */
srclocal = dstc_preread(c, ast, 0xFF, 1, src);
srclocal = dstc_preread(c, 0xFF, 1, src);
/* Pull down dest (find destlocal) */
if (dest.flags & DST_SLOT_REF) {
writeback = 1;
destlocal = srclocal;
reflocal = dstc_lslotn(c, 0xFF, 2);
dstc_emit(c, ast,
(dstc_const(c, ast, dest.constant) << 16) |
dstc_emit(c,
(dstc_const(c, dest.constant) << 16) |
(reflocal << 8) |
DOP_LOAD_CONSTANT);
} else if (dest.envindex >= 0) {
@ -559,7 +576,7 @@ void dstc_copy(
/* srclocal -> destlocal */
if (srclocal != destlocal) {
dstc_emit(c, ast,
dstc_emit(c,
((uint32_t)(srclocal) << 16) |
((uint32_t)(destlocal) << 8) |
DOP_MOVE_NEAR);
@ -567,18 +584,18 @@ void dstc_copy(
/* destlocal -> dest */
if (writeback == 1) {
dstc_emit(c, ast,
dstc_emit(c,
(destlocal << 16) |
(reflocal << 8) |
DOP_PUT_INDEX);
} else if (writeback == 2) {
dstc_emit(c, ast,
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, ast,
dstc_emit(c,
((uint32_t)(dest.index) << 16) |
((uint32_t)(destlocal) << 8) |
DOP_MOVE_FAR);
@ -592,13 +609,13 @@ void dstc_copy(
}
/* Generate the return instruction for a slot. */
DstSlot dstc_return(DstCompiler *c, DstAst *ast, DstSlot s) {
DstSlot dstc_return(DstCompiler *c, DstSlot s) {
if (!(s.flags & DST_SLOT_RETURNED)) {
if (s.flags & DST_SLOT_CONSTANT && dst_checktype(s.constant, DST_NIL)) {
dstc_emit(c, ast, DOP_RETURN_NIL);
dstc_emit(c, DOP_RETURN_NIL);
} else {
int32_t ls = dstc_preread(c, ast, 0xFFFF, 1, s);
dstc_emit(c, ast, DOP_RETURN | (ls << 8));
int32_t ls = dstc_preread(c, 0xFFFF, 1, s);
dstc_emit(c, DOP_RETURN | (ls << 8));
dstc_postread(c, s, ls);
}
s.flags |= DST_SLOT_RETURNED;
@ -624,77 +641,69 @@ DstSlot dstc_gettarget(DstFopts opts) {
}
/* Get a bunch of slots for function arguments */
DstSM *dstc_toslots(DstCompiler *c, const Dst *vals, int32_t len) {
DstSlot *dstc_toslots(DstCompiler *c, const Dst *vals, int32_t len) {
int32_t i;
DstSM *ret = NULL;
DstSlot *ret = NULL;
DstFopts subopts = dstc_fopts_default(c);
for (i = 0; i < len; i++) {
DstSM sm;
sm.slot = dstc_value(subopts, vals[i]);
sm.map = dst_ast_node(vals[i]);
dst_v_push(ret, sm);
dst_v_push(ret, dstc_value(subopts, vals[i]));
}
return ret;
}
/* Get a bunch of slots for function arguments */
DstSM *dstc_toslotskv(DstCompiler *c, Dst ds) {
DstSM *ret = NULL;
DstSlot *dstc_toslotskv(DstCompiler *c, Dst ds) {
DstSlot *ret = NULL;
const DstKV *kv = NULL;
DstFopts subopts = dstc_fopts_default(c);
while ((kv = dstc_next(ds, kv))) {
DstSM km, vm;
km.slot = dstc_value(subopts, kv->key);
km.map = dst_ast_node(kv->key);
vm.slot = dstc_value(subopts, kv->value);
vm.map = dst_ast_node(kv->value);
dst_v_push(ret, km);
dst_v_push(ret, vm);
dst_v_push(ret, dstc_value(subopts, kv->key));
dst_v_push(ret, dstc_value(subopts, kv->value));
}
return ret;
}
/* Push slots load via dstc_toslots. */
void dstc_pushslots(DstCompiler *c, DstAst *ast, DstSM *sms) {
void dstc_pushslots(DstCompiler *c, DstSlot *slots) {
int32_t i;
for (i = 0; i < dst_v_count(sms) - 2; i += 3) {
int32_t ls1 = dstc_preread(c, sms[i].map, 0xFF, 1, sms[i].slot);
int32_t ls2 = dstc_preread(c, sms[i + 1].map, 0xFF, 2, sms[i + 1].slot);
int32_t ls3 = dstc_preread(c, sms[i + 2].map, 0xFF, 3, sms[i + 2].slot);
dstc_emit(c, ast,
for (i = 0; i < dst_v_count(slots) - 2; i += 3) {
int32_t ls1 = dstc_preread(c, 0xFF, 1, slots[i]);
int32_t ls2 = dstc_preread(c, 0xFF, 2, slots[i + 1]);
int32_t ls3 = dstc_preread(c, 0xFF, 3, slots[i + 2]);
dstc_emit(c,
(ls3 << 24) |
(ls2 << 16) |
(ls1 << 8) |
DOP_PUSH_3);
dstc_postread(c, sms[i].slot, ls1);
dstc_postread(c, sms[i + 1].slot, ls2);
dstc_postread(c, sms[i + 2].slot, ls3);
dstc_postread(c, slots[i], ls1);
dstc_postread(c, slots[i + 1], ls2);
dstc_postread(c, slots[i + 2], ls3);
}
if (i == dst_v_count(sms) - 2) {
int32_t ls1 = dstc_preread(c, sms[i].map, 0xFF, 1, sms[i].slot);
int32_t ls2 = dstc_preread(c, sms[i + 1].map, 0xFFFF, 2, sms[i + 1].slot);
dstc_emit(c, ast,
if (i == dst_v_count(slots) - 2) {
int32_t ls1 = dstc_preread(c, 0xFF, 1, slots[i]);
int32_t ls2 = dstc_preread(c, 0xFFFF, 2, slots[i + 1]);
dstc_emit(c,
(ls2 << 16) |
(ls1 << 8) |
DOP_PUSH_2);
dstc_postread(c, sms[i].slot, ls1);
dstc_postread(c, sms[i + 1].slot, ls2);
} else if (i == dst_v_count(sms) - 1) {
int32_t ls1 = dstc_preread(c, sms[i].map, 0xFFFFFF, 1, sms[i].slot);
dstc_emit(c, ast,
dstc_postread(c, slots[i], ls1);
dstc_postread(c, slots[i + 1], ls2);
} else if (i == dst_v_count(slots) - 1) {
int32_t ls1 = dstc_preread(c, 0xFFFFFF, 1, slots[i]);
dstc_emit(c,
(ls1 << 8) |
DOP_PUSH);
dstc_postread(c, sms[i].slot, ls1);
dstc_postread(c, slots[i], ls1);
}
}
/* Free slots loaded via dstc_toslots */
void dstc_freeslots(DstCompiler *c, DstSM *sms) {
void dstc_freeslots(DstCompiler *c, DstSlot *slots) {
int32_t i;
for (i = 0; i < dst_v_count(sms); i++) {
dstc_freeslot(c, sms[i].slot);
for (i = 0; i < dst_v_count(slots); i++) {
dstc_freeslot(c, slots[i]);
}
dst_v_free(sms);
dst_v_free(slots);
}
/* Compile some code that will be thrown away. Used to ensure
@ -715,7 +724,7 @@ void dstc_throwaway(DstFopts opts, Dst x) {
}
/* Compile a call or tailcall instruction */
static DstSlot dstc_call(DstFopts opts, DstAst *ast, DstSM *sms, DstSlot fun) {
static DstSlot dstc_call(DstFopts opts, DstSlot *slots, DstSlot fun) {
DstSlot retslot;
int32_t localindex;
DstCompiler *c = opts.compiler;
@ -723,57 +732,57 @@ static DstSlot dstc_call(DstFopts opts, DstAst *ast, DstSM *sms, DstSlot fun) {
if (fun.flags & DST_SLOT_CONSTANT) {
if (dst_checktype(fun.constant, DST_CFUNCTION)) {
const DstCFunOptimizer *o = dstc_cfunopt(dst_unwrap_cfunction(fun.constant));
if (o && o->can_optimize(opts, ast, sms)) {
if (o && o->can_optimize(opts, slots)) {
specialized = 1;
retslot = o->optimize(opts, ast, sms);
retslot = o->optimize(opts, slots);
}
}
/* TODO dst function inlining (no c functions)*/
}
if (!specialized) {
dstc_pushslots(c, ast, sms);
localindex = dstc_preread(c, ast, 0xFF, 1, fun);
dstc_pushslots(c, slots);
localindex = dstc_preread(c, 0xFF, 1, fun);
if (opts.flags & DST_FOPTS_TAIL) {
dstc_emit(c, ast, (localindex << 8) | DOP_TAILCALL);
dstc_emit(c, (localindex << 8) | DOP_TAILCALL);
retslot = dstc_cslot(dst_wrap_nil());
retslot.flags = DST_SLOT_RETURNED;
} else {
retslot = dstc_gettarget(opts);
dstc_emit(c, ast, (localindex << 16) | (retslot.index << 8) | DOP_CALL);
dstc_emit(c, (localindex << 16) | (retslot.index << 8) | DOP_CALL);
}
dstc_postread(c, fun, localindex);
}
dstc_freeslots(c, sms);
dstc_freeslots(c, slots);
return retslot;
}
static DstSlot dstc_array(DstFopts opts, DstAst *ast, Dst x) {
static DstSlot dstc_array(DstFopts opts, Dst x) {
DstCompiler *c = opts.compiler;
DstArray *a = dst_unwrap_array(x);
return dstc_call(opts, ast,
return dstc_call(opts,
dstc_toslots(c, a->data, a->count),
dstc_cslot(dst_wrap_cfunction(dst_core_array)));
}
static DstSlot dstc_tablector(DstFopts opts, DstAst *ast, Dst x, DstCFunction cfun) {
static DstSlot dstc_tablector(DstFopts opts, Dst x, DstCFunction cfun) {
DstCompiler *c = opts.compiler;
return dstc_call(opts, ast, dstc_toslotskv(c, x), dstc_cslot(dst_wrap_cfunction(cfun)));
return dstc_call(opts, dstc_toslotskv(c, x), dstc_cslot(dst_wrap_cfunction(cfun)));
}
static DstSlot dstc_bufferctor(DstFopts opts, DstAst *ast, Dst x) {
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, ast,
return dstc_call(opts,
dstc_toslots(c, &onearg, 1),
dstc_cslot(dst_wrap_cfunction(dst_core_buffer)));
}
/* Compile a symbol */
DstSlot dstc_symbol(DstFopts opts, DstAst *ast, const uint8_t *sym) {
DstSlot dstc_symbol(DstFopts opts, const uint8_t *sym) {
if (dst_string_length(sym) && sym[0] != ':') {
/* Non keyword */
return dstc_resolve(opts.compiler, ast, sym);
return dstc_resolve(opts.compiler, sym);
} else {
/* Keyword */
return dstc_cslot(dst_wrap_symbol(sym));
@ -783,18 +792,16 @@ DstSlot dstc_symbol(DstFopts opts, DstAst *ast, const uint8_t *sym) {
/* Compile a single value */
DstSlot dstc_value(DstFopts opts, Dst x) {
DstSlot ret;
DstAst *ast;
DstCompiler *c = opts.compiler;
int macrorecur = 0;
opts.compiler->recursion_guard--;
ast = dst_ast_node(x);
x = dst_ast_unwrap1(x);
dstc_ast_push(c, x);
recur:
if (dstc_iserr(&opts)) {
return dstc_cslot(dst_wrap_nil());
}
if (opts.compiler->recursion_guard <= 0) {
dstc_cerror(opts.compiler, ast, "recursed too deeply");
dstc_cerror(opts.compiler, "recursed too deeply");
return dstc_cslot(dst_wrap_nil());
}
switch (dst_type(x)) {
@ -804,7 +811,7 @@ recur:
case DST_SYMBOL:
{
const uint8_t *sym = dst_unwrap_symbol(x);
ret = dstc_symbol(opts, ast, sym);
ret = dstc_symbol(opts, sym);
break;
}
case DST_TUPLE:
@ -820,12 +827,12 @@ recur:
ret = dstc_cslot(x);
} else {
/* Symbols could be specials */
headval = dst_ast_unwrap1(tup[0]);
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, ast, dst_tuple_length(tup) - 1, tup + 1);
ret = s->compile(opts, dst_tuple_length(tup) - 1, tup + 1);
compiled = 1;
} else {
/* Check macro */
@ -834,7 +841,7 @@ recur:
if (btype == DST_BINDING_MACRO &&
dst_checktype(macVal, DST_FUNCTION)) {
if (macrorecur++ > DST_RECURSION_GUARD) {
dstc_cerror(c, ast, "macro expansion recursed too deeply");
dstc_cerror(c, "macro expansion recursed too deeply");
return dstc_cslot(dst_wrap_nil());
} else {
DstFunction *f = dst_unwrap_function(macVal);
@ -843,7 +850,7 @@ recur:
dst_gcunlock(lock);
if (status != DST_SIGNAL_OK) {
const uint8_t *es = dst_formatc("error in macro expansion: %V", x);
dstc_error(c, ast, es);
dstc_error(c, es);
}
/* Tail recur on the value */
goto recur;
@ -856,35 +863,37 @@ recur:
subopts.flags = DST_FUNCTION | DST_CFUNCTION;
head = dstc_value(subopts, tup[0]);
/* Add compile function call */
ret = dstc_call(opts, ast, dstc_toslots(c, tup + 1, dst_tuple_length(tup) - 1), head);
ret = dstc_call(opts, dstc_toslots(c, tup + 1, dst_tuple_length(tup) - 1), head);
}
}
}
break;
case DST_ARRAY:
ret = dstc_array(opts, ast, x);
ret = dstc_array(opts, x);
break;
case DST_STRUCT:
ret = dstc_tablector(opts, ast, x, dst_core_struct);
ret = dstc_tablector(opts, x, dst_core_struct);
break;
case DST_TABLE:
ret = dstc_tablector(opts, ast, x, dst_core_table);
ret = dstc_tablector(opts, x, dst_core_table);
break;
case DST_BUFFER:
ret = dstc_bufferctor(opts, ast, x);
ret = dstc_bufferctor(opts, x);
break;
}
if (dstc_iserr(&opts)) {
return dstc_cslot(dst_wrap_nil());
}
if (opts.flags & DST_FOPTS_TAIL) {
ret = dstc_return(opts.compiler, ast, ret);
ret = dstc_return(opts.compiler, ret);
}
if (opts.flags & DST_FOPTS_HINT && !dstc_sequal(opts.hint, ret)) {
dstc_copy(opts.compiler, ast, opts.hint, ret);
dstc_copy(opts.compiler, opts.hint, ret);
ret = opts.hint;
}
opts.compiler->recursion_guard++;
/* Only pop on good path in case of error. */
dstc_ast_pop(c);
return ret;
}
@ -906,7 +915,7 @@ DstFuncDef *dstc_pop_funcdef(DstCompiler *c) {
def->defs_length = dst_v_count(scope.defs);
def->defs = dst_v_flatten(scope.defs);
/* Copy bytecode */
/* Copy bytecode (only last chunk) */
def->bytecode_length = dst_v_count(c->buffer) - scope.bytecode_start;
if (def->bytecode_length) {
size_t s = sizeof(int32_t) * def->bytecode_length;
@ -924,21 +933,17 @@ DstFuncDef *dstc_pop_funcdef(DstCompiler *c) {
DST_OUT_OF_MEMORY;
}
for (i = 0; i < dst_v_count(c->mapbuffer); i++) {
DstAst *a = c->mapbuffer[i];
DstSourceMapping mapping;
if (a) {
mapping.start = a->source_start;
mapping.end = a->source_end;
} else {
mapping.start = -1;
mapping.end = -1;
}
def->sourcemap[i] = mapping;
def->sourcemap[i] = c->mapbuffer[i];
}
dst_v__cnt(c->mapbuffer) = scope.bytecode_start;
}
}
/* Get source from parser */
if (c->parser && (c->parser->flags & DST_PARSEFLAG_SOURCEMAP)) {
def->source = dst_to_string(c->parser->source);
}
def->arity = 0;
def->flags = 0;
if (scope.flags & DST_SCOPE_ENV) {
@ -952,12 +957,14 @@ DstFuncDef *dstc_pop_funcdef(DstCompiler *c) {
}
/* Initialize a compiler */
static void dstc_init(DstCompiler *c, DstTable *env) {
static void dstc_init(DstCompiler *c, DstTable *env, DstParser *p) {
c->scopes = NULL;
c->buffer = NULL;
c->mapbuffer = NULL;
c->recursion_guard = DST_RECURSION_GUARD;
c->env = env;
c->parser = p;
c->ast_stack = NULL;
/* Init result */
c->result.error = NULL;
c->result.status = DST_COMPILE_OK;
@ -972,16 +979,17 @@ static void dstc_deinit(DstCompiler *c) {
dst_v_free(c->scopes);
dst_v_free(c->buffer);
dst_v_free(c->mapbuffer);
dst_v_free(c->ast_stack);
c->env = NULL;
}
/* Compile a form. */
DstCompileResult dst_compile(Dst source, DstTable *env, int flags) {
DstCompileResult dst_compile(Dst source, DstTable *env, int flags, DstParser *p) {
DstCompiler c;
DstFopts fopts;
(void) flags;
dstc_init(&c, env);
dstc_init(&c, env, p);
/* Push a function scope */
dstc_scope(&c, DST_SCOPE_FUNCTION | DST_SCOPE_TOP);
@ -1010,9 +1018,15 @@ int dst_compile_cfun(DstArgs args) {
DstCompileResult res;
DstTable *t;
DstTable *env;
DST_FIXARITY(args, 2);
DST_MINARITY(args, 2);
DST_MAXARITY(args, 3);
DST_ARG_TABLE(env, args, 1);
res = dst_compile(args.v[0], env, 0);
DstParser *p = NULL;
if (args.n == 3) {
p = dst_check_parser(args.v[2]);
if (!p) DST_THROW(args, "expected parser for second argument");
}
res = dst_compile(args.v[0], env, 0, p);
if (res.status == DST_COMPILE_OK) {
DST_RETURN_FUNCTION(args, dst_thunk(res.funcdef));
} else {

View File

@ -54,12 +54,6 @@ struct DstSlot {
Dst constant; /* If the slot has a constant value */
};
/* Slot and map pairing */
typedef struct DstSM {
DstSlot slot;
DstAst *map;
} DstSM;
#define DST_SCOPE_FUNCTION 1
#define DST_SCOPE_ENV 2
#define DST_SCOPE_TOP 4
@ -106,11 +100,17 @@ struct DstCompiler {
DstScope *scopes;
uint32_t *buffer;
DstAst **mapbuffer;
DstSourceMapping *mapbuffer;
/* Keep track of where we are in the source */
DstSourceMapping *ast_stack;
/* Hold the environment */
DstTable *env;
/* Hold a reference to a parser if we need it */
DstParser *parser;
DstCompileResult result;
};
@ -133,18 +133,23 @@ DstFopts dstc_fopts_default(DstCompiler *c);
* optimizations should be tried before compiling a normal function call. */
struct DstCFunOptimizer {
DstCFunction cfun;
int (*can_optimize)(DstFopts opts, DstAst *ast, DstSM *args);
DstSlot (*optimize)(DstFopts opts, DstAst *ast, DstSM *args);
int (*can_optimize)(DstFopts opts, DstSlot *args);
DstSlot (*optimize)(DstFopts opts, DstSlot *args);
};
/* A grouping of a named special and the corresponding compiler fragment */
struct DstSpecial {
const char *name;
DstSlot (*compile)(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv);
DstSlot (*compile)(DstFopts opts, int32_t argn, const Dst *argv);
};
/****************************************************/
/* Manipulate the ast stack for source mapping reasons. */
void dstc_ast_push(DstCompiler *c, Dst x);
void dstc_ast_pop(DstCompiler *c);
DstSourceMapping dstc_ast(DstCompiler *c);
/* Get a cfunction optimizer. Return NULL if none exists. */
const DstCFunOptimizer *dstc_cfunopt(DstCFunction cfun);
@ -178,7 +183,6 @@ void dstc_nameslot(DstCompiler *c, const uint8_t *sym, DstSlot s);
* that can be used in an instruction. */
int32_t dstc_preread(
DstCompiler *c,
DstAst *ast,
int32_t max,
int nth,
DstSlot s);
@ -189,7 +193,6 @@ void dstc_postread(DstCompiler *c, DstSlot s, int32_t index);
/* Move value from one slot to another. Cannot copy to constant slots. */
void dstc_copy(
DstCompiler *c,
DstAst *ast,
DstSlot dest,
DstSlot src);
@ -197,27 +200,27 @@ void dstc_copy(
void dstc_throwaway(DstFopts opts, Dst x);
/* Generate the return instruction for a slot. */
DstSlot dstc_return(DstCompiler *c, DstAst *ast, DstSlot s);
DstSlot dstc_return(DstCompiler *c, DstSlot s);
/* Get a target slot for emitting an instruction. Will always return
* a local slot. */
DstSlot dstc_gettarget(DstFopts opts);
/* Get a bunch of slots for function arguments */
DstSM *dstc_toslots(DstCompiler *c, const Dst *vals, int32_t len);
DstSlot *dstc_toslots(DstCompiler *c, const Dst *vals, int32_t len);
/* Get a bunch of slots for function arguments */
DstSM *dstc_toslotskv(DstCompiler *c, Dst ds);
DstSlot *dstc_toslotskv(DstCompiler *c, Dst ds);
/* Push slots load via dstc_toslots. */
void dstc_pushslots(DstCompiler *c, DstAst *ast, DstSM *sms);
void dstc_pushslots(DstCompiler *c, DstSlot *slots);
/* Free slots loaded via dstc_toslots */
void dstc_freeslots(DstCompiler *c, DstSM *sms);
void dstc_freeslots(DstCompiler *c, DstSlot *slots);
/* Store an error */
void dstc_error(DstCompiler *c, DstAst *ast, const uint8_t *m);
void dstc_cerror(DstCompiler *c, DstAst *ast, const char *m);
void dstc_error(DstCompiler *c, const uint8_t *m);
void dstc_cerror(DstCompiler *c, const char *m);
/* Dispatch to correct form compiler */
DstSlot dstc_value(DstFopts opts, Dst x);
@ -234,13 +237,10 @@ DstFuncDef *dstc_pop_funcdef(DstCompiler *c);
/* Create a destory slots */
DstSlot dstc_cslot(Dst x);
/* Free a slot */
void dstc_freeslot(DstCompiler *c, DstSlot slot);
/* Search for a symbol */
DstSlot dstc_resolve(DstCompiler *c, DstAst *ast, const uint8_t *sym);
DstSlot dstc_resolve(DstCompiler *c, const uint8_t *sym);
/* Emit instructions. */
void dstc_emit(DstCompiler *c, DstAst *ast, uint32_t instr);
void dstc_emit(DstCompiler *c, uint32_t instr);
#endif

View File

@ -23,23 +23,24 @@
#include <dst/dst.h>
#include <dst/dstcorelib.h>
#include <dst/dstcompile.h>
#include <dst/dstparse.h>
/* Run a string */
int dst_dobytes(DstTable *env, const uint8_t *bytes, int32_t len) {
int dst_dobytes(DstTable *env, const uint8_t *bytes, int32_t len, const char *sourcePath) {
DstParser parser;
int errflags = 0;
int32_t index = 0;
int dudeol = 0;
int done = 0;
Dst source = sourcePath ? dst_cstringv(sourcePath) : dst_wrap_nil();
dst_parser_init(&parser, DST_PARSEFLAG_SOURCEMAP);
dst_parser_init(&parser, sourcePath ? DST_PARSEFLAG_SOURCEMAP : 0);
parser.source = source;
while (!errflags && !done) {
switch (dst_parser_status(&parser)) {
case DST_PARSE_FULL:
{
Dst form = dst_parser_produce(&parser);
DstCompileResult cres = dst_compile(form, env, 0);
DstCompileResult cres = dst_compile(form, env, 0, &parser);
if (cres.status == DST_COMPILE_OK) {
DstFunction *f = dst_thunk(cres.funcdef);
DstFiber *fiber = dst_fiber(f, 64);
@ -85,9 +86,9 @@ int dst_dobytes(DstTable *env, const uint8_t *bytes, int32_t len) {
return errflags;
}
int dst_dostring(DstTable *env, const char *str) {
int dst_dostring(DstTable *env, const char *str, const char *sourcePath) {
int32_t len = 0;
while (str[len]) ++len;
return dst_dobytes(env, (const uint8_t *)str, len);
return dst_dobytes(env, (const uint8_t *)str, len, sourcePath);
}

View File

@ -23,22 +23,13 @@
#include <dst/dst.h>
#include <dst/dstcorelib.h>
#include <dst/dstcompile.h>
#include <dst/dstparse.h>
#include "compile.h"
#include <headerlibs/strbinsearch.h>
#include <headerlibs/vector.h>
DstSlot dstc_quote(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) {
DstSlot dstc_quote(DstFopts opts, int32_t argn, const Dst *argv) {
if (argn != 1) {
dstc_cerror(opts.compiler, ast, "expected 1 argument");
return dstc_cslot(dst_wrap_nil());
}
return dstc_cslot(dst_ast_unwrap(argv[0]));
}
DstSlot dstc_astquote(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) {
if (argn != 1) {
dstc_cerror(opts.compiler, ast, "expected 1 argument");
dstc_cerror(opts.compiler, "expected 1 argument");
return dstc_cslot(dst_wrap_nil());
}
return dstc_cslot(argv[0]);
@ -46,20 +37,17 @@ DstSlot dstc_astquote(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv)
static void destructure(DstCompiler *c, Dst left, DstSlot right,
void (*leaf)(DstCompiler *c,
DstAst *ast,
const uint8_t *sym,
DstSlot s,
DstTable *attr),
DstTable *attr) {
DstAst *ast = dst_ast_node(left);
left = dst_ast_unwrap1(left);
switch (dst_type(left)) {
default:
dstc_cerror(c, ast, "unexpected type in destructuring");
dstc_cerror(c, "unexpected type in destructuring");
break;
case DST_SYMBOL:
/* Leaf, assign right to left */
leaf(c, ast, dst_unwrap_symbol(left), right, attr);
leaf(c, dst_unwrap_symbol(left), right, attr);
break;
case DST_TUPLE:
case DST_ARRAY:
@ -70,18 +58,18 @@ static void destructure(DstCompiler *c, Dst left, DstSlot right,
for (i = 0; i < len; i++) {
DstSlot newright;
Dst subval = values[i];
localright = dstc_preread(c, ast, 0xFF, 1, right);
localright = dstc_preread(c, 0xFF, 1, right);
localsub = dstc_lslotn(c, 0xFF, 3);
if (i < 0x100) {
dstc_emit(c, ast,
dstc_emit(c,
(i << 24) |
(localright << 16) |
(localsub << 8) |
DOP_GET_INDEX);
} else {
DstSlot islot = dstc_cslot(dst_wrap_integer(i));
int32_t locali = dstc_preread(c, ast, 0xFF, 2, islot);
dstc_emit(c, ast,
int32_t locali = dstc_preread(c, 0xFF, 2, islot);
dstc_emit(c,
(locali << 24) |
(localright << 16) |
(localsub << 8) |
@ -109,10 +97,10 @@ static void destructure(DstCompiler *c, Dst left, DstSlot right,
DstSlot newright;
DstSlot kslot = dstc_value(dstc_fopts_default(c), kv->key);
Dst subval = kv->value;
localright = dstc_preread(c, ast, 0xFF, 1, right);
localright = dstc_preread(c, 0xFF, 1, right);
localsub = dstc_lslotn(c, 0xFF, 3);
int32_t localk = dstc_preread(c, ast, 0xFF, 2, kslot);
dstc_emit(c, ast,
int32_t localk = dstc_preread(c, 0xFF, 2, kslot);
dstc_emit(c,
(localk << 24) |
(localright << 16) |
(localsub << 8) |
@ -134,28 +122,28 @@ static void destructure(DstCompiler *c, Dst left, DstSlot right,
}
DstSlot dstc_varset(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) {
DstSlot dstc_varset(DstFopts opts, int32_t argn, const Dst *argv) {
DstFopts subopts = dstc_fopts_default(opts.compiler);
DstSlot ret, dest;
Dst head;
if (argn != 2) {
dstc_cerror(opts.compiler, ast, "expected 2 arguments");
dstc_cerror(opts.compiler, "expected 2 arguments");
return dstc_cslot(dst_wrap_nil());
}
head = dst_ast_unwrap(argv[0]);
head = argv[0];
if (!dst_checktype(head, DST_SYMBOL)) {
dstc_cerror(opts.compiler, ast, "expected symbol");
dstc_cerror(opts.compiler, "expected symbol");
return dstc_cslot(dst_wrap_nil());
}
dest = dstc_resolve(opts.compiler, ast, dst_unwrap_symbol(head));
dest = dstc_resolve(opts.compiler, dst_unwrap_symbol(head));
if (!(dest.flags & DST_SLOT_MUTABLE)) {
dstc_cerror(opts.compiler, ast, "cannot set constant");
dstc_cerror(opts.compiler, "cannot set constant");
return dstc_cslot(dst_wrap_nil());
}
subopts.flags = DST_FOPTS_HINT;
subopts.hint = dest;
ret = dstc_value(subopts, argv[1]);
dstc_copy(opts.compiler, ast, dest, ret);
dstc_copy(opts.compiler, dest, ret);
return ret;
}
@ -164,10 +152,10 @@ static DstTable *handleattr(DstCompiler *c, int32_t argn, const Dst *argv) {
int32_t i;
DstTable *tab = dst_table(2);
for (i = 1; i < argn - 1; i++) {
Dst attr = dst_ast_unwrap1(argv[i]);
Dst attr = argv[i];
switch (dst_type(attr)) {
default:
dstc_cerror(c, dst_ast_node(argv[i]), "could not add metadata to binding");
dstc_cerror(c, "could not add metadata to binding");
break;
case DST_SYMBOL:
dst_table_put(tab, attr, dst_wrap_true());
@ -180,14 +168,14 @@ static DstTable *handleattr(DstCompiler *c, int32_t argn, const Dst *argv) {
return tab;
}
static DstSlot dohead(DstCompiler *c, DstFopts opts, DstAst *ast, Dst *head, int32_t argn, const Dst *argv) {
static DstSlot dohead(DstCompiler *c, DstFopts opts, Dst *head, int32_t argn, const Dst *argv) {
DstFopts subopts = dstc_fopts_default(c);
DstSlot ret;
if (argn < 2) {
dstc_cerror(c, ast, "expected at least 2 arguments");
dstc_cerror(c, "expected at least 2 arguments");
return dstc_cslot(dst_wrap_nil());
}
*head = dst_ast_unwrap1(argv[0]);
*head = argv[0];
subopts.flags = opts.flags & ~(DST_FOPTS_TAIL | DST_FOPTS_DROP);
subopts.hint = opts.hint;
ret = dstc_value(subopts, argv[argn - 1]);
@ -195,7 +183,7 @@ static DstSlot dohead(DstCompiler *c, DstFopts opts, DstAst *ast, Dst *head, int
}
/* Def or var a symbol in a local scope */
static DstSlot namelocal(DstCompiler *c, DstAst *ast, Dst head, int32_t flags, DstSlot ret) {
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 ||
@ -208,7 +196,7 @@ static DstSlot namelocal(DstCompiler *c, DstAst *ast, Dst head, int32_t flags, D
localslot.flags = flags;
localslot.envindex = -1;
localslot.constant = dst_wrap_nil();
dstc_copy(c, ast, localslot, ret);
dstc_copy(c, localslot, ret);
ret = localslot;
}
ret.flags |= flags;
@ -218,7 +206,6 @@ static DstSlot namelocal(DstCompiler *c, DstAst *ast, Dst head, int32_t flags, D
static void varleaf(
DstCompiler *c,
DstAst *ast,
const uint8_t *sym,
DstSlot s,
DstTable *attr) {
@ -235,23 +222,23 @@ static void varleaf(
refarrayslot = refslot;
refslot.flags |= DST_SLOT_REF | DST_SLOT_NAMED | DST_SLOT_MUTABLE;
/* Generate code to set ref */
int32_t refarrayindex = dstc_preread(c, ast, 0xFF, 1, refarrayslot);
int32_t retindex = dstc_preread(c, ast, 0xFF, 2, s);
dstc_emit(c, ast,
int32_t refarrayindex = dstc_preread(c, 0xFF, 1, refarrayslot);
int32_t retindex = dstc_preread(c, 0xFF, 2, s);
dstc_emit(c,
(retindex << 16) |
(refarrayindex << 8) |
DOP_PUT_INDEX);
dstc_postread(c, refarrayslot, refarrayindex);
dstc_postread(c, s, retindex);
} else {
namelocal(c, ast, dst_wrap_symbol(sym), DST_SLOT_NAMED | DST_SLOT_MUTABLE, s) ;
namelocal(c, dst_wrap_symbol(sym), DST_SLOT_NAMED | DST_SLOT_MUTABLE, s) ;
}
}
DstSlot dstc_var(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) {
DstSlot dstc_var(DstFopts opts, int32_t argn, const Dst *argv) {
DstCompiler *c = opts.compiler;
Dst head;
DstSlot ret = dohead(c, opts, ast, &head, argn, argv);
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));
return dstc_cslot(dst_wrap_nil());
@ -259,7 +246,6 @@ DstSlot dstc_var(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) {
static void defleaf(
DstCompiler *c,
DstAst *ast,
const uint8_t *sym,
DstSlot s,
DstTable *attr) {
@ -274,10 +260,10 @@ static void defleaf(
dst_table_put(c->env, dst_wrap_symbol(sym), dst_wrap_table(tab));
/* Put value in table when evaulated */
tableindex = dstc_preread(c, ast, 0xFF, 1, tabslot);
valsymindex = dstc_preread(c, ast, 0xFF, 2, valsym);
valueindex = dstc_preread(c, ast, 0xFF, 3, s);
dstc_emit(c, ast,
tableindex = dstc_preread(c, 0xFF, 1, tabslot);
valsymindex = dstc_preread(c, 0xFF, 2, valsym);
valueindex = dstc_preread(c, 0xFF, 3, s);
dstc_emit(c,
(valueindex << 24) |
(valsymindex << 16) |
(tableindex << 8) |
@ -286,15 +272,15 @@ static void defleaf(
dstc_postread(c, valsym, valsymindex);
dstc_postread(c, s, valueindex);
} else {
namelocal(c, ast, dst_wrap_symbol(sym), DST_SLOT_NAMED, s);
namelocal(c, dst_wrap_symbol(sym), DST_SLOT_NAMED, s);
}
}
DstSlot dstc_def(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) {
DstSlot dstc_def(DstFopts opts, int32_t argn, const Dst *argv) {
DstCompiler *c = opts.compiler;
Dst head;
opts.flags &= ~DST_FOPTS_HINT;
DstSlot ret = dohead(c, opts, ast, &head, argn, argv);
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));
return dstc_cslot(dst_wrap_nil());
@ -311,7 +297,7 @@ DstSlot dstc_def(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) {
* ...
* :done
*/
DstSlot dstc_if(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) {
DstSlot dstc_if(DstFopts opts, int32_t argn, const Dst *argv) {
DstCompiler *c = opts.compiler;
int32_t labelr, labeljr, labeld, labeljd, condlocal;
DstFopts condopts, bodyopts;
@ -321,7 +307,7 @@ DstSlot dstc_if(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) {
const int drop = opts.flags & DST_FOPTS_DROP;
if (argn < 2 || argn > 3) {
dstc_cerror(c, ast, "expected 2 or 3 arguments to if");
dstc_cerror(c, "expected 2 or 3 arguments to if");
return dstc_cslot(dst_wrap_nil());
}
@ -358,27 +344,27 @@ DstSlot dstc_if(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) {
: dstc_gettarget(opts);
/* Compile jump to right */
condlocal = dstc_preread(c, ast, 0xFF, 1, cond);
condlocal = dstc_preread(c, 0xFF, 1, cond);
labeljr = dst_v_count(c->buffer);
dstc_emit(c, ast, DOP_JUMP_IF_NOT | (condlocal << 8));
dstc_emit(c, DOP_JUMP_IF_NOT | (condlocal << 8));
dstc_postread(c, cond, condlocal);
dstc_freeslot(c, cond);
/* Condition left body */
dstc_scope(c, 0);
left = dstc_value(bodyopts, truebody);
if (!drop && !tail) dstc_copy(c, ast, target, left);
if (!drop && !tail) dstc_copy(c, target, left);
dstc_popscope(c);
/* Compile jump to done */
labeljd = dst_v_count(c->buffer);
if (!tail) dstc_emit(c, ast, DOP_JUMP);
if (!tail) dstc_emit(c, DOP_JUMP);
/* Compile right body */
labelr = dst_v_count(c->buffer);
dstc_scope(c, 0);
right = dstc_value(bodyopts, falsebody);
if (!drop && !tail) dstc_copy(c, ast, target, right);
if (!drop && !tail) dstc_copy(c, target, right);
dstc_popscope(c);
/* Write jumps - only add jump lengths if jump actually emitted */
@ -392,12 +378,11 @@ DstSlot dstc_if(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) {
/* Compile a do form. Do forms execute their body sequentially and
* evaluate to the last expression in the body. */
DstSlot dstc_do(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) {
DstSlot dstc_do(DstFopts opts, int32_t argn, const Dst *argv) {
int32_t i;
DstSlot ret = dstc_cslot(dst_wrap_nil());
DstCompiler *c = opts.compiler;
DstFopts subopts = dstc_fopts_default(c);
(void) ast;
dstc_scope(c, 0);
for (i = 0; i < argn; i++) {
if (i != argn - 1) {
@ -423,7 +408,7 @@ DstSlot dstc_do(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) {
* jump :whiletop
* :done
*/
DstSlot dstc_while(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) {
DstSlot dstc_while(DstFopts opts, int32_t argn, const Dst *argv) {
DstCompiler *c = opts.compiler;
DstSlot cond;
DstFopts subopts = dstc_fopts_default(c);
@ -431,7 +416,7 @@ DstSlot dstc_while(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) {
int infinite = 0;
if (argn < 2) {
dstc_cerror(c, ast, "expected at least 2 arguments");
dstc_cerror(c, "expected at least 2 arguments");
return dstc_cslot(dst_wrap_nil());
}
@ -454,9 +439,9 @@ DstSlot dstc_while(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) {
/* Infinite loop does not need to check condition */
if (!infinite) {
condlocal = dstc_preread(c, ast, 0xFF, 1, cond);
condlocal = dstc_preread(c, 0xFF, 1, cond);
labelc = dst_v_count(c->buffer);
dstc_emit(c, ast, DOP_JUMP_IF_NOT | (condlocal << 8));
dstc_emit(c, DOP_JUMP_IF_NOT | (condlocal << 8));
dstc_postread(c, cond, condlocal);
} else {
labelc = 0;
@ -470,7 +455,7 @@ DstSlot dstc_while(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) {
/* Compile jump to whiletop */
labeljt = dst_v_count(c->buffer);
dstc_emit(c, ast, DOP_JUMP);
dstc_emit(c, DOP_JUMP);
/* Calculate jumps */
labeld = dst_v_count(c->buffer);
@ -496,7 +481,7 @@ static int32_t dstc_addfuncdef(DstCompiler *c, DstFuncDef *def) {
return dst_v_count(scope->defs) - 1;
}
DstSlot dstc_fn(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) {
DstSlot dstc_fn(DstFopts opts, int32_t argn, const Dst *argv) {
DstCompiler *c = opts.compiler;
DstFuncDef *def;
DstSlot ret;
@ -508,7 +493,7 @@ DstSlot dstc_fn(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) {
int selfref = 0;
if (argn < 2) {
dstc_cerror(c, ast, "expected at least 2 arguments to function literal");
dstc_cerror(c, "expected at least 2 arguments to function literal");
return dstc_cslot(dst_wrap_nil());
}
@ -518,26 +503,26 @@ DstSlot dstc_fn(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) {
/* Read function parameters */
parami = 0;
arity = 0;
head = dst_ast_unwrap1(argv[0]);
head = argv[0];
if (dst_checktype(head, DST_SYMBOL)) {
selfref = 1;
parami = 1;
}
if (parami >= argn) {
dstc_cerror(c, dst_ast_node(argv[0]), "expected function parameters");
dstc_cerror(c, "expected function parameters");
return dstc_cslot(dst_wrap_nil());
}
paramv = dst_ast_unwrap(argv[parami]);
paramv = argv[parami];
if (dst_seq_view(paramv, &params, &paramcount)) {
int32_t i;
for (i = 0; i < paramcount; i++) {
Dst param = dst_ast_unwrap1(params[i]);
Dst param = params[i];
if (dst_checktype(param, DST_SYMBOL)) {
DstSlot slot;
/* Check for varargs */
if (0 == dst_cstrcmp(dst_unwrap_symbol(param), "&")) {
if (i != paramcount - 2) {
dstc_cerror(c, dst_ast_node(params[i]), "variable argument symbol in unexpected location");
dstc_cerror(c, "variable argument symbol in unexpected location");
return dstc_cslot(dst_wrap_nil());
}
varargs = 1;
@ -560,7 +545,7 @@ DstSlot dstc_fn(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) {
arity++;
}
} else {
dstc_cerror(c, ast, "expected function parameters");
dstc_cerror(c, "expected function parameters");
return dstc_cslot(dst_wrap_nil());
}
@ -571,13 +556,13 @@ DstSlot dstc_fn(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) {
slot.flags = DST_SLOT_NAMED | DST_FUNCTION;
slot.constant = dst_wrap_nil();
slot.index = dstc_lsloti(c);
dstc_emit(c, ast, (slot.index << 8) | DOP_LOAD_SELF);
dstc_emit(c, (slot.index << 8) | DOP_LOAD_SELF);
dstc_nameslot(c, dst_unwrap_symbol(head), slot);
}
/* Compile function body */
if (parami + 1 == argn) {
dstc_emit(c, ast, DOP_RETURN_NIL);
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;
@ -600,13 +585,13 @@ DstSlot dstc_fn(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) {
ret = dstc_gettarget(opts);
localslot = ret.index > 0xF0 ? 0xF1 : ret.index;
dstc_emit(c, ast,
dstc_emit(c,
(defindex << 16) |
(localslot << 8) |
DOP_CLOSURE);
if (ret.index != localslot) {
dstc_emit(c, ast,
dstc_emit(c,
(ret.index << 16) |
(localslot << 8) |
DOP_MOVE_FAR);
@ -618,7 +603,6 @@ DstSlot dstc_fn(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) {
/* Keep in lexicographic order */
static const DstSpecial dstc_specials[] = {
{":=", dstc_varset},
{"ast-quote", dstc_astquote},
{"def", dstc_def},
{"do", dstc_do},
{"fn", dstc_fn},

View File

@ -24,7 +24,6 @@
#include <dst/dstopcodes.h>
#include <dst/dstcorelib.h>
#include <dst/dstasm.h>
#include <dst/dstparse.h>
#include <dst/dstcompile.h>
/* Generated header */
@ -155,7 +154,7 @@ DstTable *dst_stl_env(int flags) {
dst_env_def(env, "_env", ret);
/* Run bootstrap source */
dst_dobytes(env, dst_stl_bootstrap_gen, sizeof(dst_stl_bootstrap_gen));
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));

View File

@ -223,7 +223,6 @@ DstFuncDef *dst_funcdef_alloc() {
def->slotcount = 0;
def->arity = 0;
def->source = NULL;
def->sourcepath = NULL;
def->sourcemap = NULL;
def->name = NULL;
def->defs = NULL;

View File

@ -370,8 +370,6 @@ static Dst doframe(DstStackFrame *frame) {
}
if (def->source) {
dst_table_put(t, dst_csymbolv(":source"), dst_wrap_string(def->source));
} else if (def->sourcepath) {
dst_table_put(t, dst_csymbolv(":sourcepath"), dst_wrap_string(def->sourcepath));
}
}
return dst_wrap_table(t);

View File

@ -161,8 +161,6 @@ static void dst_mark_funcdef(DstFuncDef *def) {
}
if (def->source)
dst_mark_string(def->source);
if (def->sourcepath)
dst_mark_string(def->sourcepath);
if (def->name)
dst_mark_string(def->name);
}

View File

@ -21,7 +21,121 @@
*/
#include <dst/dst.h>
#include <dst/dstparse.h>
/* custom equals and hash for parse map */
static int32_t identity_hash(Dst x) {
int32_t hash;
if (sizeof(double) == sizeof(void *)) {
/* Assuming 8 byte pointer */
uint64_t i = dst_u64(x);
hash = (int32_t)(i & 0xFFFFFFFF);
/* Get a bit more entropy by shifting the low bits out */
hash >>= 3;
hash ^= (int32_t) (i >> 32);
} else {
/* Assuming 4 byte pointer (or smaller) */
hash = (int32_t) ((char *)dst_unwrap_pointer(x) - (char *)0);
hash >>= 2;
}
return hash;
}
static int identity_equals(Dst lhs, Dst rhs) {
DstType lhs_type = dst_type(lhs);
DstType rhs_type = dst_type(rhs);
if (lhs_type != rhs_type) {
return 0;
}
switch (lhs_type) {
default:
return 0;
case DST_ARRAY:
case DST_TUPLE:
case DST_BUFFER:
case DST_TABLE:
case DST_STRUCT:
return dst_unwrap_pointer(lhs) == dst_unwrap_pointer(rhs);
}
}
static int32_t pm_hashmapping(int32_t hash, int32_t cap) {
return (int32_t)((uint32_t)hash % (uint32_t)cap);
}
/* Find an empty slot in the parse map's hash table for the key */
static DstParseKV *pm_findslot(DstParser *p, Dst key) {
if (!p->pm_capacity)
return NULL;
int32_t hash = identity_hash(key);
int32_t index = pm_hashmapping(hash, p->pm_capacity);
for (int32_t j = index; j < p->pm_capacity; j++) {
if (dst_checktype(p->pm_kvs[j].key, DST_NIL)) {
return p->pm_kvs + j;
}
}
for (int32_t j = 0; j < index; j++) {
if (dst_checktype(p->pm_kvs[j].key, DST_NIL)) {
return p->pm_kvs + j;
}
}
return NULL;
}
/* Rehash a parse map */
static void pm_rehash(DstParser *p, int32_t newCapacity) {
int32_t oldCapacity = p->pm_capacity;
DstParseKV *oldKvs = p->pm_kvs;
p->pm_kvs = malloc(sizeof(DstParseKV) * newCapacity);
p->pm_capacity = newCapacity;
if (!p->pm_kvs) {
DST_OUT_OF_MEMORY;
}
for (int32_t i = 0; i < newCapacity; i++) {
p->pm_kvs[i].key = dst_wrap_nil();
}
for (int32_t i = 0; i < oldCapacity; i++) {
DstParseKV source_kv = oldKvs[i];
if (!dst_checktype(source_kv.key, DST_NIL)) {
DstParseKV *dest_kv = pm_findslot(p, source_kv.key);
*dest_kv = source_kv;
}
}
}
/* Add a value to the parsemap */
static void pm_put(DstParser *p, Dst key, int32_t start, int32_t end) {
/* guard against unsupported key types (noop) */
if (!identity_equals(key, key)) return;
int32_t newcount = p->pm_count + 1;
if (newcount * 2 >= p->pm_capacity) {
pm_rehash(p, 4 * newcount);
}
DstParseKV *dest = pm_findslot(p, key);
dest->key = key;
dest->start = start;
dest->end = end;
p->pm_count = newcount;
}
/* Get a value from the parse map. The returned pointer
* should be read and discarded immediately. */
static DstParseKV *pm_get(DstParser *p, Dst ast) {
if (!p->pm_capacity)
return NULL;
int32_t hash = identity_hash(ast);
int32_t index = pm_hashmapping(hash, p->pm_capacity);
for (int32_t j = index; j < p->pm_capacity; j++) {
if (identity_equals(p->pm_kvs[j].key, ast)) {
return p->pm_kvs + j;
}
}
for (int32_t j = 0; j < index; j++) {
if (identity_equals(p->pm_kvs[j].key, ast)) {
return p->pm_kvs + j;
}
}
return NULL;
}
/* Quote a value */
static Dst quote(Dst x) {
@ -169,14 +283,14 @@ static void popstate(DstParser *p, Dst val) {
/* Quote the returned value qcount times */
for (i = 0; i < len; i++) {
if (p->flags & DST_PARSEFLAG_SOURCEMAP)
val = dst_ast_wrap(val, (int32_t) top.start, (int32_t) p->index);
pm_put(p, val, (int32_t) top.start, (int32_t) p->index);
val = quote(val);
}
newtop->qcount = 0;
/* Ast wrap */
if (p->flags & DST_PARSEFLAG_SOURCEMAP)
val = dst_ast_wrap(val, (int32_t) top.start, (int32_t) p->index);
pm_put(p, val, (int32_t) top.start, (int32_t) p->index);
newtop->argn++;
push_arg(p, val);
@ -561,6 +675,16 @@ Dst dst_parser_produce(DstParser *parser) {
return ret;
}
int dst_parser_lookup(DstParser *parser, Dst key, DstSourceMapping *out) {
DstParseKV *results = pm_get(parser, key);
if (results) {
out->start = results->start;
out->end = results->end;
return 1;
}
return 0;
}
void dst_parser_init(DstParser *parser, int flags) {
parser->args = NULL;
parser->states = NULL;
@ -575,6 +699,12 @@ void dst_parser_init(DstParser *parser, int flags) {
parser->index = 0;
parser->lookback = -1;
parser->flags = flags;
parser->source = dst_wrap_nil();
parser->pm_kvs = NULL;
parser->pm_count = 0;
parser->pm_capacity = 0;
pushstate(parser, root, PFLAG_CONTAINER);
}
@ -582,6 +712,7 @@ void dst_parser_deinit(DstParser *parser) {
free(parser->args);
free(parser->buf);
free(parser->states);
free(parser->pm_kvs);
}
/* C functions */
@ -590,9 +721,16 @@ static int parsermark(void *p, size_t size) {
size_t i;
DstParser *parser = (DstParser *)p;
(void) size;
dst_mark(parser->source);
for (i = 0; i < parser->argcount; i++) {
dst_mark(parser->args[i]);
}
/* Mark parser map */
for (int32_t i = 0; i < parser->pm_capacity; i++) {
if (!dst_checktype(parser->pm_kvs[i].key, DST_NIL)) {
dst_mark(parser->pm_kvs[i].key);
}
}
return 0;
}
@ -603,12 +741,21 @@ static int parsergc(void *p, size_t size) {
return 0;
}
DstAbstractType dst_parse_parsertype = {
":parser.parser",
static DstAbstractType dst_parse_parsertype = {
":core.parser",
parsergc,
parsermark
};
DstParser *dst_check_parser(Dst x) {
if (!dst_checktype(x, DST_ABSTRACT))
return NULL;
void *abstract = dst_unwrap_abstract(x);
if (dst_abstract_type(abstract) != &dst_parse_parsertype)
return NULL;
return (DstParser *)abstract;
}
/* C Function parser */
static int cfun_parser(DstArgs args) {
int flags = 0;
@ -745,39 +892,19 @@ static int cfun_state(DstArgs args) {
DST_RETURN_STRING(args, str);
}
/* AST */
static int cfun_unwrap1(DstArgs args) {
DST_FIXARITY(args, 1);
DST_RETURN(args, dst_ast_unwrap1(args.v[0]));
}
static int cfun_unwrap(DstArgs args) {
DST_FIXARITY(args, 1);
DST_RETURN(args, dst_ast_unwrap(args.v[0]));
}
static int cfun_wrap(DstArgs args) {
DST_FIXARITY(args, 1);
DST_RETURN(args, dst_ast_wrap(args.v[0], -1, -1));
}
static int cfun_node(DstArgs args) {
DstAst *ast;
Dst *tup;
int32_t start, end;
DST_FIXARITY(args, 1);
ast = dst_ast_node(args.v[0]);
if (ast) {
start = ast->source_start;
end = ast->source_end;
} else {
start = -1;
end = -1;
static int cfun_lookup(DstArgs args) {
DstParser *p;
DST_FIXARITY(args, 2);
DST_CHECKABSTRACT(args, 0, &dst_parse_parsertype);
p = (DstParser *) dst_unwrap_abstract(args.v[0]);
DstParseKV *results = pm_get(p, args.v[1]);
if (results) {
Dst t[2];
t[0] = dst_wrap_integer(results->start);
t[1] = dst_wrap_integer(results->end);
DST_RETURN_TUPLE(args, dst_tuple_n(t, 2));
}
tup = dst_tuple_begin(2);
tup[0] = dst_wrap_integer(start);
tup[1] = dst_wrap_integer(end);
DST_RETURN_TUPLE(args, dst_tuple_end(tup));
DST_RETURN_NIL(args);
}
static const DstReg cfuns[] = {
@ -789,10 +916,7 @@ static const DstReg cfuns[] = {
{"parser.status", cfun_status},
{"parser.flush", cfun_flush},
{"parser.state", cfun_state},
{"ast.unwrap", cfun_unwrap},
{"ast.unwrap1", cfun_unwrap1},
{"ast.wrap", cfun_wrap},
{"ast.node", cfun_node},
{"parser.lookup", cfun_lookup},
{NULL, NULL}
};

View File

@ -36,6 +36,17 @@ extern "C" {
#include "dsttypes.h"
/* Parsing */
void dst_parser_init(DstParser *parser, int flags);
void dst_parser_deinit(DstParser *parser);
int dst_parser_consume(DstParser *parser, uint8_t c);
enum DstParserStatus dst_parser_status(DstParser *parser);
Dst dst_parser_produce(DstParser *parser);
const char *dst_parser_error(DstParser *parser);
void dst_parser_flush(DstParser *parser);
int dst_parser_lookup(DstParser *parser, Dst key, DstSourceMapping *out);
DstParser *dst_check_parser(Dst x);
/* Number scanning */
Dst dst_scan_number(const uint8_t *src, int32_t len);
int32_t dst_scan_integer(const uint8_t *str, int32_t len, int *err);

View File

@ -42,15 +42,15 @@ struct DstCompileResult {
int32_t error_start;
int32_t error_end;
};
DstCompileResult dst_compile(Dst source, DstTable *env, int flags);
DstCompileResult dst_compile(Dst source, DstTable *env, int flags, DstParser *parser);
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);
int dst_dostring(DstTable *env, const char *str);
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
}

View File

@ -100,6 +100,8 @@ 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);
/* Useful for compiler */
Dst dst_op_add(Dst lhs, Dst rhs);

View File

@ -1,82 +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_PARSE_H_defined
#define DST_PARSE_H_defined
#ifdef __cplusplus
extern "C" {
#endif
#include "dsttypes.h"
/* AST */
Dst dst_ast_wrap(Dst x, int32_t start, int32_t end);
DstAst *dst_ast_node(Dst x);
Dst dst_ast_unwrap1(Dst x);
Dst dst_ast_unwrap(Dst x);
typedef struct DstParseState DstParseState;
typedef struct DstParser DstParser;
enum DstParserStatus {
DST_PARSE_ROOT,
DST_PARSE_ERROR,
DST_PARSE_FULL,
DST_PARSE_PENDING
};
struct DstParser {
Dst* args;
size_t argcount;
size_t argcap;
DstParseState *states;
size_t statecount;
size_t statecap;
uint8_t *buf;
size_t bufcount;
size_t bufcap;
const char *error;
size_t index;
int lookback;
int flags;
};
/* Parsing */
#define DST_PARSEFLAG_SOURCEMAP 1
void dst_parser_init(DstParser *parser, int flags);
void dst_parser_deinit(DstParser *parser);
int dst_parser_consume(DstParser *parser, uint8_t c);
enum DstParserStatus dst_parser_status(DstParser *parser);
Dst dst_parser_produce(DstParser *parser);
const char *dst_parser_error(DstParser *parser);
void dst_parser_flush(DstParser *parser);
int dst_parse_cfun(DstArgs args);
int dst_lib_parse(DstArgs args);
#ifdef __cplusplus
}
#endif
#endif /* DST_PARSE_H_defined */

View File

@ -91,7 +91,6 @@ typedef struct DstKV DstKV;
typedef struct DstStackFrame DstStackFrame;
typedef struct DstAbstractType DstAbstractType;
typedef struct DstArgs DstArgs;
typedef struct DstAst DstAst;
typedef struct DstReg DstReg;
typedef struct DstSourceMapping DstSourceMapping;
typedef int (*DstCFunction)(DstArgs args);
@ -478,7 +477,6 @@ struct DstFuncDef {
/* Various debug information */
DstSourceMapping *sourcemap;
const uint8_t *source;
const uint8_t *sourcepath;
const uint8_t *name;
uint32_t flags;
@ -490,6 +488,8 @@ struct DstFuncDef {
int32_t defs_length;
};
#define DST_PARSEFLAG_SOURCEMAP 1
/* A fuction environment */
struct DstFuncEnv {
union {
@ -507,6 +507,44 @@ struct DstFunction {
DstFuncEnv *envs[];
};
/* Parser types */
typedef struct {
Dst key;
int32_t start;
int32_t end;
} DstParseKV;
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;
DstParseKV *pm_kvs;
int32_t pm_capacity;
int32_t pm_count;
Dst source; /* optional source path/string */
size_t argcount;
size_t argcap;
size_t statecount;
size_t statecap;
size_t bufcount;
size_t bufcap;
size_t index;
int lookback;
int flags;
};
/* Defines an abstract type */
struct DstAbstractType {
const char *name;
@ -525,15 +563,6 @@ struct DstReg {
DstCFunction cfun;
};
/* ASTs are simple wrappers around values. They contain information about sourcemapping
* and other meta data. Possibly types? They are used mainly during compilation and parsing */
struct DstAst {
Dst value;
int32_t source_start;
int32_t source_end;
int flags;
};
#ifdef __cplusplus
}
#endif

View File

@ -1,5 +1,4 @@
# Copyright 2017-2018 (C) Calvin Rose
(do
(var *should-repl* :private false)

View File

@ -47,7 +47,7 @@ int main(int argc, char **argv) {
dst_line_init();
/* Run startup script */
status = dst_dobytes(env, dst_mainclient_init, sizeof(dst_mainclient_init));
status = dst_dobytes(env, dst_mainclient_init, sizeof(dst_mainclient_init), "init.dst");
/* Deinitialize vm */
dst_deinit();

View File

@ -1,186 +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>
/* Mark an ast node */
static int dst_ast_gcmark(void *p, size_t size) {
DstAst *ast = (DstAst *)p;
(void) size;
dst_mark(ast->value);
return 0;
}
/* AST type */
static DstAbstractType dst_ast_type = {
":parser.ast",
NULL,
dst_ast_gcmark
};
/* Create an ast type */
Dst dst_ast_wrap(Dst x, int32_t start, int32_t end) {
DstAst *ast = dst_abstract(&dst_ast_type, sizeof(DstAst));
ast->value = x;
ast->source_start = start;
ast->source_end = end;
ast->flags = 1 << dst_type(x);
return dst_wrap_abstract(ast);
}
/* Get the node associated with a value */
DstAst *dst_ast_node(Dst x) {
if (dst_checktype(x, DST_ABSTRACT) &&
dst_abstract_type(dst_unwrap_abstract(x)) == &dst_ast_type) {
DstAst *ast = (DstAst *)dst_unwrap_abstract(x);
return ast;
}
return NULL;
}
/* Unwrap an ast value one level deep */
Dst dst_ast_unwrap1(Dst x) {
if (dst_checktype(x, DST_ABSTRACT) &&
dst_abstract_type(dst_unwrap_abstract(x)) == &dst_ast_type) {
DstAst *ast = (DstAst *)dst_unwrap_abstract(x);
return ast->value;
}
return x;
}
Dst dst_ast_unwrap(Dst x);
static Dst astunwrap_array(DstArray *other) {
DstArray *array;
Dst diffval;
int32_t i, prescan;
for (prescan = 0; prescan < other->count; prescan++) {
diffval = dst_ast_unwrap(other->data[prescan]);
if (!dst_equals(diffval, other->data[prescan])) break;
}
if (prescan == other->count) return dst_wrap_array(other);
array = dst_array(other->count);
for (i = 0; i < prescan; i++) {
array->data[i] = other->data[i];
}
array->data[prescan] = diffval;
for (i = prescan + 1; i < other->count; i++) {
array->data[i] = dst_ast_unwrap(other->data[i]);
}
array->count = other->count;
return dst_wrap_array(array);
}
static Dst astunwrap_tuple(const Dst *other) {
Dst *tuple;
int32_t i, prescan;
Dst diffval;
for (prescan = 0; prescan < dst_tuple_length(other); prescan++) {
diffval = dst_ast_unwrap(other[prescan]);
if (!dst_equals(diffval, other[prescan])) break;
}
if (prescan == dst_tuple_length(other)) return dst_wrap_tuple(other);
tuple = dst_tuple_begin(dst_tuple_length(other));
for (i = 0; i < prescan; i++) {
tuple[i] = other[i];
}
tuple[prescan] = diffval;
for (i = prescan + 1; i < dst_tuple_length(other); i++) {
tuple[i] = dst_ast_unwrap(other[i]);
}
return dst_wrap_tuple(dst_tuple_end(tuple));
}
static Dst astunwrap_struct(const DstKV *other) {
DstKV *st;
const DstKV *prescan, *iter;
Dst diffval, diffkey;
prescan = NULL;
while ((prescan = dst_struct_next(other, prescan))) {
diffkey = dst_ast_unwrap(prescan->key);
diffval = dst_ast_unwrap(prescan->value);
if (!dst_equals(diffkey, prescan->key) ||
!dst_equals(diffval, prescan->value))
break;
}
if (!prescan) return dst_wrap_struct(other);
st = dst_struct_begin(dst_struct_length(other));
iter = NULL;
while ((iter = dst_struct_next(other, iter))) {
if (iter == prescan) break;
dst_struct_put(st, iter->key, iter->value);
}
dst_struct_put(st, diffkey, diffval);
while ((iter = dst_struct_next(other, iter))) {
dst_struct_put(st,
dst_ast_unwrap(iter->key),
dst_ast_unwrap(iter->value));
}
return dst_wrap_struct(dst_struct_end(st));
}
static Dst astunwrap_table(DstTable *other) {
DstTable *table;
const DstKV *prescan, *iter;
Dst diffval, diffkey;
prescan = NULL;
while ((prescan = dst_table_next(other, prescan))) {
diffkey = dst_ast_unwrap(prescan->key);
diffval = dst_ast_unwrap(prescan->value);
if (!dst_equals(diffkey, prescan->key) ||
!dst_equals(diffval, prescan->value))
break;
}
if (!prescan) return dst_wrap_table(other);
table = dst_table(other->capacity);
table->proto = other->proto;
iter = NULL;
while ((iter = dst_table_next(other, iter))) {
if (iter == prescan) break;
dst_table_put(table, iter->key, iter->value);
}
dst_table_put(table, diffkey, diffval);
while ((iter = dst_table_next(other, iter))) {
dst_table_put(table,
dst_ast_unwrap(iter->key),
dst_ast_unwrap(iter->value));
}
return dst_wrap_table(table);
}
/* Unwrap an ast value recursively. Preserve as much structure as possible
* to avoid unecessary allocation. */
Dst dst_ast_unwrap(Dst x) {
x = dst_ast_unwrap1(x);
switch (dst_type(x)) {
default:
return x;
case DST_ARRAY:
return astunwrap_array(dst_unwrap_array(x));
case DST_TUPLE:
return astunwrap_tuple(dst_unwrap_tuple(x));
case DST_STRUCT:
return astunwrap_struct(dst_unwrap_struct(x));
case DST_TABLE:
return astunwrap_table(dst_unwrap_table(x));
}
}

View File

@ -18,7 +18,6 @@
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
(print "Current working directory is: " (os.cwd))
(import test.helper :prefix "" :exit true)
(start-suite 0)

View File

@ -18,7 +18,6 @@
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
(print "Current working directory is: " (os.cwd))
(import test.helper :prefix "" :exit true)
(start-suite 1)