From 94a20847230807d6030231b6ae888c0e1cbf2d9d Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Tue, 19 Mar 2019 13:36:26 -0400 Subject: [PATCH] Add tostring method for abstract types. This lets abstract types customize how they print for debugging. --- src/core/inttypes.c | 19 +++++++++++-- src/core/io.c | 1 + src/core/parse.c | 1 + src/core/peg.c | 1 + src/core/pp.c | 62 +++++++++++++++++++++++-------------------- src/core/typedarray.c | 4 ++- src/core/util.c | 1 + src/include/janet.h | 2 ++ 8 files changed, 59 insertions(+), 32 deletions(-) diff --git a/src/core/inttypes.c b/src/core/inttypes.c index 660616a7..abafc6ee 100644 --- a/src/core/inttypes.c +++ b/src/core/inttypes.c @@ -23,6 +23,7 @@ #include #include #include +#include #ifndef JANET_AMALG #include @@ -45,6 +46,18 @@ static void int64_unmarshal(void *p, JanetMarshalContext *ctx) { *((int64_t *)p) = janet_unmarshal_int64(ctx); } +static void it_s64_tostring(void *p, JanetBuffer *buffer) { + char str[32]; + sprintf(str, "", *((int64_t *)p)); + janet_buffer_push_cstring(buffer, str); +} + +static void it_u64_tostring(void *p, JanetBuffer *buffer) { + char str[32]; + sprintf(str, "", *((uint64_t *)p)); + janet_buffer_push_cstring(buffer, str); +} + static const JanetAbstractType it_s64_type = { "core/s64", NULL, @@ -52,7 +65,8 @@ static const JanetAbstractType it_s64_type = { it_s64_get, NULL, int64_marshal, - int64_unmarshal + int64_unmarshal, + it_s64_tostring }; static const JanetAbstractType it_u64_type = { @@ -62,7 +76,8 @@ static const JanetAbstractType it_u64_type = { it_u64_get, NULL, int64_marshal, - int64_unmarshal + int64_unmarshal, + it_u64_tostring }; int64_t janet_unwrap_s64(Janet x) { diff --git a/src/core/io.c b/src/core/io.c index 204d440e..d582a372 100644 --- a/src/core/io.c +++ b/src/core/io.c @@ -58,6 +58,7 @@ JanetAbstractType cfun_io_filetype = { io_file_get, NULL, NULL, + NULL, NULL }; diff --git a/src/core/parse.c b/src/core/parse.c index a7874b0f..74659f54 100644 --- a/src/core/parse.c +++ b/src/core/parse.c @@ -650,6 +650,7 @@ static JanetAbstractType janet_parse_parsertype = { parserget, NULL, NULL, + NULL, NULL }; diff --git a/src/core/peg.c b/src/core/peg.c index 46d786dd..74aa440b 100644 --- a/src/core/peg.c +++ b/src/core/peg.c @@ -986,6 +986,7 @@ static JanetAbstractType peg_type = { NULL, NULL, NULL, + NULL, NULL }; diff --git a/src/core/pp.c b/src/core/pp.c index b842bec9..0ca8e5be 100644 --- a/src/core/pp.c +++ b/src/core/pp.c @@ -201,8 +201,14 @@ void janet_description_b(JanetBuffer *buffer, Janet x) { janet_escape_buffer_b(buffer, janet_unwrap_buffer(x)); return; case JANET_ABSTRACT: { - const char *n = janet_abstract_type(janet_unwrap_abstract(x))->name; - string_description_b(buffer, n, janet_unwrap_abstract(x)); + void *p = janet_unwrap_abstract(x); + const JanetAbstractType *at = janet_abstract_type(p); + if (at->tostring) { + at->tostring(p, buffer); + } else { + const char *n = at->name; + string_description_b(buffer, n, janet_unwrap_abstract(x)); + } return; } case JANET_CFUNCTION: { @@ -456,38 +462,18 @@ static void pushtypes(JanetBuffer *buffer, int types) { } } -/* Helper function for formatting strings. Useful for generating error messages and the like. - * Similar to printf, but specialized for operating with janet. */ -const uint8_t *janet_formatc(const char *format, ...) { - va_list args; - int32_t len = 0; - int32_t i; - const uint8_t *ret; - JanetBuffer buffer; - JanetBuffer *bufp = &buffer; - - /* Calculate length */ - while (format[len]) len++; - - /* Initialize buffer */ - janet_buffer_init(bufp, len); - - /* Start args */ - va_start(args, format); - - /* Iterate length */ - for (i = 0; i < len; i++) { - uint8_t c = format[i]; - switch (c) { +void janet_formatb(JanetBuffer *bufp, const char *format, va_list args) { + for (const char *c = format; *c; c++) { + switch (*c) { default: - janet_buffer_push_u8(bufp, c); + janet_buffer_push_u8(bufp, *c); break; case '%': { - if (i + 1 >= len) + if (c[1] == '\0') break; - switch (format[++i]) { + switch (*++c) { default: - janet_buffer_push_u8(bufp, format[i]); + janet_buffer_push_u8(bufp, *c); break; case 'f': number_to_string_b(bufp, va_arg(args, double)); @@ -535,7 +521,25 @@ const uint8_t *janet_formatc(const char *format, ...) { } } } +} +/* Helper function for formatting strings. Useful for generating error messages and the like. + * Similar to printf, but specialized for operating with janet. */ +const uint8_t *janet_formatc(const char *format, ...) { + va_list args; + const uint8_t *ret; + JanetBuffer buffer; + int32_t len = 0; + + /* Calculate length, init buffer and args */ + while (format[len]) len++; + janet_buffer_init(&buffer, len); + va_start(args, format); + + /* Run format */ + janet_formatb(&buffer, format, args); + + /* Iterate length */ va_end(args); ret = janet_string(buffer.data, buffer.count); diff --git a/src/core/typedarray.c b/src/core/typedarray.c index 42a07087..7260384e 100644 --- a/src/core/typedarray.c +++ b/src/core/typedarray.c @@ -117,6 +117,7 @@ static const JanetAbstractType ta_buffer_type = { NULL, ta_buffer_marshal, ta_buffer_unmarshal, + NULL }; static int ta_mark(void *p, size_t s) { @@ -273,7 +274,8 @@ static const JanetAbstractType ta_view_type = { ta_getter, ta_setter, ta_view_marshal, - ta_view_unmarshal + ta_view_unmarshal, + NULL }; JanetTArrayBuffer *janet_tarray_buffer(size_t size) { diff --git a/src/core/util.c b/src/core/util.c index 0caa0219..214b6418 100644 --- a/src/core/util.c +++ b/src/core/util.c @@ -293,6 +293,7 @@ static const JanetAbstractType type_wrap = { NULL, NULL, NULL, + NULL, NULL }; diff --git a/src/include/janet.h b/src/include/janet.h index 091acb2f..8f983749 100644 --- a/src/include/janet.h +++ b/src/include/janet.h @@ -833,6 +833,7 @@ struct JanetAbstractType { void (*put)(void *data, Janet key, Janet value); void (*marshal)(void *p, JanetMarshalContext *ctx); void (*unmarshal)(void *p, JanetMarshalContext *ctx); + void (*tostring)(void *p, JanetBuffer *buffer); }; struct JanetReg { @@ -1101,6 +1102,7 @@ JANET_API void janet_description_b(JanetBuffer *buffer, Janet x); #define janet_cstringv(cstr) janet_wrap_string(janet_cstring(cstr)) #define janet_stringv(str, len) janet_wrap_string(janet_string((str), (len))) JANET_API const uint8_t *janet_formatc(const char *format, ...); +JANET_API void janet_formatb(JanetBuffer *bufp, const char *format, va_list args); /* Symbol functions */ JANET_API const uint8_t *janet_symbol(const uint8_t *str, int32_t len);