1
0
mirror of https://github.com/janet-lang/janet synced 2025-01-12 00:20:26 +00:00

Remove lots of headers. Add parse c function.

This commit is contained in:
Calvin Rose 2017-06-24 14:27:29 -04:00
parent 70478a410b
commit c3d65cb91d
12 changed files with 304 additions and 679 deletions

View File

@ -8,7 +8,7 @@ PREFIX=/usr/local
GST_TARGET=client/gst GST_TARGET=client/gst
GST_CORELIB=core/libgst.a GST_CORELIB=core/libgst.a
GST_INTERNAL_HEADERS=$(addprefix core/, cache.h) 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) all: $(GST_TARGET)
@ -16,7 +16,7 @@ all: $(GST_TARGET)
##### The core vm and runtime ##### ##### The core vm and runtime #####
################################### ###################################
GST_CORE_SOURCES=$(addprefix core/,\ 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) value.c vm.c ds.c gc.c thread.c serialize.c)
GST_CORE_OBJECTS=$(patsubst %.c,%.o,$(GST_CORE_SOURCES)) GST_CORE_OBJECTS=$(patsubst %.c,%.o,$(GST_CORE_SOURCES))
@ -49,6 +49,6 @@ clean:
rm vgcore.* || true rm vgcore.* || true
test: $(GST_TARGET) test: $(GST_TARGET)
gsttests/basic.gst $(GST_TARGET) gsttests/basic.gst
.PHONY: clean install run debug valgrind .PHONY: clean install run debug valgrind

View File

