mirror of
https://github.com/janet-lang/janet
synced 2024-11-24 17:27:18 +00:00
Strip trailing whitespace from many files.
Add native modules to import with module.native-path.
This commit is contained in:
parent
245fb948f1
commit
fb409201b4
@ -30,7 +30,7 @@
|
||||
/* Convert a slot to to an integer for bytecode */
|
||||
|
||||
/* Types of instructions (some of them) */
|
||||
/* _0arg - op.---.--.-- (return-nil, noop, vararg arguments)
|
||||
/* _0arg - op.---.--.-- (return-nil, noop, vararg arguments)
|
||||
* _s - op.src.--.-- (push1)
|
||||
* _l - op.XX.XX.XX (jump)
|
||||
* _ss - op.dest.XX.XX (move, swap)
|
||||
@ -200,7 +200,7 @@ static void dst_asm_errorv(DstAssembler *a, const uint8_t *m) {
|
||||
}
|
||||
|
||||
/* Add a closure environment to the assembler. Sub funcdefs may need
|
||||
* to reference outer function environments, and may change the outer environment.
|
||||
* to reference outer function environments, and may change the outer environment.
|
||||
* Returns the index of the environment in the assembler's environments, or -1
|
||||
* if not found. */
|
||||
static int32_t dst_asm_addenv(DstAssembler *a, Dst envname) {
|
||||
@ -360,7 +360,7 @@ static uint32_t doarg(
|
||||
|
||||
/* Provide parsing methods for the different kinds of arguments */
|
||||
static uint32_t read_instruction(
|
||||
DstAssembler *a,
|
||||
DstAssembler *a,
|
||||
const DstInstructionDef *idef,
|
||||
const Dst *argt) {
|
||||
uint32_t instr = idef->opcode;
|
||||
@ -516,7 +516,7 @@ static DstAssembleResult dst_asm1(DstAssembler *parent, Dst source, int flags) {
|
||||
return result;
|
||||
}
|
||||
|
||||
dst_asm_assert(&a,
|
||||
dst_asm_assert(&a,
|
||||
dst_checktype(s, DST_STRUCT) ||
|
||||
dst_checktype(s, DST_TABLE),
|
||||
"expected struct or table for assembly source");
|
||||
@ -547,7 +547,7 @@ static DstAssembleResult dst_asm1(DstAssembler *parent, Dst source, int flags) {
|
||||
Dst v = arr[i];
|
||||
if (dst_checktype(v, DST_TUPLE)) {
|
||||
const Dst *t = dst_unwrap_tuple(v);
|
||||
int32_t j;
|
||||
int32_t j;
|
||||
for (j = 0; j < dst_tuple_length(t); j++) {
|
||||
if (!dst_checktype(t[j], DST_SYMBOL))
|
||||
dst_asm_error(&a, "slot names must be symbols");
|
||||
@ -681,7 +681,7 @@ static DstAssembleResult dst_asm1(DstAssembler *parent, Dst source, int flags) {
|
||||
dst_asm_error(&a, "bytecode expected");
|
||||
}
|
||||
a.errindex = -1;
|
||||
|
||||
|
||||
/* Check for source mapping */
|
||||
x = dst_get(s, dst_csymbolv("sourcemap"));
|
||||
if (dst_seq_view(x, &arr, &count)) {
|
||||
@ -737,7 +737,7 @@ static const DstInstructionDef *dst_asm_reverse_lookup(uint32_t instr) {
|
||||
uint32_t opcode = instr & 0x7F;
|
||||
for (i = 0; i < sizeof(dst_ops)/sizeof(DstInstructionDef); i++) {
|
||||
const DstInstructionDef *def = dst_ops + i;
|
||||
if (def->opcode == opcode)
|
||||
if (def->opcode == opcode)
|
||||
return def;
|
||||
}
|
||||
return NULL;
|
||||
@ -792,23 +792,23 @@ Dst dst_asm_decode_instruction(uint32_t instr) {
|
||||
case DIT_SC:
|
||||
case DIT_SU:
|
||||
case DIT_SD:
|
||||
return tup3(name,
|
||||
return tup3(name,
|
||||
dst_wrap_integer(oparg(1, 0xFF)),
|
||||
dst_wrap_integer(oparg(2, 0xFFFF)));
|
||||
case DIT_SI:
|
||||
case DIT_SL:
|
||||
return tup3(name,
|
||||
return tup3(name,
|
||||
dst_wrap_integer(oparg(1, 0xFF)),
|
||||
dst_wrap_integer((int32_t)instr >> 16));
|
||||
case DIT_SSS:
|
||||
case DIT_SES:
|
||||
case DIT_SSU:
|
||||
return tup4(name,
|
||||
return tup4(name,
|
||||
dst_wrap_integer(oparg(1, 0xFF)),
|
||||
dst_wrap_integer(oparg(2, 0xFF)),
|
||||
dst_wrap_integer(oparg(3, 0xFF)));
|
||||
case DIT_SSI:
|
||||
return tup4(name,
|
||||
return tup4(name,
|
||||
dst_wrap_integer(oparg(1, 0xFF)),
|
||||
dst_wrap_integer(oparg(2, 0xFF)),
|
||||
dst_wrap_integer((int32_t)instr >> 24));
|
||||
@ -825,7 +825,7 @@ Dst dst_disasm(DstFuncDef *def) {
|
||||
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_table_put(ret, dst_csymbolv("sourcepath"),
|
||||
dst_wrap_string(def->sourcepath));
|
||||
}
|
||||
if (NULL != def->source) {
|
||||
|
@ -950,7 +950,7 @@ onvalue."
|
||||
:pc pc
|
||||
:c c
|
||||
:name name
|
||||
} (get st i))
|
||||
} (get st i))
|
||||
(file.write stdout " in")
|
||||
(when c (file.write stdout " cfunction"))
|
||||
(when name (file.write stdout (string " " name)))
|
||||
@ -978,48 +978,73 @@ environment is needed, use run-context."
|
||||
"./?/init.dst"
|
||||
"./dst_modules/?.dst"
|
||||
"./dst_modules/?/init.dst"
|
||||
"/usr/local/dst/0.0.0/?.dst"
|
||||
"/usr/local/dst/0.0.0/?/init.dst"
|
||||
])
|
||||
|
||||
(defn module.find
|
||||
"Open a file given a module name."
|
||||
[name]
|
||||
(def normname (string.replace-all "." "/" name))
|
||||
(defn checkmodule
|
||||
[f testpath]
|
||||
(if f f (do
|
||||
(def p (string.replace-all "?" normname testpath))
|
||||
(def p (string.replace-all "?" normname testpath))
|
||||
(file.open p))))
|
||||
(reduce checkmodule nil module.paths))
|
||||
(def module.native-paths @[
|
||||
"./?.so"
|
||||
"./dst_modules/?.so"
|
||||
"/usr/local/dst/0.0.0/?.so"
|
||||
])
|
||||
|
||||
(def require
|
||||
"Require a module with the given name. Will search all of the paths in
|
||||
module.paths, then the path as a raw file path. Returns the new environment
|
||||
returned from compiling and running the file."
|
||||
(do
|
||||
(def cache @{})
|
||||
(def loading @{})
|
||||
(fn [path]
|
||||
|
||||
(defn transform
|
||||
[path paths]
|
||||
(def normname (string.replace-all "." "/" path))
|
||||
(array.push
|
||||
(map (fn [x] (string.replace "?" normname x)) paths)
|
||||
path))
|
||||
|
||||
(defn check-mod
|
||||
[f testpath]
|
||||
(if f f (file.open testpath)))
|
||||
|
||||
(defn find-mod [path]
|
||||
(def paths (transform path module.paths))
|
||||
(reduce check-mod nil paths))
|
||||
|
||||
(defn check-native
|
||||
[p testpath]
|
||||
(if p p (do
|
||||
(def f (file.open testpath))
|
||||
(if f (do (file.close f) testpath)))))
|
||||
|
||||
(defn find-native [path]
|
||||
(def paths (transform path module.native-paths))
|
||||
(reduce check-native nil paths))
|
||||
|
||||
(def cache @{})
|
||||
(def loading @{})
|
||||
(fn [path]
|
||||
(when (get loading path)
|
||||
(error (string "circular dependency: module " path " is loading")))
|
||||
(def check (get cache path))
|
||||
(if check check (do
|
||||
(if (or
|
||||
(= ".so" (string.slice path -3 -1))
|
||||
(= ".dll" (string.slice path -4 -1)))
|
||||
((native path))
|
||||
(do
|
||||
(def newenv (make-env))
|
||||
(put cache path newenv)
|
||||
(put loading path true)
|
||||
(def f (or (module.find path) (file.open path)))
|
||||
(if (not f)
|
||||
(error (string "could not open file for module " path)))
|
||||
(defn chunks [buf] (file.read f 1024 buf))
|
||||
(run-context newenv chunks identity default-error-handler)
|
||||
(file.close f)
|
||||
(put loading path nil)
|
||||
newenv)))))))
|
||||
(def newenv (make-env))
|
||||
(put cache path newenv)
|
||||
(put loading path true)
|
||||
|
||||
(def f (find-mod path))
|
||||
(if f
|
||||
(do
|
||||
# Normal dst module
|
||||
(defn chunks [buf] (file.read f 1024 buf))
|
||||
(run-context newenv chunks identity default-error-handler)
|
||||
(file.close f)
|
||||
(put loading path nil)
|
||||
newenv)
|
||||
(do
|
||||
# Try native module
|
||||
(def n (find-native path))
|
||||
(if (not n)
|
||||
(error (string "could not open file for module " path)))
|
||||
((native n)))))))))
|
||||
|
||||
(defn import* [env path & args]
|
||||
(def newenv (require path))
|
||||
|
@ -134,7 +134,7 @@ static const DstCFunOptimizer optimizers[] = {
|
||||
const DstCFunOptimizer *dstc_cfunopt(DstCFunction cfun) {
|
||||
size_t i;
|
||||
size_t n = sizeof(optimizers)/sizeof(DstCFunOptimizer);
|
||||
for (i = 0; i < n; i++)
|
||||
for (i = 0; i < n; i++)
|
||||
if (optimizers[i].cfun == cfun)
|
||||
return optimizers + i;
|
||||
return NULL;
|
||||
|
@ -112,7 +112,7 @@ static void slotalloci(DstCompiler *c, int32_t index) {
|
||||
void dstc_sfreei(DstCompiler *c, int32_t index) {
|
||||
DstScope *scope = &dst_v_last(c->scopes);
|
||||
/* Don't free the pre allocated slots */
|
||||
if (index >= 0 && (index < 0xF0 || index > 0xFF) &&
|
||||
if (index >= 0 && (index < 0xF0 || index > 0xFF) &&
|
||||
index < (dst_v_count(scope->slots) << 5))
|
||||
scope->slots[index >> 5] &= ~(1 << (index & 0x1F));
|
||||
}
|
||||
@ -182,7 +182,7 @@ void dstc_popscope(DstCompiler *c) {
|
||||
if (!(scope.flags & (DST_SCOPE_FUNCTION | DST_SCOPE_UNUSED)) && oldcount > 1) {
|
||||
int32_t i;
|
||||
DstScope *newscope = &dst_v_last(c->scopes);
|
||||
if (newscope->smax < scope.smax)
|
||||
if (newscope->smax < scope.smax)
|
||||
newscope->smax = scope.smax;
|
||||
|
||||
/* Keep upvalue slots */
|
||||
@ -320,7 +320,7 @@ DstSlot dstc_resolve(
|
||||
}
|
||||
scope++;
|
||||
}
|
||||
|
||||
|
||||
ret.envindex = envindex;
|
||||
return ret;
|
||||
}
|
||||
@ -372,7 +372,7 @@ static void dstc_loadconst(DstCompiler *c, DstAst *ast, Dst k, int32_t dest) {
|
||||
{
|
||||
int32_t i = dst_unwrap_integer(k);
|
||||
if (i <= INT16_MAX && i >= INT16_MIN) {
|
||||
dstc_emit(c, ast,
|
||||
dstc_emit(c, ast,
|
||||
(i << 16) |
|
||||
(dest << 8) |
|
||||
DOP_LOAD_INTEGER);
|
||||
@ -384,7 +384,7 @@ static void dstc_loadconst(DstCompiler *c, DstAst *ast, Dst k, int32_t dest) {
|
||||
do_constant:
|
||||
{
|
||||
int32_t cindex = dstc_const(c, ast, k);
|
||||
dstc_emit(c, ast,
|
||||
dstc_emit(c, ast,
|
||||
(cindex << 16) |
|
||||
(dest << 8) |
|
||||
DOP_LOAD_CONSTANT);
|
||||
@ -412,26 +412,26 @@ int32_t dstc_preread(
|
||||
dstc_loadconst(c, ast, 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, ast,
|
||||
(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, ast,
|
||||
((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, ast,
|
||||
((uint32_t)(s.index) << 16) |
|
||||
((uint32_t)(ret) << 8) |
|
||||
DOP_MOVE_NEAR);
|
||||
} else {
|
||||
/* We have a normal slot that fits in the required bit width */
|
||||
/* We have a normal slot that fits in the required bit width */
|
||||
ret = s.index;
|
||||
}
|
||||
return ret;
|
||||
@ -517,7 +517,7 @@ void dstc_copy(
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Process: src -> srclocal -> destlocal -> dest */
|
||||
|
||||
/* src -> srclocal */
|
||||
@ -550,14 +550,14 @@ void dstc_copy(
|
||||
DOP_MOVE_NEAR);
|
||||
}
|
||||
|
||||
/* destlocal -> dest */
|
||||
/* destlocal -> dest */
|
||||
if (writeback == 1) {
|
||||
dstc_emit(c, ast,
|
||||
(destlocal << 16) |
|
||||
(reflocal << 8) |
|
||||
DOP_PUT_INDEX);
|
||||
} else if (writeback == 2) {
|
||||
dstc_emit(c, ast,
|
||||
dstc_emit(c, ast,
|
||||
((uint32_t)(dest.index) << 24) |
|
||||
((uint32_t)(dest.envindex) << 16) |
|
||||
((uint32_t)(destlocal) << 8) |
|
||||
@ -646,7 +646,7 @@ void dstc_pushslots(DstCompiler *c, DstAst *ast, DstSM *sms) {
|
||||
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,
|
||||
dstc_emit(c, ast,
|
||||
(ls3 << 24) |
|
||||
(ls2 << 16) |
|
||||
(ls1 << 8) |
|
||||
@ -658,7 +658,7 @@ void dstc_pushslots(DstCompiler *c, DstAst *ast, DstSM *sms) {
|
||||
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,
|
||||
dstc_emit(c, ast,
|
||||
(ls2 << 16) |
|
||||
(ls1 << 8) |
|
||||
DOP_PUSH_2);
|
||||
@ -666,7 +666,7 @@ void dstc_pushslots(DstCompiler *c, DstAst *ast, DstSM *sms) {
|
||||
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_emit(c, ast,
|
||||
(ls1 << 8) |
|
||||
DOP_PUSH);
|
||||
dstc_postread(c, sms[i].slot, ls1);
|
||||
@ -694,7 +694,7 @@ void dstc_throwaway(DstFopts opts, Dst x) {
|
||||
dstc_popscope(c);
|
||||
if (NULL != c->buffer) {
|
||||
dst_v__cnt(c->buffer) = bufstart;
|
||||
if (NULL != c->mapbuffer)
|
||||
if (NULL != c->mapbuffer)
|
||||
dst_v__cnt(c->mapbuffer) = mapbufstart;
|
||||
}
|
||||
}
|
||||
@ -762,7 +762,7 @@ DstSlot dstc_symbol(DstFopts opts, DstAst *ast, const uint8_t *sym) {
|
||||
} else {
|
||||
/* Keyword */
|
||||
return dstc_cslot(dst_wrap_symbol(sym));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Compile a single value */
|
||||
@ -850,10 +850,10 @@ recur:
|
||||
}
|
||||
break;
|
||||
case DST_ARRAY:
|
||||
ret = dstc_array(opts, ast, x);
|
||||
ret = dstc_array(opts, ast, x);
|
||||
break;
|
||||
case DST_STRUCT:
|
||||
ret = dstc_tablector(opts, ast, x, dst_core_struct);
|
||||
ret = dstc_tablector(opts, ast, x, dst_core_struct);
|
||||
break;
|
||||
case DST_TABLE:
|
||||
ret = dstc_tablector(opts, ast, x, dst_core_table);
|
||||
|
@ -104,7 +104,7 @@ struct DstScope {
|
||||
struct DstCompiler {
|
||||
int recursion_guard;
|
||||
DstScope *scopes;
|
||||
|
||||
|
||||
uint32_t *buffer;
|
||||
DstAst **mapbuffer;
|
||||
|
||||
|
@ -216,7 +216,7 @@ static int cfun_concat(DstArgs args) {
|
||||
case DST_ARRAY:
|
||||
case DST_TUPLE:
|
||||
{
|
||||
int32_t j, len;
|
||||
int32_t j, len;
|
||||
const Dst *vals;
|
||||
dst_seq_view(args.v[i], &vals, &len);
|
||||
for (j = 0; j < len; j++)
|
||||
|
@ -190,7 +190,7 @@ static int cfun_int(DstArgs args) {
|
||||
for (i = 1; i < args.n; i++) {
|
||||
int32_t integer;
|
||||
DST_ARG_INTEGER(integer, args, i);
|
||||
if (dst_buffer_push_u32(buffer, (uint32_t) integer))
|
||||
if (dst_buffer_push_u32(buffer, (uint32_t) integer))
|
||||
DST_THROW(args, "buffer overflow");
|
||||
}
|
||||
DST_RETURN(args, args.v[0]);
|
||||
@ -205,7 +205,7 @@ static int cfun_chars(DstArgs args) {
|
||||
int32_t len;
|
||||
const uint8_t *str;
|
||||
DST_ARG_BYTES(str, len, args, i);
|
||||
if (dst_buffer_push_bytes(buffer, str, len))
|
||||
if (dst_buffer_push_bytes(buffer, str, len))
|
||||
DST_THROW(args, "buffer overflow");
|
||||
}
|
||||
DST_RETURN(args, args.v[0]);
|
||||
|
@ -191,7 +191,7 @@ int32_t dst_verify(DstFuncDef *def) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Verify last instruction is either a jump, return, return-nil, or tailcall. Eventually,
|
||||
/* Verify last instruction is either a jump, return, return-nil, or tailcall. Eventually,
|
||||
* some real flow analysis would be ideal, but this should be very effective. Will completely
|
||||
* prevent running over the end of bytecode. However, valid functions with dead code will
|
||||
* be rejected. */
|
||||
|
@ -149,7 +149,7 @@ int dst_core_array(DstArgs args) {
|
||||
int dst_core_table(DstArgs args) {
|
||||
int32_t i;
|
||||
DstTable *table = dst_table(args.n >> 1);
|
||||
if (args.n & 1)
|
||||
if (args.n & 1)
|
||||
DST_THROW(args, "expected even number of arguments");
|
||||
for (i = 0; i < args.n; i += 2) {
|
||||
dst_table_put(table, args.v[i], args.v[i + 1]);
|
||||
|
@ -189,7 +189,7 @@ recur:
|
||||
dst_gc_mark(fiber);
|
||||
|
||||
dst_mark_function(fiber->root);
|
||||
|
||||
|
||||
i = fiber->frame;
|
||||
j = fiber->stackstart - DST_FRAME_SIZE;
|
||||
while (i > 0) {
|
||||
@ -218,7 +218,7 @@ static void dst_deinit_block(DstGCMemoryHeader *block) {
|
||||
switch (block->flags & DST_MEM_TYPEBITS) {
|
||||
default:
|
||||
case DST_MEMORY_FUNCTION:
|
||||
break; /* Do nothing for non gc types */
|
||||
break; /* Do nothing for non gc types */
|
||||
case DST_MEMORY_SYMBOL:
|
||||
dst_symbol_deinit((const uint8_t *)mem + 2 * sizeof(int32_t));
|
||||
break;
|
||||
@ -233,7 +233,7 @@ static void dst_deinit_block(DstGCMemoryHeader *block) {
|
||||
break;
|
||||
case DST_MEMORY_BUFFER:
|
||||
dst_buffer_deinit((DstBuffer *) mem);
|
||||
break;
|
||||
break;
|
||||
case DST_MEMORY_ABSTRACT:
|
||||
if (h->type->gc) {
|
||||
if (h->type->gc((void *)(h + 1), h->size)) {
|
||||
|
@ -228,7 +228,7 @@ static int dst_io_fread(DstArgs args) {
|
||||
DST_RETURN(args, dst_wrap_buffer(b));
|
||||
} else {
|
||||
DST_THROW(args, "expected one of :all, :line");
|
||||
}
|
||||
}
|
||||
} else if (!dst_checktype(args.v[1], DST_INTEGER)) {
|
||||
DST_THROW(args, "expected positive integer");
|
||||
} else {
|
||||
|
@ -35,7 +35,7 @@
|
||||
|
||||
static int os_execute(DstArgs args) {
|
||||
int nofirstarg = (args.n < 1 || !dst_checktype(args.v[0], DST_STRING));
|
||||
const char *cmd = nofirstarg
|
||||
const char *cmd = nofirstarg
|
||||
? NULL
|
||||
: (const char *) dst_unwrap_string(args.v[0]);
|
||||
int stat = system(cmd);
|
||||
|
@ -32,7 +32,7 @@ extern "C" {
|
||||
#include <dst/dsttypes.h>
|
||||
|
||||
/* The VM state. Rather than a struct that is passed
|
||||
* around, the vm state is global for simplicity. If
|
||||
* around, the vm state is global for simplicity. If
|
||||
* at some point a a global state object, or context,
|
||||
* is required to be passed around, this is waht would
|
||||
* be in it. However, thread local globals for interpreter
|
||||
|
@ -202,7 +202,7 @@ static void string_description_b(DstBuffer *buffer, const char *title, void *poi
|
||||
buffer->count += string_description_impl(buffer->data + buffer->count, title, pointer);
|
||||
}
|
||||
|
||||
/* Describes a pointer with a title (string_description("bork", myp) returns
|
||||
/* Describes a pointer with a title (string_description("bork", myp) returns
|
||||
* a string "<bork 0x12345678>") */
|
||||
static const uint8_t *string_description(const char *title, void *pointer) {
|
||||
uint8_t buf[BUFSIZE];
|
||||
@ -212,7 +212,7 @@ static const uint8_t *string_description(const char *title, void *pointer) {
|
||||
#undef HEX
|
||||
#undef BUFSIZE
|
||||
|
||||
/* TODO - add more characters to escape.
|
||||
/* TODO - add more characters to escape.
|
||||
*
|
||||
* When more escapes are added, they must correspond
|
||||
* to dst_escape_string_impl exactly or a buffer overrun could occur. */
|
||||
@ -282,7 +282,7 @@ const uint8_t *dst_escape_string(const uint8_t *str) {
|
||||
int32_t len = dst_string_length(str);
|
||||
int32_t elen = dst_escape_string_length(str, len);
|
||||
uint8_t *buf = dst_string_begin(elen);
|
||||
dst_escape_string_impl(buf, str, len);
|
||||
dst_escape_string_impl(buf, str, len);
|
||||
return dst_string_end(buf);
|
||||
}
|
||||
|
||||
@ -315,8 +315,8 @@ void dst_description_b(DstBuffer *buffer, Dst x) {
|
||||
integer_to_string_b(buffer, dst_unwrap_integer(x));
|
||||
return;
|
||||
case DST_SYMBOL:
|
||||
dst_buffer_push_bytes(buffer,
|
||||
dst_unwrap_string(x),
|
||||
dst_buffer_push_bytes(buffer,
|
||||
dst_unwrap_string(x),
|
||||
dst_string_length(dst_unwrap_string(x)));
|
||||
return;
|
||||
case DST_STRING:
|
||||
@ -328,7 +328,7 @@ void dst_description_b(DstBuffer *buffer, Dst x) {
|
||||
case DST_ABSTRACT:
|
||||
{
|
||||
const char *n = dst_abstract_type(dst_unwrap_abstract(x))->name;
|
||||
return string_description_b(buffer,
|
||||
return string_description_b(buffer,
|
||||
n[0] == ':' ? n + 1 : n,
|
||||
dst_unwrap_abstract(x));
|
||||
}
|
||||
@ -344,13 +344,13 @@ void dst_to_string_b(DstBuffer *buffer, Dst x) {
|
||||
dst_description_b(buffer, x);
|
||||
break;
|
||||
case DST_BUFFER:
|
||||
dst_buffer_push_bytes(buffer,
|
||||
dst_buffer_push_bytes(buffer,
|
||||
dst_unwrap_buffer(x)->data,
|
||||
dst_unwrap_buffer(x)->count);
|
||||
break;
|
||||
case DST_STRING:
|
||||
case DST_SYMBOL:
|
||||
dst_buffer_push_bytes(buffer,
|
||||
dst_buffer_push_bytes(buffer,
|
||||
dst_unwrap_string(x),
|
||||
dst_string_length(dst_unwrap_string(x)));
|
||||
break;
|
||||
@ -386,7 +386,7 @@ const uint8_t *dst_description(Dst x) {
|
||||
case DST_ABSTRACT:
|
||||
{
|
||||
const char *n = dst_abstract_type(dst_unwrap_abstract(x))->name;
|
||||
return string_description(
|
||||
return string_description(
|
||||
n[0] == ':' ? n + 1 : n,
|
||||
dst_unwrap_abstract(x));
|
||||
}
|
||||
@ -418,7 +418,7 @@ const uint8_t *dst_formatc(const char *format, ...) {
|
||||
const uint8_t *ret;
|
||||
DstBuffer buffer;
|
||||
DstBuffer *bufp = &buffer;
|
||||
|
||||
|
||||
/* Calculate length */
|
||||
while (format[len]) len++;
|
||||
|
||||
@ -440,13 +440,13 @@ const uint8_t *dst_formatc(const char *format, ...) {
|
||||
if (i + 1 >= len)
|
||||
break;
|
||||
switch (format[++i]) {
|
||||
default:
|
||||
default:
|
||||
dst_buffer_push_u8(bufp, format[i]);
|
||||
break;
|
||||
case 'f':
|
||||
case 'f':
|
||||
real_to_string_b(bufp, va_arg(args, double));
|
||||
break;
|
||||
case 'd':
|
||||
case 'd':
|
||||
integer_to_string_b(bufp, va_arg(args, int32_t));
|
||||
break;
|
||||
case 'S':
|
||||
@ -472,12 +472,12 @@ const uint8_t *dst_formatc(const char *format, ...) {
|
||||
dst_buffer_push_cstring(bufp, dst_type_names[va_arg(args, DstType)] + 1);
|
||||
break;
|
||||
}
|
||||
case 'V':
|
||||
case 'V':
|
||||
{
|
||||
dst_to_string_b(bufp, va_arg(args, Dst));
|
||||
break;
|
||||
}
|
||||
case 'v':
|
||||
case 'v':
|
||||
{
|
||||
dst_description_b(bufp, va_arg(args, Dst));
|
||||
break;
|
||||
@ -852,6 +852,39 @@ static int cfun_split(DstArgs args) {
|
||||
DST_RETURN_ARRAY(args, array);
|
||||
}
|
||||
|
||||
static int cfun_checkset(DstArgs args) {
|
||||
const uint8_t *set, *str;
|
||||
int32_t setlen, strlen, i;
|
||||
uint32_t bitset[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
DST_MINARITY(args, 2);
|
||||
DST_MAXARITY(args, 3);
|
||||
DST_ARG_BYTES(set, setlen, args, 0);
|
||||
DST_ARG_BYTES(str, strlen, args, 1);
|
||||
/* Populate set */
|
||||
for (i = 0; i < setlen; i++) {
|
||||
int index = set[i] >> 5;
|
||||
uint32_t mask = 1 << (set[i] & 7);
|
||||
bitset[index] |= mask;
|
||||
}
|
||||
if (args.n == 3) {
|
||||
int invert;
|
||||
DST_ARG_BOOLEAN(invert, args, 2);
|
||||
if (invert) {
|
||||
for (i = 0; i < 8; i++)
|
||||
bitset[i] = ~bitset[i];
|
||||
}
|
||||
}
|
||||
/* Check set */
|
||||
for (i = 0; i < strlen; i++) {
|
||||
int index = str[i] >> 5;
|
||||
uint32_t mask = 1 << (str[i] & 7);
|
||||
if (!(bitset[index] & mask)) {
|
||||
DST_RETURN_FALSE(args);
|
||||
}
|
||||
}
|
||||
DST_RETURN_TRUE(args);
|
||||
}
|
||||
|
||||
static const DstReg cfuns[] = {
|
||||
{"string.slice", cfun_slice},
|
||||
{"string.repeat", cfun_repeat},
|
||||
@ -865,6 +898,7 @@ static const DstReg cfuns[] = {
|
||||
{"string.replace", cfun_replace},
|
||||
{"string.replace-all", cfun_replaceall},
|
||||
{"string.split", cfun_split},
|
||||
{"string.check-set", cfun_checkset},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
@ -29,7 +29,7 @@
|
||||
*
|
||||
* This version has been modified for much greater flexibility in parsing, such
|
||||
* as choosing the radix, supporting integer output, and returning Dsts
|
||||
* directly.
|
||||
* directly.
|
||||
*
|
||||
* Numbers are of the form [-+]R[rR]I.F[eE&][-+]X where R is the radix, I is
|
||||
* the integer part, F is the fractional part, and X is the exponent. All
|
||||
@ -117,7 +117,7 @@ static double convert(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return negative
|
||||
? -ldexp(mantissa, exponent2)
|
||||
: ldexp(mantissa, exponent2);
|
||||
@ -137,11 +137,11 @@ struct DstScanRes {
|
||||
|
||||
/* Get the mantissa and exponent of decimal number. The
|
||||
* mantissa will be stored in a 64 bit unsigned integer (always positive).
|
||||
* The exponent will be in a signed 32 bit integer. Will also check if
|
||||
* The exponent will be in a signed 32 bit integer. Will also check if
|
||||
* the decimal point has been seen. Returns -1 if there is an invalid
|
||||
* number. */
|
||||
static struct DstScanRes dst_scan_impl(
|
||||
const uint8_t *str,
|
||||
const uint8_t *str,
|
||||
int32_t len) {
|
||||
|
||||
struct DstScanRes res;
|
||||
@ -257,11 +257,11 @@ static struct DstScanRes dst_scan_impl(
|
||||
seenadigit = 1;
|
||||
}
|
||||
if (eneg) res.ex -= ee; else res.ex += ee;
|
||||
}
|
||||
}
|
||||
|
||||
if (!seenadigit)
|
||||
goto error;
|
||||
|
||||
|
||||
return res;
|
||||
|
||||
error:
|
||||
@ -277,7 +277,7 @@ int32_t dst_scan_integer(
|
||||
int *err) {
|
||||
struct DstScanRes res = dst_scan_impl(str, len);
|
||||
int64_t i64;
|
||||
if (res.error) goto error;
|
||||
if (res.error) goto error;
|
||||
if (res.seenpoint) goto error;
|
||||
if (res.ex < 0) goto error;
|
||||
i64 = res.neg ? -res.mant : res.mant;
|
||||
|
@ -60,7 +60,7 @@ const DstKV *dst_struct_find(const DstKV *st, Dst key) {
|
||||
|
||||
/* Put a kv pair into a struct that has not yet been fully constructed.
|
||||
* Nil keys and values are ignored, extra keys are ignore, and duplicate keys are
|
||||
* ignored.
|
||||
* ignored.
|
||||
*
|
||||
* Runs will be in sorted order, as the collisions resolver essentially
|
||||
* preforms an in-place insertion sort. This ensures the internal structure of the
|
||||
|
@ -253,13 +253,13 @@ int dst_typemany_err(DstArgs args, int32_t n, int expected) {
|
||||
int dst_arity_err(DstArgs args, int32_t n, const char *prefix) {
|
||||
DST_THROWV(args,
|
||||
dst_wrap_string(dst_formatc(
|
||||
"expected %s%d argument%s, got %d",
|
||||
"expected %s%d argument%s, got %d",
|
||||
prefix, n, n == 1 ? "" : "s", args.n)));
|
||||
}
|
||||
|
||||
int dst_typeabstract_err(DstArgs args, int32_t n, const DstAbstractType *at) {
|
||||
DST_THROWV(args,
|
||||
dst_wrap_string(dst_formatc(
|
||||
"bad slot #%d, expected %s, got %s",
|
||||
n, at->name, typestr(args, n))));
|
||||
"bad slot #%d, expected %s, got %s",
|
||||
n, at->name, typestr(args, n))));
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ int dst_compare(Dst x, Dst y) {
|
||||
return dst_unwrap_string(x) > dst_unwrap_string(y) ? 1 : -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (dst_type(x) < dst_type(y)) ? -1 : 1;
|
||||
}
|
||||
|
||||
@ -198,7 +198,7 @@ Dst dst_get(Dst ds, Dst key) {
|
||||
* error message, and NULL if no error. */
|
||||
void dst_put(Dst ds, Dst key, Dst value) {
|
||||
switch (dst_type(ds)) {
|
||||
case DST_ARRAY:
|
||||
case DST_ARRAY:
|
||||
{
|
||||
int32_t index;
|
||||
DstArray *array = dst_unwrap_array(ds);
|
||||
|
@ -288,7 +288,7 @@ static void *op_lookup[255] = {
|
||||
|
||||
VM_OP(DOP_SUBTRACT)
|
||||
vm_binop(-);
|
||||
|
||||
|
||||
VM_OP(DOP_MULTIPLY_INTEGER)
|
||||
vm_binop_integer(*);
|
||||
|
||||
@ -303,17 +303,17 @@ static void *op_lookup[255] = {
|
||||
|
||||
VM_OP(DOP_DIVIDE_INTEGER)
|
||||
vm_assert(dst_unwrap_integer(stack[oparg(3, 0xFF)]) != 0, "integer divide error");
|
||||
vm_assert(!(dst_unwrap_integer(stack[oparg(3, 0xFF)]) == -1 &&
|
||||
vm_assert(!(dst_unwrap_integer(stack[oparg(3, 0xFF)]) == -1 &&
|
||||
dst_unwrap_integer(stack[oparg(2, 0xFF)]) == INT32_MIN),
|
||||
"integer divide error");
|
||||
vm_binop_integer(/);
|
||||
|
||||
|
||||
VM_OP(DOP_DIVIDE_IMMEDIATE)
|
||||
{
|
||||
int32_t op1 = dst_unwrap_integer(stack[oparg(2, 0xFF)]);
|
||||
int32_t op2 = *((int32_t *)pc) >> 24;
|
||||
/* Check for degenerate integer division (divide by zero, and dividing
|
||||
* min value by -1). These checks could be omitted if the arg is not
|
||||
* min value by -1). These checks could be omitted if the arg is not
|
||||
* 0 or -1. */
|
||||
if (op2 == 0)
|
||||
vm_throw("integer divide error");
|
||||
@ -362,7 +362,7 @@ static void *op_lookup[255] = {
|
||||
VM_OP(DOP_BNOT)
|
||||
stack[oparg(1, 0xFF)] = dst_wrap_integer(~dst_unwrap_integer(stack[oparg(2, 0xFFFF)]));
|
||||
vm_next();
|
||||
|
||||
|
||||
VM_OP(DOP_SHIFT_RIGHT_UNSIGNED)
|
||||
stack[oparg(1, 0xFF)] = dst_wrap_integer(
|
||||
(int32_t)(((uint32_t)dst_unwrap_integer(stack[oparg(2, 0xFF)]))
|
||||
@ -655,7 +655,7 @@ static void *op_lookup[255] = {
|
||||
stack[oparg(1, 0xFF)] = dst_wrap_function(fn);
|
||||
pc++;
|
||||
vm_checkgc_next();
|
||||
}
|
||||
}
|
||||
|
||||
VM_OP(DOP_PUSH)
|
||||
dst_fiber_push(fiber, stack[oparg(1, 0xFFFFFF)]);
|
||||
@ -664,7 +664,7 @@ static void *op_lookup[255] = {
|
||||
vm_checkgc_next();
|
||||
|
||||
VM_OP(DOP_PUSH_2)
|
||||
dst_fiber_push2(fiber,
|
||||
dst_fiber_push2(fiber,
|
||||
stack[oparg(1, 0xFF)],
|
||||
stack[oparg(2, 0xFFFF)]);
|
||||
pc++;
|
||||
@ -672,7 +672,7 @@ static void *op_lookup[255] = {
|
||||
vm_checkgc_next();
|
||||
|
||||
VM_OP(DOP_PUSH_3)
|
||||
dst_fiber_push3(fiber,
|
||||
dst_fiber_push3(fiber,
|
||||
stack[oparg(1, 0xFF)],
|
||||
stack[oparg(2, 0xFF)],
|
||||
stack[oparg(3, 0xFF)]);
|
||||
@ -685,7 +685,7 @@ static void *op_lookup[255] = {
|
||||
const Dst *vals;
|
||||
int32_t len;
|
||||
if (dst_seq_view(stack[oparg(1, 0xFFFFFF)], &vals, &len)) {
|
||||
dst_fiber_pushn(fiber, vals, len);
|
||||
dst_fiber_pushn(fiber, vals, len);
|
||||
} else {
|
||||
vm_throw("expected array/tuple");
|
||||
}
|
||||
@ -871,7 +871,7 @@ static void *op_lookup[255] = {
|
||||
dst_gcunroot(dst_wrap_fiber(fiber));
|
||||
dst_vm_fiber = old_vm_fiber;
|
||||
*out = retreg;
|
||||
/* All statuses correspond to signals except new and alive,
|
||||
/* All statuses correspond to signals except new and alive,
|
||||
* which cannot be entered when exiting the vm loop.
|
||||
* DST_SIGNAL_OK -> DST_STATUS_DEAD
|
||||
* DST_SIGNAL_YIELD -> DST_STATUS_PENDING */
|
||||
@ -888,7 +888,7 @@ static void *op_lookup[255] = {
|
||||
stack[oparg(1, 0xFF)] = retreg;
|
||||
pc++;
|
||||
vm_checkgc_next();
|
||||
}
|
||||
}
|
||||
|
||||
VM_END()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user