From 4be8e8e32f6c9de27a367eeff2cdedd33e7032b9 Mon Sep 17 00:00:00 2001 From: William Bell <62452284+Ugric@users.noreply.github.com> Date: Sat, 13 Sep 2025 01:17:16 +0100 Subject: [PATCH] add __repr__ --- src/runtime/objects/string/string.c | 42 +++++++++++++++++++++++++++++ src/runtime/objects/string/string.h | 2 ++ src/runtime/runtime.c | 29 +++++++++++++++++++- 3 files changed, 72 insertions(+), 1 deletion(-) diff --git a/src/runtime/objects/string/string.c b/src/runtime/objects/string/string.c index 1506204..4ce5d46 100644 --- a/src/runtime/objects/string/string.c +++ b/src/runtime/objects/string/string.c @@ -7,12 +7,54 @@ #include "string.h" #include "../number/number.h" #include "../object.h" +#include #include #include #include ArgonObject *ARGON_STRING_TYPE = NULL; + + + +char *c_quote_string(const char *input, size_t len) { + // Worst case: every byte becomes "\uXXXX" (6 chars) + quotes + NUL + size_t max_out = 2 + (len * 6) + 1; + char *out = malloc(max_out); + if (!out) return NULL; + + size_t j = 0; + out[j++] = '"'; + + for (size_t i = 0; i < len; i++) { + unsigned char c = (unsigned char)input[i]; + + switch (c) { + case '\n': + out[j++] = '\\'; out[j++] = 'n'; break; + case '\t': + out[j++] = '\\'; out[j++] = 't'; break; + case '\r': + out[j++] = '\\'; out[j++] = 'r'; break; + case '\\': + out[j++] = '\\'; out[j++] = '\\'; break; + case '\"': + out[j++] = '\\'; out[j++] = '\"'; break; + default: + if (isprint(c)) { + out[j++] = c; + } else { + // write \uXXXX + j += sprintf(&out[j], "\\u%04X", c); + } + } + } + + out[j++] = '"'; + out[j] = '\0'; + return out; +} + void init_string(ArgonObject*object,char *data, size_t length, uint64_t prehash, uint64_t hash) { add_builtin_field(object, field_length, diff --git a/src/runtime/objects/string/string.h b/src/runtime/objects/string/string.h index 59c02c1..15edc65 100644 --- a/src/runtime/objects/string/string.h +++ b/src/runtime/objects/string/string.h @@ -10,6 +10,8 @@ extern ArgonObject *ARGON_STRING_TYPE; +char *c_quote_string(const char *input, size_t len); + void init_string(ArgonObject*object,char *data, size_t length, uint64_t prehash, uint64_t hash); diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index 425e468..59fcc5a 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -310,6 +310,18 @@ ArgonObject *BASE_CLASS___string__(size_t argc, ArgonObject **argv, ArErr *err, return new_string_object_null_terminated(buffer); } + +ArgonObject *BASE_CLASS___repr__(size_t argc, ArgonObject **argv, + ArErr *err, RuntimeState *state) { + if (argc != 1) { + *err = create_err(0, 0, 0, "", "Runtime Error", + "__repr__ expects 1 arguments, got %" PRIu64, argc); + } + ArgonObject *string_method = get_builtin_field_for_class( + get_builtin_field(argv[0], __class__), __string__, argv[0]); + return argon_call(string_method, 0, NULL, err, state); +} + ArgonObject *BASE_CLASS___boolean__(size_t argc, ArgonObject **argv, ArErr *err, RuntimeState *state) { (void)argv; @@ -434,6 +446,18 @@ ArgonObject *ARGON_STRING_TYPE___string__(size_t argc, ArgonObject **argv, } return argv[0]; } +ArgonObject *ARGON_STRING_TYPE___repr__(size_t argc, ArgonObject **argv, + ArErr *err, RuntimeState *state) { + (void)state; + if (argc != 1) { + *err = create_err(0, 0, 0, "", "Runtime Error", + "__repr__ expects 1 arguments, got %" PRIu64, argc); + } + char* quoted = c_quote_string(argv[0]->value.as_str->data,argv[0]->value.as_str->length); + ArgonObject* result = new_string_object_null_terminated(quoted); + free(quoted); + return result; +} ArgonObject *ARGON_STRING_TYPE___hash__(size_t argc, ArgonObject **argv, ArErr *err, RuntimeState *state) { (void)state; @@ -591,7 +615,7 @@ void bootstrap_types() { create_argon_native_function("__string__", BASE_CLASS___string__)); add_builtin_field( BASE_CLASS, __repr__, - create_argon_native_function("__repr__", BASE_CLASS___string__)); + create_argon_native_function("__repr__", BASE_CLASS___repr__)); add_builtin_field( ARGON_TYPE_TYPE, __call__, create_argon_native_function("__call__", ARGON_TYPE_TYPE___call__)); @@ -619,6 +643,9 @@ void bootstrap_types() { add_builtin_field( ARGON_STRING_TYPE, __string__, create_argon_native_function("__string__", ARGON_STRING_TYPE___string__)); + add_builtin_field( + ARGON_STRING_TYPE, __repr__, + create_argon_native_function("__repr__", ARGON_STRING_TYPE___repr__)); add_builtin_field( ARGON_BOOL_TYPE, __new__, create_argon_native_function("__new__", ARGON_BOOL_TYPE___new__));