From 656942f612f46ad912190307c3d39460e0ab940b Mon Sep 17 00:00:00 2001 From: "K. Lange" Date: Sat, 9 Jan 2021 10:12:50 +0900 Subject: [PATCH] Cleanup and useful builtins --- README.md | 6 ++++-- builtins.c | 32 +++++++++++++++++++++++++++++ builtins.krk | 32 +++++++++++++++++++++++++++++ test/day4.krk | 10 --------- test/testLinesFromReadme.krk.expect | 2 +- vm.c | 11 ++++++---- 6 files changed, 76 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 5f9c6cf..926a56d 100644 --- a/README.md +++ b/README.md @@ -842,7 +842,9 @@ There is a single, shared VM state. `krk_initVM()` will initialize the compiler `krk_interpret` compiles and executes a block of code and takes the following arguments: +```c KrkValue krk_interpret(const char *sourceText, int newModuleScope, char *fromName, char *fromFile); +``` If `newModuleScope` is non-zero, the interpreter will parse code in the context of a new _module_ and the `KrkValue` returned will be a `module` object. @@ -948,8 +950,8 @@ Here we have created a new class named `MyNameClass` and exposed it through the ```c - myNewClass->base = vm.objectClass; \ - krk_tableAddAll(&vm.objectClass->methods, &myNewClass->methods); \ + myNewClass->base = vm.objectClass; + krk_tableAddAll(&vm.objectClass->methods, &myNewClass->methods); ``` We also want to make sure that our new class fits into the general inheritence hierarchy, which typically means inheriting from `vm.objectClass` - we do this by setting our new class's `base` pointer to `vm.objectClass` and copying `vm.objectClass`'s method table. Now we can start customizing our class with its own methods. diff --git a/builtins.c b/builtins.c index a82985f..23f894d 100644 --- a/builtins.c +++ b/builtins.c @@ -46,6 +46,38 @@ const char krk_builtinsSrc[] = " def items(self):\n" " return [(k,self[k]) for k in self.keys()]\n" "\n" +"class set():\n" +" def __init__(self, iter=[]):\n" +" self._dict = {}\n" +" self.__inrepr = 0\n" +" for v in iter:\n" +" self._dict[v] = 1\n" +" def __contains__(self, v):\n" +" return v in self._dict\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" +" self.__inrepr = 0\n" +" return b\n" +" def add(self,v):\n" +" self._dict[v] = 1\n" +" def __iter__(self):\n" +" return self._dict.keys().__iter__()\n" +"\n" +"__builtins__.set = set\n" +"\n" +"def any(iter):\n" +" for v in iter:\n" +" if v: return True\n" +" return False\n" +"__builtins__.any = any\n" +"\n" +"def all(iter):\n" +" for v in iter:\n" +" if not v: return False\n" +" return True\n" +"__builtins__.all = all\n" +"\n" "class Helper():\n" " '''You seem to already know how to use this.'''\n" " def __call__(self,obj=None):\n" diff --git a/builtins.krk b/builtins.krk index b1f4ade..31f7d18 100644 --- a/builtins.krk +++ b/builtins.krk @@ -45,6 +45,38 @@ class dict(): def items(self): return [(k,self[k]) for k in self.keys()] +class set(): + def __init__(self, iter=[]): + self._dict = {} + self.__inrepr = 0 + for v in iter: + self._dict[v] = 1 + def __contains__(self, v): + return v in self._dict + 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()])+'}' + self.__inrepr = 0 + return b + def add(self,v): + self._dict[v] = 1 + def __iter__(self): + return self._dict.keys().__iter__() + +__builtins__.set = set + +def any(iter): + for v in iter: + if v: return True + return False +__builtins__.any = any + +def all(iter): + for v in iter: + if not v: return False + return True +__builtins__.all = all + class Helper(): '''You seem to already know how to use this.''' def __call__(self,obj=None): diff --git a/test/day4.krk b/test/day4.krk index b0bccfd..281d5f7 100644 --- a/test/day4.krk +++ b/test/day4.krk @@ -2,16 +2,6 @@ from fileio import open let f = open('test/day4.in') let lines = f.read().split('\n')[:-1] -def any(iterator): - for v in iterator: - if v: return True - return False - -def all(iterator): - for v in iterator: - if not v: return False - return True - def is_digits(val, cnt): if len(val) != cnt: return False diff --git a/test/testLinesFromReadme.krk.expect b/test/testLinesFromReadme.krk.expect index 5d8b16c..5fc3887 100644 --- a/test/testLinesFromReadme.krk.expect +++ b/test/testLinesFromReadme.krk.expect @@ -1 +1 @@ -['', 'Kuroko is a bytecode-interpreted, dynamic, strongly-typed language with syntax similar to Python.', '', 'The bytecode VM / compiler is substantially based on Robert Nystrom\'s [_Crafting Interpreters_](https://craftinginterpreters.com/).'] +['# Kuroko - A bytecode-compiled scripting language', '', 'Kuroko is a bytecode-interpreted, dynamic, strongly-typed language with syntax similar to Python.', ''] diff --git a/vm.c b/vm.c index 4e6ec48..38e05fd 100644 --- a/vm.c +++ b/vm.c @@ -1120,8 +1120,6 @@ _finishArg: * * If callValue returns 0, the VM should already be in the exception state * and it is not necessary to raise another exception. - * - * TODO: Instances with __call__ method. */ int krk_callValue(KrkValue callee, int argCount, int extra) { if (IS_OBJECT(callee)) { @@ -1700,7 +1698,7 @@ static KrkValue _string_join(int argc, KrkValue argv[], int hasKw) { /* TODO: Support any object with an __iter__ - kinda need an internal method to do that well. */ if (!IS_INSTANCE(argv[1]) || !AS_INSTANCE(argv[1])->_internal || !((KrkObj*)AS_INSTANCE(argv[1])->_internal)->type == OBJ_FUNCTION) { - krk_runtimeError(vm.exceptions.typeError, "*expresssion value is not a list."); + krk_runtimeError(vm.exceptions.typeError, "str.join(): expected a list"); return NONE_VAL(); } @@ -1774,6 +1772,10 @@ static int charIn(char c, const char * str) { return 0; } +/** + * Implements all three of strip, lstrip, rstrip. + * Set which = 0, 1, 2 respectively + */ static KrkValue _string_strip_shared(int argc, KrkValue argv[], int which) { if (!IS_STRING(argv[0])) return NONE_VAL(); size_t start = 0; @@ -2180,7 +2182,8 @@ static KrkValue _repr_str(int argc, KrkValue argv[]) { case '\n': *(tmp++) = '\\'; *(tmp++) = 'n'; break; case '\r': *(tmp++) = '\\'; *(tmp++) = 'r'; break; case '\t': *(tmp++) = '\\'; *(tmp++) = 't'; break; - case '\'': *(tmp++) = '\\'; *(tmp++) = '\''; break; + case '\'': *(tmp++) = '\\'; *(tmp++) = '\''; break; + case '\\': *(tmp++) = '\\'; *(tmp++) = '\\'; break; case 27: *(tmp++) = '\\'; *(tmp++) = '['; break; default: *(tmp++) = *c; break; }