From 98fea9bb64b14adbfcb54c85b738cfa251abe4b6 Mon Sep 17 00:00:00 2001 From: "K. Lange" Date: Sun, 10 Jan 2021 12:30:34 +0900 Subject: [PATCH] print() should __str__, not __repr__; repl should __repr__, not printValue... printValue() probably shouldn't exist... and that's about it. --- README.md | 43 ++++++++++++++++++++++++++++++++++++++++--- builtins.c | 1 + builtins.krk | 1 + kuroko.c | 14 +++++++++++--- src/fileio.c | 1 + value.c | 16 ++++++++-------- vm.c | 1 + 7 files changed, 63 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 4601bb3..1bd2035 100644 --- a/README.md +++ b/README.md @@ -477,11 +477,24 @@ for i in l: # 3 ``` +If an iterator returns tuples, the values can be unpacked into multiple variables: + +```py +let l = [(1,2),(3,4),(5,6)] +for left, right in l: + print(left, right) +# → 1 2 +# 3 4 +# 5 6 +``` + +An exception will be raised if a tuple returned by the iterator has the wrong size for unpacking, or if a value returned is not a tuple. + ### Iterators The special method `__iter__` should return an iterator. An iterator should be a function which increments an internal state and returns the next value. If there are no values remaining, return the iterator itself. -An example of an iterator is the `range` built-in class, which is defined like this: +An example of an iterator is the `range` built-in class, which was previously defined like this: ```py class range: @@ -531,7 +544,7 @@ f[7] = "bar" # You asked to set ind=7 to bar ``` -### String Slicing +### Slicing Substrings can be extracted from strings via slicing: @@ -546,9 +559,16 @@ print("Hello world!"[-1:]) _**NOTE**: Step values are not yet supported._ +Lists can also be sliced: + +```py +print([1,2,3,4,5,6][3:]) +# → [4, 5, 6] +``` + ### String Conversion -If an object implements the `__str__` method, it will be called to produce string values when concatenating or printing. +If an object implements the `__str__` method, it will be called to produce string values through casting or printing. ```py class Foo: @@ -559,6 +579,23 @@ print(f) # → (I am a Foo!) ``` +The `__repr__` method serves a similar purpose and is used when the REPL displays values or when they used in string representations of collections. The implementations of `__str__` and `__repr__` can be different: + +```py +class Foo: + def __str__(): + return "What is a Foo but a miserable pile of methods?" + def __repr__(): + return "[Foo instance]" +let f = Foo() +print(f) +print([f,f,f]) +# → What is a Foo but a miserable pile of methods? +# [[Foo instance], [Foo instance], [Foo instance]] +``` + +As in Python, `__repr__` is intended to provide a canonical string representation which, if possible, should be usable to recreate the object. + ### File I/O The module `fileio` provides an interface for opening, reading, and writing files, including `stdin`/`stdout`/`stderr`. diff --git a/builtins.c b/builtins.c index fbfec95..1b7b61f 100644 --- a/builtins.c +++ b/builtins.c @@ -54,6 +54,7 @@ const char krk_builtinsSrc[] = " self._dict[v] = 1\n" " def __contains__(self, v):\n" " return v in self._dict\n" +" def __str__(self): return self.__repr__()\n" " def __repr__(self):\n" " if self.__inrepr: return '{}' # sets are supposed to be unhashable, but whatever\n" " let b='{'+', '.join([repr(k) for k in self._dict.keys()])+'}'\n" diff --git a/builtins.krk b/builtins.krk index fcab004..50f38a5 100644 --- a/builtins.krk +++ b/builtins.krk @@ -53,6 +53,7 @@ class set(): self._dict[v] = 1 def __contains__(self, v): return v in self._dict + def __str__(self): return self.__repr__() def __repr__(self): if self.__inrepr: return '{}' # sets are supposed to be unhashable, but whatever let b='{'+', '.join([repr(k) for k in self._dict.keys()])+'}' diff --git a/kuroko.c b/kuroko.c index 1b4737a..4e2bbf1 100644 --- a/kuroko.c +++ b/kuroko.c @@ -512,9 +512,17 @@ int main(int argc, char * argv[]) { if (valid) { KrkValue result = krk_interpret(allData, 0, "",""); if (!IS_NONE(result)) { - fprintf(stdout, " \033[1;30m=> "); - krk_printValue(stdout, result); - fprintf(stdout, "\033[0m\n"); + KrkClass * type = AS_CLASS(krk_typeOf(1,&result)); + const char * formatStr = " \033[1;30m=> %s\033[0m\n"; + if (type->_reprer) { + krk_push(result); + result = krk_callSimple(OBJECT_VAL(type->_reprer), 1, 0); + fprintf(stdout, formatStr, AS_CSTRING(result)); + } else if (type->_tostr) { + krk_push(result); + result = krk_callSimple(OBJECT_VAL(type->_reprer), 1, 0); + fprintf(stdout, formatStr, AS_CSTRING(result)); + } krk_resetStack(); } free(allData); diff --git a/src/fileio.c b/src/fileio.c index 2b168fd..d19fd69 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -303,6 +303,7 @@ KrkValue krk_module_onload_fileio(void) { krk_defineNative(&FileClass->methods, ".__init__", krk_file_reject_init); krk_defineNative(&FileClass->methods, ".__enter__", krk_file_enter); krk_defineNative(&FileClass->methods, ".__exit__", krk_file_exit); + krk_finalizeClass(FileClass); /* Make an instance for stdout, stderr, and stdin */ makeFileInstance(module, "stdin",stdin); diff --git a/value.c b/value.c index 90252a0..bd95953 100644 --- a/value.c +++ b/value.c @@ -53,16 +53,16 @@ void krk_printValue(FILE * f, KrkValue printable) { } return; } - krk_push(printable); - if (krk_bindMethod(AS_CLASS(krk_typeOf(1,(KrkValue[]){printable})), AS_STRING(vm.specialMethodNames[METHOD_REPR]))) { - switch (krk_callValue(krk_peek(0), 0, 0)) { - case 2: printable = krk_pop(); break; - case 1: printable = krk_runNext(); break; - default: fprintf(f, "[unable to print object at address %p]", (void*)AS_OBJECT(printable)); return; - } + KrkClass * type = AS_CLASS(krk_typeOf(1,&printable)); + if (type->_tostr) { + krk_push(printable); + printable = krk_callSimple(OBJECT_VAL(type->_tostr), 1, 0); + fprintf(f, "%s", AS_CSTRING(printable)); + } else if (type->_reprer) { + krk_push(printable); + printable = krk_callSimple(OBJECT_VAL(type->_reprer), 1, 0); fprintf(f, "%s", AS_CSTRING(printable)); } else { - krk_pop(); fprintf(f, "%s", krk_typeName(printable)); } } diff --git a/vm.c b/vm.c index 913bda2..bacef9b 100644 --- a/vm.c +++ b/vm.c @@ -2625,6 +2625,7 @@ void krk_initVM(int flags) { /* Attach new repr/str */ krk_defineNative(&vm.moduleClass->methods, ".__repr__", _module_repr); krk_defineNative(&vm.moduleClass->methods, ".__str__", _module_repr); + krk_finalizeClass(vm.moduleClass); /* Build a __builtins__ namespace for some extra functions. */ vm.builtins = krk_newInstance(vm.moduleClass);