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
static KrkClass * mapobject;
KRK_FUNC(map,{
FUNCTION_TAKES_AT_LEAST(2);
#define CURRENT_CTYPE KrkInstance *
#define CURRENT_NAME self
/* Make a map object */
krk_push(OBJECT_VAL(krk_newInstance(mapobject)));
#define IS_map(o) (krk_isInstanceOf(o,map))
#define AS_map(o) (AS_INSTANCE(o))
static KrkClass * map;
KRK_METHOD(map,__init__,{
METHOD_TAKES_AT_LEAST(2);
/* 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 */
KrkTuple * iters = krk_newTuple(argc - 1);
KrkTuple * iters = krk_newTuple(argc - 2);
krk_push(OBJECT_VAL(iters));
/* 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();
for (int i = 1; i < argc; ++i) {
for (int i = 2; i < argc; ++i) {
KrkClass * type = krk_getType(argv[i]);
if (!type->_iter) {
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;
}
return krk_pop();
return argv[0];
})
#define CURRENT_CTYPE KrkInstance *
#define CURRENT_NAME self
#define IS_mapobject(o) (krk_isInstanceOf(o,mapobject))
#define AS_mapobject(o) (AS_INSTANCE(o))
KRK_METHOD(mapobject,__iter__,{
KRK_METHOD(map,__iter__,{
METHOD_TAKES_NONE();
return OBJECT_VAL(self);
})
KRK_METHOD(mapobject,__call__,{
KRK_METHOD(map,__call__,{
METHOD_TAKES_NONE();
size_t stackOffset = krk_currentThread.stackTop - krk_currentThread.stack;
/* Get members */
KrkValue function = 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("_iterables")), &iterators) || !IS_TUPLE(iterators)) return krk_runtimeError(vm.exceptions->valueError, "corrupt map object");
krk_push(function);
/* Go through each iterator */
for (size_t i = 0; i < AS_TUPLE(iterators)->values.count; ++i) {
/* 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();
/* End iteration whenever one runs out */
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);
}
}
/* Call the function */
return krk_callSimple(function, AS_TUPLE(iterators)->values.count, 0);
})
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));
KrkValue val = krk_callSimple(function, AS_TUPLE(iterators)->values.count, 0);
krk_currentThread.stackTop = krk_currentThread.stack + stackOffset;
return val;
})
KRK_FUNC(zip,{
@ -293,33 +291,31 @@ KRK_FUNC(zip,{
return krk_callSimple(map, argc+1, 0);
})
#define IS_filterobject(o) (krk_isInstanceOf(o,filterobject))
#define AS_filterobject(o) (AS_INSTANCE(o))
static KrkClass * filterobject;
KRK_FUNC(filter,{
FUNCTION_TAKES_EXACTLY(2);
/* Make a filter object */
krk_push(OBJECT_VAL(krk_newInstance(filterobject)));
krk_attachNamedValue(&AS_INSTANCE(krk_peek(0))->fields, "_function", argv[0]);
KrkClass * type = krk_getType(argv[1]);
#define IS_filter(o) (krk_isInstanceOf(o,filter))
#define AS_filter(o) (AS_INSTANCE(o))
static KrkClass * filter;
KRK_METHOD(filter,__init__,{
METHOD_TAKES_EXACTLY(2);
krk_attachNamedValue(&self->fields, "_function", argv[1]);
KrkClass * type = krk_getType(argv[2]);
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);
if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL();
krk_attachNamedValue(&AS_INSTANCE(krk_peek(0))->fields, "_iterator", asIter);
return krk_pop();
krk_attachNamedValue(&self->fields, "_iterator", asIter);
return argv[0];
})
KRK_METHOD(filterobject,__iter__,{
KRK_METHOD(filter,__iter__,{
METHOD_TAKES_NONE();
return OBJECT_VAL(self);
})
KRK_METHOD(filterobject,__call__,{
KRK_METHOD(filter,__call__,{
METHOD_TAKES_NONE();
size_t stackOffset = krk_currentThread.stackTop - krk_currentThread.stack;
KrkValue function = NONE_VAL();
KrkValue iterator = NONE_VAL();
@ -331,7 +327,10 @@ KRK_METHOD(filterobject,__call__,{
krk_push(krk_callSimple(iterator, 0, 0));
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 (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__,{
METHOD_TAKES_NONE();
char tmp[1024];
size_t len = sprintf(tmp, "<filter object at %p>", (void*)self);
return OBJECT_VAL(krk_copyString(tmp,len));
})
#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);
#define IS_enumerate(o) (krk_isInstanceOf(o,enumerate))
#define AS_enumerate(o) (AS_INSTANCE(o))
static KrkClass * enumerate;
KRK_METHOD(enumerate,__init__,{
METHOD_TAKES_EXACTLY(1);
KrkValue start = INTEGER_VAL(0);
if (hasKw) krk_tableGet(AS_DICT(argv[argc]), OBJECT_VAL(S("start")), &start);
/* Make a enumerate object */
krk_push(OBJECT_VAL(krk_newInstance(enumerateobject)));
krk_attachNamedValue(&AS_INSTANCE(krk_peek(0))->fields, "_counter", start);
krk_attachNamedValue(&self->fields, "_counter", start);
/* Attach iterator */
KrkClass * type = krk_getType(argv[0]);
KrkClass * type = krk_getType(argv[1]);
if (!type->_iter) {
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);
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();
return OBJECT_VAL(self);
})
extern KrkValue krk_operator_add (KrkValue a, KrkValue b);
KRK_METHOD(enumerateobject,__call__,{
KRK_METHOD(enumerate,__call__,{
METHOD_TAKES_NONE();
size_t stackOffset = krk_currentThread.stackTop - krk_currentThread.stack;
KrkValue counter = NONE_VAL();
KrkValue iterator = NONE_VAL();
@ -404,11 +397,13 @@ KRK_METHOD(enumerateobject,__call__,{
krk_push(krk_callSimple(iterator, 0, 0));
if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) {
krk_currentThread.stackTop = krk_currentThread.stack + stackOffset;
return NONE_VAL();
}
if (krk_valuesEqual(iterator, krk_peek(0))) {
krk_pop();
krk_pop();
krk_currentThread.stackTop = krk_currentThread.stack + stackOffset;
return OBJECT_VAL(self);
}
@ -419,14 +414,9 @@ KRK_METHOD(enumerateobject,__call__,{
krk_push(krk_operator_add(counter, INTEGER_VAL(1)));
krk_attachNamedValue(&self->fields, "_counter", krk_pop());
return krk_pop();
})
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));
KrkValue out = krk_pop();
krk_currentThread.stackTop = krk_currentThread.stack + stackOffset;
return out;
})
#define unpackArray(counter, indexer) do { \
@ -951,23 +941,26 @@ void _createAndBind_builtins(void) {
krk_finalizeClass(LicenseReader);
krk_attachNamedObject(&vm.builtins->fields, "license", (KrkObj*)krk_newInstance(LicenseReader));
krk_makeClass(vm.builtins, &mapobject, "mapobject", vm.baseClasses->objectClass);
BIND_METHOD(mapobject,__iter__);
BIND_METHOD(mapobject,__call__);
BIND_METHOD(mapobject,__repr__);
krk_finalizeClass(mapobject);
krk_makeClass(vm.builtins, &map, "map", vm.baseClasses->objectClass);
KRK_DOC(map, "Return an iterator that applies a function to a series of iterables");
BIND_METHOD(map,__init__);
BIND_METHOD(map,__iter__);
BIND_METHOD(map,__call__);
krk_finalizeClass(map);
krk_makeClass(vm.builtins, &filterobject, "filterobject", vm.baseClasses->objectClass);
BIND_METHOD(filterobject,__iter__);
BIND_METHOD(filterobject,__call__);
BIND_METHOD(filterobject,__repr__);
krk_finalizeClass(filterobject);
krk_makeClass(vm.builtins, &filter, "filter", vm.baseClasses->objectClass);
KRK_DOC(filter, "Return an iterator that returns only the items from an iterable for which the given function returns true.");
BIND_METHOD(filter,__init__);
BIND_METHOD(filter,__iter__);
BIND_METHOD(filter,__call__);
krk_finalizeClass(filter);
krk_makeClass(vm.builtins, &enumerateobject, "enumerateobject", vm.baseClasses->objectClass);
BIND_METHOD(enumerateobject,__iter__);
BIND_METHOD(enumerateobject,__call__);
BIND_METHOD(enumerateobject,__repr__);
krk_finalizeClass(enumerateobject);
krk_makeClass(vm.builtins, &enumerate, "enumerate", vm.baseClasses->objectClass);
KRK_DOC(enumerate, "Return an iterator that produces a tuple with a count the iterated values of the passed iteratable.");
BIND_METHOD(enumerate,__init__);
BIND_METHOD(enumerate,__iter__);
BIND_METHOD(enumerate,__call__);
krk_finalizeClass(enumerate);
BUILTIN_FUNCTION("isinstance", FUNC_NAME(krk,isinstance),
"@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("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("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("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.");

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']]