mirror of
https://github.com/janet-lang/janet
synced 2024-11-28 11:09:54 +00:00
More work on c library interface and io library.
This commit is contained in:
parent
3262316e60
commit
6df88f225f
4
Makefile
4
Makefile
@ -31,7 +31,7 @@ CLIBS=-lm -ldl
|
||||
PREFIX=/usr/local
|
||||
DST_TARGET=dst
|
||||
DEBUGGER=lldb
|
||||
DST_INTERNAL_HEADERS=$(addprefix core/,symcache.h opcodes.h strtod.h compile.h gc.h sourcemap.h util.h)
|
||||
DST_INTERNAL_HEADERS=$(addprefix core/,symcache.h opcodes.h compile.h gc.h sourcemap.h util.h)
|
||||
DST_HEADERS=$(addprefix include/dst/,dst.h dstconfig.h dsttypes.h dststate.h dststl.h)
|
||||
DST_C_LIBS=$(addprefix libs/,testlib.so)
|
||||
|
||||
@ -64,7 +64,7 @@ $(DST_TARGET): $(DST_CORE_SOURCES) $(DST_CLIENT_SOURCES) $(DST_ALL_HEADERS)
|
||||
#######################
|
||||
|
||||
%.so: %.c $(DST_HEADERS)
|
||||
$(CC) $(CFLAGS) -shared -undefined dynamic_lookup -o $@ $<
|
||||
$(CC) $(CFLAGS) -DDST_LIB -shared -undefined dynamic_lookup -o $@ $<
|
||||
|
||||
|
||||
###################
|
||||
|
@ -270,7 +270,8 @@ int main(int argc, char **argv) {
|
||||
/* Set up VM */
|
||||
dst_init();
|
||||
dst_vm_gc_interval = gcinterval;
|
||||
env = dst_loadstl(DST_LOAD_ROOT);
|
||||
env = dst_stl_env();
|
||||
dst_gcroot(env);
|
||||
|
||||
/* Read the arguments. Only process files. */
|
||||
for (i = 1; i < argc; ++i) {
|
||||
|
@ -728,7 +728,7 @@ DstSlot dstc_tuple(DstFopts opts) {
|
||||
}
|
||||
|
||||
static DstSlot dstc_array(DstFopts opts) {
|
||||
return dstc_call(opts, dstc_toslots(opts, 0), dstc_cslot(dst_wrap_cfunction(dst_stl_array)));
|
||||
return dstc_call(opts, dstc_toslots(opts, 0), dstc_cslot(dst_wrap_cfunction(dst_cfun_array)));
|
||||
}
|
||||
|
||||
static DstSlot dstc_tablector(DstFopts opts, DstCFunction cfun) {
|
||||
@ -763,10 +763,10 @@ DstSlot dstc_value(DstFopts opts) {
|
||||
ret = dstc_array(opts);
|
||||
break;
|
||||
case DST_STRUCT:
|
||||
ret = dstc_tablector(opts, dst_stl_struct);
|
||||
ret = dstc_tablector(opts, dst_cfun_struct);
|
||||
break;
|
||||
case DST_TABLE:
|
||||
ret = dstc_tablector(opts, dst_stl_table);
|
||||
ret = dstc_tablector(opts, dst_cfun_table);
|
||||
break;
|
||||
}
|
||||
if (opts.flags & DST_FOPTS_TAIL) {
|
||||
|
@ -216,8 +216,12 @@ static void dst_deinit_block(DstGCMemoryHeader *block) {
|
||||
free(((DstFunction *)mem)->envs);
|
||||
break;
|
||||
case DST_MEMORY_ABSTRACT:
|
||||
if (h->type->finalize)
|
||||
h->type->finalize((void *)(h + 1), h->size);
|
||||
if (h->type->gc) {
|
||||
if (h->type->gc((void *)(h + 1), h->size)) {
|
||||
/* finalizer failed. try again later? */
|
||||
;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DST_MEMORY_FUNCENV:
|
||||
{
|
||||
|
296
core/io.c
296
core/io.c
@ -22,179 +22,233 @@
|
||||
|
||||
#include <dst/dst.h>
|
||||
|
||||
DstAbstractType dst_stl_filetype = {
|
||||
"stl.file",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
#define IO_WRITE 1
|
||||
#define IO_READ 2
|
||||
#define IO_APPEND 4
|
||||
#define IO_UPDATE 8
|
||||
#define IO_NOT_CLOSEABLE 16
|
||||
#define IO_CLOSED 32
|
||||
#define IO_BINARY 64
|
||||
#define IO_SERIALIZABLE 128
|
||||
|
||||
typedef struct IOFile IOFile;
|
||||
struct IOFile {
|
||||
FILE *file;
|
||||
int flags;
|
||||
};
|
||||
|
||||
static int dst_io_gc(void *p, size_t len);
|
||||
|
||||
DstAbstractType dst_io_filetype = {
|
||||
"io.file",
|
||||
dst_io_gc
|
||||
};
|
||||
|
||||
/* Check argupments to fopen */
|
||||
static int checkflags(const uint8_t *str, int32_t len) {
|
||||
int flags = 0;
|
||||
int32_t i;
|
||||
if (!len || len > 3) return -1;
|
||||
switch (*str) {
|
||||
default:
|
||||
return -1;
|
||||
case 'w':
|
||||
flags |= IO_WRITE;
|
||||
break;
|
||||
case 'a':
|
||||
flags |= IO_APPEND;
|
||||
break;
|
||||
case 'r':
|
||||
flags |= IO_READ;
|
||||
break;
|
||||
}
|
||||
for (i = 1; i < len; i++) {
|
||||
switch (str[i]) {
|
||||
default:
|
||||
return -1;
|
||||
case '+':
|
||||
if (flags & IO_UPDATE) return -1;
|
||||
flags |= IO_UPDATE;
|
||||
break;
|
||||
case 'b':
|
||||
if (flags & IO_BINARY) return -1;
|
||||
flags |= IO_BINARY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
/* Check file argument */
|
||||
static FILE **checkfile(int32_t argn, Dst *argv, Dst *ret, int32_t n) {
|
||||
FILE **fp;
|
||||
if (n >= argn) {
|
||||
*ret = dst_cstringv("expected stl.file");
|
||||
static IOFile *checkfile(DstArgs args, int32_t n) {
|
||||
IOFile *iof;
|
||||
if (n >= args.n) {
|
||||
dst_throw(args, "expected io.file");
|
||||
return NULL;
|
||||
}
|
||||
if (!dst_checktype(argv[n], DST_ABSTRACT)) {
|
||||
*ret = dst_cstringv("expected stl.file");
|
||||
if (!dst_checktype(args.v[n], DST_ABSTRACT)) {
|
||||
dst_throw(args, "expected io.file");
|
||||
return NULL;
|
||||
}
|
||||
fp = (FILE **) dst_unwrap_abstract(argv[n]);
|
||||
if (dst_abstract_type(fp) != &dst_stl_filetype) {
|
||||
*ret = dst_cstringv("expected stl.file");
|
||||
iof = (IOFile *) dst_unwrap_abstract(args.v[n]);
|
||||
if (dst_abstract_type(iof) != &dst_io_filetype) {
|
||||
dst_throw(args, "expected io.file");
|
||||
return NULL;
|
||||
}
|
||||
return fp;
|
||||
return iof;
|
||||
}
|
||||
|
||||
/* Check buffer argument */
|
||||
static DstBuffer *checkbuffer(int32_t argn, Dst *argv, Dst *ret, int32_t n, int optional) {
|
||||
if (optional && n == argn) {
|
||||
static DstBuffer *checkbuffer(DstArgs args, int32_t n, int optional) {
|
||||
if (optional && n == args.n) {
|
||||
return dst_buffer(0);
|
||||
}
|
||||
if (n >= argn) {
|
||||
*ret = dst_cstringv("expected buffer");
|
||||
if (n >= args.n) {
|
||||
dst_throw(args, "expected buffer");
|
||||
return NULL;
|
||||
}
|
||||
if (!dst_checktype(argv[n], DST_BUFFER)) {
|
||||
*ret = dst_cstringv("expected buffer");
|
||||
if (!dst_checktype(args.v[n], DST_BUFFER)) {
|
||||
dst_throw(args, "expected buffer");
|
||||
return NULL;
|
||||
}
|
||||
return dst_unwrap_abstract(argv[n]);
|
||||
return dst_unwrap_abstract(args.v[n]);
|
||||
}
|
||||
|
||||
/* Check char array argument */
|
||||
static int checkchars(int32_t argn, Dst *argv, Dst *ret, int32_t n, const uint8_t **str, int32_t *len) {
|
||||
if (n >= argn) {
|
||||
*ret = dst_cstringv("expected string/buffer");
|
||||
static int checkchars(DstArgs args, int32_t n, const uint8_t **str, int32_t *len) {
|
||||
if (n >= args.n) {
|
||||
dst_throw(args, "expected string/buffer");
|
||||
return 0;
|
||||
}
|
||||
if (!dst_chararray_view(argv[n], str, len)) {
|
||||
*ret = dst_cstringv("expected string/buffer");
|
||||
if (!dst_chararray_view(args.v[n], str, len)) {
|
||||
dst_throw(args, "expected string/buffer");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static Dst makef(FILE *f, int flags) {
|
||||
IOFile *iof = (IOFile *) dst_abstract(&dst_io_filetype, sizeof(IOFile));
|
||||
iof->file = f;
|
||||
iof->flags = flags;
|
||||
return dst_wrap_abstract(iof);
|
||||
}
|
||||
|
||||
/* Open a a file and return a userdata wrapper around the C file API. */
|
||||
int dst_stl_fileopen(int32_t argn, Dst *argv, Dst *ret) {
|
||||
if (argn < 2) {
|
||||
*ret = dst_cstringv("expected at least 2 arguments");
|
||||
return 1;
|
||||
}
|
||||
const uint8_t *fname = dst_to_string(argv[0]);
|
||||
const uint8_t *fmode = dst_to_string(argv[1]);
|
||||
static int dst_io_fopen(DstArgs args) {
|
||||
const uint8_t *fname, *fmode;
|
||||
int32_t modelen;
|
||||
FILE *f;
|
||||
FILE **fp;
|
||||
int flags;
|
||||
if (args.n < 1 || args.n > 2) return dst_throw(args, "expected 1 or 2 arguments");
|
||||
if (!dst_checktype(args.v[0], DST_STRING)) return dst_throw(args, "expected string filename");
|
||||
fname = dst_unwrap_string(args.v[0]);
|
||||
if (args.n == 2) {
|
||||
if (!dst_checktype(args.v[1], DST_STRING)) return dst_throw(args, "expected string mode");
|
||||
fmode = dst_unwrap_string(args.v[1]);
|
||||
modelen = dst_string_length(fmode);
|
||||
} else {
|
||||
fmode = (const uint8_t *)"r";
|
||||
modelen = 1;
|
||||
}
|
||||
if ((flags = checkflags(fmode, modelen)) < 0) return dst_throw(args, "invalid file mode");
|
||||
f = fopen((const char *)fname, (const char *)fmode);
|
||||
if (!f) {
|
||||
*ret = dst_cstringv("could not open file");
|
||||
return 1;
|
||||
}
|
||||
fp = dst_abstract(&dst_stl_filetype, sizeof(FILE *));
|
||||
*fp = f;
|
||||
*ret = dst_wrap_abstract(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read an entire file into memory */
|
||||
int dst_stl_slurp(int32_t argn, Dst *argv, Dst *ret) {
|
||||
DstBuffer *b;
|
||||
size_t fsize;
|
||||
FILE *f;
|
||||
FILE **fp = checkfile(argn, argv, ret, 0);
|
||||
if (!fp) return 1;
|
||||
b = checkbuffer(argn, argv, ret, 1, 1);
|
||||
if (!b) return 1;
|
||||
f = *fp;
|
||||
/* Read whole file */
|
||||
fseek(f, 0, SEEK_END);
|
||||
fsize = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
if (fsize > INT32_MAX || dst_buffer_extra(b, fsize)) {
|
||||
*ret = dst_cstringv("buffer overflow");
|
||||
return 1;
|
||||
}
|
||||
/* Ensure buffer size */
|
||||
if (fsize != fread((char *)(b->data + b->count), fsize, 1, f)) {
|
||||
*ret = dst_cstringv("error reading file");
|
||||
return 1;
|
||||
}
|
||||
b->count += fsize;
|
||||
/* return */
|
||||
*ret = dst_wrap_buffer(b);
|
||||
return 0;
|
||||
if (!f) return dst_throw(args, "could not open file");
|
||||
return dst_return(args, makef(f, flags));
|
||||
}
|
||||
|
||||
/* Read a certain number of bytes into memory */
|
||||
int dst_stl_fileread(int32_t argn, Dst *argv, Dst *ret) {
|
||||
static int dst_io_fread(DstArgs args) {
|
||||
DstBuffer *b;
|
||||
FILE *f;
|
||||
int32_t len;
|
||||
FILE **fp = checkfile(argn, argv, ret, 0);
|
||||
if (!fp) return 1;
|
||||
if (!dst_checktype(argv[1], DST_INTEGER)) {
|
||||
*ret = dst_cstringv("expected positive integer");
|
||||
return 1;
|
||||
}
|
||||
len = dst_unwrap_integer(argv[1]);
|
||||
if (len < 0) {
|
||||
*ret = dst_cstringv("expected positive integer");
|
||||
return 1;
|
||||
}
|
||||
b = checkbuffer(argn, argv, ret, 2, 1);
|
||||
size_t ntoread, nread;
|
||||
IOFile *iof = checkfile(args, 0);
|
||||
if (!iof) return 1;
|
||||
if (!dst_checktype(args.v[1], DST_INTEGER)) return dst_throw(args, "expected positive integer");
|
||||
len = dst_unwrap_integer(args.v[1]);
|
||||
if (len < 0) return dst_throw(args, "expected positive integer");
|
||||
b = checkbuffer(args, 2, 1);
|
||||
if (!b) return 1;
|
||||
|
||||
f = *fp;
|
||||
if (!(iof->flags & (IO_READ | IO_UPDATE))) return dst_throw(args, "file is not readable");
|
||||
/* Ensure buffer size */
|
||||
if (dst_buffer_extra(b, len)) {
|
||||
*ret = dst_cstringv("buffer overflow");
|
||||
return 1;
|
||||
}
|
||||
b->count += fread((char *)(b->data + b->count), len, 1, f) * len;
|
||||
*ret = dst_wrap_buffer(b);
|
||||
return 0;
|
||||
if (dst_buffer_extra(b, len)) return dst_throw(args, "buffer overflow");
|
||||
ntoread = len;
|
||||
nread = fread((char *)(b->data + b->count), 1, ntoread, iof->file);
|
||||
if (nread != ntoread && ferror(iof->file)) return dst_throw(args, "could not read file");
|
||||
b->count += len;
|
||||
return dst_return(args, dst_wrap_buffer(b));
|
||||
}
|
||||
|
||||
/* Write bytes to a file */
|
||||
int dst_stl_filewrite(int32_t argn, Dst *argv, Dst *ret) {
|
||||
FILE *f;
|
||||
static int dst_io_fwrite(DstArgs args) {
|
||||
int32_t len, i;
|
||||
FILE **fp = checkfile(argn, argv, ret, 0);
|
||||
const uint8_t *str;
|
||||
if (!fp) return 1;
|
||||
if (!dst_checktype(argv[1], DST_INTEGER)) {
|
||||
*ret = dst_cstringv("expected positive integer");
|
||||
return 1;
|
||||
IOFile *iof = checkfile(args, 0);
|
||||
if (!iof) return 1;
|
||||
if (!(iof->flags & (IO_WRITE | IO_APPEND | IO_UPDATE)))
|
||||
return dst_throw(args, "file is not writeable");
|
||||
for (i = 1; i < args.n; i++) {
|
||||
if (!checkchars(args, i, &str, &len)) return 1;
|
||||
if (!fwrite(str, len, 1, iof->file)) return dst_throw(args, "error writing to file");
|
||||
}
|
||||
len = dst_unwrap_integer(argv[1]);
|
||||
if (len < 0) {
|
||||
*ret = dst_cstringv("expected positive integer");
|
||||
return 1;
|
||||
return dst_return(args, dst_wrap_abstract(iof));
|
||||
}
|
||||
|
||||
for (i = 1; i < argn; i++) {
|
||||
if (!checkchars(argn, argv, ret, i, &str, &len)) return 1;
|
||||
|
||||
f = *fp;
|
||||
if (len != (int32_t) fwrite(str, len, 1, f)) {
|
||||
*ret = dst_cstringv("error writing to file");
|
||||
return 1;
|
||||
/* Flush the bytes in the file */
|
||||
static int dst_io_fflush(DstArgs args) {
|
||||
IOFile *iof = checkfile(args, 0);
|
||||
if (!iof) return 1;
|
||||
if (!(iof->flags & (IO_WRITE | IO_APPEND | IO_UPDATE)))
|
||||
return dst_throw(args, "file is not flushable");
|
||||
if (fflush(iof->file)) return dst_throw(args, "could not flush file");
|
||||
return dst_return(args, dst_wrap_abstract(iof));
|
||||
}
|
||||
|
||||
/* Cleanup a file */
|
||||
static int dst_io_gc(void *p, size_t len) {
|
||||
(void) len;
|
||||
IOFile *iof = (IOFile *)p;
|
||||
if (!(iof->flags & (IO_NOT_CLOSEABLE | IO_CLOSED))) {
|
||||
return fclose(iof->file);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Close a file */
|
||||
int dst_stl_fileclose(int32_t argn, Dst *argv, Dst *ret) {
|
||||
FILE *f;
|
||||
FILE **fp = checkfile(argn, argv, ret, 0);
|
||||
if (!fp) return 1;
|
||||
f = *fp;
|
||||
if (fclose(f)) {
|
||||
*ret = dst_cstringv("could not close file");
|
||||
return 1;
|
||||
static int dst_io_fclose(DstArgs args) {
|
||||
IOFile *iof = checkfile(args, 0);
|
||||
if (!iof) return 1;
|
||||
if (iof->flags & (IO_CLOSED | IO_NOT_CLOSEABLE)) return dst_throw(args, "could not close file");
|
||||
if (fclose(iof->file)) return dst_throw(args, "could not close file");
|
||||
iof->flags |= IO_CLOSED;
|
||||
return dst_return(args, dst_wrap_abstract(iof));
|
||||
}
|
||||
|
||||
/* Define the entry point of the library */
|
||||
#ifdef DST_LIB
|
||||
#define dst_io_init _dst_init
|
||||
#endif
|
||||
|
||||
/* Module entry point */
|
||||
int dst_io_init(DstArgs args) {
|
||||
DstTable *module = dst_get_module(args);
|
||||
dst_module_def(module, "fopen", dst_wrap_cfunction(dst_io_fopen));
|
||||
dst_module_def(module, "fclose", dst_wrap_cfunction(dst_io_fclose));
|
||||
dst_module_def(module, "fread", dst_wrap_cfunction(dst_io_fread));
|
||||
dst_module_def(module, "fwrite", dst_wrap_cfunction(dst_io_fwrite));
|
||||
dst_module_def(module, "fflush", dst_wrap_cfunction(dst_io_fflush));
|
||||
|
||||
/* stdout */
|
||||
dst_module_def(module, "stdout",
|
||||
makef(stdout, IO_APPEND | IO_NOT_CLOSEABLE | IO_SERIALIZABLE));
|
||||
|
||||
/* stderr */
|
||||
dst_module_def(module, "stderr",
|
||||
makef(stderr, IO_APPEND | IO_NOT_CLOSEABLE | IO_SERIALIZABLE));
|
||||
|
||||
/* stdin */
|
||||
dst_module_def(module, "stdin",
|
||||
makef(stdin, IO_READ | IO_NOT_CLOSEABLE | IO_SERIALIZABLE));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
99
core/math.c
99
core/math.c
@ -293,3 +293,102 @@ int dst_modf(DstArgs args) {
|
||||
*args.ret = dst_wrap_tuple(dst_tuple_end(tup));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Comparison */
|
||||
#define DST_DEFINE_COMPARATOR(name, pred)\
|
||||
static int dst_math_##name(DstArgs args) {\
|
||||
int32_t i;\
|
||||
for (i = 0; i < args.n - 1; i++) {\
|
||||
if (dst_compare(args.v[i], args.v[i+1]) pred) {\
|
||||
*args.ret = dst_wrap_false();\
|
||||
return 0;\
|
||||
}\
|
||||
}\
|
||||
*args.ret = dst_wrap_true();\
|
||||
return 0;\
|
||||
}
|
||||
|
||||
DST_DEFINE_COMPARATOR(ascending, >= 0)
|
||||
DST_DEFINE_COMPARATOR(descending, <= 0)
|
||||
DST_DEFINE_COMPARATOR(notdescending, > 0)
|
||||
DST_DEFINE_COMPARATOR(notascending, < 0)
|
||||
|
||||
/* Boolean logic */
|
||||
static int dst_math_equal(DstArgs args) {
|
||||
int32_t i;
|
||||
for (i = 0; i < args.n - 1; i++) {
|
||||
if (!dst_equals(args.v[i], args.v[i+1])) {
|
||||
*args.ret = dst_wrap_false();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*args.ret = dst_wrap_true();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dst_math_notequal(DstArgs args) {
|
||||
int32_t i;
|
||||
for (i = 0; i < args.n - 1; i++) {
|
||||
if (dst_equals(args.v[i], args.v[i+1])) {
|
||||
*args.ret = dst_wrap_false();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*args.ret = dst_wrap_true();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dst_math_not(DstArgs args) {
|
||||
*args.ret = dst_wrap_boolean(args.n == 0 || !dst_truthy(args.v[0]));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* CMath entry point */
|
||||
|
||||
/* Define the entry point of the library */
|
||||
#ifdef DST_LIB
|
||||
#define dst_math_init _dst_init
|
||||
#endif
|
||||
|
||||
/* Module entry point */
|
||||
int dst_math_init(DstArgs args) {
|
||||
DstTable *module = dst_get_module(args);
|
||||
dst_module_def(module, "int", dst_wrap_cfunction(dst_int));
|
||||
dst_module_def(module, "real", dst_wrap_cfunction(dst_real));
|
||||
dst_module_def(module, "+", dst_wrap_cfunction(dst_add));
|
||||
dst_module_def(module, "-", dst_wrap_cfunction(dst_subtract));
|
||||
dst_module_def(module, "*", dst_wrap_cfunction(dst_multiply));
|
||||
dst_module_def(module, "/", dst_wrap_cfunction(dst_divide));
|
||||
dst_module_def(module, "%", dst_wrap_cfunction(dst_modulo));
|
||||
dst_module_def(module, "=", dst_wrap_cfunction(dst_math_equal));
|
||||
dst_module_def(module, "not=", dst_wrap_cfunction(dst_math_notequal));
|
||||
dst_module_def(module, "<", dst_wrap_cfunction(dst_math_ascending));
|
||||
dst_module_def(module, ">", dst_wrap_cfunction(dst_math_descending));
|
||||
dst_module_def(module, "<=", dst_wrap_cfunction(dst_math_notdescending));
|
||||
dst_module_def(module, ">=", dst_wrap_cfunction(dst_math_notascending));
|
||||
dst_module_def(module, "|", dst_wrap_cfunction(dst_bor));
|
||||
dst_module_def(module, "&", dst_wrap_cfunction(dst_band));
|
||||
dst_module_def(module, "^", dst_wrap_cfunction(dst_bxor));
|
||||
dst_module_def(module, "~", dst_wrap_cfunction(dst_bnot));
|
||||
dst_module_def(module, ">>", dst_wrap_cfunction(dst_lshift));
|
||||
dst_module_def(module, "<<", dst_wrap_cfunction(dst_rshift));
|
||||
dst_module_def(module, ">>>", dst_wrap_cfunction(dst_lshiftu));
|
||||
dst_module_def(module, "not", dst_wrap_cfunction(dst_math_not));
|
||||
dst_module_def(module, "cos", dst_wrap_cfunction(dst_cos));
|
||||
dst_module_def(module, "sin", dst_wrap_cfunction(dst_sin));
|
||||
dst_module_def(module, "tan", dst_wrap_cfunction(dst_tan));
|
||||
dst_module_def(module, "acos", dst_wrap_cfunction(dst_acos));
|
||||
dst_module_def(module, "asin", dst_wrap_cfunction(dst_asin));
|
||||
dst_module_def(module, "atan", dst_wrap_cfunction(dst_atan));
|
||||
dst_module_def(module, "exp", dst_wrap_cfunction(dst_exp));
|
||||
dst_module_def(module, "log", dst_wrap_cfunction(dst_log));
|
||||
dst_module_def(module, "log10", dst_wrap_cfunction(dst_log10));
|
||||
dst_module_def(module, "sqrt", dst_wrap_cfunction(dst_sqrt));
|
||||
dst_module_def(module, "floor", dst_wrap_cfunction(dst_floor));
|
||||
dst_module_def(module, "ceil", dst_wrap_cfunction(dst_ceil));
|
||||
dst_module_def(module, "pow", dst_wrap_cfunction(dst_pow));
|
||||
dst_module_def(module, "pi", dst_wrap_real(M_PI));
|
||||
dst_module_def(module, "\xCF\x80", dst_wrap_real(M_PI));
|
||||
dst_module_def(module, "e", dst_wrap_real(M_E));
|
||||
return 0;
|
||||
}
|
||||
|
@ -69,5 +69,6 @@ int dst_load_native(DstArgs args) {
|
||||
*args.ret = dst_wrap_string(error);
|
||||
return 1;
|
||||
}
|
||||
return init(args);
|
||||
*args.ret = dst_wrap_cfunction(init);
|
||||
return 0;
|
||||
}
|
||||
|
@ -21,7 +21,6 @@
|
||||
*/
|
||||
|
||||
#include <dst/dst.h>
|
||||
#include "strtod.h"
|
||||
|
||||
/* Checks if a string slice is equal to a string constant */
|
||||
static int check_str_const(const char *ref, const uint8_t *start, const uint8_t *end) {
|
||||
|
322
core/stl.c
322
core/stl.c
@ -24,17 +24,10 @@
|
||||
#include <dst/dststl.h>
|
||||
|
||||
int dst_stl_push(DstArgs args) {
|
||||
if (args.n != 2) {
|
||||
*args.ret = dst_cstringv("expected 2 arguments");
|
||||
return 1;
|
||||
}
|
||||
if (!dst_checktype(args.v[0], DST_ARRAY)) {
|
||||
*args.ret = dst_cstringv("expected array");
|
||||
return 1;
|
||||
}
|
||||
if (args.n != 2) return dst_throw(args, "expected 2 arguments");
|
||||
if (!dst_checktype(args.v[0], DST_ARRAY)) return dst_throw(args, "expected array");
|
||||
dst_array_push(dst_unwrap_array(args.v[0]), args.v[1]);
|
||||
*args.ret = args.v[0];
|
||||
return 0;
|
||||
return dst_return(args, args.v[0]);
|
||||
}
|
||||
|
||||
int dst_stl_parse(DstArgs args) {
|
||||
@ -43,14 +36,8 @@ int dst_stl_parse(DstArgs args) {
|
||||
DstParseResult res;
|
||||
const char *status_string = "ok";
|
||||
DstTable *t;
|
||||
if (args.n < 1) {
|
||||
*args.ret = dst_cstringv("expected at least on argument");
|
||||
return 1;
|
||||
}
|
||||
if (!dst_chararray_view(args.v[0], &src, &len)) {
|
||||
*args.ret = dst_cstringv("expected string/buffer");
|
||||
return 1;
|
||||
}
|
||||
if (args.n < 1) return dst_throw(args, "expected at least on argument");
|
||||
if (!dst_chararray_view(args.v[0], &src, &len)) return dst_throw(args, "expected string/buffer");
|
||||
res = dst_parse(src, len);
|
||||
t = dst_table(4);
|
||||
switch (res.status) {
|
||||
@ -72,39 +59,32 @@ int dst_stl_parse(DstArgs args) {
|
||||
if (res.status == DST_PARSE_OK) dst_table_put(t, dst_cstringv("value"), res.value);
|
||||
if (res.status == DST_PARSE_ERROR) dst_table_put(t, dst_cstringv("error"), dst_wrap_string(res.error));
|
||||
dst_table_put(t, dst_cstringv("bytes-read"), dst_wrap_integer(res.bytes_read));
|
||||
*args.ret = dst_wrap_table(t);
|
||||
return 0;
|
||||
return dst_return(args, dst_wrap_table(t));
|
||||
}
|
||||
|
||||
int dst_stl_compile(DstArgs args) {
|
||||
DstCompileOptions opts;
|
||||
DstCompileResult res;
|
||||
DstTable *t;
|
||||
if (args.n < 1) {
|
||||
*args.ret = dst_cstringv("expected at least on argument");
|
||||
return 1;
|
||||
}
|
||||
if (args.n >= 3 && !dst_checktype(args.v[2], DST_TUPLE)) {
|
||||
*args.ret = dst_cstringv("expected source map to be tuple");
|
||||
return 1;
|
||||
}
|
||||
if (args.n < 1)
|
||||
return dst_throw(args, "expected at least one argument");
|
||||
if (args.n >= 3 && !dst_checktype(args.v[2], DST_TUPLE))
|
||||
return dst_throw(args, "expected source map to be tuple");
|
||||
opts.source = args.v[0];
|
||||
opts.env = args.n >= 2 ? args.v[1] : dst_loadstl(0);
|
||||
opts.env = args.n >= 2 ? args.v[1] : dst_stl_env();
|
||||
opts.sourcemap = args.n >= 3 ? dst_unwrap_tuple(args.v[2]) : NULL;
|
||||
opts.flags = 0;
|
||||
res = dst_compile(opts);
|
||||
if (res.status == DST_COMPILE_OK) {
|
||||
DstFunction *fun = dst_compile_func(res);
|
||||
*args.ret = dst_wrap_function(fun);
|
||||
return dst_return(args, dst_wrap_function(fun));
|
||||
} else {
|
||||
t = dst_table(2);
|
||||
dst_table_put(t, dst_cstringv("error"), dst_wrap_string(res.error));
|
||||
dst_table_put(t, dst_cstringv("error-start"), dst_wrap_integer(res.error_start));
|
||||
dst_table_put(t, dst_cstringv("error-end"), dst_wrap_integer(res.error_end));
|
||||
*args.ret = dst_wrap_table(t);
|
||||
return dst_return(args, dst_wrap_table(t));
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int dst_stl_exit(DstArgs args) {
|
||||
@ -159,92 +139,75 @@ int dst_stl_string(DstArgs args) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dst_stl_buffer_to_string(DstArgs args) {
|
||||
DstBuffer *b;
|
||||
if (args.n != 1) return dst_throw(args, "expected 1 argument");
|
||||
if (!dst_checktype(args.v[0], DST_BUFFER)) return dst_throw(args, "expected buffer");
|
||||
b = dst_unwrap_buffer(args.v[0]);
|
||||
return dst_return(args, dst_wrap_string(dst_string(b->data, b->count)));
|
||||
}
|
||||
|
||||
int dst_stl_asm(DstArgs args) {
|
||||
DstAssembleOptions opts;
|
||||
DstAssembleResult res;
|
||||
if (args.n < 1) {
|
||||
*args.ret = dst_cstringv("expected assembly source");
|
||||
return 1;
|
||||
}
|
||||
if (args.n < 1) return dst_throw(args, "expected assembly source");
|
||||
opts.source = args.v[0];
|
||||
opts.flags = 0;
|
||||
res = dst_asm(opts);
|
||||
if (res.status == DST_ASSEMBLE_OK) {
|
||||
*args.ret = dst_wrap_function(dst_asm_func(res));
|
||||
return 0;
|
||||
return dst_return(args, dst_wrap_function(dst_asm_func(res)));
|
||||
} else {
|
||||
*args.ret = dst_wrap_string(res.error);
|
||||
return 1;
|
||||
return dst_throwv(args, dst_wrap_string(res.error));
|
||||
}
|
||||
}
|
||||
|
||||
int dst_stl_disasm(DstArgs args) {
|
||||
DstFunction *f;
|
||||
if (args.n < 1 || !dst_checktype(args.v[0], DST_FUNCTION)) {
|
||||
*args.ret = dst_cstringv("expected function");
|
||||
return 1;
|
||||
}
|
||||
if (args.n < 1 || !dst_checktype(args.v[0], DST_FUNCTION))
|
||||
return dst_throw(args, "expected function");
|
||||
f = dst_unwrap_function(args.v[0]);
|
||||
*args.ret = dst_disasm(f->def);
|
||||
return 0;
|
||||
return dst_return(args, dst_disasm(f->def));
|
||||
}
|
||||
|
||||
int dst_stl_tuple(DstArgs args) {
|
||||
*args.ret = dst_wrap_tuple(dst_tuple_n(args.v, args.n));
|
||||
return 0;
|
||||
int dst_cfun_tuple(DstArgs args) {
|
||||
return dst_return(args, dst_wrap_tuple(dst_tuple_n(args.v, args.n)));
|
||||
}
|
||||
|
||||
int dst_stl_array(DstArgs args) {
|
||||
int dst_cfun_array(DstArgs args) {
|
||||
DstArray *array = dst_array(args.n);
|
||||
array->count = args.n;
|
||||
memcpy(array->data, args.v, args.n * sizeof(Dst));
|
||||
*args.ret = dst_wrap_array(array);
|
||||
return 0;
|
||||
return dst_return(args, dst_wrap_array(array));
|
||||
}
|
||||
|
||||
int dst_stl_table(DstArgs args) {
|
||||
int dst_cfun_table(DstArgs args) {
|
||||
int32_t i;
|
||||
DstTable *table = dst_table(args.n >> 1);
|
||||
if (args.n & 1) {
|
||||
*args.ret = dst_cstringv("expected even number of arguments");
|
||||
return 1;
|
||||
}
|
||||
if (args.n & 1) return 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]);
|
||||
}
|
||||
*args.ret = dst_wrap_table(table);
|
||||
return 0;
|
||||
return dst_return(args, dst_wrap_table(table));
|
||||
}
|
||||
|
||||
int dst_stl_struct(DstArgs args) {
|
||||
int dst_cfun_struct(DstArgs args) {
|
||||
int32_t i;
|
||||
DstKV *st = dst_struct_begin(args.n >> 1);
|
||||
if (args.n & 1) {
|
||||
*args.ret = dst_cstringv("expected even number of arguments");
|
||||
return 1;
|
||||
}
|
||||
if (args.n & 1) return dst_throw(args, "expected even number of arguments");
|
||||
for (i = 0; i < args.n; i += 2) {
|
||||
dst_struct_put(st, args.v[i], args.v[i + 1]);
|
||||
}
|
||||
*args.ret = dst_wrap_struct(dst_struct_end(st));
|
||||
return 0;
|
||||
return dst_return(args, dst_wrap_struct(dst_struct_end(st)));
|
||||
}
|
||||
|
||||
int dst_stl_fiber(DstArgs args) {
|
||||
DstFiber *fiber;
|
||||
if (args.n < 1) {
|
||||
*args.ret = dst_cstringv("expected at least one argument");
|
||||
return 1;
|
||||
}
|
||||
if (!dst_checktype(args.v[0], DST_FUNCTION)) {
|
||||
*args.ret = dst_cstringv("expected a function");
|
||||
return 1;
|
||||
}
|
||||
if (args.n < 1) return dst_throw(args, "expected at least one argument");
|
||||
if (!dst_checktype(args.v[0], DST_FUNCTION)) return dst_throw(args, "expected a function");
|
||||
fiber = dst_fiber(64);
|
||||
dst_fiber_funcframe(fiber, dst_unwrap_function(args.v[0]));
|
||||
fiber->parent = dst_vm_fiber;
|
||||
*args.ret = dst_wrap_fiber(fiber);
|
||||
return 0;
|
||||
return dst_return(args, dst_wrap_fiber(fiber));
|
||||
}
|
||||
|
||||
int dst_stl_buffer(DstArgs args) {
|
||||
@ -255,60 +218,41 @@ int dst_stl_buffer(DstArgs args) {
|
||||
int32_t len = dst_string_length(bytes);
|
||||
dst_buffer_push_bytes(buffer, bytes, len);
|
||||
}
|
||||
*args.ret = dst_wrap_buffer(buffer);
|
||||
return 0;
|
||||
return dst_return(args, dst_wrap_buffer(buffer));
|
||||
}
|
||||
|
||||
int dst_stl_gensym(DstArgs args) {
|
||||
if (args.n > 1) {
|
||||
*args.ret = dst_cstringv("expected one argument");
|
||||
return 1;
|
||||
}
|
||||
if (args.n > 1) return dst_throw(args, "expected one argument");
|
||||
if (args.n == 0) {
|
||||
*args.ret = dst_wrap_symbol(dst_symbol_gen(NULL, 0));
|
||||
return dst_return(args, dst_wrap_symbol(dst_symbol_gen(NULL, 0)));
|
||||
} else {
|
||||
const uint8_t *s = dst_to_string(args.v[0]);
|
||||
*args.ret = dst_wrap_symbol(dst_symbol_gen(s, dst_string_length(s)));
|
||||
return dst_return(args, dst_wrap_symbol(dst_symbol_gen(s, dst_string_length(s))));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dst_stl_length(DstArgs args) {
|
||||
if (args.n != 1) {
|
||||
*args.ret = dst_cstringv("expected at least 1 argument");
|
||||
return 1;
|
||||
}
|
||||
*args.ret = dst_wrap_integer(dst_length(args.v[0]));
|
||||
return 0;
|
||||
if (args.n != 1) return dst_throw(args, "expected at least 1 argument");
|
||||
return dst_return(args, dst_wrap_integer(dst_length(args.v[0])));
|
||||
}
|
||||
|
||||
int dst_stl_get(DstArgs args) {
|
||||
int32_t i;
|
||||
Dst ds;
|
||||
if (args.n < 1) {
|
||||
*args.ret = dst_cstringv("expected at least 1 argument");
|
||||
return 1;
|
||||
}
|
||||
if (args.n < 1) return dst_throw(args, "expected at least 1 argument");
|
||||
ds = args.v[0];
|
||||
for (i = 1; i < args.n; i++) {
|
||||
ds = dst_get(ds, args.v[i]);
|
||||
if (dst_checktype(ds, DST_NIL))
|
||||
break;
|
||||
}
|
||||
*args.ret = ds;
|
||||
return 0;
|
||||
return dst_return(args, ds);
|
||||
}
|
||||
|
||||
int dst_stl_status(DstArgs args) {
|
||||
const char *status;
|
||||
if (args.n != 1) {
|
||||
*args.ret = dst_cstringv("expected 1 argument");
|
||||
return 1;
|
||||
}
|
||||
if (!dst_checktype(args.v[0], DST_FIBER)) {
|
||||
*args.ret = dst_cstringv("expected fiber");
|
||||
return 1;
|
||||
}
|
||||
if (args.n != 1) return dst_throw(args, "expected 1 argument");
|
||||
if (!dst_checktype(args.v[0], DST_FIBER)) return dst_throw(args, "expected fiber");
|
||||
switch(dst_unwrap_fiber(args.v[0])->status) {
|
||||
case DST_FIBER_PENDING:
|
||||
status = "pending";
|
||||
@ -326,21 +270,15 @@ int dst_stl_status(DstArgs args) {
|
||||
status = "error";
|
||||
break;
|
||||
}
|
||||
*args.ret = dst_cstringv(status);
|
||||
return 0;
|
||||
return dst_return(args, dst_cstringv(status));
|
||||
}
|
||||
|
||||
int dst_stl_put(DstArgs args) {
|
||||
Dst ds, key, value;
|
||||
DstArgs subargs = args;
|
||||
if (args.n < 3) {
|
||||
*args.ret = dst_cstringv("expected at least 3 arguments");
|
||||
return 1;
|
||||
}
|
||||
if (args.n < 3) return dst_throw(args, "expected at least 3 arguments");
|
||||
subargs.n -= 2;
|
||||
if (dst_stl_get(subargs)) {
|
||||
return 1;
|
||||
}
|
||||
if (dst_stl_get(subargs)) return 1;
|
||||
ds = *args.ret;
|
||||
key = args.v[args.n - 2];
|
||||
value = args.v[args.n - 1];
|
||||
@ -348,123 +286,61 @@ int dst_stl_put(DstArgs args) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dst_stl_equal(DstArgs args) {
|
||||
int32_t i;
|
||||
for (i = 0; i < args.n - 1; i++) {
|
||||
if (!dst_equals(args.v[i], args.v[i+1])) {
|
||||
*args.ret = dst_wrap_false();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*args.ret = dst_wrap_true();
|
||||
int dst_stl_gccollect(DstArgs args) {
|
||||
(void) args;
|
||||
dst_collect();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dst_stl_notequal(DstArgs args) {
|
||||
int32_t i;
|
||||
for (i = 0; i < args.n - 1; i++) {
|
||||
if (dst_equals(args.v[i], args.v[i+1])) {
|
||||
*args.ret = dst_wrap_false();
|
||||
return 0;
|
||||
int dst_stl_type(DstArgs args) {
|
||||
if (args.n != 1) return dst_throw(args, "expected 1 argument");
|
||||
if (dst_checktype(args.v[0], DST_ABSTRACT)) {
|
||||
return dst_return(args, dst_cstringv(dst_abstract_type(dst_unwrap_abstract(args.v[0]))->name));
|
||||
} else {
|
||||
return dst_return(args, dst_cstringv(dst_type_names[dst_type(args.v[0])]));
|
||||
}
|
||||
}
|
||||
*args.ret = dst_wrap_true();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dst_stl_not(DstArgs args) {
|
||||
*args.ret = dst_wrap_boolean(args.n == 0 || !dst_truthy(args.v[0]));
|
||||
return 0;
|
||||
}
|
||||
Dst dst_stl_env() {
|
||||
Dst ret;
|
||||
DstArgs args;
|
||||
DstTable *module = dst_table(0);
|
||||
ret = dst_wrap_table(module);
|
||||
args.n = 1;
|
||||
args.v = &ret;
|
||||
args.ret = &ret;
|
||||
|
||||
#define DST_DEFINE_COMPARATOR(name, pred)\
|
||||
static int dst_stl_##name(DstArgs args) {\
|
||||
int32_t i;\
|
||||
for (i = 0; i < args.n - 1; i++) {\
|
||||
if (dst_compare(args.v[i], args.v[i+1]) pred) {\
|
||||
*args.ret = dst_wrap_false();\
|
||||
return 0;\
|
||||
}\
|
||||
}\
|
||||
*args.ret = dst_wrap_true();\
|
||||
return 0;\
|
||||
}
|
||||
dst_module_def(module, "native", dst_wrap_cfunction(dst_load_native));
|
||||
dst_module_def(module, "push", dst_wrap_cfunction(dst_stl_push));
|
||||
dst_module_def(module, "parse", dst_wrap_cfunction(dst_stl_parse));
|
||||
dst_module_def(module, "compile", dst_wrap_cfunction(dst_stl_compile));
|
||||
dst_module_def(module, "print", dst_wrap_cfunction(dst_stl_print));
|
||||
dst_module_def(module, "describe", dst_wrap_cfunction(dst_stl_describe));
|
||||
dst_module_def(module, "string", dst_wrap_cfunction(dst_stl_string));
|
||||
dst_module_def(module, "buffer-to-string", dst_wrap_cfunction(dst_stl_buffer_to_string));
|
||||
dst_module_def(module, "table", dst_wrap_cfunction(dst_cfun_table));
|
||||
dst_module_def(module, "array", dst_wrap_cfunction(dst_cfun_array));
|
||||
dst_module_def(module, "tuple", dst_wrap_cfunction(dst_cfun_tuple));
|
||||
dst_module_def(module, "struct", dst_wrap_cfunction(dst_cfun_struct));
|
||||
dst_module_def(module, "fiber", dst_wrap_cfunction(dst_stl_fiber));
|
||||
dst_module_def(module, "status", dst_wrap_cfunction(dst_stl_status));
|
||||
dst_module_def(module, "buffer", dst_wrap_cfunction(dst_stl_buffer));
|
||||
dst_module_def(module, "gensym", dst_wrap_cfunction(dst_stl_gensym));
|
||||
dst_module_def(module, "asm", dst_wrap_cfunction(dst_stl_asm));
|
||||
dst_module_def(module, "disasm", dst_wrap_cfunction(dst_stl_disasm));
|
||||
dst_module_def(module, "get", dst_wrap_cfunction(dst_stl_get));
|
||||
dst_module_def(module, "put", dst_wrap_cfunction(dst_stl_put));
|
||||
dst_module_def(module, "length", dst_wrap_cfunction(dst_stl_length));
|
||||
dst_module_def(module, "gccollect", dst_wrap_cfunction(dst_stl_gccollect));
|
||||
dst_module_def(module, "type", dst_wrap_cfunction(dst_stl_type));
|
||||
dst_module_def(module, "exit!", dst_wrap_cfunction(dst_stl_exit));
|
||||
|
||||
DST_DEFINE_COMPARATOR(ascending, >= 0)
|
||||
DST_DEFINE_COMPARATOR(descending, <= 0)
|
||||
DST_DEFINE_COMPARATOR(notdescending, > 0)
|
||||
DST_DEFINE_COMPARATOR(notascending, < 0)
|
||||
/* Allow references to the environment */
|
||||
dst_module_def(module, "_env", ret);
|
||||
|
||||
static DstReg stl[] = {
|
||||
{"push", dst_stl_push},
|
||||
{"load-native", dst_load_native},
|
||||
{"parse", dst_stl_parse},
|
||||
{"compile", dst_stl_compile},
|
||||
{"int", dst_int},
|
||||
{"real", dst_real},
|
||||
{"print", dst_stl_print},
|
||||
{"describe", dst_stl_describe},
|
||||
{"string", dst_stl_string},
|
||||
{"table", dst_stl_table},
|
||||
{"array", dst_stl_array},
|
||||
{"tuple", dst_stl_tuple},
|
||||
{"struct", dst_stl_struct},
|
||||
{"fiber", dst_stl_fiber},
|
||||
{"status", dst_stl_status},
|
||||
{"buffer", dst_stl_buffer},
|
||||
{"gensym", dst_stl_gensym},
|
||||
{"asm", dst_stl_asm},
|
||||
{"disasm", dst_stl_disasm},
|
||||
{"get", dst_stl_get},
|
||||
{"put", dst_stl_put},
|
||||
{"length", dst_stl_length},
|
||||
{"+", dst_add},
|
||||
{"-", dst_subtract},
|
||||
{"*", dst_multiply},
|
||||
{"/", dst_divide},
|
||||
{"%", dst_modulo},
|
||||
{"cos", dst_cos},
|
||||
{"sin", dst_sin},
|
||||
{"tan", dst_tan},
|
||||
{"acos", dst_acos},
|
||||
{"asin", dst_asin},
|
||||
{"atan", dst_atan},
|
||||
{"exp", dst_exp},
|
||||
{"log", dst_log},
|
||||
{"log10", dst_log10},
|
||||
{"sqrt", dst_sqrt},
|
||||
{"floor", dst_floor},
|
||||
{"ceil", dst_ceil},
|
||||
{"pow", dst_pow},
|
||||
{"=", dst_stl_equal},
|
||||
{"not=", dst_stl_notequal},
|
||||
{"<", dst_stl_ascending},
|
||||
{">", dst_stl_descending},
|
||||
{"<=", dst_stl_notdescending},
|
||||
{">=", dst_stl_notascending},
|
||||
{"|", dst_bor},
|
||||
{"&", dst_band},
|
||||
{"^", dst_bxor},
|
||||
{">>", dst_lshift},
|
||||
{"<<", dst_rshift},
|
||||
{">>>", dst_lshiftu},
|
||||
{"not", dst_stl_not},
|
||||
{"fopen", dst_stl_fileopen},
|
||||
{"fclose", dst_stl_fileclose},
|
||||
{"fwrite", dst_stl_filewrite},
|
||||
{"fread", dst_stl_fileread},
|
||||
{"exit!", dst_stl_exit}
|
||||
};
|
||||
/*Load auxiliary modules */
|
||||
dst_io_init(args);
|
||||
dst_math_init(args);
|
||||
|
||||
Dst dst_loadstl(int flags) {
|
||||
Dst ret = dst_loadreg(stl, sizeof(stl)/sizeof(DstReg));
|
||||
if (flags & DST_LOAD_ROOT) {
|
||||
dst_gcroot(ret);
|
||||
}
|
||||
if (dst_checktype(ret, DST_TABLE)) {
|
||||
DstTable *v = dst_table(1);
|
||||
dst_table_put(v, dst_csymbolv("value"), ret);
|
||||
dst_put(ret, dst_csymbolv("_env"), dst_wrap_table(v));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -21,7 +21,6 @@
|
||||
*/
|
||||
|
||||
#include <dst/dst.h>
|
||||
#include "strtod.h"
|
||||
#include "gc.h"
|
||||
#include "util.h"
|
||||
|
||||
@ -107,7 +106,7 @@ const uint8_t *dst_cstring(const char *str) {
|
||||
#define DST_BUFSIZE 36
|
||||
|
||||
static int32_t real_to_string_impl(uint8_t *buf, double x) {
|
||||
int count = snprintf((char *) buf, DST_BUFSIZE, "%.17gr", x);
|
||||
int count = snprintf((char *) buf, DST_BUFSIZE, "%.17g", x);
|
||||
return (int32_t) count;
|
||||
}
|
||||
|
||||
|
@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 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_STRTOD_H_defined
|
||||
#define DST_STRTOD_H_defined
|
||||
|
||||
Dst dst_scan_number(
|
||||
const uint8_t *str,
|
||||
int32_t len);
|
||||
|
||||
#endif
|
42
core/util.c
42
core/util.c
@ -107,6 +107,34 @@ int dst_cstrcmp(const uint8_t *str, const char *other) {
|
||||
return (other[index] == '\0') ? 0 : -1;
|
||||
}
|
||||
|
||||
/* Add a module definition */
|
||||
void dst_module_def(DstTable *module, const char *name, Dst val) {
|
||||
DstTable *subt = dst_table(1);
|
||||
dst_table_put(subt, dst_csymbolv("value"), val);
|
||||
dst_table_put(module, dst_csymbolv(name), dst_wrap_table(subt));
|
||||
}
|
||||
|
||||
/* Add a module var */
|
||||
void dst_module_var(DstTable *module, const char *name, Dst val) {
|
||||
DstArray *array = dst_array(1);
|
||||
DstTable *subt = dst_table(1);
|
||||
dst_array_push(array, val);
|
||||
dst_table_put(subt, dst_csymbolv("ref"), dst_wrap_array(array));
|
||||
dst_table_put(module, dst_csymbolv(name), dst_wrap_table(subt));
|
||||
}
|
||||
|
||||
/* Get module from the arguments passed to library */
|
||||
DstTable *dst_get_module(DstArgs args) {
|
||||
DstTable *module;
|
||||
if (args.n >= 1 && dst_checktype(args.v[0], DST_TABLE)) {
|
||||
module = dst_unwrap_table(args.v[0]);
|
||||
} else {
|
||||
module = dst_table(0);
|
||||
}
|
||||
*args.ret = dst_wrap_table(module);
|
||||
return module;
|
||||
}
|
||||
|
||||
/* Do a binary search on a static array of structs. Each struct must
|
||||
* have a string as its first element, and the struct must be sorted
|
||||
* lexogrpahically by that element. */
|
||||
@ -181,20 +209,6 @@ int dst_hashtable_view(Dst tab, const DstKV **data, int32_t *len, int32_t *cap)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Load c functions into an environment */
|
||||
Dst dst_loadreg(DstReg *regs, size_t count) {
|
||||
size_t i;
|
||||
DstTable *t = dst_table(count);
|
||||
for (i = 0; i < count; i++) {
|
||||
Dst sym = dst_csymbolv(regs[i].name);
|
||||
Dst func = dst_wrap_cfunction(regs[i].function);
|
||||
DstTable *subt = dst_table(1);
|
||||
dst_table_put(subt, dst_csymbolv("value"), func);
|
||||
dst_table_put(t, sym, dst_wrap_table(subt));
|
||||
}
|
||||
return dst_wrap_table(t);
|
||||
}
|
||||
|
||||
/* Vector code */
|
||||
|
||||
/* Grow the buffer dynamically. Used for push operations. */
|
||||
|
@ -55,9 +55,12 @@ static int dst_update_fiber() {
|
||||
static int dst_continue(Dst *returnreg) {
|
||||
|
||||
/* VM state */
|
||||
Dst *stack;
|
||||
uint32_t *pc;
|
||||
DstFunction *func;
|
||||
register Dst *stack;
|
||||
register uint32_t *pc;
|
||||
register DstFunction *func;
|
||||
|
||||
/* Keep in mind the garbage collector cannot see this value.
|
||||
* Values stored here should be used immediately */
|
||||
Dst retreg;
|
||||
|
||||
/* Eventually use computed gotos for more effient vm loop. */
|
||||
|
@ -158,6 +158,8 @@ void *dst_abstract(const DstAbstractType *type, size_t size);
|
||||
int dst_equals(Dst x, Dst y);
|
||||
int32_t dst_hash(Dst x);
|
||||
int dst_compare(Dst x, Dst y);
|
||||
|
||||
/* Data structure functions */
|
||||
Dst dst_get(Dst ds, Dst key);
|
||||
void dst_put(Dst ds, Dst key, Dst value);
|
||||
const DstKV *dst_next(Dst ds, const DstKV *kv);
|
||||
@ -179,19 +181,29 @@ int dst_init();
|
||||
void dst_deinit();
|
||||
int dst_run(Dst callee, Dst *returnreg);
|
||||
|
||||
/* Misc */
|
||||
Dst dst_loadreg(DstReg *regs, size_t count);
|
||||
/* 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);
|
||||
double dst_scan_real(const uint8_t *str, int32_t len, int *err);
|
||||
|
||||
/* Module helpers */
|
||||
DstTable *dst_get_module(DstArgs args);
|
||||
void dst_module_def(DstTable *module, const char *name, Dst val);
|
||||
void dst_module_var(DstTable *module, const char *name, Dst val);
|
||||
|
||||
/* C Function helpers */
|
||||
#define dst_throw(a, e) (*((a).ret) = dst_cstringv(e), 1)
|
||||
#define dst_throwv(a, v) (*((a).ret) = (v), 1)
|
||||
#define dst_return(a, v) (*((a).ret) = (v), 0)
|
||||
|
||||
/* Compile */
|
||||
DstCompileResult dst_compile(DstCompileOptions opts);
|
||||
DstFunction *dst_compile_func(DstCompileResult result);
|
||||
|
||||
/* STL */
|
||||
#define DST_LOAD_ROOT 1
|
||||
Dst dst_loadstl(int flags);
|
||||
Dst dst_stl_env();
|
||||
int dst_io_init(DstArgs args);
|
||||
int dst_math_init(DstArgs args);
|
||||
|
||||
/* GC */
|
||||
void dst_mark(Dst x);
|
||||
|
@ -25,53 +25,31 @@
|
||||
|
||||
#include "dsttypes.h"
|
||||
|
||||
/* File type definition */
|
||||
extern DstAbstractType dst_stl_filetype;
|
||||
|
||||
/* Basic C Functions. These are good
|
||||
* candidates for optimizations like bytecode
|
||||
* inlining and costant folding */
|
||||
int dst_int(DstArgs args);
|
||||
int dst_real(DstArgs args);
|
||||
|
||||
int dst_add(DstArgs args);
|
||||
int dst_subtract(DstArgs args);
|
||||
int dst_multiply(DstArgs args);
|
||||
int dst_divide(DstArgs args);
|
||||
int dst_modulo(DstArgs args);
|
||||
|
||||
int dst_acos(DstArgs args);
|
||||
int dst_asin(DstArgs args);
|
||||
int dst_atan(DstArgs args);
|
||||
int dst_cos(DstArgs args);
|
||||
int dst_cosh(DstArgs args);
|
||||
int dst_sin(DstArgs args);
|
||||
int dst_sinh(DstArgs args);
|
||||
int dst_tan(DstArgs args);
|
||||
int dst_tanh(DstArgs args);
|
||||
int dst_exp(DstArgs args);
|
||||
int dst_log(DstArgs args);
|
||||
int dst_log10(DstArgs args);
|
||||
int dst_sqrt(DstArgs args);
|
||||
int dst_ceil(DstArgs args);
|
||||
int dst_fabs(DstArgs args);
|
||||
int dst_floor(DstArgs args);
|
||||
int dst_pow(DstArgs args);
|
||||
|
||||
int dst_stl_table(DstArgs args);
|
||||
int dst_stl_array(DstArgs args);
|
||||
int dst_stl_struct(DstArgs args);
|
||||
int dst_stl_tuple(DstArgs args);
|
||||
|
||||
int dst_band(DstArgs args);
|
||||
int dst_bor(DstArgs args);
|
||||
int dst_bxor(DstArgs args);
|
||||
|
||||
int dst_lshift(DstArgs arsg);
|
||||
int dst_rshift(DstArgs args);
|
||||
int dst_lshiftu(DstArgs args);
|
||||
|
||||
int dst_stl_fileopen(DstArgs args);
|
||||
int dst_stl_slurp(DstArgs args);
|
||||
int dst_stl_fileread(DstArgs args);
|
||||
int dst_stl_filewrite(DstArgs args);
|
||||
int dst_stl_fileclose(DstArgs args);
|
||||
/* Native type constructors */
|
||||
int dst_cfun_table(DstArgs args);
|
||||
int dst_cfun_array(DstArgs args);
|
||||
int dst_cfun_struct(DstArgs args);
|
||||
int dst_cfun_tuple(DstArgs args);
|
||||
|
||||
/* Initialize builtin libraries */
|
||||
int dst_io_init(DstArgs args);
|
||||
int dst_cmath_init(DstArgs args);
|
||||
|
||||
#endif /* DST_MATH_H_defined */
|
||||
|
@ -40,7 +40,6 @@ typedef struct DstTable DstTable;
|
||||
typedef struct DstFiber DstFiber;
|
||||
|
||||
/* Other structs */
|
||||
typedef struct DstReg DstReg;
|
||||
typedef struct DstAbstractHeader DstAbstractHeader;
|
||||
typedef struct DstFuncDef DstFuncDef;
|
||||
typedef struct DstFuncEnv DstFuncEnv;
|
||||
@ -304,12 +303,6 @@ Dst dst_wrap_abstract(void *x);
|
||||
/* End of tagged union implementation */
|
||||
#endif
|
||||
|
||||
/* Used for creating libraries of cfunctions. */
|
||||
struct DstReg {
|
||||
const char *name;
|
||||
DstCFunction function;
|
||||
};
|
||||
|
||||
/* Hold components of arguments passed to DstCFunction. */
|
||||
struct DstArgs {
|
||||
int32_t n;
|
||||
@ -419,9 +412,7 @@ struct DstFunction {
|
||||
/* Defines an abstract type */
|
||||
struct DstAbstractType {
|
||||
const char *name;
|
||||
int (*serialize)(void *data, size_t len);
|
||||
int (*deserialize)();
|
||||
void (*finalize)(void *data, size_t len);
|
||||
int (*gc)(void *data, size_t len);
|
||||
};
|
||||
|
||||
/* Contains information about userdata */
|
||||
|
@ -1,19 +1,14 @@
|
||||
#include <dst/dst.h>
|
||||
|
||||
static void additem(DstTable *t, const char *name, Dst val) {
|
||||
DstTable *subt = dst_table(1);
|
||||
dst_table_put(subt, dst_csymbolv("value"), val);
|
||||
dst_table_put(t, dst_csymbolv(name), dst_wrap_table(subt));
|
||||
}
|
||||
#ifdef DST_LIB
|
||||
#define dst_entry _dst_init
|
||||
#else
|
||||
#define dst_entry dst_testlib_init
|
||||
#endif
|
||||
|
||||
int _dst_init(int32_t argn, Dst *argv, Dst *ret) {
|
||||
DstTable *table;
|
||||
if (argn >= 2 && dst_checktype(argv[1], DST_TABLE)) {
|
||||
table = dst_unwrap_table(argv[1]);
|
||||
} else {
|
||||
table = dst_table(0);
|
||||
}
|
||||
additem(table, "pi", dst_wrap_real(M_PI));
|
||||
*ret = dst_wrap_table(table);
|
||||
int dst_entry(DstArgs args) {
|
||||
DstTable *module = dst_get_module(args);
|
||||
dst_module_def(module, "pi", dst_wrap_real(M_PI));
|
||||
*args.ret = dst_wrap_table(module);
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user