1
0
mirror of https://github.com/janet-lang/janet synced 2025-10-30 07:03:02 +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

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));
}
}