mirror of
https://github.com/janet-lang/janet
synced 2025-01-11 08:00:27 +00:00
Add vararg support to compiler. Seems to be leak in parser.
This commit is contained in:
parent
6adc2a5268
commit
7b83247c07
4
Makefile
4
Makefile
@ -27,8 +27,8 @@ $(GST_CORELIB): $(GST_CORE_OBJECTS) $(GST_HEADERS)
|
|||||||
##############################
|
##############################
|
||||||
GST_CLIENT_SOURCES=client/main.c
|
GST_CLIENT_SOURCES=client/main.c
|
||||||
GST_CLIENT_OBJECTS=$(patsubst %.c,%.o,$(GST_CLIENT_SOURCES))
|
GST_CLIENT_OBJECTS=$(patsubst %.c,%.o,$(GST_CLIENT_SOURCES))
|
||||||
$(GST_TARGET): $(GST_CLIENT_OBJECTS) $(GST_CORELIB)
|
$(GST_TARGET): $(GST_CLIENT_OBJECTS) $(GST_CORE_OBJECTS)
|
||||||
$(CC) $(CFLAGS) -o $(GST_TARGET) $(GST_CLIENT_OBJECTS) $(GST_CORELIB)
|
$(CC) $(CFLAGS) -o $(GST_TARGET) $(GST_CLIENT_OBJECTS) $(GST_CORE_OBJECTS)
|
||||||
|
|
||||||
# Compile all .c to .o
|
# Compile all .c to .o
|
||||||
%.o : %.c $(GST_HEADERS) $(GST_INTERNAL_HEADERS)
|
%.o : %.c $(GST_HEADERS) $(GST_INTERNAL_HEADERS)
|
||||||
|
@ -66,51 +66,44 @@ int debug_run(Gst *vm, FILE *in) {
|
|||||||
char buffer[1024] = {0};
|
char buffer[1024] = {0};
|
||||||
const char *reader = buffer;
|
const char *reader = buffer;
|
||||||
GstValue ast;
|
GstValue ast;
|
||||||
GstValue *tup;
|
|
||||||
GstArray *arr;
|
|
||||||
GstParser p;
|
GstParser p;
|
||||||
/* Init parser */
|
/* Init parser */
|
||||||
gst_parser(&p, vm);
|
gst_parser(&p, vm);
|
||||||
/* Create do struct */
|
|
||||||
arr = gst_array(vm, 10);
|
|
||||||
gst_array_push(vm, arr, gst_string_cv(vm, "do"));
|
|
||||||
/* Get and parse input until we have a full form */
|
/* Get and parse input until we have a full form */
|
||||||
while (p.status != GST_PARSER_ERROR) {
|
while (p.status != GST_PARSER_ERROR) {
|
||||||
if (*reader == '\0') {
|
if (*reader == '\0') {
|
||||||
if (!fgets(buffer, sizeof(buffer), in)) {
|
if (!fgets(buffer, sizeof(buffer), in)) {
|
||||||
break;
|
|
||||||
}
|
|
||||||
reader = buffer;
|
|
||||||
}
|
|
||||||
reader += gst_parse_cstring(&p, reader);
|
|
||||||
if (gst_parse_hasvalue(&p))
|
|
||||||
gst_array_push(vm, arr, gst_parse_consume(&p));
|
|
||||||
}
|
|
||||||
/* Turn array into tuple */
|
|
||||||
tup = gst_tuple_begin(vm, arr->count);
|
|
||||||
gst_memcpy(tup, arr->data, arr->count * sizeof(GstValue));
|
|
||||||
ast = gst_wrap_tuple(gst_tuple_end(vm, tup));
|
|
||||||
/* Check if file read in correctly */
|
|
||||||
if (p.error) {
|
|
||||||
printf("Parse error: %s\n", p.error);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
/* Check that parser is complete */
|
/* Check that parser is complete */
|
||||||
if (p.status != GST_PARSER_FULL && p.status != GST_PARSER_ROOT) {
|
if (p.status != GST_PARSER_FULL && p.status != GST_PARSER_ROOT) {
|
||||||
printf("Unexpected end of source\n");
|
printf("Unexpected end of source\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return debug_compile_and_run(vm, ast, gst_wrap_nil());
|
return 0;
|
||||||
|
}
|
||||||
|
reader = buffer;
|
||||||
|
}
|
||||||
|
if (p.status != GST_PARSER_FULL)
|
||||||
|
reader += gst_parse_cstring(&p, reader);
|
||||||
|
if (gst_parse_hasvalue(&p)) {
|
||||||
|
ast = gst_parse_consume(&p);
|
||||||
|
debug_compile_and_run(vm, ast, gst_wrap_nil());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Check if file read in correctly */
|
||||||
|
if (p.error) {
|
||||||
|
printf("Parse error: %s\n", p.error);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A simple repl */
|
/* A simple repl */
|
||||||
int debug_repl(Gst *vm) {
|
int debug_repl(Gst *vm) {
|
||||||
const char *buffer, *reader;
|
const char *buffer, *reader;
|
||||||
GstParser p;
|
GstParser p;
|
||||||
|
buffer = reader = NULL;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* Init parser */
|
/* Init parser */
|
||||||
gst_parser(&p, vm);
|
gst_parser(&p, vm);
|
||||||
buffer = reader = NULL;
|
|
||||||
while (p.status != GST_PARSER_ERROR && p.status != GST_PARSER_FULL) {
|
while (p.status != GST_PARSER_ERROR && p.status != GST_PARSER_FULL) {
|
||||||
gst_parse_cstring(&p, "\n");
|
gst_parse_cstring(&p, "\n");
|
||||||
if (p.status == GST_PARSER_ERROR || p.status == GST_PARSER_FULL)
|
if (p.status == GST_PARSER_ERROR || p.status == GST_PARSER_FULL)
|
||||||
|
@ -572,7 +572,7 @@ static Slot compile_block(GstCompiler *c, FormOptions opts, const GstValue *form
|
|||||||
|
|
||||||
/* Extract the last n bytes from the buffer and use them to construct
|
/* Extract the last n bytes from the buffer and use them to construct
|
||||||
* a function definition. */
|
* a function definition. */
|
||||||
static GstFuncDef *compiler_gen_funcdef(GstCompiler *c, uint32_t lastNBytes, uint32_t arity) {
|
static GstFuncDef *compiler_gen_funcdef(GstCompiler *c, uint32_t lastNBytes, uint32_t arity, int varargs) {
|
||||||
GstScope *scope = c->tail;
|
GstScope *scope = c->tail;
|
||||||
GstBuffer *buffer = c->buffer;
|
GstBuffer *buffer = c->buffer;
|
||||||
GstFuncDef *def = gst_alloc(c->vm, sizeof(GstFuncDef));
|
GstFuncDef *def = gst_alloc(c->vm, sizeof(GstFuncDef));
|
||||||
@ -601,10 +601,20 @@ static GstFuncDef *compiler_gen_funcdef(GstCompiler *c, uint32_t lastNBytes, uin
|
|||||||
/* Initialize the new FuncDef */
|
/* Initialize the new FuncDef */
|
||||||
def->locals = scope->frameSize;
|
def->locals = scope->frameSize;
|
||||||
def->arity = arity;
|
def->arity = arity;
|
||||||
def->flags = 0;
|
def->flags = varargs ? GST_FUNCDEF_FLAG_VARARG : 0;
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check if a string a cstring are equal */
|
||||||
|
static int equal_cstr(const uint8_t *str, const char *cstr) {
|
||||||
|
uint32_t i;
|
||||||
|
for (i = 0; i < gst_string_length(str); ++i) {
|
||||||
|
if (cstr[i] == 0) return 0;
|
||||||
|
if (str[i] != ((const uint8_t *)cstr)[i]) return 0;
|
||||||
|
}
|
||||||
|
return cstr[i] == 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Compile a function from a function literal source form */
|
/* Compile a function from a function literal source form */
|
||||||
static Slot compile_function(GstCompiler *c, FormOptions opts, const GstValue *form) {
|
static Slot compile_function(GstCompiler *c, FormOptions opts, const GstValue *form) {
|
||||||
GstScope *scope = c->tail;
|
GstScope *scope = c->tail;
|
||||||
@ -616,6 +626,8 @@ static Slot compile_function(GstCompiler *c, FormOptions opts, const GstValue *f
|
|||||||
GstArray *params;
|
GstArray *params;
|
||||||
FormOptions subOpts = form_options_default();
|
FormOptions subOpts = form_options_default();
|
||||||
Slot ret;
|
Slot ret;
|
||||||
|
int varargs;
|
||||||
|
uint32_t arity;
|
||||||
if (opts.resultUnused) return nil_slot();
|
if (opts.resultUnused) return nil_slot();
|
||||||
ret = compiler_get_target(c, opts);
|
ret = compiler_get_target(c, opts);
|
||||||
subGstScope = compiler_push_scope(c, 0);
|
subGstScope = compiler_push_scope(c, 0);
|
||||||
@ -623,10 +635,19 @@ static Slot compile_function(GstCompiler *c, FormOptions opts, const GstValue *f
|
|||||||
if (form[current].type != GST_ARRAY)
|
if (form[current].type != GST_ARRAY)
|
||||||
c_error(c, "expected function arguments array");
|
c_error(c, "expected function arguments array");
|
||||||
params = form[current++].data.array;
|
params = form[current++].data.array;
|
||||||
|
arity = params->count;
|
||||||
for (i = 0; i < params->count; ++i) {
|
for (i = 0; i < params->count; ++i) {
|
||||||
GstValue param = params->data[i];
|
GstValue param = params->data[i];
|
||||||
if (param.type != GST_STRING)
|
if (param.type != GST_STRING)
|
||||||
c_error(c, "function parameters should be strings");
|
c_error(c, "function parameters should be strings");
|
||||||
|
/* Check for varargs */
|
||||||
|
if (equal_cstr(param.data.string, "&")) {
|
||||||
|
if (i != params->count - 1) {
|
||||||
|
c_error(c, "& is reserved for vararg argument in function");
|
||||||
|
}
|
||||||
|
varargs = 1;
|
||||||
|
arity--;
|
||||||
|
}
|
||||||
/* The compiler puts the parameter locals
|
/* The compiler puts the parameter locals
|
||||||
* in the right place by default - at the beginning
|
* in the right place by default - at the beginning
|
||||||
* of the stack frame. */
|
* of the stack frame. */
|
||||||
@ -643,7 +664,7 @@ static Slot compile_function(GstCompiler *c, FormOptions opts, const GstValue *f
|
|||||||
{
|
{
|
||||||
GstValue newVal;
|
GstValue newVal;
|
||||||
uint16_t literalIndex;
|
uint16_t literalIndex;
|
||||||
GstFuncDef *def = compiler_gen_funcdef(c, buffer->count - sizeBefore, params->count);
|
GstFuncDef *def = compiler_gen_funcdef(c, buffer->count - sizeBefore, arity, varargs);
|
||||||
/* Add this FuncDef as a literal in the outer scope */
|
/* Add this FuncDef as a literal in the outer scope */
|
||||||
newVal.type = GST_FUNCDEF;
|
newVal.type = GST_FUNCDEF;
|
||||||
newVal.data.def = def;
|
newVal.data.def = def;
|
||||||
@ -1121,7 +1142,7 @@ GstFunction *gst_compiler_compile(GstCompiler *c, GstValue form) {
|
|||||||
/* Create a scope */
|
/* Create a scope */
|
||||||
opts.isTail = 1;
|
opts.isTail = 1;
|
||||||
compiler_return(c, compile_value(c, opts, form));
|
compiler_return(c, compile_value(c, opts, form));
|
||||||
def = compiler_gen_funcdef(c, c->buffer->count, 0);
|
def = compiler_gen_funcdef(c, c->buffer->count, 0, 0);
|
||||||
{
|
{
|
||||||
GstFuncEnv *env = gst_alloc(c->vm, sizeof(GstFuncEnv));
|
GstFuncEnv *env = gst_alloc(c->vm, sizeof(GstFuncEnv));
|
||||||
GstFunction *func = gst_alloc(c->vm, sizeof(GstFunction));
|
GstFunction *func = gst_alloc(c->vm, sizeof(GstFunction));
|
||||||
|
44
core/parse.c
44
core/parse.c
@ -80,14 +80,11 @@ static GstParseState *parser_pop(GstParser * p) {
|
|||||||
/* Quote a value */
|
/* Quote a value */
|
||||||
static GstValue quote(GstParser *p, GstValue x) {
|
static GstValue quote(GstParser *p, GstValue x) {
|
||||||
/* Load a quote form to get the string literal */
|
/* Load a quote form to get the string literal */
|
||||||
GstValue tuplev;
|
|
||||||
GstValue *tuple;
|
GstValue *tuple;
|
||||||
tuple = gst_tuple_begin(p->vm, 2);
|
tuple = gst_tuple_begin(p->vm, 2);
|
||||||
tuple[0] = gst_string_cv(p->vm, "quote");
|
tuple[0] = gst_string_cv(p->vm, "quote");
|
||||||
tuple[1] = x;
|
tuple[1] = x;
|
||||||
tuplev.type = GST_TUPLE;
|
return gst_wrap_tuple(gst_tuple_end(p->vm, tuple));
|
||||||
tuplev.data.tuple = gst_tuple_end(p->vm, tuple);
|
|
||||||
return tuplev;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add a new, empty ParseState to the ParseStack. */
|
/* Add a new, empty ParseState to the ParseStack. */
|
||||||
@ -156,7 +153,7 @@ static int is_symbol_char(uint8_t c) {
|
|||||||
if (c >= '0' && c <= ':') return 1;
|
if (c >= '0' && c <= ':') return 1;
|
||||||
if (c >= '<' && c <= '@') return 1;
|
if (c >= '<' && c <= '@') return 1;
|
||||||
if (c >= '*' && c <= '/') return 1;
|
if (c >= '*' && c <= '/') return 1;
|
||||||
if (c >= '#' && c <= '&') return 1;
|
if (c >= '$' && c == '&') return 1;
|
||||||
if (c == '_') return 1;
|
if (c == '_') return 1;
|
||||||
if (c == '^') return 1;
|
if (c == '^') return 1;
|
||||||
if (c == '!') return 1;
|
if (c == '!') return 1;
|
||||||
@ -574,14 +571,14 @@ static const GstUserType gst_stl_parsetype = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Create a parser */
|
/* Create a parser */
|
||||||
int gst_stl_parser(Gst *vm) {
|
static int gst_stl_parser(Gst *vm) {
|
||||||
GstParser *p = gst_userdata(vm, sizeof(GstParser), &gst_stl_parsetype);
|
GstParser *p = gst_userdata(vm, sizeof(GstParser), &gst_stl_parsetype);
|
||||||
gst_parser(p, vm);
|
gst_parser(p, vm);
|
||||||
gst_c_return(vm, gst_wrap_userdata(p));
|
gst_c_return(vm, gst_wrap_userdata(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Consume a value from the parser */
|
/* Consume a value from the parser */
|
||||||
int gst_stl_parser_consume(Gst *vm) {
|
static int gst_stl_parser_consume(Gst *vm) {
|
||||||
GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype);
|
GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype);
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
gst_c_throwc(vm, "expected parser");
|
gst_c_throwc(vm, "expected parser");
|
||||||
@ -591,7 +588,7 @@ int gst_stl_parser_consume(Gst *vm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the parser has a value to consume */
|
/* Check if the parser has a value to consume */
|
||||||
int gst_stl_parser_hasvalue(Gst *vm) {
|
static int gst_stl_parser_hasvalue(Gst *vm) {
|
||||||
GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype);
|
GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype);
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
gst_c_throwc(vm, "expected parser");
|
gst_c_throwc(vm, "expected parser");
|
||||||
@ -599,7 +596,7 @@ int gst_stl_parser_hasvalue(Gst *vm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Parse a single byte. Returns if the byte was successfully parsed. */
|
/* Parse a single byte. Returns if the byte was successfully parsed. */
|
||||||
int gst_stl_parser_byte(Gst *vm) {
|
static int gst_stl_parser_byte(Gst *vm) {
|
||||||
GstInteger b;
|
GstInteger b;
|
||||||
GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype);
|
GstParser *p = gst_check_userdata(vm, 0, &gst_stl_parsetype);
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
@ -616,7 +613,7 @@ int gst_stl_parser_byte(Gst *vm) {
|
|||||||
|
|
||||||
/* Parse a string or buffer. Returns nil if the entire char array is parsed,
|
/* Parse a string or buffer. Returns nil if the entire char array is parsed,
|
||||||
* otherwise returns the remainder of what could not be parsed. */
|
* otherwise returns the remainder of what could not be parsed. */
|
||||||
int gst_stl_parser_charseq(Gst *vm) {
|
static int gst_stl_parser_charseq(Gst *vm) {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
const uint8_t *data;
|
const uint8_t *data;
|
||||||
@ -638,6 +635,32 @@ int gst_stl_parser_charseq(Gst *vm) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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 */
|
/* The module */
|
||||||
static const GstModuleItem gst_parser_module[] = {
|
static const GstModuleItem gst_parser_module[] = {
|
||||||
{"parser", gst_stl_parser},
|
{"parser", gst_stl_parser},
|
||||||
@ -645,6 +668,7 @@ static const GstModuleItem gst_parser_module[] = {
|
|||||||
{"parse-consume", gst_stl_parser_consume},
|
{"parse-consume", gst_stl_parser_consume},
|
||||||
{"parse-hasvalue", gst_stl_parser_hasvalue},
|
{"parse-hasvalue", gst_stl_parser_hasvalue},
|
||||||
{"parse-charseq", gst_stl_parser_charseq},
|
{"parse-charseq", gst_stl_parser_charseq},
|
||||||
|
{"parse-status", gst_stl_parser_status},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
30
core/stl.c
30
core/stl.c
@ -142,6 +142,9 @@ int gst_stl_length(Gst *vm) {
|
|||||||
case GST_TABLE:
|
case GST_TABLE:
|
||||||
ret.data.integer = x.data.table->count;
|
ret.data.integer = x.data.table->count;
|
||||||
break;
|
break;
|
||||||
|
case GST_STRUCT:
|
||||||
|
ret.data.integer = gst_struct_length(x.data.st);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
gst_c_return(vm, ret);
|
gst_c_return(vm, ret);
|
||||||
}
|
}
|
||||||
@ -179,14 +182,17 @@ int gst_stl_slice(Gst *vm) {
|
|||||||
int32_t from, to;
|
int32_t from, to;
|
||||||
GstValue x;
|
GstValue x;
|
||||||
const GstValue *data;
|
const GstValue *data;
|
||||||
|
const uint8_t *cdata;
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
uint32_t newlength;
|
uint32_t newlength;
|
||||||
GstInteger num;
|
GstInteger num;
|
||||||
|
|
||||||
/* Get data */
|
/* Get data */
|
||||||
x = gst_arg(vm, 0);
|
x = gst_arg(vm, 0);
|
||||||
if (!gst_seq_view(x, &data, &length))
|
if (!gst_seq_view(x, &data, &length) &&
|
||||||
|
!gst_chararray_view(x, &cdata, &length)) {
|
||||||
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) {
|
||||||
@ -207,7 +213,7 @@ int gst_stl_slice(Gst *vm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check from bad bounds */
|
/* Check from bad bounds */
|
||||||
if (from < 0 || to < 0)
|
if (from < 0 || to < 0 || to < from)
|
||||||
gst_c_throwc(vm, "index out of bounds");
|
gst_c_throwc(vm, "index out of bounds");
|
||||||
|
|
||||||
/* Build slice */
|
/* Build slice */
|
||||||
@ -216,11 +222,18 @@ int gst_stl_slice(Gst *vm) {
|
|||||||
GstValue *tup = gst_tuple_begin(vm, newlength);
|
GstValue *tup = gst_tuple_begin(vm, newlength);
|
||||||
gst_memcpy(tup, data + from, newlength * sizeof(GstValue));
|
gst_memcpy(tup, data + from, newlength * sizeof(GstValue));
|
||||||
gst_c_return(vm, gst_wrap_tuple(gst_tuple_end(vm, tup)));
|
gst_c_return(vm, gst_wrap_tuple(gst_tuple_end(vm, tup)));
|
||||||
} else {
|
} else if (x.type == GST_ARRAY) {
|
||||||
GstArray *arr = gst_array(vm, newlength);
|
GstArray *arr = gst_array(vm, newlength);
|
||||||
arr->count = newlength;
|
arr->count = newlength;
|
||||||
gst_memcpy(arr->data, data + from, newlength * sizeof(GstValue));
|
gst_memcpy(arr->data, data + from, newlength * sizeof(GstValue));
|
||||||
gst_c_return(vm, gst_wrap_array(arr));
|
gst_c_return(vm, gst_wrap_array(arr));
|
||||||
|
} else if (x.type == GST_STRING) {
|
||||||
|
gst_c_return(vm, gst_wrap_string(gst_string_b(vm, x.data.string + from, newlength)));
|
||||||
|
} else { /* buffer */
|
||||||
|
GstBuffer *b = gst_buffer(vm, newlength);
|
||||||
|
gst_memcpy(b->data, x.data.buffer->data, newlength);
|
||||||
|
b->count = newlength;
|
||||||
|
gst_c_return(vm, gst_wrap_buffer(b));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -539,6 +552,16 @@ int gst_stl_namespace_set(Gst *vm) {
|
|||||||
gst_c_return(vm, gst_wrap_nil());
|
gst_c_return(vm, gst_wrap_nil());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get the table or struct associated with a given namespace */
|
||||||
|
int gst_stl_namespace_get(Gst *vm) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
/****/
|
/****/
|
||||||
/* IO */
|
/* IO */
|
||||||
/****/
|
/****/
|
||||||
@ -715,6 +738,7 @@ static const GstModuleItem const std_module[] = {
|
|||||||
{"export!", gst_stl_export},
|
{"export!", gst_stl_export},
|
||||||
{"namespace", gst_stl_namespace},
|
{"namespace", gst_stl_namespace},
|
||||||
{"namespace-set!", gst_stl_namespace_set},
|
{"namespace-set!", gst_stl_namespace_set},
|
||||||
|
{"namespace-get", gst_stl_namespace_get},
|
||||||
{"push!", gst_stl_push},
|
{"push!", gst_stl_push},
|
||||||
{"pop!", gst_stl_pop},
|
{"pop!", gst_stl_pop},
|
||||||
{"peek", gst_stl_peek},
|
{"peek", gst_stl_peek},
|
||||||
|
12
libs/pp.gst
12
libs/pp.gst
@ -1,4 +1,4 @@
|
|||||||
# Pretty print
|
(do
|
||||||
|
|
||||||
# Declare pretty print
|
# Declare pretty print
|
||||||
(: pp nil)
|
(: pp nil)
|
||||||
@ -50,7 +50,11 @@
|
|||||||
|
|
||||||
# Define pretty print
|
# Define pretty print
|
||||||
(: pp (fn [x seen]
|
(: pp (fn [x seen]
|
||||||
(: h (get handlers (type x)))
|
(: handler (get handlers (type x)))
|
||||||
((if h h tostring) x seen)))
|
(: handler (if handler handler tostring))
|
||||||
|
(handler x seen)))
|
||||||
|
|
||||||
# (print (pp [1 {4 5 6 7} 2 3]))
|
# Export pretty print
|
||||||
|
(export! 'pp pp)
|
||||||
|
|
||||||
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user