C-ify some more collection methods
This commit is contained in:
parent
abff851af0
commit
85e7c667b4
44
builtins.c
44
builtins.c
@ -1,32 +1,8 @@
|
||||
const char krk_builtinsSrc[] =
|
||||
"# Please avoid using double quotes or escape sequences\n"
|
||||
"# in this file to allow it to be easily converted to C.\n"
|
||||
"class list():\n"
|
||||
" 'Resizable array with direct constant-time indexing.'\n"
|
||||
" def extend(i):\n"
|
||||
" 'Add all entries from an iterable to the end of this list.'\n"
|
||||
" if isinstance(i,list):\n"
|
||||
" return self._extend_fast(i)\n"
|
||||
" for v in i:\n"
|
||||
" self.append(v)\n"
|
||||
" return self.__len__()\n"
|
||||
" def __str__(self): return self.__repr__()\n"
|
||||
" def __repr__(self):\n"
|
||||
" if self.__inrepr: return '[...]'\n"
|
||||
" self.__inrepr=1\n"
|
||||
" let b='['+', '.join([repr(i) for i in self])+']'\n"
|
||||
" self.__inrepr=0\n"
|
||||
" return b\n"
|
||||
"\n"
|
||||
"class dict():\n"
|
||||
" 'Hashmap of arbitrary keys to arbitrary values.'\n"
|
||||
" def __str__(self): return self.__repr__()\n"
|
||||
" def __repr__(self):\n"
|
||||
" if self.__inrepr: return '{...}'\n"
|
||||
" self.__inrepr = 1\n"
|
||||
" let b='{'+', '.join([repr(k)+': '+repr(self[k]) for k in self.keys()])+'}'\n"
|
||||
" self.__inrepr = 0\n"
|
||||
" return b\n"
|
||||
" def keys(self):\n"
|
||||
" 'Returns an iterable of the keys in this dictionary.'\n"
|
||||
" class KeyIterator():\n"
|
||||
@ -119,31 +95,15 @@ const char krk_builtinsSrc[] =
|
||||
"\n"
|
||||
"let help = Helper()\n"
|
||||
"\n"
|
||||
"let _licenseText = '''\n"
|
||||
"Copyright (c) 2020-2021 K. Lange <klange@toaruos.org>\n"
|
||||
"\n"
|
||||
"Permission to use, copy, modify, and/or distribute this software for any\n"
|
||||
"purpose with or without fee is hereby granted, provided that the above\n"
|
||||
"copyright notice and this permission notice appear in all copies.\n"
|
||||
"\n"
|
||||
"THE SOFTWARE IS PROVIDED 'AS IS' AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n"
|
||||
"WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n"
|
||||
"MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n"
|
||||
"ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n"
|
||||
"WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n"
|
||||
"ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n"
|
||||
"OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n"
|
||||
"'''\n"
|
||||
"\n"
|
||||
"class LicenseReader():\n"
|
||||
" def __call__(self):\n"
|
||||
" print(_licenseText)\n"
|
||||
" from help import __licenseText\n"
|
||||
" print(__licenseText)\n"
|
||||
" def __repr__(self):\n"
|
||||
" return 'Copyright 2020-2021 K. Lange <klange@toaruos.org>. Type `license()` for more information.'\n"
|
||||
"\n"
|
||||
"let license = LicenseReader()\n"
|
||||
"\n"
|
||||
"__builtins__.list = list\n"
|
||||
"__builtins__.dict = dict\n"
|
||||
"__builtins__.help = help\n"
|
||||
"__builtins__.license = license\n"
|
||||
|
44
builtins.krk
44
builtins.krk
@ -1,31 +1,7 @@
|
||||
# Please avoid using double quotes or escape sequences
|
||||
# in this file to allow it to be easily converted to C.
|
||||
class list():
|
||||
'Resizable array with direct constant-time indexing.'
|
||||
def extend(i):
|
||||
'Add all entries from an iterable to the end of this list.'
|
||||
if isinstance(i,list):
|
||||
return self._extend_fast(i)
|
||||
for v in i:
|
||||
self.append(v)
|
||||
return self.__len__()
|
||||
def __str__(self): return self.__repr__()
|
||||
def __repr__(self):
|
||||
if self.__inrepr: return '[...]'
|
||||
self.__inrepr=1
|
||||
let b='['+', '.join([repr(i) for i in self])+']'
|
||||
self.__inrepr=0
|
||||
return b
|
||||
|
||||
class dict():
|
||||
'Hashmap of arbitrary keys to arbitrary values.'
|
||||
def __str__(self): return self.__repr__()
|
||||
def __repr__(self):
|
||||
if self.__inrepr: return '{...}'
|
||||
self.__inrepr = 1
|
||||
let b='{'+', '.join([repr(k)+': '+repr(self[k]) for k in self.keys()])+'}'
|
||||
self.__inrepr = 0
|
||||
return b
|
||||
def keys(self):
|
||||
'Returns an iterable of the keys in this dictionary.'
|
||||
class KeyIterator():
|
||||
@ -118,31 +94,15 @@ class Helper():
|
||||
|
||||
let help = Helper()
|
||||
|
||||
let _licenseText = '''
|
||||
Copyright (c) 2020-2021 K. Lange <klange@toaruos.org>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS' AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
'''
|
||||
|
||||
class LicenseReader():
|
||||
def __call__(self):
|
||||
print(_licenseText)
|
||||
from help import __licenseText
|
||||
print(__licenseText)
|
||||
def __repr__(self):
|
||||
return 'Copyright 2020-2021 K. Lange <klange@toaruos.org>. Type `license()` for more information.'
|
||||
|
||||
let license = LicenseReader()
|
||||
|
||||
__builtins__.list = list
|
||||
__builtins__.dict = dict
|
||||
__builtins__.help = help
|
||||
__builtins__.license = license
|
||||
|
@ -20,3 +20,20 @@ and attribute field names is available.
|
||||
def interactive():
|
||||
'''Runs the detailed help tool. Currently that means just printing a longer help string.'''
|
||||
print(__introText)
|
||||
|
||||
let __licenseText = '''
|
||||
Copyright (c) 2020-2021 K. Lange <klange@toaruos.org>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS' AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
'''
|
||||
|
||||
|
1
object.c
1
object.c
@ -15,6 +15,7 @@ static KrkObj * allocateObject(size_t size, ObjType type) {
|
||||
KrkObj * object = (KrkObj*)krk_reallocate(NULL, 0, size);
|
||||
object->type = type;
|
||||
object->isMarked = 0;
|
||||
object->inRepr = 0;
|
||||
object->next = vm.objects;
|
||||
vm.objects = object;
|
||||
return object;
|
||||
|
3
object.h
3
object.h
@ -44,7 +44,8 @@ typedef enum {
|
||||
|
||||
struct Obj {
|
||||
ObjType type;
|
||||
char isMarked;
|
||||
unsigned char isMarked:1;
|
||||
unsigned char inRepr:1;
|
||||
struct Obj * next;
|
||||
};
|
||||
|
||||
|
@ -44,7 +44,7 @@ def find_depth(bag):
|
||||
while to_scan:
|
||||
let i = to_scan.pop(0)
|
||||
count += 1
|
||||
to_scan._extend_fast(descriptions[i])
|
||||
to_scan.extend(descriptions[i])
|
||||
return count
|
||||
|
||||
print("A shiny gold bag contains", find_depth('shiny gold'), "bags.")
|
||||
|
168
vm.c
168
vm.c
@ -474,6 +474,50 @@ static KrkValue _dict_key_at_index(int argc, KrkValue argv[]) {
|
||||
return OBJECT_VAL(outValue);
|
||||
}
|
||||
|
||||
static KrkValue _dict_repr(int argc, KrkValue argv[]) {
|
||||
KrkValue self = argv[0];
|
||||
if (AS_OBJECT(self)->inRepr) return OBJECT_VAL(S("{...}"));
|
||||
KrkValue _dict_internal = OBJECT_VAL(AS_INSTANCE(argv[0])->_internal);
|
||||
krk_push(OBJECT_VAL(S("{")));
|
||||
|
||||
AS_OBJECT(self)->inRepr = 1;
|
||||
|
||||
size_t c = 0;
|
||||
size_t len = AS_DICT(_dict_internal)->capacity;
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
KrkTableEntry * entry = &AS_DICT(_dict_internal)->entries[i];
|
||||
|
||||
if (IS_KWARGS(entry->key)) continue;
|
||||
|
||||
if (c > 0) {
|
||||
krk_push(OBJECT_VAL(S(", ")));
|
||||
addObjects();
|
||||
}
|
||||
|
||||
c++;
|
||||
|
||||
KrkClass * type = AS_CLASS(krk_typeOf(1, &entry->key));
|
||||
krk_push(entry->key);
|
||||
krk_push(krk_callSimple(OBJECT_VAL(type->_reprer), 1, 0));
|
||||
addObjects();
|
||||
|
||||
krk_push(OBJECT_VAL(S(": ")));
|
||||
addObjects();
|
||||
|
||||
type = AS_CLASS(krk_typeOf(1, &entry->value));
|
||||
krk_push(entry->value);
|
||||
krk_push(krk_callSimple(OBJECT_VAL(type->_reprer), 1, 0));
|
||||
addObjects();
|
||||
}
|
||||
|
||||
AS_OBJECT(self)->inRepr = 0;
|
||||
|
||||
krk_push(OBJECT_VAL(S("}")));
|
||||
addObjects();
|
||||
return krk_pop();
|
||||
|
||||
}
|
||||
|
||||
static KrkValue _dict_nth_key_fast(size_t capacity, KrkTableEntry * entries, size_t index) {
|
||||
size_t found = 0;
|
||||
for (size_t i = 0; i < capacity; ++i) {
|
||||
@ -552,22 +596,89 @@ static KrkValue _list_append(int argc, KrkValue argv[]) {
|
||||
}
|
||||
|
||||
/**
|
||||
* list.extend but only for lists...
|
||||
* list.__repr__
|
||||
*/
|
||||
static KrkValue _list_extend_fast(int argc, KrkValue argv[]) {
|
||||
KrkValue _list_internal_self = OBJECT_VAL(AS_INSTANCE(argv[0])->_internal);
|
||||
KrkValue _list_internal_them = OBJECT_VAL(AS_INSTANCE(argv[1])->_internal);
|
||||
static KrkValue _list_repr(int argc, KrkValue argv[]) {
|
||||
KrkValue self = argv[0];
|
||||
if (AS_OBJECT(self)->inRepr) return OBJECT_VAL(S("[...]"));
|
||||
KrkValue _list_internal = OBJECT_VAL(AS_INSTANCE(argv[0])->_internal);
|
||||
krk_push(OBJECT_VAL(S("[")));
|
||||
|
||||
size_t totalSize = AS_LIST(_list_internal_self)->count + AS_LIST(_list_internal_them)->count;
|
||||
if (AS_LIST(_list_internal_self)->capacity < totalSize) {
|
||||
size_t old = AS_LIST(_list_internal_self)->capacity;
|
||||
AS_LIST(_list_internal_self)->capacity = totalSize;
|
||||
AS_LIST(_list_internal_self)->values = GROW_ARRAY(KrkValue, AS_LIST(_list_internal_self)->values, old, totalSize);
|
||||
AS_OBJECT(self)->inRepr = 1;
|
||||
|
||||
size_t len = AS_LIST(_list_internal)->count;
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
KrkClass * type = AS_CLASS(krk_typeOf(1, &AS_LIST(_list_internal)->values[i]));
|
||||
krk_push(AS_LIST(_list_internal)->values[i]);
|
||||
krk_push(krk_callSimple(OBJECT_VAL(type->_reprer), 1, 0));
|
||||
addObjects();
|
||||
if (i + 1 < len) {
|
||||
krk_push(OBJECT_VAL(S(", ")));
|
||||
addObjects();
|
||||
}
|
||||
}
|
||||
memcpy(&AS_LIST(_list_internal_self)->values[AS_LIST(_list_internal_self)->count],
|
||||
AS_LIST(_list_internal_them)->values, sizeof(KrkValue) * AS_LIST(_list_internal_them)->count);
|
||||
AS_LIST(_list_internal_self)->count = totalSize;
|
||||
return INTEGER_VAL(totalSize);
|
||||
|
||||
AS_OBJECT(self)->inRepr = 0;
|
||||
|
||||
krk_push(OBJECT_VAL(S("]")));
|
||||
addObjects();
|
||||
return krk_pop();
|
||||
}
|
||||
|
||||
static KrkValue _list_extend(int argc, KrkValue argv[]) {
|
||||
KrkInstance * self = AS_INSTANCE(argv[0]);
|
||||
KrkValue _list_internal = OBJECT_VAL(self->_internal);
|
||||
KrkValueArray * positionals = AS_LIST(_list_internal);
|
||||
#define unpackArray(counter, indexer) do { \
|
||||
if (positionals->count + counter > positionals->capacity) { \
|
||||
size_t old = positionals->capacity; \
|
||||
positionals->capacity = positionals->count + counter; \
|
||||
positionals->values = GROW_ARRAY(KrkValue,positionals->values,old,positionals->capacity); \
|
||||
} \
|
||||
for (size_t i = 0; i < counter; ++i) { \
|
||||
positionals->values[positionals->count] = indexer; \
|
||||
positionals->count++; \
|
||||
} \
|
||||
} while (0)
|
||||
KrkValue value = argv[1];
|
||||
//UNPACK_ARRAY(); /* This should be a macro that does all of these things. */
|
||||
if (IS_TUPLE(value)) {
|
||||
unpackArray(AS_TUPLE(value)->values.count, AS_TUPLE(value)->values.values[i]);
|
||||
} else if (IS_INSTANCE(value) && AS_INSTANCE(value)->_class == vm.baseClasses.listClass) {
|
||||
KrkValue _list_internal = OBJECT_VAL(AS_INSTANCE(value)->_internal);
|
||||
unpackArray(AS_LIST(_list_internal)->count, AS_LIST(_list_internal)->values[i]);
|
||||
} else if (IS_INSTANCE(value) && AS_INSTANCE(value)->_class == vm.baseClasses.dictClass) {
|
||||
KrkValue _dict_internal = OBJECT_VAL(AS_INSTANCE(value)->_internal);
|
||||
unpackArray(AS_DICT(_dict_internal)->count, _dict_nth_key_fast(AS_DICT(_dict_internal)->capacity, AS_DICT(_dict_internal)->entries, i));
|
||||
} else if (IS_STRING(value)) {
|
||||
unpackArray(AS_STRING(value)->codesLength, _string_get(2,(KrkValue[]){value,INTEGER_VAL(i)}));
|
||||
} else {
|
||||
KrkClass * type = AS_CLASS(krk_typeOf(1,&argv[1]));
|
||||
if (type->_iter) {
|
||||
/* Create the iterator */
|
||||
size_t stackOffset = vm.stackTop - vm.stack;
|
||||
krk_push(argv[1]);
|
||||
krk_push(krk_callSimple(OBJECT_VAL(type->_iter), 1, 0));
|
||||
|
||||
do {
|
||||
/* Call it until it gives us itself */
|
||||
krk_push(vm.stack[stackOffset]);
|
||||
krk_push(krk_callSimple(krk_peek(0), 0, 1));
|
||||
if (krk_valuesSame(vm.stack[stackOffset], krk_peek(0))) {
|
||||
/* We're done. */
|
||||
krk_pop(); /* The result of iteration */
|
||||
krk_pop(); /* The iterator */
|
||||
break;
|
||||
}
|
||||
_list_append(2, (KrkValue[]){argv[0], krk_peek(0)});
|
||||
krk_pop();
|
||||
} while (1);
|
||||
} else {
|
||||
krk_runtimeError(vm.exceptions.typeError, "'%s' object is not iterable", krk_typeName(value));
|
||||
}
|
||||
}
|
||||
#undef unpackArray
|
||||
return NONE_VAL();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3372,6 +3483,21 @@ void krk_initVM(int flags) {
|
||||
krk_defineNative(&vm.baseClasses.bytesClass->methods, ".__get__", _bytes_get);
|
||||
krk_defineNative(&vm.baseClasses.bytesClass->methods, ".__eq__", _bytes_eq);
|
||||
krk_finalizeClass(vm.baseClasses.bytesClass);
|
||||
ADD_BASE_CLASS(vm.baseClasses.listClass, "list", vm.objectClass);
|
||||
krk_defineNative(&vm.baseClasses.listClass->methods, ".__init__", _list_init);
|
||||
krk_defineNative(&vm.baseClasses.listClass->methods, ".__get__", _list_get);
|
||||
krk_defineNative(&vm.baseClasses.listClass->methods, ".__set__", _list_set);
|
||||
krk_defineNative(&vm.baseClasses.listClass->methods, ".__delitem__", _list_pop);
|
||||
krk_defineNative(&vm.baseClasses.listClass->methods, ".__len__", _list_len);
|
||||
krk_defineNative(&vm.baseClasses.listClass->methods, ".__str__", _list_repr);
|
||||
krk_defineNative(&vm.baseClasses.listClass->methods, ".__repr__", _list_repr);
|
||||
krk_defineNative(&vm.baseClasses.listClass->methods, ".__contains__", _list_contains);
|
||||
krk_defineNative(&vm.baseClasses.listClass->methods, ".__getslice__", _list_slice);
|
||||
krk_defineNative(&vm.baseClasses.listClass->methods, ".__iter__", _list_iter);
|
||||
krk_defineNative(&vm.baseClasses.listClass->methods, ".append", _list_append);
|
||||
krk_defineNative(&vm.baseClasses.listClass->methods, ".extend", _list_extend);
|
||||
krk_defineNative(&vm.baseClasses.listClass->methods, ".pop", _list_pop);
|
||||
krk_finalizeClass(vm.baseClasses.listClass);
|
||||
|
||||
/* Build global builtin functions. */
|
||||
BUILTIN_FUNCTION("listOf", krk_list_of);
|
||||
@ -3437,24 +3563,12 @@ void krk_initVM(int flags) {
|
||||
/* Now we can attach the native initializers and getters/setters to
|
||||
* the list and dict types by pulling them out of the global namespace,
|
||||
* as they were exported by builtins.krk */
|
||||
krk_tableGet(&vm.builtins->fields,OBJECT_VAL(S("list")),&val);
|
||||
vm.baseClasses.listClass = AS_CLASS(val);
|
||||
krk_defineNative(&vm.baseClasses.listClass->methods, ".__init__", _list_init);
|
||||
krk_defineNative(&vm.baseClasses.listClass->methods, ".__get__", _list_get);
|
||||
krk_defineNative(&vm.baseClasses.listClass->methods, ".__set__", _list_set);
|
||||
krk_defineNative(&vm.baseClasses.listClass->methods, ".__delitem__", _list_pop);
|
||||
krk_defineNative(&vm.baseClasses.listClass->methods, ".__len__", _list_len);
|
||||
krk_defineNative(&vm.baseClasses.listClass->methods, ".__contains__", _list_contains);
|
||||
krk_defineNative(&vm.baseClasses.listClass->methods, ".__getslice__", _list_slice);
|
||||
krk_defineNative(&vm.baseClasses.listClass->methods, ".__iter__", _list_iter);
|
||||
krk_defineNative(&vm.baseClasses.listClass->methods, ".append", _list_append);
|
||||
krk_defineNative(&vm.baseClasses.listClass->methods, ".pop", _list_pop);
|
||||
krk_defineNative(&vm.baseClasses.listClass->methods, "._extend_fast", _list_extend_fast);
|
||||
krk_finalizeClass(vm.baseClasses.listClass);
|
||||
|
||||
krk_tableGet(&vm.builtins->fields,OBJECT_VAL(S("dict")),&val);
|
||||
vm.baseClasses.dictClass = AS_CLASS(val);
|
||||
krk_defineNative(&vm.baseClasses.dictClass->methods, ".__init__", _dict_init);
|
||||
krk_defineNative(&vm.baseClasses.dictClass->methods, ".__str__", _dict_repr);
|
||||
krk_defineNative(&vm.baseClasses.dictClass->methods, ".__repr__", _dict_repr);
|
||||
krk_defineNative(&vm.baseClasses.dictClass->methods, ".__get__", _dict_get);
|
||||
krk_defineNative(&vm.baseClasses.dictClass->methods, ".__set__", _dict_set);
|
||||
krk_defineNative(&vm.baseClasses.dictClass->methods, ".__delitem__", _dict_delitem);
|
||||
|
Loading…
x
Reference in New Issue
Block a user