@ -23,9 +23,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <gst/gst.h> #include <gst/gst.h>
#include <gst/parse.h>
#include <gst/compile.h>
#include <gst/stl.h>
/* Use readline support for now */ /* Use readline support for now */
#include <readline/readline.h> #include <readline/readline.h>
@ -38,9 +35,6 @@ int debug_compile_and_run(Gst *vm, GstValue ast, GstValue last) {
/* Try to compile generated AST */ /* Try to compile generated AST */
gst_compiler(&c, vm); gst_compiler(&c, vm);
gst_compiler_usemodule(&c, "std"); 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); gst_compiler_global(&c, "_", last);
func = gst_wrap_function(gst_compiler_compile(&c, ast)); func = gst_wrap_function(gst_compiler_compile(&c, ast));
/* Check for compilation errors */ /* Check for compilation errors */
@ -147,8 +141,7 @@ int main(int argc, const char **argv) {
gst_init(&vm); gst_init(&vm);
gst_stl_load(&vm); gst_stl_load(&vm);
gst_parse_load(&vm);
gst_compile_load(&vm);
if (argc > 1) { if (argc > 1) {
const char *filename; const char *filename;
FILE *f; FILE *f;

View File

@ -21,7 +21,6 @@
*/ */
#include <gst/gst.h> #include <gst/gst.h>
#include <gst/compile.h>
/* During compilation, FormOptions are passed to ASTs /* During compilation, FormOptions are passed to ASTs
* as configuration options to allow for some optimizations. */ * as configuration options to allow for some optimizations. */
@ -1209,35 +1208,4 @@ GstFunction *gst_compiler_compile(GstCompiler *c, GstValue form) {
func->env = env; func->env = env;
return func; 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);
}

View File

@ -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 <gst/disasm.h>
/* 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");
}
}

View File

@ -21,39 +21,9 @@
*/ */
#include <gst/gst.h> #include <gst/gst.h>
#include <gst/parse.h>
static const char UNEXPECTED_CLOSING_DELIM[] = "Unexpected closing delimiter"; 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 */ /* Handle error in parsing */
#define p_error(p, e) ((p)->error = (e), (p)->status = GST_PARSER_ERROR) #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 */ /* Handle a character */
static void dispatch_char(GstParser *p, uint8_t c) { void gst_parse_byte(GstParser *p, uint8_t c) {
int done = 0; int done = 0;
++p->index; ++p->index;
/* Dispatch character to state */ /* Dispatch character to state */
@ -464,7 +434,7 @@ int gst_parse_cstring(GstParser *p, const char *string) {
return 0; return 0;
while ((p->status == GST_PARSER_PENDING || p->status == GST_PARSER_ROOT) while ((p->status == GST_PARSER_PENDING || p->status == GST_PARSER_ROOT)
&& (string[bytesRead] != '\0')) { && (string[bytesRead] != '\0')) {
dispatch_char(p, string[bytesRead++]); gst_parse_byte(p, string[bytesRead++]);
} }
return bytesRead; return bytesRead;
} }
@ -476,16 +446,11 @@ int gst_parse_string(GstParser *p, const uint8_t *string) {
return 0; return 0;
for (i = 0; i < gst_string_length(string); ++i) { for (i = 0; i < gst_string_length(string); ++i) {
if (p->status != GST_PARSER_PENDING && p->status != GST_PARSER_ROOT) break; 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; 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 /* 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 * so, the parser will not parse any more input until that value
* is consumed. */ * is consumed. */
@ -511,148 +476,4 @@ void gst_parser(GstParser *p, Gst *vm) {
p->error = NULL; p->error = NULL;
p->status = GST_PARSER_ROOT; p->status = GST_PARSER_ROOT;
p->value.type = GST_NIL; 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);
}

View File

@ -513,9 +513,6 @@ const char *gst_serialize_impl(
write_int(x.data.integer); write_int(x.data.integer);
} }
return NULL; return NULL;
/*case GST_CFUNCTION:*/
/* TODO */
break;
default: default:
break; break;
} }

View File

@ -21,11 +21,6 @@
*/ */
#include <gst/gst.h> #include <gst/gst.h>
#include <gst/parse.h>
#include <gst/compile.h>
#include <gst/stl.h>
#include <gst/disasm.h>
static const char GST_EXPECTED_INTEGER[] = "expected integer"; static const char GST_EXPECTED_INTEGER[] = "expected integer";
static const char GST_EXPECTED_STRING[] = "expected string"; 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 */ /* Get the table or struct associated with a given namespace */
int gst_stl_namespace_get(Gst *vm) { int gst_stl_namespace_get(Gst *vm) {
return gst_callc(vm, gst_stl_get, 2, gst_wrap_table(vm->modules), gst_arg(vm, 0)); 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()); 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 */ /* 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 */ /* Force garbage collection */
int gst_stl_gcollect(Gst *vm) { int gst_stl_gcollect(Gst *vm) {
gst_collect(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))); 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 */ /* Bootstraping */
/****/ /****/
@ -946,6 +1074,22 @@ static const GstModuleItem std_module[] = {
{"blshift", gst_stl_blshift}, {"blshift", gst_stl_blshift},
{"brshift", gst_stl_brshift}, {"brshift", gst_stl_brshift},
{"bnot", gst_stl_bnot}, {"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 */ /* Other */
{"not", gst_stl_not}, {"not", gst_stl_not},
{"length", gst_stl_length}, {"length", gst_stl_length},
@ -988,7 +1132,6 @@ static const GstModuleItem std_module[] = {
{"funcenv", gst_stl_funcenv}, {"funcenv", gst_stl_funcenv},
{"funcdef", gst_stl_funcdef}, {"funcdef", gst_stl_funcdef},
{"funcparent", gst_stl_funcparent}, {"funcparent", gst_stl_funcparent},
{"dasm", gst_stl_dasm},
{"gcollect", gst_stl_gcollect}, {"gcollect", gst_stl_gcollect},
{"debugp", gst_stl_debugp}, {"debugp", gst_stl_debugp},
{NULL, NULL} {NULL, NULL}
@ -996,6 +1139,16 @@ static const GstModuleItem std_module[] = {
/* Load all libraries */ /* Load all libraries */
void gst_stl_load(Gst *vm) { void gst_stl_load(Gst *vm) {
gst_stlio_load(vm); /* Load the normal c functions */
gst_module(vm, "std", std_module); 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));
} }

View File

@ -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 <gst/gst.h>
#include <setjmp.h>
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 */

View File

@ -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 <gst/gst.h>
#include <stdio.h>
/* 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

View File

@ -25,6 +25,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdarg.h> #include <stdarg.h>
#include <setjmp.h>
/* String utils */ /* String utils */
#define gst_string_raw(s) ((uint32_t *)(s) - 2) #define gst_string_raw(s) ((uint32_t *)(s) - 2)
@ -161,6 +162,10 @@ typedef struct GstFuncEnv GstFuncEnv;
typedef union GstValueUnion GstValueUnion; typedef union GstValueUnion GstValueUnion;
typedef struct GstModuleItem GstModuleItem; typedef struct GstModuleItem GstModuleItem;
typedef struct GstUserType GstUserType; typedef struct GstUserType GstUserType;
typedef struct GstParser GstParser;
typedef struct GstParseState GstParseState;
typedef struct GstCompiler GstCompiler;
typedef struct GstScope GstScope;
/* C Api data types */ /* C Api data types */
struct GstModuleItem { struct GstModuleItem {
@ -312,6 +317,62 @@ struct Gst {
GstValue ret; /* Returned value from gst_start. */ 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 */ /* Bytecode */
enum GstOpCode { enum GstOpCode {
GST_OP_FLS, /* Load false */ GST_OP_FLS, /* Load false */
@ -456,6 +517,28 @@ const char *gst_deserialize(
const char *gst_serialize(Gst *vm, GstBuffer *buffer, GstValue x); 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 */ /* GC */
/****/ /****/
@ -488,6 +571,12 @@ GstValue gst_arg(Gst *vm, uint32_t index);
void gst_set_arg(Gst *vm, uint32_t index, GstValue x); void gst_set_arg(Gst *vm, uint32_t index, GstValue x);
uint32_t gst_count_args(Gst *vm); uint32_t gst_count_args(Gst *vm);
/***/
/* Stl */
/***/
void gst_stl_load(Gst *vm);
/****/ /****/
/* C Api */ /* C Api */
/****/ /****/

View File

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

View File

@ -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 <gst/gst.h>
/* Load the standard library */
void gst_stl_load(Gst *vm);
#endif // stl_h_INCLUDED