1
0
mirror of https://github.com/janet-lang/janet synced 2025-10-30 07:03:02 +00:00

Version 2 of new source mapping.

This commit is contained in:
Calvin Rose
2018-06-29 01:15:47 -04:00
parent bb406133de
commit 2e472ec9a3
11 changed files with 109 additions and 729 deletions

View File

@@ -931,15 +931,17 @@ respectively.
This function can be used to implement a repl very easily, simply
pass a function that reads line from stdin to chunks, and print to
onvalue."
[env chunks onvalue onerr]
[env chunks onvalue onerr where]
# Are we done yet?
(var going true)
# The parser object
(def p (parser.new 1))
(if where (parser.set-source p where))
# Fiber stream of characters
(var byteindex 0)
(def chars (coro
(def buf @"")
(var len 1)
@@ -948,6 +950,7 @@ onvalue."
(chunks buf p)
(:= len (length buf))
(loop [i :range [0 len]]
(++ byteindex)
(yield (get buf i))))
0))
@@ -956,31 +959,36 @@ onvalue."
(while going
(switch (parser.status p)
:full (yield (parser.produce p))
:error (onerr "parse" (parser.error p))
:error (onerr where "parse" (string (parser.error p) " at byte index " byteindex))
(switch (fiber.status chars)
:new (parser.byte p (resume chars))
:pending (parser.byte p (resume chars))
(:= going false))))
(when (not= :root (parser.status p))
(onerr "parse" "unexpected end of source"))))
(onerr where "parse" "unexpected end of source"))))
# Evaluate 1 source form
(defn eval1 [source]
(var good true)
(def f (fiber.new (fn []
(def res (compile source env))
(def res (compile source env p))
(if (= (type res) :function)
(res)
(do
(:= good false)
(onerr "compile" (get res :error))))) :a))
(def {:error err :error-start errs :error-end erre} res)
(onerr where "compile"
(if (<= 0 errs)
(string err " at (" errs ":" erre ")")
err)))))
:a))
(def res (resume f))
(when good
(def sig (fiber.status f))
(if going
(if (= sig :dead)
(onvalue res)
(onerr "runtime" res f)))))
(onerr where "runtime" res f)))))
# Run loop
(def oldenv *env*)
@@ -991,8 +999,8 @@ onvalue."
env)
(defn default-error-handler
[t x f]
(file.write stdout (string t " error: "))
[source t x f]
(file.write stdout (string t " error in " source ": "))
(if (bytes? x)
(do (file.write stdout x)
(file.write stdout "\n"))
@@ -1014,11 +1022,12 @@ onvalue."
(if name
(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) ")"))
(if source
(do
(file.write stdout " [" source "]")
(if source-start (file.write stdout " at byte range ("
(string source-start) ":" (string source-end) ")")))
(if pc (file.write stdout " at (pc=" (string pc) ")")))
(when tail (file.write stdout " (tailcall)"))
(file.write stdout "\n"))))
@@ -1033,7 +1042,7 @@ environment is needed, use run-context."
(if ret
(buffer.push-string buf ret)))
(var returnval nil)
(run-context *env* chunks (fn [x] (:= returnval x)) default-error-handler)
(run-context *env* chunks (fn [x] (:= returnval x)) default-error-handler "eval")
returnval)
(def module.paths @[
@@ -1097,7 +1106,7 @@ returned from compiling and running the file."
(error (string "circular dependency: module " path " is loading")))
(def {
:exit exit-on-error
} args)
} (or args {}))
(def check (get cache path))
(if check check (do
(def newenv (make-env))
@@ -1110,8 +1119,9 @@ returned from compiling and running the file."
(defn chunks [buf] (file.read f 1024 buf))
(run-context newenv chunks identity
(if exit-on-error
(fn [a b c] (default-error-handler a b c) (os.exit 1))
default-error-handler))
(fn [a b c d] (default-error-handler a b c d) (os.exit 1))
default-error-handler)
path)
(file.close f)
(put loading path nil)
newenv)
@@ -1161,7 +1171,7 @@ get a chunk of source code. Should return nil for end of file."
(put newenv '_ @{:value x})
(pp x)))
(default onerr default-error-handler)
(run-context newenv getchunk onvalue onerr))
(run-context newenv getchunk onvalue onerr "repl"))
(defn all-symbols
"Get all symbols available in the current environment."

View File

@@ -32,6 +32,9 @@
void dstc_ast_push(DstCompiler *c, Dst x) {
DstSourceMapping mapping;
if (c->result.status == DST_COMPILE_ERROR) {
return;
}
if (c->parser) {
int found = dst_parser_lookup(c->parser, x, &mapping);
if (!found) {
@@ -51,6 +54,9 @@ void dstc_ast_push(DstCompiler *c, Dst x) {
}
void dstc_ast_pop(DstCompiler *c) {
if (c->result.status == DST_COMPILE_ERROR) {
return;
}
dst_v_pop(c->ast_stack);
}
@@ -941,7 +947,7 @@ DstFuncDef *dstc_pop_funcdef(DstCompiler *c) {
/* Get source from parser */
if (c->parser && (c->parser->flags & DST_PARSEFLAG_SOURCEMAP)) {
def->source = dst_to_string(c->parser->source);
def->source = c->parser->source;
}
def->arity = 0;
@@ -968,9 +974,9 @@ static void dstc_init(DstCompiler *c, DstTable *env, DstParser *p) {
/* Init result */
c->result.error = NULL;
c->result.status = DST_COMPILE_OK;
c->result.funcdef = NULL;
c->result.error_start = -1;
c->result.error_end = -1;
c->result.funcdef = NULL;
}
/* Deinitialize a compiler struct */
@@ -1004,8 +1010,12 @@ DstCompileResult dst_compile(Dst source, DstTable *env, int flags, DstParser *p)
if (c.result.status == DST_COMPILE_OK) {
DstFuncDef *def = dstc_pop_funcdef(&c);
def->name = dst_cstring("[thunk]");
def->name = dst_cstring("_thunk");
c.result.funcdef = def;
} else {
DstSourceMapping m = dstc_ast(&c);
c.result.error_start = m.start;
c.result.error_end = m.end;
}
dstc_deinit(&c);

View File

@@ -31,7 +31,7 @@ int dst_dobytes(DstTable *env, const uint8_t *bytes, int32_t len, const char *so
int32_t index = 0;
int dudeol = 0;
int done = 0;
Dst source = sourcePath ? dst_cstringv(sourcePath) : dst_wrap_nil();
const uint8_t *source = sourcePath ? dst_cstring(sourcePath) : NULL;
dst_parser_init(&parser, sourcePath ? DST_PARSEFLAG_SOURCEMAP : 0);
parser.source = source;

View File

@@ -22,119 +22,34 @@
#include <dst/dst.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);
int32_t nextid = p->pm_count;
if (!dst_checktype(key, DST_TUPLE))
return;
dst_tuple_id(dst_unwrap_tuple(key)) = nextid;
p->pm_count++;
if (nextid >= p->pm_capacity) {
int32_t newCapacity = 2 * nextid + 2;
DstSourceMapping *newPms = realloc(p->pms, sizeof(DstSourceMapping) * newCapacity);
if (!newPms) {
DST_OUT_OF_MEMORY;
}
p->pms = newPms;
}
DstParseKV *dest = pm_findslot(p, key);
dest->key = key;
dest->start = start;
dest->end = end;
p->pm_count = newcount;
p->pms[nextid].start = start;
p->pms[nextid].end = end;
}
/* 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)
static DstSourceMapping *pm_get(DstParser *p, Dst ast) {
if (!dst_checktype(ast, DST_TUPLE))
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;
int32_t id = dst_tuple_id(dst_unwrap_tuple(ast));
if (id < 0 || id >= p->pm_count)
return NULL;
return p->pms + id;
}
/* Quote a value */
@@ -676,10 +591,9 @@ Dst dst_parser_produce(DstParser *parser) {
}
int dst_parser_lookup(DstParser *parser, Dst key, DstSourceMapping *out) {
DstParseKV *results = pm_get(parser, key);
DstSourceMapping *results = pm_get(parser, key);
if (results) {
out->start = results->start;
out->end = results->end;
*out = *results;
return 1;
}
return 0;
@@ -699,9 +613,9 @@ void dst_parser_init(DstParser *parser, int flags) {
parser->index = 0;
parser->lookback = -1;
parser->flags = flags;
parser->source = dst_wrap_nil();
parser->source = NULL;
parser->pm_kvs = NULL;
parser->pms = NULL;
parser->pm_count = 0;
parser->pm_capacity = 0;
@@ -712,7 +626,7 @@ void dst_parser_deinit(DstParser *parser) {
free(parser->args);
free(parser->buf);
free(parser->states);
free(parser->pm_kvs);
free(parser->pms);
}
/* C functions */
@@ -721,16 +635,12 @@ static int parsermark(void *p, size_t size) {
size_t i;
DstParser *parser = (DstParser *)p;
(void) size;
dst_mark(parser->source);
if (parser->source) {
dst_mark(dst_wrap_string(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;
}
@@ -897,7 +807,7 @@ static int cfun_lookup(DstArgs args) {
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]);
DstSourceMapping *results = pm_get(p, args.v[1]);
if (results) {
Dst t[2];
t[0] = dst_wrap_integer(results->start);
@@ -907,6 +817,17 @@ static int cfun_lookup(DstArgs args) {
DST_RETURN_NIL(args);
}
static int cfun_setsource(DstArgs args) {
DstParser *p;
const uint8_t *source;
DST_FIXARITY(args, 2);
DST_CHECKABSTRACT(args, 0, &dst_parse_parsertype);
p = (DstParser *) dst_unwrap_abstract(args.v[0]);
DST_ARG_STRING(source, args, 1);
p->source = source;
DST_RETURN(args, args.v[0]);
}
static const DstReg cfuns[] = {
{"parser.new", cfun_parser},
{"parser.produce", cfun_produce},
@@ -917,6 +838,7 @@ static const DstReg cfuns[] = {
{"parser.flush", cfun_flush},
{"parser.state", cfun_state},
{"parser.lookup", cfun_lookup},
{"parser.set-source", cfun_setsource},
{NULL, NULL}
};

View File

@@ -40,7 +40,6 @@ DstKV *dst_struct_begin(int32_t count) {
dst_struct_length(st) = count;
dst_struct_capacity(st) = capacity;
dst_struct_hash(st) = 0;
(dst_struct_raw(st)[3]) = 0;
return st;
}

View File

@@ -30,9 +30,10 @@
* which should be filled with Dsts. The memory will not be collected until
* dst_tuple_end is called. */
Dst *dst_tuple_begin(int32_t length) {
char *data = dst_gcalloc(DST_MEMORY_TUPLE, 2 * sizeof(int32_t) + length * sizeof(Dst));
Dst *tuple = (Dst *)(data + (2 * sizeof(int32_t)));
char *data = dst_gcalloc(DST_MEMORY_TUPLE, 4 * sizeof(int32_t) + length * sizeof(Dst));
Dst *tuple = (Dst *)(data + (4 * sizeof(int32_t)));
dst_tuple_length(tuple) = length;
dst_tuple_id(tuple) = -1;
return tuple;
}

View File

@@ -78,9 +78,10 @@ int dst_buffer_push_u32(DstBuffer *buffer, uint32_t x);
int dst_buffer_push_u64(DstBuffer *buffer, uint64_t x);
/* Tuple */
#define dst_tuple_raw(t) ((int32_t *)(t) - 2)
#define dst_tuple_raw(t) ((int32_t *)(t) - 4)
#define dst_tuple_length(t) (dst_tuple_raw(t)[0])
#define dst_tuple_hash(t) ((dst_tuple_raw(t)[1]))
#define dst_tuple_id(t) ((dst_tuple_raw(t)[2]))
Dst *dst_tuple_begin(int32_t length);
const Dst *dst_tuple_end(Dst *tuple);
const Dst *dst_tuple_n(Dst *values, int32_t n);

View File

@@ -507,13 +507,6 @@ 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;
@@ -530,10 +523,10 @@ struct DstParser {
const char *error;
DstParseState *states;
uint8_t *buf;
DstParseKV *pm_kvs;
const uint8_t *source; /* optional source path/string */
DstSourceMapping *pms;
int32_t pm_capacity;
int32_t pm_count;
Dst source; /* optional source path/string */
size_t argcount;
size_t argcap;
size_t statecount;