1
0
mirror of https://github.com/janet-lang/janet synced 2024-06-22 21:23:16 +00:00

More work on c library interface and io library.

This commit is contained in:
bakpakin 2018-01-15 20:14:21 -05:00
parent 3262316e60
commit 6df88f225f
17 changed files with 464 additions and 468 deletions

View File

@ -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 $@ $<
###################

View File

@ -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) {

View File

@ -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) {

View File

@ -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:
{

302
core/io.c
View File

@ -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;
}
/* 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]);
FILE *f;
FILE **fp;
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;
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);
}
/* Read an entire file into memory */
int dst_stl_slurp(int32_t argn, Dst *argv, Dst *ret) {
DstBuffer *b;
size_t fsize;
/* Open a a file and return a userdata wrapper around the C file API. */
static int dst_io_fopen(DstArgs args) {
const uint8_t *fname, *fmode;
int32_t modelen;
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;
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;
}
/* 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 ((flags = checkflags(fmode, modelen)) < 0) return dst_throw(args, "invalid file mode");
f = fopen((const char *)fname, (const char *)fmode);
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;
}
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;
}
return dst_return(args, dst_wrap_abstract(iof));
}
/* 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;
}

View File

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

View File

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

View File

@ -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) {

View File

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

View File

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

View File

@ -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

View File

@ -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. */

View File

@ -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. */

View File

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

View File

@ -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 */

View File

@ -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 */

View File

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