diff --git a/client/main.c b/client/main.c index eea0e97e..57b91b5a 100644 --- a/client/main.c +++ b/client/main.c @@ -157,7 +157,7 @@ static int debug_repl(Gst *vm) { continue; } if (!debug_compile_and_run(vm, gst_parse_consume(&p), vm->ret)) { - printf("%s\n", gst_to_string(vm, vm->ret)); + printf("%s\n", gst_description(vm, vm->ret)); } } } diff --git a/core/stl.c b/core/stl.c index f48354ae..91e4a0b2 100644 --- a/core/stl.c +++ b/core/stl.c @@ -832,83 +832,11 @@ int gst_stl_gcollect(Gst *vm) { return GST_RETURN_OK; } -/* Static debug print helper */ -static GstInteger gst_stl_debugp_helper(Gst *vm, GstBuffer *b, GstTable *seen, GstValue x, GstInteger next, int depth) { - GstValue check = gst_table_get(seen, x); - const uint8_t *str; - /* Prevent a stack overflow */ - if (depth++ > GST_RECURSION_GUARD) - return -1; - if (check.type == GST_INTEGER) { - str = gst_to_string(vm, check); - gst_buffer_append_cstring(vm, b, ""); - } else { - uint8_t open, close; - uint32_t len, i; - const GstValue *data; - switch (x.type) { - default: - str = gst_to_string(vm, x); - gst_buffer_append(vm, b, str, gst_string_length(str)); - return next; - case GST_STRUCT: - open = '<'; close = '>'; - break; - case GST_TABLE: - open = '{'; close = '}'; - break; - case GST_TUPLE: - open = '('; close = ')'; - break; - case GST_ARRAY: - open = '['; close = ']'; - break; - } - gst_table_put(vm, seen, x, gst_wrap_integer(next++)); - gst_buffer_push(vm, b, open); - if (gst_hashtable_view(x, &data, &len)) { - int isfirst = 1; - for (i = 0; i < len; i += 2) { - if (data[i].type != GST_NIL) { - if (isfirst) - isfirst = 0; - else - gst_buffer_push(vm, b, ' '); - next = gst_stl_debugp_helper(vm, b, seen, data[i], next, depth); - if (next == -1) - return -1; - gst_buffer_push(vm, b, ' '); - next = gst_stl_debugp_helper(vm, b, seen, data[i + 1], next, depth); - if (next == -1) - return -1; - } - } - } else if (gst_seq_view(x, &data, &len)) { - for (i = 0; i < len; ++i) { - next = gst_stl_debugp_helper(vm, b, seen, data[i], next, depth); - if (next == -1) - return -1; - if (i != len - 1) - gst_buffer_push(vm, b, ' '); - } - } - gst_buffer_push(vm, b, close); - } - return next; -} - /* Debug print */ -int gst_stl_debugp(Gst *vm) { +int gst_stl_description(Gst *vm) { GstValue x = gst_arg(vm, 0); - GstBuffer *buf = gst_buffer(vm, 10); - GstInteger res = gst_stl_debugp_helper(vm, buf, gst_table(vm, 10), x, 0, 0); - if (res == -1) { - gst_c_throwc(vm, "recursed too deeply in debugp"); - } else { - gst_c_return(vm, gst_wrap_string(gst_buffer_to_string(vm, buf))); - } + const uint8_t *buf = gst_description(vm, x); + gst_c_return(vm, gst_wrap_string(buf)); } /***/ @@ -1169,7 +1097,7 @@ static const GstModuleItem std_module[] = { {"funcdef", gst_stl_funcdef}, {"funcparent", gst_stl_funcparent}, {"gcollect", gst_stl_gcollect}, - {"debugp", gst_stl_debugp}, + {"description", gst_stl_description}, {"global-def", gst_stl_def}, {"global-var", gst_stl_var}, {NULL, NULL} diff --git a/core/util.c b/core/util.c index 0b195a22..8d24c532 100644 --- a/core/util.c +++ b/core/util.c @@ -238,6 +238,81 @@ GstInteger gst_endrange(GstInteger raw, uint32_t len) { return raw; } + +/* Static debug print helper */ +static GstInteger gst_description_helper(Gst *vm, GstBuffer *b, GstTable *seen, GstValue x, GstInteger next, int depth) { + GstValue check = gst_table_get(seen, x); + const uint8_t *str; + /* Prevent a stack overflow */ + if (depth++ > GST_RECURSION_GUARD) + return -1; + if (check.type == GST_INTEGER) { + str = gst_to_string(vm, check); + gst_buffer_append_cstring(vm, b, ""); + } else { + uint8_t open, close; + uint32_t len, i; + const GstValue *data; + switch (x.type) { + default: + str = gst_to_string(vm, x); + gst_buffer_append(vm, b, str, gst_string_length(str)); + return next; + case GST_STRUCT: + open = '<'; close = '>'; + break; + case GST_TABLE: + open = '{'; close = '}'; + break; + case GST_TUPLE: + open = '('; close = ')'; + break; + case GST_ARRAY: + open = '['; close = ']'; + break; + } + gst_table_put(vm, seen, x, gst_wrap_integer(next++)); + gst_buffer_push(vm, b, open); + if (gst_hashtable_view(x, &data, &len)) { + int isfirst = 1; + for (i = 0; i < len; i += 2) { + if (data[i].type != GST_NIL) { + if (isfirst) + isfirst = 0; + else + gst_buffer_push(vm, b, ' '); + next = gst_description_helper(vm, b, seen, data[i], next, depth); + if (next == -1) + gst_buffer_append_cstring(vm, b, "..."); + gst_buffer_push(vm, b, ' '); + next = gst_description_helper(vm, b, seen, data[i + 1], next, depth); + if (next == -1) + gst_buffer_append_cstring(vm, b, "..."); + } + } + } else if (gst_seq_view(x, &data, &len)) { + for (i = 0; i < len; ++i) { + next = gst_description_helper(vm, b, seen, data[i], next, depth); + if (next == -1) + return -1; + if (i != len - 1) + gst_buffer_push(vm, b, ' '); + } + } + gst_buffer_push(vm, b, close); + } + return next; +} + +/* Debug print. Returns a description of an object as a buffer. */ +const uint8_t *gst_description(Gst *vm, GstValue x) { + GstBuffer *buf = gst_buffer(vm, 10); + gst_description_helper(vm, buf, gst_table(vm, 10), x, 0, 0); + return gst_buffer_to_string(vm, buf); +} + int gst_callc(Gst *vm, GstCFunction fn, int numargs, ...) { int result, i; va_list args; diff --git a/gsttests/basic.gst b/gsttests/basic.gst index 1f668ceb..e2129247 100644 --- a/gsttests/basic.gst +++ b/gsttests/basic.gst @@ -58,7 +58,7 @@ (def scheck (fn [x] (def dat (serialize x)) (def deser (deserialize dat)) - (assert (= x deser) (string "serialize " (debugp x))) + (assert (= x deser) (string "serialize " (description x))) )) (scheck 1) diff --git a/include/gst/gst.h b/include/gst/gst.h index b1f0d5ad..c2343fd8 100644 --- a/include/gst/gst.h +++ b/include/gst/gst.h @@ -1,16 +1,16 @@ /* * 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 @@ -496,13 +496,13 @@ GstValue gst_table_next(GstTable *o, GstValue key); #define gst_thread_stack(t) ((t)->data + (t)->count) GstThread *gst_thread(Gst *vm, GstValue callee, uint32_t capacity); GstThread *gst_thread_reset(Gst *vm, GstThread *thread, GstValue callee); -void gst_thread_ensure_extra(Gst *vm, GstThread *thread, uint32_t extra); -void gst_thread_push(Gst *vm, GstThread *thread, GstValue x); -void gst_thread_pushnil(Gst *vm, GstThread *thread, uint32_t n); -void gst_thread_tuplepack(Gst *vm, GstThread *thread, uint32_t n); -GstValue *gst_thread_beginframe(Gst *vm, GstThread *thread, GstValue callee, uint32_t arity); +void gst_thread_ensure_extra(Gst *vm, GstThread *thread, uint32_t extra); +void gst_thread_push(Gst *vm, GstThread *thread, GstValue x); +void gst_thread_pushnil(Gst *vm, GstThread *thread, uint32_t n); +void gst_thread_tuplepack(Gst *vm, GstThread *thread, uint32_t n); +GstValue *gst_thread_beginframe(Gst *vm, GstThread *thread, GstValue callee, uint32_t arity); void gst_thread_endframe(Gst *vm, GstThread *thread); -GstValue *gst_thread_popframe(Gst *vm, GstThread *thread); +GstValue *gst_thread_popframe(Gst *vm, GstThread *thread); uint32_t gst_thread_countframes(GstThread *thread); /****/ @@ -661,5 +661,6 @@ void gst_env_put(Gst *vm, GstTable *env, GstValue key, GstValue value); void gst_env_putc(Gst *vm, GstTable *env, const char *key, GstValue value); void gst_env_putvar(Gst *vm, GstTable *env, GstValue key, GstValue value); void gst_env_putvarc(Gst *vm, GstTable *env, const char *key, GstValue value); +const uint8_t *gst_description(Gst *vm, GstValue x); #endif // GST_H_defined