Finish C-ifying dicts
This commit is contained in:
parent
ad29dadf68
commit
935ad8096d
@ -1,29 +1,6 @@
|
||||
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 dict():\n"
|
||||
" 'Hashmap of arbitrary keys to arbitrary values.'\n"
|
||||
" def keys(self):\n"
|
||||
" 'Returns an iterable of the keys in this dictionary.'\n"
|
||||
" class KeyIterator():\n"
|
||||
" def __init__(self,t):\n"
|
||||
" self.t=t\n"
|
||||
" def __iter__(self):\n"
|
||||
" let i=0\n"
|
||||
" let c=self.t.capacity()\n"
|
||||
" def _():\n"
|
||||
" let o=(False,None)\n"
|
||||
" while not o[0] and i<c:\n"
|
||||
" o=self.t._key_at_index(i)\n"
|
||||
" i++\n"
|
||||
" if not o[0]:\n"
|
||||
" return _\n"
|
||||
" return o[1]\n"
|
||||
" return _\n"
|
||||
" return KeyIterator(self)\n"
|
||||
" 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"
|
||||
@ -92,7 +69,6 @@ const char krk_builtinsSrc[] =
|
||||
"\n"
|
||||
"let license = LicenseReader()\n"
|
||||
"\n"
|
||||
"__builtins__.dict = dict\n"
|
||||
"__builtins__.help = help\n"
|
||||
"__builtins__.license = license\n"
|
||||
"\n"
|
||||
|
@ -1,28 +1,5 @@
|
||||
# Please avoid using double quotes or escape sequences
|
||||
# in this file to allow it to be easily converted to C.
|
||||
class dict():
|
||||
'Hashmap of arbitrary keys to arbitrary values.'
|
||||
def keys(self):
|
||||
'Returns an iterable of the keys in this dictionary.'
|
||||
class KeyIterator():
|
||||
def __init__(self,t):
|
||||
self.t=t
|
||||
def __iter__(self):
|
||||
let i=0
|
||||
let c=self.t.capacity()
|
||||
def _():
|
||||
let o=(False,None)
|
||||
while not o[0] and i<c:
|
||||
o=self.t._key_at_index(i)
|
||||
i++
|
||||
if not o[0]:
|
||||
return _
|
||||
return o[1]
|
||||
return _
|
||||
return KeyIterator(self)
|
||||
def items(self):
|
||||
return [(k,self[k]) for k in self.keys()]
|
||||
|
||||
class set():
|
||||
def __init__(self, iter=[]):
|
||||
self._dict = {}
|
||||
@ -91,7 +68,6 @@ class LicenseReader():
|
||||
|
||||
let license = LicenseReader()
|
||||
|
||||
__builtins__.dict = dict
|
||||
__builtins__.help = help
|
||||
__builtins__.license = license
|
||||
|
||||
|
200
src/vm.c
200
src/vm.c
@ -425,24 +425,6 @@ static KrkValue _dict_capacity(int argc, KrkValue argv[]) {
|
||||
return INTEGER_VAL(AS_DICT(argv[0])->capacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* dict._key_at_index(internalIndex)
|
||||
*/
|
||||
static KrkValue _dict_key_at_index(int argc, KrkValue argv[]) {
|
||||
if (argc < 2) return krk_runtimeError(vm.exceptions.argumentError, "wrong number of arguments");
|
||||
if (!IS_INTEGER(argv[1])) return krk_runtimeError(vm.exceptions.typeError, "expected integer index but got %s", krk_typeName(argv[1]));
|
||||
int i = AS_INTEGER(argv[1]);
|
||||
if (i < 0 || i > (int)AS_DICT(argv[0])->capacity) return krk_runtimeError(vm.exceptions.indexError, "hash table index is out of range: %d", i);
|
||||
KrkTableEntry entry = AS_DICT(argv[0])->entries[i];
|
||||
KrkTuple * outValue = krk_newTuple(2);
|
||||
krk_push(OBJECT_VAL(outValue));
|
||||
outValue->values.values[0] = IS_KWARGS(entry.key) ? BOOLEAN_VAL(0) : BOOLEAN_VAL(1);
|
||||
outValue->values.values[1] = IS_KWARGS(entry.key) ? NONE_VAL() : entry.key;
|
||||
outValue->values.count = 2;
|
||||
krk_pop();
|
||||
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("{...}"));
|
||||
@ -2871,6 +2853,102 @@ static KrkValue _all(int argc, KrkValue argv[]) {
|
||||
return BOOLEAN_VAL(1);
|
||||
}
|
||||
|
||||
struct DictItems {
|
||||
KrkInstance inst;
|
||||
KrkValue dict;
|
||||
size_t i;
|
||||
};
|
||||
|
||||
static void _dictitems_gcscan(KrkInstance * self) {
|
||||
krk_markValue(((struct DictItems*)self)->dict);
|
||||
}
|
||||
|
||||
static KrkValue _dictitems_init(int argc, KrkValue argv[]) {
|
||||
struct DictItems * self = (struct DictItems*)AS_OBJECT(argv[0]);
|
||||
self->dict = argv[1];
|
||||
self->i = 0;
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
static KrkValue _dictitems_iter(int argc, KrkValue argv[]) {
|
||||
/* Reset index and return self as iteration object */
|
||||
struct DictItems * self = (struct DictItems*)AS_OBJECT(argv[0]);
|
||||
self->i = 0;
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
static KrkValue _dictitems_call(int argc, KrkValue argv[]) {
|
||||
struct DictItems * self = (struct DictItems*)AS_OBJECT(argv[0]);
|
||||
do {
|
||||
if (self->i >= AS_DICT(self->dict)->capacity) return argv[0];
|
||||
if (!IS_KWARGS(AS_DICT(self->dict)->entries[self->i].key)) {
|
||||
KrkTuple * outValue = krk_newTuple(2);
|
||||
krk_push(OBJECT_VAL(outValue));
|
||||
outValue->values.values[0] = AS_DICT(self->dict)->entries[self->i].key;
|
||||
outValue->values.values[1] = AS_DICT(self->dict)->entries[self->i].value;
|
||||
outValue->values.count = 2;
|
||||
self->i++;
|
||||
return krk_pop();
|
||||
}
|
||||
self->i++;
|
||||
} while (1);
|
||||
}
|
||||
|
||||
/* TODO: dictitems could really use a nice repr */
|
||||
static KrkValue _dict_items(int argc, KrkValue argv[]) {
|
||||
KrkInstance * output = krk_newInstance(vm.baseClasses.dictitemsClass);
|
||||
krk_push(OBJECT_VAL(output));
|
||||
_dictitems_init(2, (KrkValue[]){krk_peek(0), argv[0]});
|
||||
krk_pop();
|
||||
return OBJECT_VAL(output);
|
||||
}
|
||||
|
||||
struct DictKeys {
|
||||
KrkInstance inst;
|
||||
KrkValue dict;
|
||||
size_t i;
|
||||
};
|
||||
|
||||
static void _dictkeys_gcscan(KrkInstance * self) {
|
||||
krk_markValue(((struct DictKeys*)self)->dict);
|
||||
}
|
||||
|
||||
static KrkValue _dictkeys_init(int argc, KrkValue argv[]) {
|
||||
struct DictKeys * self = (struct DictKeys*)AS_OBJECT(argv[0]);
|
||||
self->dict = argv[1];
|
||||
self->i = 0;
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
static KrkValue _dictkeys_iter(int argc, KrkValue argv[]) {
|
||||
/* reset indext and return self as iteration object */
|
||||
struct DictKeys * self = (struct DictKeys*)AS_OBJECT(argv[0]);
|
||||
self->i = 0;
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
static KrkValue _dictkeys_call(int argc, KrkValue argv[]) {
|
||||
struct DictKeys * self = (struct DictKeys*)AS_OBJECT(argv[0]);
|
||||
do {
|
||||
if (self->i >= AS_DICT(self->dict)->capacity) return argv[0];
|
||||
if (!IS_KWARGS(AS_DICT(self->dict)->entries[self->i].key)) {
|
||||
krk_push(AS_DICT(self->dict)->entries[self->i].key);
|
||||
self->i++;
|
||||
return krk_pop();
|
||||
}
|
||||
self->i++;
|
||||
} while (1);
|
||||
}
|
||||
|
||||
/* TODO: dictkeys could really use a nice repr */
|
||||
static KrkValue _dict_keys(int argc, KrkValue argv[]) {
|
||||
KrkInstance * output = krk_newInstance(vm.baseClasses.dictkeysClass);
|
||||
krk_push(OBJECT_VAL(output));
|
||||
_dictkeys_init(2, (KrkValue[]){krk_peek(0), argv[0]});
|
||||
krk_pop();
|
||||
return OBJECT_VAL(output);
|
||||
}
|
||||
|
||||
struct TupleIter {
|
||||
KrkInstance inst;
|
||||
KrkValue myTuple;
|
||||
@ -2878,17 +2956,9 @@ struct TupleIter {
|
||||
};
|
||||
|
||||
static KrkValue _tuple_iter_init(int argc, KrkValue argv[]) {
|
||||
KrkInstance * self = AS_INSTANCE(argv[0]);
|
||||
krk_push(argv[0]);
|
||||
|
||||
((struct TupleIter*)self)->myTuple = argv[0];
|
||||
((struct TupleIter*)self)->i = 0;
|
||||
|
||||
/* Otherwise we need to bother with a _ongcmark, _ongcsweep */
|
||||
krk_attachNamedValue(&self->fields, "_tuple", argv[0]);
|
||||
krk_pop(); /* myTuple */
|
||||
krk_pop(); /* self */
|
||||
|
||||
struct TupleIter * self = (struct TupleIter *)AS_OBJECT(argv[0]);
|
||||
self->myTuple = argv[0];
|
||||
self->i = 0;
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
@ -2897,13 +2967,13 @@ static void _tuple_iter_gcscan(KrkInstance * self) {
|
||||
}
|
||||
|
||||
static KrkValue _tuple_iter_call(int argc, KrkValue argv[]) {
|
||||
KrkInstance * self = AS_INSTANCE(argv[0]);
|
||||
KrkValue t = ((struct TupleIter*)self)->myTuple; /* Tuple to iterate */
|
||||
int i = ((struct TupleIter*)self)->i;
|
||||
struct TupleIter * self = (struct TupleIter *)AS_OBJECT(argv[0]);
|
||||
KrkValue t = self->myTuple; /* Tuple to iterate */
|
||||
int i = self->i;
|
||||
if (i >= (krk_integer_type)AS_TUPLE(t)->values.count) {
|
||||
return argv[0];
|
||||
} else {
|
||||
((struct TupleIter*)self)->i = i+1;
|
||||
self->i = i+1;
|
||||
return AS_TUPLE(t)->values.values[i];
|
||||
}
|
||||
}
|
||||
@ -3466,6 +3536,23 @@ void krk_initVM(int flags) {
|
||||
krk_defineNative(&vm.baseClasses.listClass->methods, ".insert", _list_insert);
|
||||
krk_finalizeClass(vm.baseClasses.listClass);
|
||||
vm.baseClasses.listClass->docstring = S("Mutable sequence of arbitrary values.");
|
||||
ADD_BASE_CLASS(vm.baseClasses.dictClass, "dict", vm.objectClass);
|
||||
vm.baseClasses.dictClass->allocSize = sizeof(KrkDict);
|
||||
vm.baseClasses.dictClass->_ongcscan = _dict_gcscan;
|
||||
vm.baseClasses.dictClass->_ongcsweep = _dict_gcsweep;
|
||||
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);
|
||||
krk_defineNative(&vm.baseClasses.dictClass->methods, ".__len__", _dict_len);
|
||||
krk_defineNative(&vm.baseClasses.dictClass->methods, ".__contains__", _dict_contains);
|
||||
krk_defineNative(&vm.baseClasses.dictClass->methods, ".keys", _dict_keys);
|
||||
krk_defineNative(&vm.baseClasses.dictClass->methods, ".items", _dict_items);
|
||||
krk_defineNative(&vm.baseClasses.dictClass->methods, ".capacity", _dict_capacity);
|
||||
krk_finalizeClass(vm.baseClasses.dictClass);
|
||||
vm.baseClasses.dictClass->docstring = S("Mapping of arbitrary keys to values.");
|
||||
|
||||
/* Build global builtin functions. */
|
||||
BUILTIN_FUNCTION("listOf", krk_list_of, "Convert argument sequence to list object.");
|
||||
@ -3523,40 +3610,27 @@ void krk_initVM(int flags) {
|
||||
krk_defineNative(&vm.baseClasses.tupleiteratorClass->methods, ".__call__", _tuple_iter_call);
|
||||
krk_finalizeClass(vm.baseClasses.tupleiteratorClass);
|
||||
|
||||
/**
|
||||
* Read the managed code builtins module, which contains the base
|
||||
* definitions for collections so we can pull them into the global
|
||||
* namespace and attach their __init__/__get__/__set__, etc. methods.
|
||||
*
|
||||
* A significant subset of the VM's functionality is lost without
|
||||
* these classes being available, but it should still work to some degree.
|
||||
*/
|
||||
ADD_BASE_CLASS(vm.baseClasses.dictitemsClass, "dictitems", vm.objectClass);
|
||||
vm.baseClasses.dictitemsClass->allocSize = sizeof(struct DictItems);
|
||||
vm.baseClasses.dictitemsClass->_ongcscan = _dictitems_gcscan;
|
||||
krk_defineNative(&vm.baseClasses.dictitemsClass->methods, ".__init__", _dictitems_init);
|
||||
krk_defineNative(&vm.baseClasses.dictitemsClass->methods, ".__iter__", _dictitems_iter);
|
||||
krk_defineNative(&vm.baseClasses.dictitemsClass->methods, ".__call__", _dictitems_call);
|
||||
krk_finalizeClass(vm.baseClasses.dictitemsClass);
|
||||
|
||||
ADD_BASE_CLASS(vm.baseClasses.dictkeysClass, "dictkeys", vm.objectClass);
|
||||
vm.baseClasses.dictkeysClass->allocSize = sizeof(struct DictKeys);
|
||||
vm.baseClasses.dictkeysClass->_ongcscan = _dictkeys_gcscan;
|
||||
krk_defineNative(&vm.baseClasses.dictkeysClass->methods, ".__init__", _dictkeys_init);
|
||||
krk_defineNative(&vm.baseClasses.dictkeysClass->methods, ".__iter__", _dictkeys_iter);
|
||||
krk_defineNative(&vm.baseClasses.dictkeysClass->methods, ".__call__", _dictkeys_call);
|
||||
krk_finalizeClass(vm.baseClasses.dictkeysClass);
|
||||
|
||||
/* This module is slowly being deprecated. */
|
||||
KrkValue builtinsModule = krk_interpret(krk_builtinsSrc,1,"__builtins__","__builtins__");
|
||||
if (!IS_OBJECT(builtinsModule)) {
|
||||
/* ... hence, this is a warning and not a complete failure. */
|
||||
fprintf(stderr, "VM startup failure: Failed to load __builtins__ module.\n");
|
||||
} else {
|
||||
KrkValue val;
|
||||
/* 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("dict")),&val);
|
||||
vm.baseClasses.dictClass = AS_CLASS(val);
|
||||
vm.baseClasses.dictClass->allocSize = sizeof(KrkDict);
|
||||
vm.baseClasses.dictClass->_ongcscan = _dict_gcscan;
|
||||
vm.baseClasses.dictClass->_ongcsweep = _dict_gcsweep;
|
||||
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);
|
||||
krk_defineNative(&vm.baseClasses.dictClass->methods, ".__len__", _dict_len);
|
||||
krk_defineNative(&vm.baseClasses.dictClass->methods, ".__contains__", _dict_contains);
|
||||
krk_defineNative(&vm.baseClasses.dictClass->methods, ".capacity", _dict_capacity);
|
||||
krk_defineNative(&vm.baseClasses.dictClass->methods, "._key_at_index", _dict_key_at_index);
|
||||
krk_finalizeClass(vm.baseClasses.dictClass);
|
||||
}
|
||||
|
||||
/* The VM is now ready to start executing code. */
|
||||
|
3
src/vm.h
3
src/vm.h
@ -109,9 +109,10 @@ typedef struct {
|
||||
KrkClass * striteratorClass;
|
||||
KrkClass * tupleiteratorClass;
|
||||
|
||||
/* These are actually defined in builtins.krk and are real instances */
|
||||
KrkClass * listClass;
|
||||
KrkClass * dictClass;
|
||||
KrkClass * dictitemsClass;
|
||||
KrkClass * dictkeysClass;
|
||||
} baseClasses;
|
||||
|
||||
KrkValue currentException;
|
||||
|
Loading…
Reference in New Issue
Block a user