From c3d65cb91d3bb748bf036786214090660f357779 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Sat, 24 Jun 2017 14:27:29 -0400 Subject: [PATCH] Remove lots of headers. Add parse c function. --- Makefile | 6 +- client/main.c | 9 +- core/compile.c | 34 +----- core/disasm.c | 194 ------------------------------- core/parse.c | 187 +----------------------------- core/serialize.c | 3 - core/stl.c | 259 +++++++++++++++++++++++++++++++++--------- include/gst/compile.h | 59 ---------- include/gst/disasm.h | 39 ------- include/gst/gst.h | 89 +++++++++++++++ include/gst/parse.h | 72 ------------ include/gst/stl.h | 32 ------ 12 files changed, 304 insertions(+), 679 deletions(-) delete mode 100644 core/disasm.c delete mode 100644 include/gst/compile.h delete mode 100644 include/gst/disasm.h delete mode 100644 include/gst/parse.h delete mode 100644 include/gst/stl.h diff --git a/Makefile b/Makefile index 5fc1c8db..6361ab01 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ PREFIX=/usr/local GST_TARGET=client/gst GST_CORELIB=core/libgst.a GST_INTERNAL_HEADERS=$(addprefix core/, cache.h) -GST_HEADERS=$(addprefix include/gst/, gst.h stl.h compile.h disasm.h parse.h) +GST_HEADERS=$(addprefix include/gst/, gst.h) all: $(GST_TARGET) @@ -16,7 +16,7 @@ all: $(GST_TARGET) ##### The core vm and runtime ##### ################################### GST_CORE_SOURCES=$(addprefix core/,\ - compile.c disasm.c parse.c stl.c ids.c util.c\ + compile.c parse.c stl.c ids.c util.c\ value.c vm.c ds.c gc.c thread.c serialize.c) GST_CORE_OBJECTS=$(patsubst %.c,%.o,$(GST_CORE_SOURCES)) @@ -49,6 +49,6 @@ clean: rm vgcore.* || true test: $(GST_TARGET) - gsttests/basic.gst + $(GST_TARGET) gsttests/basic.gst .PHONY: clean install run debug valgrind diff --git a/client/main.c b/client/main.c index 08fb124c..8e413bd3 100644 --- a/client/main.c +++ b/client/main.c @@ -23,9 +23,6 @@ #include #include #include -#include -#include -#include /* Use readline support for now */ #include @@ -38,9 +35,6 @@ int debug_compile_and_run(Gst *vm, GstValue ast, GstValue last) { /* Try to compile generated AST */ gst_compiler(&c, vm); gst_compiler_usemodule(&c, "std"); - gst_compiler_usemodule(&c, "std.io"); - gst_compiler_usemodule(&c, "std.parse"); - gst_compiler_usemodule(&c, "std.compile"); gst_compiler_global(&c, "_", last); func = gst_wrap_function(gst_compiler_compile(&c, ast)); /* Check for compilation errors */ @@ -147,8 +141,7 @@ int main(int argc, const char **argv) { gst_init(&vm); gst_stl_load(&vm); - gst_parse_load(&vm); - gst_compile_load(&vm); + if (argc > 1) { const char *filename; FILE *f; diff --git a/core/compile.c b/core/compile.c index 7b07d77c..9f27785f 100644 --- a/core/compile.c +++ b/core/compile.c @@ -21,7 +21,6 @@ */ #include -#include /* During compilation, FormOptions are passed to ASTs * as configuration options to allow for some optimizations. */ @@ -1209,35 +1208,4 @@ GstFunction *gst_compiler_compile(GstCompiler *c, GstValue form) { func->env = env; return func; } -} - -/***/ -/* Stl */ -/***/ - -/* Compile a value */ -static int gst_stl_compile(Gst *vm) { - GstFunction *ret; - GstValue std; - GstCompiler c; - gst_compiler(&c, vm); - std = gst_table_get(vm->modules, gst_string_cv(vm, "std")); - gst_compiler_globals(&c, std); - gst_compiler_globals(&c, gst_arg(vm, 1)); - gst_compiler_nilglobals(&c, gst_arg(vm, 2)); - ret = gst_compiler_compile(&c, gst_arg(vm, 0)); - if (!ret) - gst_c_throw(vm, c.error); - gst_c_return(vm, gst_wrap_function(ret)); -} - -/* The module stuff */ -static const GstModuleItem gst_compile_module[] = { - {"compile", gst_stl_compile}, - {NULL, NULL} -}; - -/* Load compiler library */ -void gst_compile_load(Gst *vm) { - gst_module(vm, "std.compile", gst_compile_module); -} +} \ No newline at end of file diff --git a/core/disasm.c b/core/disasm.c deleted file mode 100644 index 116d155c..00000000 --- a/core/disasm.c +++ /dev/null @@ -1,194 +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. -*/ - -#include - -/* Width of padded opcode names */ -#define OP_WIDTH 20 - -/* Print various register and arguments to instructions */ -static void dasm_print_slot(FILE *out, uint16_t index) { fprintf(out, "%d ", index); } -static void dasm_print_i16(FILE *out, int16_t number) { fprintf(out, "#%d ", number); } -static void dasm_print_i32(FILE *out, int32_t number) { fprintf(out, "#%d ", number); } -static void dasm_print_f64(FILE *out, double number) { fprintf(out, "#%f ", number); } -static void dasm_print_literal(FILE *out, uint16_t index) { fprintf(out, "(%d) ", index); } -static void dasm_print_upvalue(FILE *out, uint16_t level, uint16_t index) { - fprintf(out, "<%d, %d> ", level, index); -} - -/* Print the name of the argument but pad it */ -static void dasm_print_arg(FILE *out, const char *name) { - uint32_t i = 0; - char c; - while ((c = *name++)) { - putc(c, out); - ++i; - } - for (; i < OP_WIDTH; ++i) - fputc(' ', out); -} - -/* Print instructions that take a fixed number of arguments */ -static uint32_t dasm_fixed_op(FILE *out, const uint16_t *current, - const char * name, uint32_t size) { - uint32_t i; - dasm_print_arg(out, name); - for (i = 1; i <= size; ++i) - dasm_print_slot(out, current[i]); - return size + 1; -} - -/* Print instructions that take a variable number of arguments */ -static uint32_t dasm_varg_op(FILE *out, const uint16_t *current, - const char * name, uint32_t extra) { - uint32_t i, argCount; - dasm_print_arg(out, name); - for (i = 0; i < extra; ++i) { - dasm_print_slot(out, current[i + 1]); - } - argCount = current[extra + 1]; - if (extra) - fprintf(out, ": "); /* Argument separator */ - for (i = 0; i < argCount; ++i) { - dasm_print_slot(out, current[i + extra + 2]); - } - return argCount + extra + 2; -} - -/* Print the disassembly for a function definition */ -void gst_dasm_funcdef(FILE *out, GstFuncDef *def) { - gst_dasm(out, def->byteCode, def->byteCodeLen); -} - -/* Print the disassembly for a function */ -void gst_dasm_function(FILE *out, GstFunction *f) { - gst_dasm(out, f->def->byteCode, f->def->byteCodeLen); -} - -/* Disassemble some bytecode and display it as opcode + arguments assembly */ -void gst_dasm(FILE *out, uint16_t *byteCode, uint32_t len) { - uint16_t *current = byteCode; - uint16_t *end = byteCode + len; - - while (current < end) { - switch (*current) { - default: - current += dasm_fixed_op(out, current, "unknown", 0); - break; - case GST_OP_FLS: - current += dasm_fixed_op(out, current, "loadFalse", 1); - break; - case GST_OP_TRU: - current += dasm_fixed_op(out, current, "loadTrue", 1); - break; - case GST_OP_NIL: - current += dasm_fixed_op(out, current, "loadNil", 1); - break; - case GST_OP_I16: - dasm_print_arg(out, "loadInt16"); - dasm_print_slot(out, current[1]); - dasm_print_i16(out, ((int16_t *)current)[2]); - current += 3; - break; - case GST_OP_UPV: - dasm_print_arg(out, "loadUpValue"); - dasm_print_slot(out, current[1]); - dasm_print_upvalue(out, current[2], current[3]); - current += 4; - break; - case GST_OP_JIF: - dasm_print_arg(out, "jumpIf"); - dasm_print_slot(out, current[1]); - dasm_print_i32(out, ((int32_t *)(current + 2))[0]); - current += 4; - break; - case GST_OP_JMP: - dasm_print_arg(out, "jump"); - dasm_print_i32(out, ((int32_t *)(current + 1))[0]); - current += 3; - break; - case GST_OP_SUV: - dasm_print_arg(out, "setUpValue"); - dasm_print_slot(out, current[1]); - dasm_print_upvalue(out, current[2], current[3]); - current += 4; - break; - case GST_OP_CST: - dasm_print_arg(out, "loadLiteral"); - dasm_print_slot(out, current[1]); - dasm_print_literal(out, current[2]); - current += 3; - break; - case GST_OP_I32: - dasm_print_arg(out, "loadInt32"); - dasm_print_slot(out, current[1]); - dasm_print_i32(out, ((int32_t *)(current + 2))[0]); - current += 4; - break; - case GST_OP_F64: - dasm_print_arg(out, "loadFloat64"); - dasm_print_slot(out, current[1]); - dasm_print_f64(out, ((double *)(current + 2))[0]); - current += 6; - break; - case GST_OP_MOV: - current += dasm_fixed_op(out, current, "move", 2); - break; - case GST_OP_CLN: - dasm_print_arg(out, "makeClosure"); - dasm_print_slot(out, current[1]); - dasm_print_literal(out, current[2]); - current += 3; - break; - case GST_OP_ARR: - current += dasm_varg_op(out, current, "array", 1); - break; - case GST_OP_DIC: - current += dasm_varg_op(out, current, "table", 1); - break; - case GST_OP_TUP: - current += dasm_varg_op(out, current, "tuple", 1); - break; - case GST_OP_RET: - current += dasm_fixed_op(out, current, "return", 1); - break; - case GST_OP_RTN: - current += dasm_fixed_op(out, current, "returnNil", 0); - break; - case GST_OP_PSK: - current += dasm_varg_op(out, current, "pushArgs", 0); - break; - case GST_OP_PAR: - current += dasm_fixed_op(out, current, "pushSeq", 1); - break; - case GST_OP_CAL: - current += dasm_fixed_op(out, current, "call", 2); - break; - case GST_OP_TCL: - current += dasm_fixed_op(out, current, "tailCall", 1); - break; - case GST_OP_TRN: - current += dasm_fixed_op(out, current, "transfer", 3); - } - fprintf(out, "\n"); - } -} diff --git a/core/parse.c b/core/parse.c index e4b7eec3..6b32cfe1 100644 --- a/core/parse.c +++ b/core/parse.c @@ -21,39 +21,9 @@ */ #include -#include static const char UNEXPECTED_CLOSING_DELIM[] = "Unexpected closing delimiter"; -/* The type of a ParseState */ -typedef enum ParseType { - PTYPE_FORM, - PTYPE_STRING, - PTYPE_TOKEN -} ParseType; - -/* Contain a parse state that goes on the parse stack */ -struct GstParseState { - ParseType type; - union { - struct { - uint8_t endDelimiter; - GstArray *array; - } form; - struct { - GstBuffer *buffer; - uint32_t count; - uint32_t accum; - enum { - STRING_STATE_BASE, - STRING_STATE_ESCAPE, - STRING_STATE_ESCAPE_UNICODE, - STRING_STATE_ESCAPE_HEX - } state; - } string; - } buf; -}; - /* Handle error in parsing */ #define p_error(p, e) ((p)->error = (e), (p)->status = GST_PARSER_ERROR) @@ -429,7 +399,7 @@ static int form_state(GstParser *p, uint8_t c) { } /* Handle a character */ -static void dispatch_char(GstParser *p, uint8_t c) { +void gst_parse_byte(GstParser *p, uint8_t c) { int done = 0; ++p->index; /* Dispatch character to state */ @@ -464,7 +434,7 @@ int gst_parse_cstring(GstParser *p, const char *string) { return 0; while ((p->status == GST_PARSER_PENDING || p->status == GST_PARSER_ROOT) && (string[bytesRead] != '\0')) { - dispatch_char(p, string[bytesRead++]); + gst_parse_byte(p, string[bytesRead++]); } return bytesRead; } @@ -476,16 +446,11 @@ int gst_parse_string(GstParser *p, const uint8_t *string) { return 0; for (i = 0; i < gst_string_length(string); ++i) { if (p->status != GST_PARSER_PENDING && p->status != GST_PARSER_ROOT) break; - dispatch_char(p, string[i]); + gst_parse_byte(p, string[i]); } return i; } -/* Parse a single byte */ -void gst_parse_byte(GstParser *p, uint8_t byte) { - dispatch_char(p, byte); -} - /* Check if a parser has a value that needs to be handled. If * so, the parser will not parse any more input until that value * is consumed. */ @@ -511,148 +476,4 @@ void gst_parser(GstParser *p, Gst *vm) { p->error = NULL; p->status = GST_PARSER_ROOT; p->value.type = GST_NIL; -} - -/* GC mark a parser */ -static void gst_stl_parser_mark(Gst *vm, void *data, uint32_t len) { - uint32_t i; - GstParser *p = (GstParser *) data; - if (len != sizeof(GstParser)) - return; - gst_mark_mem(vm, p->data); - gst_mark_value(vm, p->value); - for (i = 0; i < p->count; ++i) { - GstParseState *ps = p->data + i; - switch (ps->type) { - case PTYPE_FORM: - gst_mark_value(vm, gst_wrap_array(ps->buf.form.array)); - break; - case PTYPE_STRING: - case PTYPE_TOKEN: - gst_mark_value(vm, gst_wrap_buffer(ps->buf.string.buffer)); - break; - } - } -} - -/***/ -/* Stl functions */ -/***/ - -/* Parse filetype */ -static const GstUserType gst_stl_parsetype = { - "std.parser", - NULL, - NULL, - NULL, - &gst_stl_parser_mark -}; - -/* Create a parser */ -static int gst_stl_parser(Gst *vm) { - GstParser *p = gst_userdata(vm, sizeof(GstParser), &gst_stl_parsetype); - gst_parser(p, vm); - gst_c_return(vm, gst_wrap_userdata(p)); -} - -/* Consume a value from the parser */ -static int gst_stl_parser_consume(Gst *vm) { - GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype); - if (p == NULL) - gst_c_throwc(vm, "expected parser"); - if (p->status == GST_PARSER_ERROR) - gst_c_return(vm, gst_string_cv(vm, p->error)); - if (!gst_parse_hasvalue(p)) - gst_c_throwc(vm, "parser has no pending value"); - gst_c_return(vm, gst_parse_consume(p)); -} - -/* Check if the parser has a value to consume */ -static int gst_stl_parser_hasvalue(Gst *vm) { - GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype); - if (p == NULL) - gst_c_throwc(vm, "expected parser"); - gst_c_return(vm, gst_wrap_boolean(gst_parse_hasvalue(p))); -} - -/* Parse a single byte. Returns if the byte was successfully parsed. */ -static int gst_stl_parser_byte(Gst *vm) { - GstInteger b; - GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype); - if (p == NULL) - gst_c_throwc(vm, "expected parser"); - if (!gst_check_integer(vm, 1, &b)) - gst_c_throwc(vm, "expected integer"); - if (p->status == GST_PARSER_PENDING || p->status == GST_PARSER_ROOT) { - dispatch_char(p, b); - gst_c_return(vm, gst_wrap_boolean(1)); - } else { - gst_c_return(vm, gst_wrap_boolean(0)); - } -} - -/* Parse a string or buffer. Returns nil if the entire char array is parsed, -* otherwise returns the remainder of what could not be parsed. */ -static int gst_stl_parser_charseq(Gst *vm) { - uint32_t i; - uint32_t len; - const uint8_t *data; - GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype); - if (p == NULL) - gst_c_throwc(vm, "expected parser"); - if (!gst_chararray_view(gst_arg(vm, 1), &data, &len)) - gst_c_throwc(vm, "expected string/buffer"); - for (i = 0; i < len; ++i) { - if (p->status != GST_PARSER_PENDING && p->status != GST_PARSER_ROOT) break; - dispatch_char(p, data[i]); - } - if (i == len) { - /* No remainder */ - gst_c_return(vm, gst_wrap_nil()); - } else { - /* We have remaining characters */ - gst_c_return(vm, gst_wrap_string(gst_string_b(vm, data + i, len - i))); - } -} - -/* Get status of parser */ -static int gst_stl_parser_status(Gst *vm) { - GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype); - const char *cstr; - if (p == NULL) - gst_c_throwc(vm, "expected parser"); - switch (p->status) { - case GST_PARSER_ERROR: - cstr = "error"; - break; - case GST_PARSER_FULL: - cstr = "full"; - break; - case GST_PARSER_PENDING: - cstr = "pending"; - break; - case GST_PARSER_ROOT: - cstr = "root"; - break; - default: - cstr = "unknown"; - break; - } - gst_c_return(vm, gst_string_cv(vm, cstr)); -} - -/* The module */ -static const GstModuleItem gst_parser_module[] = { - {"parser", gst_stl_parser}, - {"parse-byte", gst_stl_parser_byte}, - {"parse-consume", gst_stl_parser_consume}, - {"parse-hasvalue", gst_stl_parser_hasvalue}, - {"parse-charseq", gst_stl_parser_charseq}, - {"parse-status", gst_stl_parser_status}, - {NULL, NULL} -}; - -/* Load the module */ -void gst_parse_load(Gst *vm) { - gst_module(vm, "std.parse", gst_parser_module); -} +} \ No newline at end of file diff --git a/core/serialize.c b/core/serialize.c index 1a57431e..7f75d00a 100644 --- a/core/serialize.c +++ b/core/serialize.c @@ -513,9 +513,6 @@ const char *gst_serialize_impl( write_int(x.data.integer); } return NULL; - /*case GST_CFUNCTION:*/ - /* TODO */ - break; default: break; } diff --git a/core/stl.c b/core/stl.c index d8b5b2f7..4a0ef6d5 100644 --- a/core/stl.c +++ b/core/stl.c @@ -21,11 +21,6 @@ */ #include -#include -#include -#include - -#include static const char GST_EXPECTED_INTEGER[] = "expected integer"; static const char GST_EXPECTED_STRING[] = "expected string"; @@ -682,12 +677,6 @@ int gst_stl_namespace_set(Gst *vm) { /* Get the table or struct associated with a given namespace */ int gst_stl_namespace_get(Gst *vm) { return gst_callc(vm, gst_stl_get, 2, gst_wrap_table(vm->modules), gst_arg(vm, 0)); - /*GstValue name = gst_arg(vm, 0);*/ - /*GstValue check;*/ - /*if (name.type != GST_STRING)*/ - /*gst_c_throwc(vm, "expected string");*/ - /*check = gst_table_get(vm->modules, name);*/ - /*gst_c_return(vm, check);*/ } /***/ @@ -808,49 +797,10 @@ int gst_stl_close(Gst *vm) { gst_c_return(vm, gst_wrap_nil()); } -/* Functions in the io module */ -static const GstModuleItem io_dat[] = { - {"open", gst_stl_open}, - {"slurp", gst_stl_slurp}, - {"read", gst_stl_read}, - {"write", gst_stl_write}, - {NULL, NULL} -}; - -/* Load the io module */ -void gst_stlio_load(Gst *vm) { - /* Load the normal c functions */ - gst_module_mutable(vm, "std.io", io_dat); - /* Wrap stdin and stdout */ - FILE **inp = gst_userdata(vm, sizeof(FILE *), &gst_stl_filetype); - FILE **outp = gst_userdata(vm, sizeof(FILE *), &gst_stl_filetype); - *inp = stdin; - *outp = stdout; - gst_module_put(vm, "std.io", "stdin", gst_wrap_userdata(inp)); - gst_module_put(vm, "std.io", "stdout", gst_wrap_userdata(outp)); -} - /****/ /* Temporary */ /****/ -/* These functions should definitely be moved to a different module, removed, 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; -} - /* Force garbage collection */ int gst_stl_gcollect(Gst *vm) { gst_collect(vm); @@ -923,6 +873,184 @@ int gst_stl_debugp(Gst *vm) { gst_c_return(vm, gst_wrap_string(gst_buffer_to_string(vm, buf))); } +/***/ +/* Parsing */ +/***/ + +/* GC mark a parser */ +static void gst_stl_parser_mark(Gst *vm, void *data, uint32_t len) { + uint32_t i; + GstParser *p = (GstParser *) data; + if (len != sizeof(GstParser)) + return; + gst_mark_mem(vm, p->data); + gst_mark_value(vm, p->value); + for (i = 0; i < p->count; ++i) { + GstParseState *ps = p->data + i; + switch (ps->type) { + case PTYPE_FORM: + gst_mark_value(vm, gst_wrap_array(ps->buf.form.array)); + break; + case PTYPE_STRING: + case PTYPE_TOKEN: + gst_mark_value(vm, gst_wrap_buffer(ps->buf.string.buffer)); + break; + } + } +} + +/* Parse filetype */ +static const GstUserType gst_stl_parsetype = { + "std.parser", + NULL, + NULL, + NULL, + &gst_stl_parser_mark +}; + +/* Create a parser */ +static int gst_stl_parser(Gst *vm) { + GstParser *p = gst_userdata(vm, sizeof(GstParser), &gst_stl_parsetype); + gst_parser(p, vm); + gst_c_return(vm, gst_wrap_userdata(p)); +} + +/* Consume a value from the parser */ +static int gst_stl_parser_consume(Gst *vm) { + GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype); + if (p == NULL) + gst_c_throwc(vm, "expected parser"); + if (p->status == GST_PARSER_ERROR) + gst_c_return(vm, gst_string_cv(vm, p->error)); + if (!gst_parse_hasvalue(p)) + gst_c_throwc(vm, "parser has no pending value"); + gst_c_return(vm, gst_parse_consume(p)); +} + +/* Check if the parser has a value to consume */ +static int gst_stl_parser_hasvalue(Gst *vm) { + GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype); + if (p == NULL) + gst_c_throwc(vm, "expected parser"); + gst_c_return(vm, gst_wrap_boolean(gst_parse_hasvalue(p))); +} + +/* Parse a single byte. Returns if the byte was successfully parsed. */ +static int gst_stl_parser_byte(Gst *vm) { + GstInteger b; + GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype); + if (p == NULL) + gst_c_throwc(vm, "expected parser"); + if (!gst_check_integer(vm, 1, &b)) + gst_c_throwc(vm, "expected integer"); + if (p->status == GST_PARSER_PENDING || p->status == GST_PARSER_ROOT) { + gst_parse_byte(p, b); + gst_c_return(vm, gst_wrap_boolean(1)); + } else { + gst_c_return(vm, gst_wrap_boolean(0)); + } +} + +/* Parse a string or buffer. Returns nil if the entire char array is parsed, +* otherwise returns the remainder of what could not be parsed. */ +static int gst_stl_parser_charseq(Gst *vm) { + uint32_t i; + uint32_t len; + const uint8_t *data; + GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype); + if (p == NULL) + gst_c_throwc(vm, "expected parser"); + if (!gst_chararray_view(gst_arg(vm, 1), &data, &len)) + gst_c_throwc(vm, "expected string/buffer"); + for (i = 0; i < len; ++i) { + if (p->status != GST_PARSER_PENDING && p->status != GST_PARSER_ROOT) break; + gst_parse_byte(p, data[i]); + } + if (i == len) { + /* No remainder */ + gst_c_return(vm, gst_wrap_nil()); + } else { + /* We have remaining characters */ + gst_c_return(vm, gst_wrap_string(gst_string_b(vm, data + i, len - i))); + } +} + +/* Get status of parser */ +static int gst_stl_parser_status(Gst *vm) { + GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype); + const char *cstr; + if (p == NULL) + gst_c_throwc(vm, "expected parser"); + switch (p->status) { + case GST_PARSER_ERROR: + cstr = "error"; + break; + case GST_PARSER_FULL: + cstr = "full"; + break; + case GST_PARSER_PENDING: + cstr = "pending"; + break; + case GST_PARSER_ROOT: + cstr = "root"; + break; + default: + cstr = "unknown"; + break; + } + gst_c_return(vm, gst_string_cv(vm, cstr)); +} + +/* Parse a string */ +static int gst_stl_parse(Gst *vm) { + uint32_t len, i; + GstParser p; + const uint8_t *data; + if (!gst_chararray_view(gst_arg(vm, 0), &data, &len)) + gst_c_throwc(vm, "expected string/buffer to parse"); + gst_parser(&p, vm); + for (i = 0; i < len; ++i) { + if (p.status != GST_PARSER_PENDING && p.status != GST_PARSER_ROOT) break; + gst_parse_byte(&p, data[i]); + } + switch (p.status) { + case GST_PARSER_ERROR: + gst_c_throwc(vm, p.error); + break; + case GST_PARSER_FULL: + gst_c_return(vm, p.value); + break; + case GST_PARSER_PENDING: + case GST_PARSER_ROOT: + gst_c_throwc(vm, "unexpected end of source"); + break; + default: + gst_c_throwc(vm, "unknown error parsing"); + break; + } + return 0; +} + +/***/ +/* Compilation */ +/***/ + +/* Compile a value */ +static int gst_stl_compile(Gst *vm) { + GstFunction *ret; + GstValue std; + GstCompiler c; + gst_compiler(&c, vm); + std = gst_table_get(vm->modules, gst_string_cv(vm, "std")); + gst_compiler_globals(&c, std); + gst_compiler_globals(&c, gst_arg(vm, 1)); + gst_compiler_nilglobals(&c, gst_arg(vm, 2)); + ret = gst_compiler_compile(&c, gst_arg(vm, 0)); + if (!ret) + gst_c_throw(vm, c.error); + gst_c_return(vm, gst_wrap_function(ret)); +} + /****/ /* Bootstraping */ /****/ @@ -946,6 +1074,22 @@ static const GstModuleItem std_module[] = { {"blshift", gst_stl_blshift}, {"brshift", gst_stl_brshift}, {"bnot", gst_stl_bnot}, + /* IO */ + {"open", gst_stl_open}, + {"slurp", gst_stl_slurp}, + {"read", gst_stl_read}, + {"write", gst_stl_write}, + /* Parsing */ + {"parser", gst_stl_parser}, + {"parse-byte", gst_stl_parser_byte}, + {"parse-consume", gst_stl_parser_consume}, + {"parse-hasvalue", gst_stl_parser_hasvalue}, + {"parse-charseq", gst_stl_parser_charseq}, + {"parse-status", gst_stl_parser_status}, + {"parse-status", gst_stl_parser_status}, +{"parse", gst_stl_parse}, + /* Compile */ + {"compile", gst_stl_compile}, /* Other */ {"not", gst_stl_not}, {"length", gst_stl_length}, @@ -988,7 +1132,6 @@ static const GstModuleItem std_module[] = { {"funcenv", gst_stl_funcenv}, {"funcdef", gst_stl_funcdef}, {"funcparent", gst_stl_funcparent}, - {"dasm", gst_stl_dasm}, {"gcollect", gst_stl_gcollect}, {"debugp", gst_stl_debugp}, {NULL, NULL} @@ -996,6 +1139,16 @@ static const GstModuleItem std_module[] = { /* Load all libraries */ void gst_stl_load(Gst *vm) { - gst_stlio_load(vm); - gst_module(vm, "std", std_module); + /* Load the normal c functions */ + gst_module_mutable(vm, "std", std_module); + /* Wrap stdin and stdout */ + FILE **inp = gst_userdata(vm, sizeof(FILE *), &gst_stl_filetype); + FILE **outp = gst_userdata(vm, sizeof(FILE *), &gst_stl_filetype); + FILE **errp = gst_userdata(vm, sizeof(FILE *), &gst_stl_filetype); + *inp = stdin; + *outp = stdout; + *errp = stderr; + gst_module_put(vm, "std", "stdin", gst_wrap_userdata(inp)); + gst_module_put(vm, "std", "stdout", gst_wrap_userdata(outp)); + gst_module_put(vm, "std", "stderr", gst_wrap_userdata(outp)); } diff --git a/include/gst/compile.h b/include/gst/compile.h deleted file mode 100644 index 4f594cf3..00000000 --- a/include/gst/compile.h +++ /dev/null @@ -1,59 +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 COMPILE_H_9VXF71HY -#define COMPILE_H_9VXF71HY - -#include -#include - -typedef struct GstCompiler GstCompiler; -typedef struct GstScope GstScope; - -/* Compilation state */ -struct GstCompiler { - Gst *vm; - GstValue error; - jmp_buf onError; - GstScope *tail; - GstBuffer *buffer; -}; - -/* Initialize the Compiler */ -void gst_compiler(GstCompiler *c, Gst *vm); - -/* Add many globals */ -void gst_compiler_globals(GstCompiler *c, GstValue env); - -/* Register a global for the compilation environment. */ -void gst_compiler_global(GstCompiler *c, const char *name, GstValue x); - -/* Use a module */ -void gst_compiler_usemodule(GstCompiler *c, const char *modulename); - -/* Compile a function that evaluates the given form. */ -GstFunction *gst_compiler_compile(GstCompiler *c, GstValue form); - -/* Load the library */ -void gst_compile_load(Gst *vm); - -#endif /* end of include guard: COMPILE_H_9VXF71HY */ diff --git a/include/gst/disasm.h b/include/gst/disasm.h deleted file mode 100644 index 79cc7214..00000000 --- a/include/gst/disasm.h +++ /dev/null @@ -1,39 +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 disasm_h_INCLUDED -#define disasm_h_INCLUDED - -#include -#include - -/* Print disassembly for a given funciton */ -void gst_dasm(FILE * out, uint16_t * byteCode, uint32_t len); - -/* Print the disassembly for a function definition */ -void gst_dasm_funcdef(FILE * out, GstFuncDef * def); - -/* Print the disassembly for a function */ -void gst_dasm_function(FILE * out, GstFunction * f); - -#endif // disasm_h_INCLUDED - diff --git a/include/gst/gst.h b/include/gst/gst.h index 982d0e5c..a7225d70 100644 --- a/include/gst/gst.h +++ b/include/gst/gst.h @@ -25,6 +25,7 @@ #include #include +#include /* String utils */ #define gst_string_raw(s) ((uint32_t *)(s) - 2) @@ -161,6 +162,10 @@ typedef struct GstFuncEnv GstFuncEnv; typedef union GstValueUnion GstValueUnion; typedef struct GstModuleItem GstModuleItem; typedef struct GstUserType GstUserType; +typedef struct GstParser GstParser; +typedef struct GstParseState GstParseState; +typedef struct GstCompiler GstCompiler; +typedef struct GstScope GstScope; /* C Api data types */ struct GstModuleItem { @@ -312,6 +317,62 @@ struct Gst { GstValue ret; /* Returned value from gst_start. */ }; +/* The type of a ParseState */ +typedef enum ParseType { + PTYPE_FORM, + PTYPE_STRING, + PTYPE_TOKEN +} ParseType; + +/* Contain a parse state that goes on the parse stack */ +struct GstParseState { + ParseType type; + union { + struct { + uint8_t endDelimiter; + GstArray *array; + } form; + struct { + GstBuffer *buffer; + uint32_t count; + uint32_t accum; + enum { + STRING_STATE_BASE, + STRING_STATE_ESCAPE, + STRING_STATE_ESCAPE_UNICODE, + STRING_STATE_ESCAPE_HEX + } state; + } string; + } buf; +}; + +/* Holds the parsing state */ +struct GstParser { + Gst *vm; + const char *error; + GstParseState *data; + GstValue value; + uint32_t count; + uint32_t cap; + uint32_t index; + uint32_t quoteCount; + enum { + GST_PARSER_PENDING = 0, + GST_PARSER_FULL, + GST_PARSER_ERROR, + GST_PARSER_ROOT + } status; +}; + +/* Compilation state */ +struct GstCompiler { + Gst *vm; + GstValue error; + jmp_buf onError; + GstScope *tail; + GstBuffer *buffer; +}; + /* Bytecode */ enum GstOpCode { GST_OP_FLS, /* Load false */ @@ -456,6 +517,28 @@ const char *gst_deserialize( const char *gst_serialize(Gst *vm, GstBuffer *buffer, GstValue x); +/***/ +/* Parsing */ +/***/ + +void gst_parser(GstParser *p, Gst *vm); +int gst_parse_cstring(GstParser *p, const char *string); +int gst_parse_string(GstParser *p, const uint8_t *string); +void gst_parse_byte(GstParser *p, uint8_t byte); +int gst_parse_hasvalue(GstParser *p); +GstValue gst_parse_consume(GstParser *p); + +/***/ +/* Compilation */ +/***/ + +void gst_compiler(GstCompiler *c, Gst *vm); +void gst_compiler_nilglobals(GstCompiler *c, GstValue env); +void gst_compiler_globals(GstCompiler *c, GstValue env); +void gst_compiler_global(GstCompiler *c, const char *name, GstValue x); +void gst_compiler_usemodule(GstCompiler *c, const char *modulename); +GstFunction *gst_compiler_compile(GstCompiler *c, GstValue form); + /****/ /* GC */ /****/ @@ -488,6 +571,12 @@ GstValue gst_arg(Gst *vm, uint32_t index); void gst_set_arg(Gst *vm, uint32_t index, GstValue x); uint32_t gst_count_args(Gst *vm); +/***/ +/* Stl */ +/***/ + +void gst_stl_load(Gst *vm); + /****/ /* C Api */ /****/ diff --git a/include/gst/parse.h b/include/gst/parse.h deleted file mode 100644 index 6f8b04ef..00000000 --- a/include/gst/parse.h +++ /dev/null @@ -1,72 +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 PARSE_H_ONYWMADW -#define PARSE_H_ONYWMADW - -#include - -typedef struct GstParser GstParser; -typedef struct GstParseState GstParseState; - -/* Holds the parsing state */ -struct GstParser { - Gst *vm; - const char *error; - GstParseState *data; - GstValue value; - uint32_t count; - uint32_t cap; - uint32_t index; - uint32_t quoteCount; - enum { - GST_PARSER_PENDING = 0, - GST_PARSER_FULL, - GST_PARSER_ERROR, - GST_PARSER_ROOT - } status; -}; - -/* Initialize a parser */ -void gst_parser(GstParser *p, Gst *vm); - -/* Parse a c style string. Returns number of bytes read */ -int gst_parse_cstring(GstParser *p, const char *string); - -/* Parse a gst string. Returns number of bytes read */ -int gst_parse_string(GstParser *p, const uint8_t *string); - -/* Parse a single byte */ -void gst_parse_byte(GstParser *p, uint8_t byte); - -/* Check if a parser has a value that needs to be handled. If - * so, the parser will not parse any more input until that value - * is consumed. */ -int gst_parse_hasvalue(GstParser *p); - -/* Gets a value from the parser */ -GstValue gst_parse_consume(GstParser *p); - -/* Load the parsing library */ -void gst_parse_load(Gst *vm); - -#endif /* end of include guard: PARSE_H_ONYWMADW */ diff --git a/include/gst/stl.h b/include/gst/stl.h deleted file mode 100644 index d9b57953..00000000 --- a/include/gst/stl.h +++ /dev/null @@ -1,32 +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 stl_h_INCLUDED -#define stl_h_INCLUDED - -#include - -/* Load the standard library */ -void gst_stl_load(Gst *vm); - -#endif // stl_h_INCLUDED -