Fix broken stack handling in and make map,enumerate,filter object inits
This commit is contained in:
parent
3b8c521776
commit
c68eb093e8
170
src/builtins.c
170
src/builtins.c
@ -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
1
test/testEnumerate.krk
Normal file
@ -0,0 +1 @@
|
||||
print(list(enumerate(range(30))))
|
1
test/testEnumerate.krk.expect
Normal file
1
test/testEnumerate.krk.expect
Normal 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
1
test/testFilter.krk
Normal file
@ -0,0 +1 @@
|
||||
print(list(filter(lambda x: x % 2 == 0, range(10))))
|
1
test/testFilter.krk.expect
Normal file
1
test/testFilter.krk.expect
Normal file
@ -0,0 +1 @@
|
||||
[0, 2, 4, 6, 8]
|
15
test/testIamVeryConfused.krk
Normal file
15
test/testIamVeryConfused.krk
Normal 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)
|
4
test/testIamVeryConfused.krk.expect
Normal file
4
test/testIamVeryConfused.krk.expect
Normal 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
18
test/testMap.krk
Normal 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
7
test/testMap.krk.expect
Normal 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']]
|
Loading…
Reference in New Issue
Block a user