Fix broken stack handling in and make map,enumerate,filter object inits

This commit is contained in:
K Lange 2021-03-21 16:47:13 +09:00
parent 3b8c521776
commit c68eb093e8
9 changed files with 128 additions and 90 deletions

View File

@ -201,25 +201,27 @@ KRK_FUNC(all,{
}) })
#undef unpackArray #undef unpackArray
static KrkClass * mapobject; #define CURRENT_CTYPE KrkInstance *
KRK_FUNC(map,{ #define CURRENT_NAME self
FUNCTION_TAKES_AT_LEAST(2);
/* Make a map object */ #define IS_map(o) (krk_isInstanceOf(o,map))
krk_push(OBJECT_VAL(krk_newInstance(mapobject))); #define AS_map(o) (AS_INSTANCE(o))
static KrkClass * map;
KRK_METHOD(map,__init__,{
METHOD_TAKES_AT_LEAST(2);
/* Attach the function to it */ /* Attach the function to it */
krk_attachNamedValue(&AS_INSTANCE(krk_peek(0))->fields, "_function", argv[0]); krk_attachNamedValue(&self->fields, "_function", argv[1]);
/* Make the iter objects */ /* Make the iter objects */
KrkTuple * iters = krk_newTuple(argc - 1); KrkTuple * iters = krk_newTuple(argc - 2);
krk_push(OBJECT_VAL(iters)); krk_push(OBJECT_VAL(iters));
/* Attach the tuple to the object */ /* Attach the tuple to the object */
krk_attachNamedValue(&AS_INSTANCE(krk_peek(1))->fields, "_iterables", krk_peek(0)); krk_attachNamedValue(&self->fields, "_iterables", krk_peek(0));
krk_pop(); krk_pop();
for (int i = 1; i < argc; ++i) { for (int i = 2; i < argc; ++i) {
KrkClass * type = krk_getType(argv[i]); KrkClass * type = krk_getType(argv[i]);
if (!type->_iter) { if (!type->_iter) {
return krk_runtimeError(vm.exceptions->typeError, "'%s' is not iterable", krk_typeName(argv[i])); return krk_runtimeError(vm.exceptions->typeError, "'%s' is not iterable", krk_typeName(argv[i]));
@ -231,22 +233,19 @@ KRK_FUNC(map,{
iters->values.values[iters->values.count++] = asIter; iters->values.values[iters->values.count++] = asIter;
} }
return krk_pop(); return argv[0];
}) })
#define CURRENT_CTYPE KrkInstance * KRK_METHOD(map,__iter__,{
#define CURRENT_NAME self
#define IS_mapobject(o) (krk_isInstanceOf(o,mapobject))
#define AS_mapobject(o) (AS_INSTANCE(o))
KRK_METHOD(mapobject,__iter__,{
METHOD_TAKES_NONE(); METHOD_TAKES_NONE();
return OBJECT_VAL(self); return OBJECT_VAL(self);
}) })
KRK_METHOD(mapobject,__call__,{ KRK_METHOD(map,__call__,{
METHOD_TAKES_NONE(); METHOD_TAKES_NONE();
size_t stackOffset = krk_currentThread.stackTop - krk_currentThread.stack;
/* Get members */ /* Get members */
KrkValue function = NONE_VAL(); KrkValue function = NONE_VAL();
KrkValue iterators = NONE_VAL(); KrkValue iterators = NONE_VAL();
@ -254,6 +253,8 @@ KRK_METHOD(mapobject,__call__,{
if (!krk_tableGet(&self->fields, OBJECT_VAL(S("_function")), &function)) return krk_runtimeError(vm.exceptions->valueError, "corrupt map object"); if (!krk_tableGet(&self->fields, OBJECT_VAL(S("_function")), &function)) return krk_runtimeError(vm.exceptions->valueError, "corrupt map object");
if (!krk_tableGet(&self->fields, OBJECT_VAL(S("_iterables")), &iterators) || !IS_TUPLE(iterators)) return krk_runtimeError(vm.exceptions->valueError, "corrupt map object"); if (!krk_tableGet(&self->fields, OBJECT_VAL(S("_iterables")), &iterators) || !IS_TUPLE(iterators)) return krk_runtimeError(vm.exceptions->valueError, "corrupt map object");
krk_push(function);
/* Go through each iterator */ /* Go through each iterator */
for (size_t i = 0; i < AS_TUPLE(iterators)->values.count; ++i) { for (size_t i = 0; i < AS_TUPLE(iterators)->values.count; ++i) {
/* Obtain the next value and push it */ /* Obtain the next value and push it */
@ -262,19 +263,16 @@ KRK_METHOD(mapobject,__call__,{
if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL(); if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL();
/* End iteration whenever one runs out */ /* End iteration whenever one runs out */
if (krk_valuesEqual(krk_peek(0), AS_TUPLE(iterators)->values.values[i])) { if (krk_valuesEqual(krk_peek(0), AS_TUPLE(iterators)->values.values[i])) {
for (size_t j = 0; j < i + 1; ++j) krk_pop();
krk_pop(); /* the function */
return OBJECT_VAL(self); return OBJECT_VAL(self);
} }
} }
/* Call the function */ /* Call the function */
return krk_callSimple(function, AS_TUPLE(iterators)->values.count, 0); KrkValue val = krk_callSimple(function, AS_TUPLE(iterators)->values.count, 0);
}) krk_currentThread.stackTop = krk_currentThread.stack + stackOffset;
return val;
KRK_METHOD(mapobject,__repr__,{
METHOD_TAKES_NONE();
char tmp[1024];
size_t len = sprintf(tmp, "<map object at %p>", (void*)self);
return OBJECT_VAL(krk_copyString(tmp,len));
}) })
KRK_FUNC(zip,{ KRK_FUNC(zip,{
@ -293,33 +291,31 @@ KRK_FUNC(zip,{
return krk_callSimple(map, argc+1, 0); return krk_callSimple(map, argc+1, 0);
}) })
#define IS_filterobject(o) (krk_isInstanceOf(o,filterobject)) #define IS_filter(o) (krk_isInstanceOf(o,filter))
#define AS_filterobject(o) (AS_INSTANCE(o)) #define AS_filter(o) (AS_INSTANCE(o))
static KrkClass * filterobject; static KrkClass * filter;
KRK_FUNC(filter,{ KRK_METHOD(filter,__init__,{
FUNCTION_TAKES_EXACTLY(2); METHOD_TAKES_EXACTLY(2);
/* Make a filter object */ krk_attachNamedValue(&self->fields, "_function", argv[1]);
krk_push(OBJECT_VAL(krk_newInstance(filterobject))); KrkClass * type = krk_getType(argv[2]);
krk_attachNamedValue(&AS_INSTANCE(krk_peek(0))->fields, "_function", argv[0]);
KrkClass * type = krk_getType(argv[1]);
if (!type->_iter) { if (!type->_iter) {
return krk_runtimeError(vm.exceptions->typeError, "'%s' is not iterable", krk_typeName(argv[1])); return krk_runtimeError(vm.exceptions->typeError, "'%s' is not iterable", krk_typeName(argv[2]));
} }
krk_push(argv[1]); krk_push(argv[2]);
KrkValue asIter = krk_callSimple(OBJECT_VAL(type->_iter), 1, 0); KrkValue asIter = krk_callSimple(OBJECT_VAL(type->_iter), 1, 0);
if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL(); if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL();
krk_attachNamedValue(&AS_INSTANCE(krk_peek(0))->fields, "_iterator", asIter); krk_attachNamedValue(&self->fields, "_iterator", asIter);
return argv[0];
return krk_pop();
}) })
KRK_METHOD(filterobject,__iter__,{ KRK_METHOD(filter,__iter__,{
METHOD_TAKES_NONE(); METHOD_TAKES_NONE();
return OBJECT_VAL(self); return OBJECT_VAL(self);
}) })
KRK_METHOD(filterobject,__call__,{ KRK_METHOD(filter,__call__,{
METHOD_TAKES_NONE(); METHOD_TAKES_NONE();
size_t stackOffset = krk_currentThread.stackTop - krk_currentThread.stack;
KrkValue function = NONE_VAL(); KrkValue function = NONE_VAL();
KrkValue iterator = NONE_VAL(); KrkValue iterator = NONE_VAL();
@ -331,7 +327,10 @@ KRK_METHOD(filterobject,__call__,{
krk_push(krk_callSimple(iterator, 0, 0)); krk_push(krk_callSimple(iterator, 0, 0));
if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL(); if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL();
if (krk_valuesEqual(iterator, krk_peek(0))) return OBJECT_VAL(self); if (krk_valuesEqual(iterator, krk_peek(0))) {
krk_currentThread.stackTop = krk_currentThread.stack + stackOffset;
return OBJECT_VAL(self);
}
if (IS_NONE(function)) { if (IS_NONE(function)) {
if (krk_isFalsey(krk_peek(0))) { if (krk_isFalsey(krk_peek(0))) {
@ -347,50 +346,44 @@ KRK_METHOD(filterobject,__call__,{
} }
} }
return krk_pop(); KrkValue out = krk_pop();
krk_currentThread.stackTop = krk_currentThread.stack + stackOffset;
return out;
} }
}) })
KRK_METHOD(filterobject,__repr__,{ #define IS_enumerate(o) (krk_isInstanceOf(o,enumerate))
METHOD_TAKES_NONE(); #define AS_enumerate(o) (AS_INSTANCE(o))
char tmp[1024]; static KrkClass * enumerate;
size_t len = sprintf(tmp, "<filter object at %p>", (void*)self); KRK_METHOD(enumerate,__init__,{
return OBJECT_VAL(krk_copyString(tmp,len)); METHOD_TAKES_EXACTLY(1);
})
#define IS_enumerateobject(o) (krk_isInstanceOf(o,enumerateobject))
#define AS_enumerateobject(o) (AS_INSTANCE(o))
static KrkClass * enumerateobject;
KRK_FUNC(enumerate,{
FUNCTION_TAKES_EXACTLY(1);
KrkValue start = INTEGER_VAL(0); KrkValue start = INTEGER_VAL(0);
if (hasKw) krk_tableGet(AS_DICT(argv[argc]), OBJECT_VAL(S("start")), &start); if (hasKw) krk_tableGet(AS_DICT(argv[argc]), OBJECT_VAL(S("start")), &start);
/* Make a enumerate object */ krk_attachNamedValue(&self->fields, "_counter", start);
krk_push(OBJECT_VAL(krk_newInstance(enumerateobject)));
krk_attachNamedValue(&AS_INSTANCE(krk_peek(0))->fields, "_counter", start);
/* Attach iterator */ /* Attach iterator */
KrkClass * type = krk_getType(argv[0]); KrkClass * type = krk_getType(argv[1]);
if (!type->_iter) { if (!type->_iter) {
return krk_runtimeError(vm.exceptions->typeError, "'%s' is not iterable", krk_typeName(argv[1])); return krk_runtimeError(vm.exceptions->typeError, "'%s' is not iterable", krk_typeName(argv[1]));
} }
krk_push(argv[0]); krk_push(argv[1]);
KrkValue asIter = krk_callSimple(OBJECT_VAL(type->_iter), 1, 0); KrkValue asIter = krk_callSimple(OBJECT_VAL(type->_iter), 1, 0);
if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL(); if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL();
krk_attachNamedValue(&AS_INSTANCE(krk_peek(0))->fields, "_iterator", asIter); krk_attachNamedValue(&self->fields, "_iterator", asIter);
return krk_pop(); return argv[0];
}) })
KRK_METHOD(enumerateobject,__iter__,{ KRK_METHOD(enumerate,__iter__,{
METHOD_TAKES_NONE(); METHOD_TAKES_NONE();
return OBJECT_VAL(self); return OBJECT_VAL(self);
}) })
extern KrkValue krk_operator_add (KrkValue a, KrkValue b); extern KrkValue krk_operator_add (KrkValue a, KrkValue b);
KRK_METHOD(enumerateobject,__call__,{ KRK_METHOD(enumerate,__call__,{
METHOD_TAKES_NONE(); METHOD_TAKES_NONE();
size_t stackOffset = krk_currentThread.stackTop - krk_currentThread.stack;
KrkValue counter = NONE_VAL(); KrkValue counter = NONE_VAL();
KrkValue iterator = NONE_VAL(); KrkValue iterator = NONE_VAL();
@ -404,11 +397,13 @@ KRK_METHOD(enumerateobject,__call__,{
krk_push(krk_callSimple(iterator, 0, 0)); krk_push(krk_callSimple(iterator, 0, 0));
if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) { if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) {
krk_currentThread.stackTop = krk_currentThread.stack + stackOffset;
return NONE_VAL(); return NONE_VAL();
} }
if (krk_valuesEqual(iterator, krk_peek(0))) { if (krk_valuesEqual(iterator, krk_peek(0))) {
krk_pop(); krk_pop();
krk_pop(); krk_pop();
krk_currentThread.stackTop = krk_currentThread.stack + stackOffset;
return OBJECT_VAL(self); return OBJECT_VAL(self);
} }
@ -419,14 +414,9 @@ KRK_METHOD(enumerateobject,__call__,{
krk_push(krk_operator_add(counter, INTEGER_VAL(1))); krk_push(krk_operator_add(counter, INTEGER_VAL(1)));
krk_attachNamedValue(&self->fields, "_counter", krk_pop()); krk_attachNamedValue(&self->fields, "_counter", krk_pop());
return krk_pop(); KrkValue out = krk_pop();
}) krk_currentThread.stackTop = krk_currentThread.stack + stackOffset;
return out;
KRK_METHOD(enumerateobject,__repr__,{
METHOD_TAKES_NONE();
char tmp[1024];
size_t len = sprintf(tmp, "<enumerate object at %p>", (void*)self);
return OBJECT_VAL(krk_copyString(tmp,len));
}) })
#define unpackArray(counter, indexer) do { \ #define unpackArray(counter, indexer) do { \
@ -951,23 +941,26 @@ void _createAndBind_builtins(void) {
krk_finalizeClass(LicenseReader); krk_finalizeClass(LicenseReader);
krk_attachNamedObject(&vm.builtins->fields, "license", (KrkObj*)krk_newInstance(LicenseReader)); krk_attachNamedObject(&vm.builtins->fields, "license", (KrkObj*)krk_newInstance(LicenseReader));
krk_makeClass(vm.builtins, &mapobject, "mapobject", vm.baseClasses->objectClass); krk_makeClass(vm.builtins, &map, "map", vm.baseClasses->objectClass);
BIND_METHOD(mapobject,__iter__); KRK_DOC(map, "Return an iterator that applies a function to a series of iterables");
BIND_METHOD(mapobject,__call__); BIND_METHOD(map,__init__);
BIND_METHOD(mapobject,__repr__); BIND_METHOD(map,__iter__);
krk_finalizeClass(mapobject); BIND_METHOD(map,__call__);
krk_finalizeClass(map);
krk_makeClass(vm.builtins, &filterobject, "filterobject", vm.baseClasses->objectClass); krk_makeClass(vm.builtins, &filter, "filter", vm.baseClasses->objectClass);
BIND_METHOD(filterobject,__iter__); KRK_DOC(filter, "Return an iterator that returns only the items from an iterable for which the given function returns true.");
BIND_METHOD(filterobject,__call__); BIND_METHOD(filter,__init__);
BIND_METHOD(filterobject,__repr__); BIND_METHOD(filter,__iter__);
krk_finalizeClass(filterobject); BIND_METHOD(filter,__call__);
krk_finalizeClass(filter);
krk_makeClass(vm.builtins, &enumerateobject, "enumerateobject", vm.baseClasses->objectClass); krk_makeClass(vm.builtins, &enumerate, "enumerate", vm.baseClasses->objectClass);
BIND_METHOD(enumerateobject,__iter__); KRK_DOC(enumerate, "Return an iterator that produces a tuple with a count the iterated values of the passed iteratable.");
BIND_METHOD(enumerateobject,__call__); BIND_METHOD(enumerate,__init__);
BIND_METHOD(enumerateobject,__repr__); BIND_METHOD(enumerate,__iter__);
krk_finalizeClass(enumerateobject); BIND_METHOD(enumerate,__call__);
krk_finalizeClass(enumerate);
BUILTIN_FUNCTION("isinstance", FUNC_NAME(krk,isinstance), BUILTIN_FUNCTION("isinstance", FUNC_NAME(krk,isinstance),
"@brief Check if an object is an instance of a type.\n" "@brief Check if an object is an instance of a type.\n"
@ -1028,9 +1021,6 @@ void _createAndBind_builtins(void) {
BUILTIN_FUNCTION("max", FUNC_NAME(krk,max), "Return the highest value in an iterable or the passed arguments."); BUILTIN_FUNCTION("max", FUNC_NAME(krk,max), "Return the highest value in an iterable or the passed arguments.");
BUILTIN_FUNCTION("id", FUNC_NAME(krk,id), "Returns the identity of an object."); BUILTIN_FUNCTION("id", FUNC_NAME(krk,id), "Returns the identity of an object.");
BUILTIN_FUNCTION("hash", FUNC_NAME(krk,hash), "Returns the hash of a value, used for table indexing."); BUILTIN_FUNCTION("hash", FUNC_NAME(krk,hash), "Returns the hash of a value, used for table indexing.");
BUILTIN_FUNCTION("map", FUNC_NAME(krk,map), "Return an iterator that applies a function to a series of iterables");
BUILTIN_FUNCTION("filter", FUNC_NAME(krk,filter), "Return an iterator that returns only the items from an iterable for which the given function returns true.");
BUILTIN_FUNCTION("enumerate", FUNC_NAME(krk,enumerate), "Return an iterator that produces a tuple with a count the iterated values of the passed iteratable.");
BUILTIN_FUNCTION("bin", FUNC_NAME(krk,bin), "Convert an integer value to a binary string."); BUILTIN_FUNCTION("bin", FUNC_NAME(krk,bin), "Convert an integer value to a binary string.");
BUILTIN_FUNCTION("zip", FUNC_NAME(krk,zip), "Returns an iterator that produces tuples of the nth element of each passed iterable."); BUILTIN_FUNCTION("zip", FUNC_NAME(krk,zip), "Returns an iterator that produces tuples of the nth element of each passed iterable.");
BUILTIN_FUNCTION("next", FUNC_NAME(krk,next), "Compatibility function. Calls an iterable."); BUILTIN_FUNCTION("next", FUNC_NAME(krk,next), "Compatibility function. Calls an iterable.");

1
test/testEnumerate.krk Normal file
View File

@ -0,0 +1 @@
print(list(enumerate(range(30))))

View File

@ -0,0 +1 @@
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9), (10, 10), (11, 11), (12, 12), (13, 13), (14, 14), (15, 15), (16, 16), (17, 17), (18, 18), (19, 19), (20, 20), (21, 21), (22, 22), (23, 23), (24, 24), (25, 25), (26, 26), (27, 27), (28, 28), (29, 29)]

1
test/testFilter.krk Normal file
View File

@ -0,0 +1 @@
print(list(filter(lambda x: x % 2 == 0, range(10))))

View File

@ -0,0 +1 @@
[0, 2, 4, 6, 8]

View File

@ -0,0 +1,15 @@
let l = list()
l.extend(range(10))
let l = list(range(10))
print(l)
let l = list(map(str,'test'))
print(l)
let l = list(map(list,['test','test','test']))
print(l)
let l = list(map(tupleOf,['foo','bar'],['baz','bix'],['three','args'],['four','args']))
print(l)

View File

@ -0,0 +1,4 @@
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
['t', 'e', 's', 't']
[['t', 'e', 's', 't'], ['t', 'e', 's', 't'], ['t', 'e', 's', 't']]
[('foo', 'baz', 'three', 'four'), ('bar', 'bix', 'args', 'args')]

18
test/testMap.krk Normal file
View File

@ -0,0 +1,18 @@
let m = map(lambda x, y: x + y, [1,2,3], [4,5,6])
for i in m:
print(i)
let m = map(lambda x, y: x + y, [1,2,3], [4,5,6])
let l = list(m)
print(l)
let l = list(map(lambda x, y: x + y, [1,2,3], [4,5,6]))
print(l)
print(list(map(lambda x, y: x + y, [1,2,3], [4,5,6])))
print(list(map(list, ['sat', 'bat', 'cat', 'mat'])))

7
test/testMap.krk.expect Normal file
View File

@ -0,0 +1,7 @@
5
7
9
[5, 7, 9]
[5, 7, 9]
[5, 7, 9]
[['s', 'a', 't'], ['b', 'a', 't'], ['c', 'a', 't'], ['m', 'a', 't']]