1
0
mirror of https://github.com/janet-lang/janet synced 2025-10-31 15:43:01 +00:00

More work.

This commit is contained in:
Calvin Rose
2017-04-24 13:12:55 -04:00
parent 5845434529
commit 81987dca45
8 changed files with 203 additions and 59 deletions

View File

@@ -26,7 +26,6 @@
#include <gst/parse.h> #include <gst/parse.h>
#include <gst/compile.h> #include <gst/compile.h>
#include <gst/stl.h> #include <gst/stl.h>
#include <gst/disasm.h>
/* Use readline support for now */ /* Use readline support for now */
#include <readline/readline.h> #include <readline/readline.h>
@@ -46,10 +45,6 @@ int debug_compile_and_run(Gst *vm, GstValue ast, GstValue env) {
printf("Compiler error: %s\n", c.error); printf("Compiler error: %s\n", c.error);
return 1; return 1;
} }
/* Print disasm */
/*printf("%c[31m===== Begin Disassembly =====\n", 27);*/
/*gst_dasm_function(stdout, func.data.function);*/
/*printf("===== End Disassembly =====%c[0m\n", 27);*/
/* Execute function */ /* Execute function */
if (gst_run(vm, func)) { if (gst_run(vm, func)) {
if (vm->crash) { if (vm->crash) {

View File

@@ -126,8 +126,8 @@ int gst_array_set(GstArray *array, uint32_t index, GstValue x) {
/* Add an item to the end of the array */ /* Add an item to the end of the array */
void gst_array_push(Gst *vm, GstArray *array, GstValue x) { void gst_array_push(Gst *vm, GstArray *array, GstValue x) {
if (array->count >= array->capacity) { if (array->count + 1>= array->capacity) {
gst_array_ensure(vm, array, 2 * array->count); gst_array_ensure(vm, array, 2 * array->count + 1);
} }
array->data[array->count++] = x; array->data[array->count++] = x;
} }

View File

@@ -267,10 +267,8 @@ void gst_collect(Gst *vm) {
/* Thread can be null */ /* Thread can be null */
if (vm->thread) if (vm->thread)
gst_mark_value(vm, gst_wrap_thread(vm->thread)); gst_mark_value(vm, gst_wrap_thread(vm->thread));
if (vm->modules) gst_mark_value(vm, gst_wrap_object(vm->modules));
gst_mark_value(vm, gst_wrap_object(vm->modules)); gst_mark_value(vm, gst_wrap_object(vm->registry));
if (vm->registry)
gst_mark_value(vm, gst_wrap_object(vm->registry));
gst_mark_value(vm, vm->ret); gst_mark_value(vm, vm->ret);
if (vm->scratch) if (vm->scratch)
gc_header(vm->scratch)->color = vm->black; gc_header(vm->scratch)->color = vm->black;

View File

@@ -25,6 +25,8 @@
#include <gst/compile.h> #include <gst/compile.h>
#include <gst/stl.h> #include <gst/stl.h>
#include <gst/disasm.h>
static const char GST_EXPECTED_NUMBER_OP[] = "expected operand to be number"; static const char GST_EXPECTED_NUMBER_OP[] = "expected operand to be number";
static const char GST_EXPECTED_STRING[] = "expected string"; static const char GST_EXPECTED_STRING[] = "expected string";
@@ -178,21 +180,10 @@ int gst_stl_slice(Gst *vm) {
uint32_t newlength; uint32_t newlength;
GstNumber num; GstNumber num;
/* Check args */
if (count < 1)
gst_c_throwc(vm, "slice takes at least one argument");
x = gst_arg(vm, 0);
/* Get data */ /* Get data */
if (x.type == GST_TUPLE) { x = gst_arg(vm, 0);
data = x.data.st; if (!gst_seq_view(x, &data, &length))
length = gst_tuple_length(x.data.st);
} else if (x.type == GST_ARRAY) {
data = x.data.array->data;
length = x.data.array->count;
} else {
gst_c_throwc(vm, "expected array or tuple"); gst_c_throwc(vm, "expected array or tuple");
}
/* Get from index */ /* Get from index */
if (count < 2) { if (count < 2) {
@@ -342,26 +333,27 @@ int gst_stl_buffer(Gst *vm) {
gst_c_return(vm, gst_wrap_buffer(buf)); gst_c_return(vm, gst_wrap_buffer(buf));
} }
/* Concatenate string */ /* Concatenate strings */
int gst_stl_strcat(Gst *vm) { int gst_stl_strcat(Gst *vm) {
uint32_t j, count, length, index; uint32_t j;
uint32_t count = gst_count_args(vm);
uint32_t length = 0;
uint32_t index = 0;
uint8_t *str; uint8_t *str;
count = gst_count_args(vm); const uint8_t *dat;
length = 0; uint32_t slen;
index = 0;
/* Find length and assert string arguments */ /* Find length and assert string arguments */
for (j = 0; j < count; ++j) { for (j = 0; j < count; ++j) {
GstValue arg = gst_arg(vm, j); if (gst_chararray_view(gst_arg(vm, j), &dat, &slen))
if (arg.type != GST_STRING) length += slen;
else
gst_c_throwc(vm, GST_EXPECTED_STRING); gst_c_throwc(vm, GST_EXPECTED_STRING);
length += gst_string_length(arg.data.string);
} }
/* Make string */ /* Make string */
str = gst_string_begin(vm, length); str = gst_string_begin(vm, length);
for (j = 0; j < count; ++j) { for (j = 0; j < count; ++j) {
GstValue arg = gst_arg(vm, j); gst_chararray_view(gst_arg(vm, j), &dat, &slen);
uint32_t slen = gst_string_length(arg.data.string); gst_memcpy(str + index, dat, slen);
gst_memcpy(str + index, arg.data.string, slen);
index += slen; index += slen;
} }
gst_c_return(vm, gst_wrap_string(gst_string_end(vm, str))); gst_c_return(vm, gst_wrap_string(gst_string_end(vm, str)));
@@ -373,9 +365,8 @@ int gst_stl_rawget(Gst *vm) {
uint32_t count; uint32_t count;
const char *err; const char *err;
count = gst_count_args(vm); count = gst_count_args(vm);
if (count != 2) { if (count != 2)
gst_c_throwc(vm, "expects 2 arguments"); gst_c_throwc(vm, "expects 2 arguments");
}
err = gst_get(gst_arg(vm, 0), gst_arg(vm, 1), &ret); err = gst_get(gst_arg(vm, 0), gst_arg(vm, 1), &ret);
if (err != NULL) if (err != NULL)
gst_c_throwc(vm, err); gst_c_throwc(vm, err);
@@ -388,15 +379,50 @@ int gst_stl_rawset(Gst *vm) {
uint32_t count; uint32_t count;
const char *err; const char *err;
count = gst_count_args(vm); count = gst_count_args(vm);
if (count != 3) { if (count != 3)
gst_c_throwc(vm, "expects 3 arguments"); gst_c_throwc(vm, "expects 3 arguments");
}
err = gst_set(vm, gst_arg(vm, 0), gst_arg(vm, 1), gst_arg(vm, 2)); err = gst_set(vm, gst_arg(vm, 0), gst_arg(vm, 1), gst_arg(vm, 2));
if (err != NULL) { if (err != NULL)
gst_c_throwc(vm, err); gst_c_throwc(vm, err);
} else { else
gst_c_return(vm, gst_arg(vm, 0)); gst_c_return(vm, gst_arg(vm, 0));
} }
/* Push to end of array */
int gst_stl_push(Gst *vm) {
GstValue ds = gst_arg(vm, 0);
if (ds.type != GST_ARRAY)
gst_c_throwc(vm, "expected array");
gst_array_push(vm, ds.data.array, gst_arg(vm, 1));
gst_c_return(vm, ds);
}
/* Pop from end of array */
int gst_stl_pop(Gst *vm) {
GstValue ds = gst_arg(vm, 0);
if (ds.type != GST_ARRAY)
gst_c_throwc(vm, "expected array");
gst_c_return(vm, gst_array_pop(ds.data.array));
}
/* Peek at end of array */
int gst_stl_peek(Gst *vm) {
GstValue ds = gst_arg(vm, 0);
if (ds.type != GST_ARRAY)
gst_c_throwc(vm, "expected array");
gst_c_return(vm, gst_array_peek(ds.data.array));
}
/* Ensure array capacity */
int gst_stl_ensure(Gst *vm) {
GstValue ds = gst_arg(vm, 0);
GstValue cap = gst_arg(vm, 1);
if (ds.type != GST_ARRAY)
gst_c_throwc(vm, "expected array");
if (cap.type != GST_NUMBER)
gst_c_throwc(vm, "expected number");
gst_array_ensure(vm, ds.data.array, (uint32_t) cap.data.number);
gst_c_return(vm, ds);
} }
/* Get next key in struct or object */ /* Get next key in struct or object */
@@ -404,9 +430,9 @@ int gst_stl_next(Gst *vm) {
GstValue ds = gst_arg(vm, 0); GstValue ds = gst_arg(vm, 0);
GstValue key = gst_arg(vm, 1); GstValue key = gst_arg(vm, 1);
if (ds.type == GST_OBJECT) { if (ds.type == GST_OBJECT) {
gst_c_return(vm, gst_object_next(ds.data.object, key)); gst_c_return(vm, gst_object_next(ds.data.object, key));
} else if (ds.type == GST_STRUCT) { } else if (ds.type == GST_STRUCT) {
gst_c_return(vm, gst_struct_next(ds.data.st, key)); gst_c_return(vm, gst_struct_next(ds.data.st, key));
} else { } else {
gst_c_throwc(vm, "expected object or struct"); gst_c_throwc(vm, "expected object or struct");
} }
@@ -446,8 +472,7 @@ int gst_stl_exit(Gst *vm) {
/* Throw error */ /* Throw error */
int gst_stl_error(Gst *vm) { int gst_stl_error(Gst *vm) {
GstValue errval = gst_arg(vm, 0); gst_c_throw(vm, gst_arg(vm, 0));
gst_c_throw(vm, errval);
} }
/****/ /****/
@@ -469,28 +494,92 @@ int gst_stl_serialize(Gst *vm) {
gst_c_return(vm, buffer); gst_c_return(vm, buffer);
} }
/****/
/* Registry */
/****/
int gst_stl_global(Gst *vm) {
gst_c_return(vm, gst_object_get(vm->registry, gst_arg(vm, 0)));
}
int gst_stl_setglobal(Gst *vm) {
gst_object_put(vm, vm->registry, gst_arg(vm, 0), gst_arg(vm, 1));
gst_c_return(vm, gst_wrap_nil());
}
/****/ /****/
/* IO */ /* IO */
/****/ /****/
/* TODO - add userdata to allow for manipulation of FILE pointers. */ /* TODO - add userdata to allow for manipulation of FILE pointers. */
/* Open a a file and return a userdata wrapper arounf the C file API. */
int gst_stl_open(Gst *vm) { int gst_stl_open(Gst *vm) {
const uint8_t *fname = gst_to_string(vm, gst_arg(vm, 0)); const uint8_t *fname = gst_to_string(vm, gst_arg(vm, 0));
const uint8_t *fmode = gst_to_string(vm, gst_arg(vm, 1)); const uint8_t *fmode = gst_to_string(vm, gst_arg(vm, 1));
FILE *f; FILE *f;
FILE **fp; FILE **fp;
GstValue *st; GstValue *st;
if (gst_count_args(vm) < 2) if (gst_count_args(vm) < 2 || gst_arg(vm, 0).type != GST_STRING
|| gst_arg(vm, 1).type != GST_STRING)
gst_c_throwc(vm, "expected filename and filemode"); gst_c_throwc(vm, "expected filename and filemode");
f = fopen((const char *)fname, (const char *)fmode); f = fopen((const char *)fname, (const char *)fmode);
if (!f) if (!f)
gst_c_throwc(vm, "could not open file"); gst_c_throwc(vm, "could not open file");
st = gst_struct_begin(vm, 0); st = gst_struct_begin(vm, 0);
fp = gst_userdata(vm, sizeof(FILE *), gst_struct_end(vm, st)); fp = gst_userdata(vm, sizeof(FILE *), gst_struct_end(vm, st));
*fp = f;
gst_c_return(vm, gst_wrap_userdata(fp)); gst_c_return(vm, gst_wrap_userdata(fp));
} }
/* Write a string to a file */
int gst_stl_write(Gst *vm) {
GstValue f = gst_arg(vm, 0);
FILE *f;
if (f.type != GST_USERDATA)
gst_c_throwc(vm, "expected file userdata");
f = *(FILE **)f.data.pointer
}
/* Read an entire file in one go. Will be faster than sequential reads for
* small to moderately sized files */
int gst_stl_slurp(Gst *vm) {
GstValue x = gst_arg(vm, 0);
const uint8_t *fname;
FILE *f;
if (gst_count_args(vm) < 1 || x.type != GST_STRING)
gst_c_throwc(vm, "expected file name");
fname = gst_to_string(vm, gst_arg(vm, 0));
f = fopen((const char *) fname, "rb");
if (!f)
gst_c_throwc(vm, "could not open file for reading");
// TODO use fseek and like functions to read file into a buffer.
}
/* Write a string to a file in one go. Overwrites an existing file. */
/****/
/* Temporary */
/****/
/* These functions should definitely be moved to a different module, remove, or
* rewritten in gst when the language is complete enough. This is not to say
* that functions in other section need not be moved. */
/* Print disassembly for a function */
int gst_stl_dasm(Gst *vm) {
GstValue x = gst_arg(vm, 0);
if (x.type == GST_FUNCTION) {
printf("%c[31m===== Begin Disassembly =====\n", 27);
gst_dasm_function(stdout, x.data.function);
printf("===== End Disassembly =====%c[0m\n", 27);
} else {
gst_c_throwc(vm, "expected function");
}
return GST_RETURN_OK;
}
/****/ /****/
/* Bootstraping */ /* Bootstraping */
/****/ /****/
@@ -523,7 +612,14 @@ static const GstModuleItem const std_module[] = {
{"next", gst_stl_next}, {"next", gst_stl_next},
{"error", gst_stl_error}, {"error", gst_stl_error},
{"serialize", gst_stl_serialize}, {"serialize", gst_stl_serialize},
{"global", gst_stl_global},
{"setglobal", gst_stl_setglobal},
{"push", gst_stl_push},
{"pop", gst_stl_pop},
{"peek", gst_stl_peek},
{"ensure", gst_stl_ensure},
{"open", gst_stl_open}, {"open", gst_stl_open},
{"dasm", gst_stl_dasm},
{NULL, NULL} {NULL, NULL}
}; };

View File

@@ -99,26 +99,18 @@ GstValue gst_cmodule_struct(Gst *vm, const GstModuleItem *mod) {
} }
void gst_module_put(Gst *vm, const char *packagename, GstValue mod) { void gst_module_put(Gst *vm, const char *packagename, GstValue mod) {
if (vm->modules == NULL)
vm->modules = gst_object(vm, 10);
gst_object_put(vm, vm->modules, gst_string_cv(vm, packagename), mod); gst_object_put(vm, vm->modules, gst_string_cv(vm, packagename), mod);
} }
GstValue gst_module_get(Gst *vm, const char *packagename) { GstValue gst_module_get(Gst *vm, const char *packagename) {
if (!vm->modules)
return gst_wrap_nil();
return gst_object_get(vm->modules, gst_string_cv(vm, packagename)); return gst_object_get(vm->modules, gst_string_cv(vm, packagename));
} }
void gst_register_put(Gst *vm, const char *name, GstValue c) { void gst_register_put(Gst *vm, const char *name, GstValue c) {
if (vm->registry == NULL)
vm->registry = gst_object(vm, 10);
gst_object_put(vm, vm->registry, gst_string_cv(vm, name), c); gst_object_put(vm, vm->registry, gst_string_cv(vm, name), c);
} }
GstValue gst_register_get(Gst *vm, const char *name) { GstValue gst_register_get(Gst *vm, const char *name) {
if (!vm->registry)
return gst_wrap_nil();
return gst_object_get(vm->registry, gst_string_cv(vm, name)); return gst_object_get(vm->registry, gst_string_cv(vm, name));
} }
@@ -126,6 +118,54 @@ GstValue gst_register_get(Gst *vm, const char *name) {
/* Misc */ /* Misc */
/****/ /****/
/* Utilities for manipulating different types with the same semantics */
/* Read both tuples and arrays as c pointers + uint32_t length. Return 1 if the
* view can be constructed, 0 if an invalid type. */
int gst_seq_view(GstValue seq, const GstValue **data, uint32_t *len) {
if (seq.type == GST_ARRAY) {
*data = seq.data.array->data;
*len = seq.data.array->count;
return 1;
} else if (seq.type == GST_TUPLE) {
*data = seq.data.st;
*len = gst_tuple_length(seq.data.st);
return 1;
}
return 0;
}
/* Read both strings and buffer as unsigned character array + uint32_t len.
* Returns 1 if the view can be constructed and 0 if the type is invalid. */
int gst_chararray_view(GstValue str, const uint8_t **data, uint32_t *len) {
if (str.type == GST_STRING) {
*data = str.data.string;
*len = gst_string_length(str.data.string);
return 1;
} else if (str.type == GST_BYTEBUFFER) {
*data = str.data.buffer->data;
*len = str.data.buffer->count;
return 1;
}
return 0;
}
/* Read both structs and objects as the entries of a hashtable with
* identical structure. Returns 1 if the view can be constructed and
* 0 if the type is invalid. */
int gst_hashtable_view(GstValue tab, const GstValue **data, uint32_t *cap) {
if (tab.type == GST_OBJECT) {
*data = tab.data.object->data;
*cap = tab.data.object->capacity;
return 1;
} else if (tab.type == GST_STRUCT) {
*data = tab.data.st;
*cap = gst_struct_capacity(tab.data.st);
return 1;
}
return 0;
}
/* Allow negative indexing to get from end of array like structure */ /* Allow negative indexing to get from end of array like structure */
/* This probably isn't very fast - look at Lua conversion function. /* This probably isn't very fast - look at Lua conversion function.
* I would like to keep this standard C for as long as possible, though. */ * I would like to keep this standard C for as long as possible, though. */

View File

@@ -253,7 +253,7 @@ int gst_continue(Gst *vm) {
vm->thread->count += newStackIndex; vm->thread->count += newStackIndex;
stack = gst_thread_stack(vm->thread); stack = gst_thread_stack(vm->thread);
gst_frame_size(stack) = size - newStackIndex; gst_frame_size(stack) = size - newStackIndex;
gst_frame_prevsize(stack) = newStackIndex; gst_frame_prevsize(stack) = newStackIndex - GST_FRAME_SIZE;
gst_frame_callee(stack) = temp; gst_frame_callee(stack) = temp;
} }
goto common_function_call; goto common_function_call;
@@ -527,9 +527,6 @@ void gst_init(Gst *vm) {
vm->black = 0; vm->black = 0;
/* Add thread */ /* Add thread */
vm->thread = NULL; vm->thread = NULL;
/* Set up global env */
vm->modules = NULL;
vm->registry = NULL;
/* Set up scratch memory */ /* Set up scratch memory */
vm->scratch = NULL; vm->scratch = NULL;
vm->scratch_len = 0; vm->scratch_len = 0;
@@ -538,6 +535,9 @@ void gst_init(Gst *vm) {
vm->cache_capacity = vm->cache == NULL ? 0 : 128; vm->cache_capacity = vm->cache == NULL ? 0 : 128;
vm->cache_count = 0; vm->cache_count = 0;
vm->cache_deleted = 0; vm->cache_deleted = 0;
/* Set up global env */
vm->modules = gst_object(vm, 10);
vm->registry = gst_object(vm, 10);
} }
/* Clear all memory associated with the VM */ /* Clear all memory associated with the VM */

View File

@@ -359,6 +359,7 @@ int gst_array_set(GstArray *array, uint32_t index, GstValue x);
void gst_array_ensure(Gst *vm, GstArray *array, uint32_t capacity); void gst_array_ensure(Gst *vm, GstArray *array, uint32_t capacity);
void gst_array_push(Gst *vm, GstArray *array, GstValue x); void gst_array_push(Gst *vm, GstArray *array, GstValue x);
GstValue gst_array_pop(GstArray *array); GstValue gst_array_pop(GstArray *array);
GstValue gst_array_peek(GstArray *array);
/****/ /****/
/* Userdata functions */ /* Userdata functions */
@@ -548,6 +549,10 @@ int gst_check_userdata(Gst *vm, uint32_t i, void *(*x));
int gst_check_funcenv(Gst *vm, uint32_t i, GstFuncEnv *(*x)); int gst_check_funcenv(Gst *vm, uint32_t i, GstFuncEnv *(*x));
int gst_check_funcdef(Gst *vm, uint32_t i, GstFuncDef *(*x)); int gst_check_funcdef(Gst *vm, uint32_t i, GstFuncDef *(*x));
int gst_seq_view(GstValue seq, const GstValue **data, uint32_t *len);
int gst_chararray_view(GstValue str, const uint8_t **data, uint32_t *len);
int gst_hashtable_view(GstValue tab, const GstValue **data, uint32_t *cap);
/****/ /****/
/* Misc */ /* Misc */
/****/ /****/

View File

@@ -3,6 +3,16 @@
# Reindent a function to be more deeply indented # Reindent a function to be more deeply indented
(: reindent (fn [x] x)) (: reindent (fn [x] x))
# Pretty print an array
(: print-array (fn [a]
(: parts [])
(: l (length a))
(: i 0)
(while (< i l)
(: i (+ 1 i)))
(apply strcat "[ " parts)))
(: handler { (: handler {
"number" tostring "number" tostring
"nil" tostring "nil" tostring