Drop krk_callSimple
Replace it with two functions that won't run into issues with trying to call bound objects, instances, etc. that weren't on the stack. In general, if you have a callable value of unknown type you should call `krk_callStack` with it on the stack followed by all of its args; to make this abundantly clear, `krk_callStack` only takes the argument count. For calling things we know to be safe (closures and natives), there is `krk_callDirect`, which should be used, for example, when calling core methods like __repr__.
This commit is contained in:
parent
bc27feca69
commit
444cb28d06
@ -91,7 +91,7 @@ KRK_FUNC(len,{
|
||||
if (!type->_len) return krk_runtimeError(vm.exceptions->typeError, "object of type '%s' has no len()", krk_typeName(argv[0]));
|
||||
krk_push(argv[0]);
|
||||
|
||||
return krk_callSimple(OBJECT_VAL(type->_len), 1, 0);
|
||||
return krk_callDirect(type->_len, 1);
|
||||
})
|
||||
|
||||
KRK_FUNC(dir,{
|
||||
@ -101,7 +101,7 @@ KRK_FUNC(dir,{
|
||||
return krk_dirObject(argc,argv,hasKw); /* Fallback */
|
||||
}
|
||||
krk_push(argv[0]);
|
||||
return krk_callSimple(OBJECT_VAL(type->_dir), 1, 0);
|
||||
return krk_callDirect(type->_dir, 1);
|
||||
})
|
||||
|
||||
KRK_FUNC(repr,{
|
||||
@ -109,7 +109,7 @@ KRK_FUNC(repr,{
|
||||
/* Everything should have a __repr__ */
|
||||
KrkClass * type = krk_getType(argv[0]);
|
||||
krk_push(argv[0]);
|
||||
return krk_callSimple(OBJECT_VAL(type->_reprer), 1, 0);
|
||||
return krk_callDirect(type->_reprer, 1);
|
||||
})
|
||||
|
||||
KRK_FUNC(ord,{
|
||||
@ -117,8 +117,9 @@ KRK_FUNC(ord,{
|
||||
KrkClass * type = krk_getType(argv[0]);
|
||||
KrkValue method;
|
||||
if (krk_tableGet(&type->methods, vm.specialMethodNames[METHOD_ORD], &method)) {
|
||||
krk_push(method);
|
||||
krk_push(argv[0]);
|
||||
return krk_callSimple(method, 1, 0);
|
||||
return krk_callStack(1);
|
||||
}
|
||||
return TYPE_ERROR(string of length 1,argv[0]);
|
||||
})
|
||||
@ -128,8 +129,9 @@ KRK_FUNC(chr,{
|
||||
KrkClass * type = krk_getType(argv[0]);
|
||||
KrkValue method;
|
||||
if (krk_tableGet(&type->methods, vm.specialMethodNames[METHOD_CHR], &method)) {
|
||||
krk_push(method);
|
||||
krk_push(argv[0]);
|
||||
return krk_callSimple(method, 1, 0);
|
||||
return krk_callStack(1);
|
||||
}
|
||||
return TYPE_ERROR(int,argv[0]);
|
||||
})
|
||||
@ -229,7 +231,7 @@ KRK_METHOD(map,__init__,{
|
||||
return krk_runtimeError(vm.exceptions->typeError, "'%s' object is not iterable", krk_typeName(argv[i]));
|
||||
}
|
||||
krk_push(argv[i]);
|
||||
KrkValue asIter = krk_callSimple(OBJECT_VAL(type->_iter), 1, 0);
|
||||
KrkValue asIter = krk_callDirect(type->_iter, 1);
|
||||
if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL();
|
||||
/* Attach it to the tuple */
|
||||
iters->values.values[iters->values.count++] = asIter;
|
||||
@ -261,7 +263,7 @@ KRK_METHOD(map,__call__,{
|
||||
for (size_t i = 0; i < AS_TUPLE(iterators)->values.count; ++i) {
|
||||
/* Obtain the next value and push it */
|
||||
krk_push(AS_TUPLE(iterators)->values.values[i]);
|
||||
krk_push(krk_callSimple(AS_TUPLE(iterators)->values.values[i], 0, 0));
|
||||
krk_push(krk_callStack(0));
|
||||
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])) {
|
||||
@ -272,7 +274,7 @@ KRK_METHOD(map,__call__,{
|
||||
}
|
||||
|
||||
/* Call the function */
|
||||
KrkValue val = krk_callSimple(function, AS_TUPLE(iterators)->values.count, 0);
|
||||
KrkValue val = krk_callStack(AS_TUPLE(iterators)->values.count);
|
||||
krk_currentThread.stackTop = krk_currentThread.stack + stackOffset;
|
||||
return val;
|
||||
})
|
||||
@ -285,12 +287,13 @@ KRK_FUNC(zip,{
|
||||
krk_tableGet(&vm.builtins->fields, OBJECT_VAL(S("map")), &map);
|
||||
krk_tableGet(&vm.builtins->fields, OBJECT_VAL(S("tupleOf")), &tupleOfFunc);
|
||||
|
||||
krk_push(map);
|
||||
krk_push(tupleOfFunc);
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
krk_push(argv[i]);
|
||||
}
|
||||
|
||||
return krk_callSimple(map, argc+1, 0);
|
||||
return krk_callStack(argc+1);
|
||||
})
|
||||
|
||||
#define IS_filter(o) (krk_isInstanceOf(o,filter))
|
||||
@ -304,7 +307,7 @@ KRK_METHOD(filter,__init__,{
|
||||
return krk_runtimeError(vm.exceptions->typeError, "'%s' object is not iterable", krk_typeName(argv[2]));
|
||||
}
|
||||
krk_push(argv[2]);
|
||||
KrkValue asIter = krk_callSimple(OBJECT_VAL(type->_iter), 1, 0);
|
||||
KrkValue asIter = krk_callDirect(type->_iter, 1);
|
||||
if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL();
|
||||
krk_attachNamedValue(&self->fields, "_iterator", asIter);
|
||||
return argv[0];
|
||||
@ -326,7 +329,7 @@ KRK_METHOD(filter,__call__,{
|
||||
|
||||
while (1) {
|
||||
krk_push(iterator);
|
||||
krk_push(krk_callSimple(iterator, 0, 0));
|
||||
krk_push(krk_callStack(0));
|
||||
|
||||
if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL();
|
||||
if (krk_valuesEqual(iterator, krk_peek(0))) {
|
||||
@ -340,8 +343,9 @@ KRK_METHOD(filter,__call__,{
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
krk_push(krk_peek(0));
|
||||
KrkValue result = krk_callSimple(function, 1, 0);
|
||||
krk_push(function);
|
||||
krk_push(krk_peek(1));
|
||||
KrkValue result = krk_callStack(1);
|
||||
if (krk_isFalsey(result)) {
|
||||
krk_pop(); /* iterator result */
|
||||
continue;
|
||||
@ -370,7 +374,7 @@ KRK_METHOD(enumerate,__init__,{
|
||||
return krk_runtimeError(vm.exceptions->typeError, "'%s' object is not iterable", krk_typeName(argv[1]));
|
||||
}
|
||||
krk_push(argv[1]);
|
||||
KrkValue asIter = krk_callSimple(OBJECT_VAL(type->_iter), 1, 0);
|
||||
KrkValue asIter = krk_callDirect(type->_iter, 1);
|
||||
if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL();
|
||||
krk_attachNamedValue(&self->fields, "_iterator", asIter);
|
||||
|
||||
@ -396,7 +400,7 @@ KRK_METHOD(enumerate,__call__,{
|
||||
krk_push(OBJECT_VAL(tupleOut));
|
||||
|
||||
krk_push(iterator);
|
||||
krk_push(krk_callSimple(iterator, 0, 0));
|
||||
krk_push(krk_callStack(0));
|
||||
|
||||
if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) {
|
||||
krk_currentThread.stackTop = krk_currentThread.stack + stackOffset;
|
||||
@ -780,13 +784,14 @@ KRK_METHOD(Helper,__call__,{
|
||||
|
||||
if (argc == 2) {
|
||||
krk_tableGet(&AS_INSTANCE(helpModule)->fields, OBJECT_VAL(S("simple")), &callable);
|
||||
krk_push(argv[1]);
|
||||
} else {
|
||||
krk_tableGet(&AS_INSTANCE(helpModule)->fields, OBJECT_VAL(S("interactive")), &callable);
|
||||
}
|
||||
|
||||
if (!IS_NONE(callable)) {
|
||||
return krk_callSimple(callable, argc == 2, 0);
|
||||
krk_push(callable);
|
||||
if (argc == 2) krk_push(argv[1]);
|
||||
return krk_callStack(argc == 2);
|
||||
}
|
||||
|
||||
return krk_runtimeError(vm.exceptions->typeError, "unexpected error");
|
||||
@ -856,23 +861,29 @@ KRK_METHOD(property,__get__,{
|
||||
if (!krk_tableGet(&self->fields, OBJECT_VAL(S("fget")), &fget))
|
||||
return krk_runtimeError(vm.exceptions->attributeError, "'%s' object has no attribute '%s'", "property", "fget");
|
||||
|
||||
krk_push(fget);
|
||||
krk_push(argv[1]);
|
||||
return krk_callSimple(fget, 1, 0);
|
||||
return krk_callStack(1);
|
||||
})
|
||||
|
||||
KRK_METHOD(property,__set__,{
|
||||
METHOD_TAKES_EXACTLY(2); /* the owner and the value */
|
||||
|
||||
krk_push(argv[1]);
|
||||
krk_push(argv[2]);
|
||||
|
||||
KrkValue fset;
|
||||
if (krk_tableGet(&self->fields, OBJECT_VAL(S("fset")), &fset))
|
||||
return krk_callSimple(fset, 2, 0);
|
||||
if (krk_tableGet(&self->fields, OBJECT_VAL(S("fset")), &fset)) {
|
||||
krk_push(fset);
|
||||
krk_push(argv[1]);
|
||||
krk_push(argv[2]);
|
||||
return krk_callStack(2);
|
||||
}
|
||||
|
||||
KrkValue fget;
|
||||
if (krk_tableGet(&self->fields, OBJECT_VAL(S("fget")), &fget))
|
||||
return krk_callSimple(fget, 2, 0);
|
||||
if (krk_tableGet(&self->fields, OBJECT_VAL(S("fget")), &fget)) {
|
||||
krk_push(fget);
|
||||
krk_push(argv[1]);
|
||||
krk_push(argv[2]);
|
||||
return krk_callStack(2);
|
||||
}
|
||||
|
||||
return krk_runtimeError(vm.exceptions->attributeError, "attribute can not be set");
|
||||
})
|
||||
@ -893,8 +904,7 @@ KRK_FUNC(hash,{
|
||||
KRK_FUNC(next,{
|
||||
FUNCTION_TAKES_EXACTLY(1);
|
||||
krk_push(argv[0]);
|
||||
krk_push(krk_callSimple(argv[0], 0, 0));
|
||||
return krk_pop();
|
||||
return krk_callStack(0);
|
||||
})
|
||||
|
||||
#ifndef STATIC_ONLY
|
||||
|
@ -50,7 +50,7 @@ static KrkValue _exception_repr(int argc, KrkValue argv[], int hasKw) {
|
||||
if (krk_tableGet(&self->fields, OBJECT_VAL(S("arg")), &arg)) {
|
||||
/* repr it */
|
||||
krk_push(arg);
|
||||
KrkValue repred = krk_callSimple(OBJECT_VAL(krk_getType(arg)->_reprer), 1, 0);
|
||||
KrkValue repred = krk_callDirect(krk_getType(arg)->_reprer, 1);
|
||||
pushStringBuilderStr(&sb, AS_CSTRING(repred), AS_STRING(repred)->length);
|
||||
}
|
||||
|
||||
@ -74,7 +74,7 @@ static KrkValue _exception_str(int argc, KrkValue argv[], int hasKw) {
|
||||
return NONE_VAL();
|
||||
} else if (!IS_STRING(arg)) {
|
||||
krk_push(arg);
|
||||
return krk_callSimple(OBJECT_VAL(krk_getType(arg)->_tostr), 1, 0);
|
||||
return krk_callDirect(krk_getType(arg)->_tostr, 1);
|
||||
} else {
|
||||
return arg;
|
||||
}
|
||||
|
@ -457,11 +457,12 @@ static int debuggerHook(KrkCallFrame * frame) {
|
||||
/* Turn our compiled expression into a callable. */
|
||||
krk_push(OBJECT_VAL(expression));
|
||||
krk_push(OBJECT_VAL(krk_newClosure(expression)));
|
||||
krk_swap(1);
|
||||
/* Stack silliness, don't ask. */
|
||||
krk_push(NONE_VAL());
|
||||
krk_pop();
|
||||
/* Call the compiled expression with no args, but claim 2 method extras. */
|
||||
krk_push(krk_callSimple(krk_peek(0), 0, 2));
|
||||
/* Call the compiled expression with no args. */
|
||||
krk_push(krk_callStack(0));
|
||||
fprintf(stderr, "\033[1;30m=> ");
|
||||
krk_printValue(stderr, krk_peek(0));
|
||||
fprintf(stderr, "\033[0m\n");
|
||||
@ -1120,10 +1121,10 @@ _finishArgs:
|
||||
const char * formatStr = " \033[1;30m=> %s\033[0m\n";
|
||||
if (type->_reprer) {
|
||||
krk_push(result);
|
||||
result = krk_callSimple(OBJECT_VAL(type->_reprer), 1, 0);
|
||||
result = krk_callDirect(type->_reprer, 1);
|
||||
} else if (type->_tostr) {
|
||||
krk_push(result);
|
||||
result = krk_callSimple(OBJECT_VAL(type->_tostr), 1, 0);
|
||||
result = krk_callDirect(type->_tostr, 1);
|
||||
}
|
||||
if (!IS_STRING(result)) {
|
||||
fprintf(stdout, " \033[1;31m=> Unable to produce representation for value.\033[0m\n");
|
||||
|
@ -495,7 +495,7 @@ extern KrkClass * krk_newClass(KrkString * name, KrkClass * base);
|
||||
*
|
||||
* Handles allocation, but not __init__, of the new instance.
|
||||
* Be sure to populate any fields expected by the class or call
|
||||
* its __init__ function (eg. with @ref krk_callSimple) as needed.
|
||||
* its __init__ function (eg. with @ref krk_callStack) as needed.
|
||||
*/
|
||||
extern KrkInstance * krk_newInstance(KrkClass * _class);
|
||||
|
||||
|
@ -234,10 +234,10 @@ extern KrkValue FUNC_NAME(str,format)(int,KrkValue*,int);
|
||||
if (type->_iter) { \
|
||||
size_t stackOffset = krk_currentThread.stackTop - krk_currentThread.stack; \
|
||||
krk_push(fromInput); \
|
||||
krk_push(krk_callSimple(OBJECT_VAL(type->_iter), 1, 0)); \
|
||||
krk_push(krk_callDirect(type->_iter,1)); \
|
||||
do { \
|
||||
krk_push(krk_currentThread.stack[stackOffset]); \
|
||||
krk_push(krk_callSimple(krk_peek(0), 0, 1)); \
|
||||
krk_push(krk_callStack(0)); \
|
||||
if (krk_valuesSame(krk_currentThread.stack[stackOffset], krk_peek(0))) { \
|
||||
krk_pop(); \
|
||||
krk_pop(); \
|
||||
|
@ -573,19 +573,16 @@ extern int krk_bindMethod(KrkClass * _class, KrkString * name);
|
||||
*
|
||||
* @param callee Value referencing a callable object.
|
||||
* @param argCount Arguments to retreive from stack.
|
||||
* @param extra Whether extra arguments below argCount should be
|
||||
* considered as part of this call frame. Generally,
|
||||
* when this is 1, the value below the arguments is
|
||||
* the callable object. Most library users will want
|
||||
* to leave this as 0 when calling normal functions,
|
||||
* bound method objects, or ubound methods when the
|
||||
* instance is included in the arguments already.
|
||||
* @param callableOnStack Whether @p callee is on the stack below the arguments,
|
||||
* which must be the case for bound methods, classes,
|
||||
* and instances, as that space will be used for the implicit
|
||||
* first argument passed to these kinds of callables.
|
||||
* @return An indicator of how the result should be obtained:
|
||||
* 1: The VM must be resumed to run managed code.
|
||||
* 2: The callable was a native function and result should be popped now.
|
||||
* Else: The call failed. An exception may have already been set.
|
||||
*/
|
||||
extern int krk_callValue(KrkValue callee, int argCount, int extra);
|
||||
extern int krk_callValue(KrkValue callee, int argCount, int callableOnStack);
|
||||
|
||||
/**
|
||||
* @brief Create a list object.
|
||||
@ -620,20 +617,31 @@ extern KrkValue krk_tuple_of(int argc, KrkValue argv[], int hasKw);
|
||||
extern KrkValue krk_set_of(int argc, KrkValue argv[], int hasKw);
|
||||
|
||||
/**
|
||||
* @brief Call a callable and manage VM state to obtain the return value.
|
||||
* @memberof KrkValue
|
||||
* @brief Call a callable on the stack with @p argCount arguments.
|
||||
*
|
||||
* This is a wrapper around various mechanisms including krk_callValue
|
||||
* intended for use by C extensions to call arbitrary functions without
|
||||
* knowledge of their implementation details. See the notes for
|
||||
* @c krk_callValue 's @c extra paramater for details on how @p isMethod is used.
|
||||
* Calls the callable @p argCount stack entries down from the top
|
||||
* of the stack, passing @p argCount arguments. Resumes execution
|
||||
* of the VM for managed calls until they are completed. Pops
|
||||
* @p argCount items from the stack and returns the result of
|
||||
* the call.
|
||||
*
|
||||
* @param value Callable object reference.
|
||||
* @param argCount Arguments to collect from the stack.
|
||||
* @param isMethod This should almost always be 0.
|
||||
* @return The return value of the function.
|
||||
*/
|
||||
extern KrkValue krk_callSimple(KrkValue value, int argCount, int isMethod);
|
||||
extern KrkValue krk_callStack(int argCount);
|
||||
|
||||
/**
|
||||
* @brief Call a closure or native function with @p argCount arguments.
|
||||
*
|
||||
* Calls the closure or native @p callable with arguments from the
|
||||
* top of the stack. @p argCount arguments are popped from the stack
|
||||
* and the return value of the call is returned.
|
||||
*
|
||||
* @param callable Closure or native function.
|
||||
* @param argCount Arguments to collect from the stack.
|
||||
* @return The return value of the function.
|
||||
*/
|
||||
extern KrkValue krk_callDirect(KrkObj * callable, int argCount);
|
||||
|
||||
/**
|
||||
* @brief Convenience function for creating new types.
|
||||
|
@ -27,7 +27,7 @@
|
||||
if (!krk_bindMethod(type, S("__float__"))) { \
|
||||
krk_pop(); \
|
||||
} else { \
|
||||
arg = krk_callSimple(krk_peek(0), 0, 1); \
|
||||
arg = krk_callStack(0); \
|
||||
} \
|
||||
} break; \
|
||||
} }
|
||||
@ -48,7 +48,7 @@ static KrkValue _math_ ## func(int argc, KrkValue argv[], int hasKw) { \
|
||||
KrkClass * type = krk_getType(argv[0]); \
|
||||
krk_push(argv[0]); \
|
||||
if (!krk_bindMethod(type, S("__" #func "__"))) REAL_NUMBER_NOT(func,argv[0]) \
|
||||
return krk_callSimple(krk_peek(0), 0, 1); \
|
||||
return krk_callStack(0); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,8 @@ KRK_FUNC(timeit,{
|
||||
struct timeval tv_before, tv_after;
|
||||
gettimeofday(&tv_before,NULL);
|
||||
for (krk_integer_type t = 0; t < times; ++t) {
|
||||
krk_callSimple(argv[0],0,0);
|
||||
krk_push(argv[0]);
|
||||
krk_callStack(0);
|
||||
}
|
||||
gettimeofday(&tv_after,NULL);
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
#define KEY_ERROR(value) {\
|
||||
KrkClass * type = krk_getType(value); \
|
||||
krk_push(value); \
|
||||
KrkValue asString = krk_callSimple(OBJECT_VAL(type->_reprer), 1, 0); \
|
||||
KrkValue asString = krk_callDirect(type->_reprer, 1); \
|
||||
if (IS_STRING(asString)) return krk_runtimeError(vm.exceptions->keyError, "%s", AS_CSTRING(asString)); \
|
||||
return krk_runtimeError(vm.exceptions->keyError, "key error"); }
|
||||
|
||||
@ -110,7 +110,7 @@ KRK_METHOD(dict,__repr__,{
|
||||
{
|
||||
KrkClass * type = krk_getType(entry->key);
|
||||
krk_push(entry->key);
|
||||
KrkValue result = krk_callSimple(OBJECT_VAL(type->_reprer), 1, 0);
|
||||
KrkValue result = krk_callDirect(type->_reprer, 1);
|
||||
if (IS_STRING(result)) {
|
||||
pushStringBuilderStr(&sb, AS_CSTRING(result), AS_STRING(result)->length);
|
||||
}
|
||||
@ -121,7 +121,7 @@ KRK_METHOD(dict,__repr__,{
|
||||
{
|
||||
KrkClass * type = krk_getType(entry->value);
|
||||
krk_push(entry->value);
|
||||
KrkValue result = krk_callSimple(OBJECT_VAL(type->_reprer), 1, 0);
|
||||
KrkValue result = krk_callDirect(type->_reprer, 1);
|
||||
if (IS_STRING(result)) {
|
||||
pushStringBuilderStr(&sb, AS_CSTRING(result), AS_STRING(result)->length);
|
||||
}
|
||||
@ -272,7 +272,7 @@ KRK_METHOD(dictitems,__repr__,{
|
||||
{
|
||||
KrkClass * type = krk_getType(entry->key);
|
||||
krk_push(entry->key);
|
||||
KrkValue result = krk_callSimple(OBJECT_VAL(type->_reprer), 1, 0);
|
||||
KrkValue result = krk_callDirect(type->_reprer, 1);
|
||||
if (IS_STRING(result)) {
|
||||
pushStringBuilderStr(&sb, AS_CSTRING(result), AS_STRING(result)->length);
|
||||
}
|
||||
@ -283,7 +283,7 @@ KRK_METHOD(dictitems,__repr__,{
|
||||
{
|
||||
KrkClass * type = krk_getType(entry->value);
|
||||
krk_push(entry->value);
|
||||
KrkValue result = krk_callSimple(OBJECT_VAL(type->_reprer), 1, 0);
|
||||
KrkValue result = krk_callDirect(type->_reprer, 1);
|
||||
if (IS_STRING(result)) {
|
||||
pushStringBuilderStr(&sb, AS_CSTRING(result), AS_STRING(result)->length);
|
||||
}
|
||||
@ -351,7 +351,7 @@ KRK_METHOD(dictkeys,__repr__,{
|
||||
{
|
||||
KrkClass * type = krk_getType(entry->key);
|
||||
krk_push(entry->key);
|
||||
KrkValue result = krk_callSimple(OBJECT_VAL(type->_reprer), 1, 0);
|
||||
KrkValue result = krk_callDirect(type->_reprer, 1);
|
||||
if (IS_STRING(result)) {
|
||||
pushStringBuilderStr(&sb, AS_CSTRING(result), AS_STRING(result)->length);
|
||||
}
|
||||
|
@ -234,7 +234,7 @@ KRK_METHOD(method,__str__,{
|
||||
|
||||
KrkClass * type = krk_getType(self->receiver);
|
||||
krk_push(self->receiver);
|
||||
KrkValue reprVal = krk_callSimple(OBJECT_VAL(type->_reprer), 1, 0);
|
||||
KrkValue reprVal = krk_callDirect(type->_reprer, 1);
|
||||
|
||||
size_t len = AS_STRING(s)->length + AS_STRING(reprVal)->length + sizeof("<bound method of >") + 1;
|
||||
char * tmp = malloc(len);
|
||||
|
@ -206,7 +206,7 @@ int krk_getAwaitable(void) {
|
||||
krk_push(method);
|
||||
krk_swap(1);
|
||||
krk_pop();
|
||||
krk_push(krk_callSimple(krk_peek(0),0,0));
|
||||
krk_push(krk_callStack(0));
|
||||
KrkClass * _type = krk_getType(krk_peek(0));
|
||||
if (!_type || !_type->_iter) {
|
||||
krk_runtimeError(vm.exceptions->attributeError, "__await__ returned non-iterator of type '%s'", krk_typeName(krk_peek(0)));
|
||||
|
@ -99,7 +99,7 @@ KRK_METHOD(list,__repr__,{
|
||||
/* repr(self[i]) */
|
||||
KrkClass * type = krk_getType(self->values.values[i]);
|
||||
krk_push(self->values.values[i]);
|
||||
KrkValue result = krk_callSimple(OBJECT_VAL(type->_reprer), 1, 0);
|
||||
KrkValue result = krk_callDirect(type->_reprer, 1);
|
||||
|
||||
if (IS_STRING(result)) {
|
||||
pushStringBuilderStr(&sb, AS_STRING(result)->chars, AS_STRING(result)->length);
|
||||
|
@ -86,7 +86,7 @@ KRK_METHOD(set,__repr__,{
|
||||
|
||||
KrkClass * type = krk_getType(entry->key);
|
||||
krk_push(entry->key);
|
||||
KrkValue result = krk_callSimple(OBJECT_VAL(type->_reprer), 1, 0);
|
||||
KrkValue result = krk_callDirect(type->_reprer, 1);
|
||||
if (IS_STRING(result)) {
|
||||
pushStringBuilderStr(&sb, AS_CSTRING(result), AS_STRING(result)->length);
|
||||
}
|
||||
@ -115,9 +115,10 @@ KRK_METHOD(set,__and__,{
|
||||
KrkTableEntry * entry = &self->entries.entries[i];
|
||||
if (IS_KWARGS(entry->key)) continue;
|
||||
|
||||
krk_push(contains);
|
||||
krk_push(argv[1]);
|
||||
krk_push(entry->key);
|
||||
KrkValue result = krk_callSimple(contains, 2, 0);
|
||||
KrkValue result = krk_callStack(2);
|
||||
|
||||
if (IS_BOOLEAN(result) && AS_BOOLEAN(result)) {
|
||||
krk_tableSet(&AS_set(outSet)->entries, entry->key, BOOLEAN_VAL(1));
|
||||
|
@ -40,7 +40,7 @@ KRK_METHOD(str,__init__,{
|
||||
/* Find the type of arg */
|
||||
krk_push(argv[1]);
|
||||
if (!krk_getType(argv[1])->_tostr) return krk_runtimeError(vm.exceptions->typeError, "Can not convert %s to str", krk_typeName(argv[1]));
|
||||
return krk_callSimple(OBJECT_VAL(krk_getType(argv[1])->_tostr), 1, 0);
|
||||
return krk_callDirect(krk_getType(argv[1])->_tostr, 1);
|
||||
})
|
||||
|
||||
KRK_METHOD(str,__add__,{
|
||||
@ -257,13 +257,13 @@ KRK_METHOD(str,format,{
|
||||
krk_push(value);
|
||||
KrkClass * type = krk_getType(value);
|
||||
if (type->_tostr) {
|
||||
asString = krk_callSimple(OBJECT_VAL(type->_tostr), 1, 0);
|
||||
asString = krk_callDirect(type->_tostr, 1);
|
||||
} else {
|
||||
if (!krk_bindMethod(type, AS_STRING(vm.specialMethodNames[METHOD_STR]))) {
|
||||
errorStr = "Failed to convert field to string.";
|
||||
goto _formatError;
|
||||
}
|
||||
asString = krk_callSimple(krk_peek(0), 0, 1);
|
||||
asString = krk_callStack(0);
|
||||
}
|
||||
if (!IS_STRING(asString)) goto _freeAndDone;
|
||||
}
|
||||
|
@ -16,10 +16,11 @@ static KrkValue _tuple_init(int argc, KrkValue argv[], int hasKw) {
|
||||
/* Convert this to a call to tupleOf(*arg) */
|
||||
KrkValue tupleOf;
|
||||
krk_tableGet(&vm.builtins->fields, OBJECT_VAL(S("tupleOf")), &tupleOf);
|
||||
krk_push(tupleOf);
|
||||
krk_push(KWARGS_VAL(KWARGS_LIST));
|
||||
krk_push(argv[1]);
|
||||
krk_push(KWARGS_VAL(1));
|
||||
krk_push(krk_callSimple(tupleOf, 3, 0));
|
||||
krk_push(krk_callStack(3));
|
||||
return krk_pop();
|
||||
} else {
|
||||
return krk_runtimeError(vm.exceptions->argumentError,
|
||||
@ -87,7 +88,7 @@ KRK_METHOD(tuple,__repr__,{
|
||||
for (size_t i = 0; i < self->values.count; ++i) {
|
||||
KrkClass * type = krk_getType(self->values.values[i]);
|
||||
krk_push(self->values.values[i]);
|
||||
KrkValue result = krk_callSimple(OBJECT_VAL(type->_reprer), 1, 0);
|
||||
KrkValue result = krk_callDirect(type->_reprer, 1);
|
||||
if (IS_STRING(result)) {
|
||||
pushStringBuilderStr(&sb, AS_STRING(result)->chars, AS_STRING(result)->length);
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ static KrkValue typeToString(KrkValue val) {
|
||||
/* Just repr it. */
|
||||
KrkClass * type = krk_getType(val);
|
||||
krk_push(val);
|
||||
return krk_callSimple(OBJECT_VAL(type->_reprer), 1, 0);
|
||||
return krk_callDirect(type->_reprer, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
4
src/os.c
4
src/os.c
@ -108,7 +108,7 @@ KRK_METHOD(Environ,__setitem__,{
|
||||
krk_push(argv[0]);
|
||||
krk_push(argv[1]);
|
||||
krk_push(argv[2]);
|
||||
return krk_callSimple(OBJECT_VAL(vm.baseClasses->dictClass->_setter), 3, 0);
|
||||
return krk_callDirect(vm.baseClasses->dictClass->_setter, 3);
|
||||
}
|
||||
|
||||
return krk_runtimeError(OSError, "%s", strerror(errno));
|
||||
@ -132,7 +132,7 @@ KRK_METHOD(Environ,__delitem__,{
|
||||
_unsetVar(key);
|
||||
krk_push(argv[0]);
|
||||
krk_push(argv[1]);
|
||||
return krk_callSimple(OBJECT_VAL(vm.baseClasses->dictClass->_delitem), 2, 0);
|
||||
return krk_callDirect(vm.baseClasses->dictClass->_delitem, 2);
|
||||
})
|
||||
|
||||
static void _loadEnviron(KrkInstance * module) {
|
||||
|
@ -44,7 +44,7 @@ inline int krk_hashValue(KrkValue value, uint32_t *hashOut) {
|
||||
KrkClass * type = krk_getType(value);
|
||||
if (type && type->_hash) {
|
||||
krk_push(value);
|
||||
KrkValue result = krk_callSimple(OBJECT_VAL(type->_hash), 1, 0);
|
||||
KrkValue result = krk_callDirect(type->_hash, 1);
|
||||
if (!IS_INTEGER(result)) goto _unhashable;
|
||||
*hashOut = (uint32_t)AS_INTEGER(result);
|
||||
return 0;
|
||||
|
@ -86,9 +86,9 @@ static void * _startthread(void * _threadObj) {
|
||||
if (!krk_tableGet(&ourType->methods, OBJECT_VAL(S("run")), &runMethod)) {
|
||||
krk_runtimeError(ThreadError, "Thread object has no run() method");
|
||||
} else {
|
||||
krk_push(runMethod);
|
||||
krk_push(OBJECT_VAL(self));
|
||||
krk_callValue(runMethod, 1, 0);
|
||||
krk_runNext();
|
||||
krk_callStack(1);
|
||||
}
|
||||
|
||||
self->alive = 0;
|
||||
|
@ -31,12 +31,12 @@ void krk_printValue(FILE * f, KrkValue printable) {
|
||||
KrkClass * type = krk_getType(printable);
|
||||
if (type->_tostr) {
|
||||
krk_push(printable);
|
||||
printable = krk_callSimple(OBJECT_VAL(type->_tostr), 1, 0);
|
||||
printable = krk_callDirect(type->_tostr, 1);
|
||||
if (!IS_STRING(printable)) return;
|
||||
fprintf(f, "%s", AS_CSTRING(printable));
|
||||
} else if (type->_reprer) {
|
||||
krk_push(printable);
|
||||
printable = krk_callSimple(OBJECT_VAL(type->_reprer), 1, 0);
|
||||
printable = krk_callDirect(type->_reprer, 1);
|
||||
if (!IS_STRING(printable)) return;
|
||||
fprintf(f, "%s", AS_CSTRING(printable));
|
||||
} else {
|
||||
@ -166,7 +166,7 @@ int krk_valuesEqual(KrkValue a, KrkValue b) {
|
||||
if (type && type->_eq) {
|
||||
krk_push(a);
|
||||
krk_push(b);
|
||||
KrkValue result = krk_callSimple(OBJECT_VAL(type->_eq),2,0);
|
||||
KrkValue result = krk_callDirect(type->_eq,2);
|
||||
if (IS_BOOLEAN(result)) return AS_BOOLEAN(result);
|
||||
if (IS_NOTIMPL(result)) goto _next;
|
||||
return !krk_isFalsey(result);
|
||||
@ -177,7 +177,7 @@ _next:
|
||||
if (type && type->_eq) {
|
||||
krk_push(b);
|
||||
krk_push(a);
|
||||
KrkValue result = krk_callSimple(OBJECT_VAL(type->_eq),2,0);
|
||||
KrkValue result = krk_callDirect(type->_eq,2);
|
||||
if (IS_BOOLEAN(result)) return AS_BOOLEAN(result);
|
||||
return !krk_isFalsey(result);
|
||||
}
|
||||
|
104
src/vm.c
104
src/vm.c
@ -190,14 +190,14 @@ void krk_dumpTraceback(void) {
|
||||
|
||||
/* Is this a SyntaxError? Handle those specially. */
|
||||
if (krk_isInstanceOf(krk_currentThread.currentException, vm.exceptions->syntaxError)) {
|
||||
KrkValue result = krk_callSimple(OBJECT_VAL(krk_getType(krk_currentThread.currentException)->_tostr), 1, 0);
|
||||
KrkValue result = krk_callDirect(krk_getType(krk_currentThread.currentException)->_tostr, 1);
|
||||
fprintf(stderr, "%s\n", AS_CSTRING(result));
|
||||
return;
|
||||
}
|
||||
/* Clear the exception state while printing the exception. */
|
||||
krk_currentThread.flags &= ~(KRK_THREAD_HAS_EXCEPTION);
|
||||
fprintf(stderr, "%s", krk_typeName(krk_currentThread.currentException));
|
||||
KrkValue result = krk_callSimple(OBJECT_VAL(krk_getType(krk_currentThread.currentException)->_tostr), 1, 0);
|
||||
KrkValue result = krk_callDirect(krk_getType(krk_currentThread.currentException)->_tostr, 1);
|
||||
if (!IS_STRING(result)) {
|
||||
fprintf(stderr, "\n");
|
||||
} else {
|
||||
@ -588,7 +588,7 @@ int krk_processComplexArguments(int argCount, KrkValueArray * positionals, KrkTa
|
||||
* `extra` is passed by `callValue` to tell us which case we have, and thus
|
||||
* where we need to restore the stack to when we return from this call.
|
||||
*/
|
||||
static int call(KrkClosure * closure, int argCount, int extra) {
|
||||
static int call(KrkClosure * closure, int argCount, int callableOnStack) {
|
||||
size_t potentialPositionalArgs = closure->function->requiredArgs + closure->function->keywordArgs;
|
||||
size_t totalArguments = closure->function->requiredArgs + closure->function->keywordArgs + !!(closure->function->flags & KRK_CODEOBJECT_FLAGS_COLLECTS_ARGS) + !!(closure->function->flags & KRK_CODEOBJECT_FLAGS_COLLECTS_KWS);
|
||||
size_t offsetOfExtraArgs = closure->function->requiredArgs + closure->function->keywordArgs;
|
||||
@ -730,7 +730,7 @@ _finishKwarg:
|
||||
|
||||
if (unlikely(closure->function->flags & (KRK_CODEOBJECT_FLAGS_IS_GENERATOR | KRK_CODEOBJECT_FLAGS_IS_COROUTINE))) {
|
||||
KrkInstance * gen = krk_buildGenerator(closure, krk_currentThread.stackTop - argCount, argCount);
|
||||
krk_currentThread.stackTop = krk_currentThread.stackTop - argCount - extra;
|
||||
krk_currentThread.stackTop = krk_currentThread.stackTop - argCount - callableOnStack;
|
||||
krk_push(OBJECT_VAL(gen));
|
||||
return 2;
|
||||
}
|
||||
@ -741,7 +741,7 @@ _finishKwarg:
|
||||
frame->closure = closure;
|
||||
frame->ip = closure->function->chunk.code;
|
||||
frame->slots = (krk_currentThread.stackTop - argCount) - krk_currentThread.stack;
|
||||
frame->outSlots = (krk_currentThread.stackTop - argCount - extra) - krk_currentThread.stack;
|
||||
frame->outSlots = (krk_currentThread.stackTop - argCount - callableOnStack) - krk_currentThread.stack;
|
||||
frame->globals = &closure->function->globalsContext->fields;
|
||||
FRAME_IN(frame);
|
||||
return 1;
|
||||
@ -775,11 +775,11 @@ _errorAfterKeywords:
|
||||
* If callValue returns 0, the VM should already be in the exception state
|
||||
* and it is not necessary to raise another exception.
|
||||
*/
|
||||
int krk_callValue(KrkValue callee, int argCount, int extra) {
|
||||
int krk_callValue(KrkValue callee, int argCount, int callableOnStack) {
|
||||
if (likely(IS_OBJECT(callee))) {
|
||||
switch (OBJECT_TYPE(callee)) {
|
||||
case KRK_OBJ_CLOSURE:
|
||||
return call(AS_CLOSURE(callee), argCount, extra);
|
||||
return call(AS_CLOSURE(callee), argCount, callableOnStack);
|
||||
case KRK_OBJ_NATIVE: {
|
||||
NativeFn native = (NativeFn)AS_NATIVE(callee)->function;
|
||||
if (unlikely(argCount && IS_KWARGS(krk_currentThread.stackTop[-1]))) {
|
||||
@ -791,7 +791,7 @@ int krk_callValue(KrkValue callee, int argCount, int extra) {
|
||||
return 0;
|
||||
}
|
||||
argCount--; /* Because that popped the kwargs value */
|
||||
krk_currentThread.stackTop -= argCount + extra; /* We can just put the stack back to normal */
|
||||
krk_currentThread.stackTop -= argCount + callableOnStack; /* We can just put the stack back to normal */
|
||||
krk_push(myList);
|
||||
krk_push(myDict);
|
||||
krk_currentThread.scratchSpace[0] = NONE_VAL();
|
||||
@ -815,7 +815,7 @@ int krk_callValue(KrkValue callee, int argCount, int extra) {
|
||||
free(stackCopy);
|
||||
}
|
||||
if (unlikely(krk_currentThread.stackTop == krk_currentThread.stack)) return 0;
|
||||
krk_currentThread.stackTop -= argCount + extra;
|
||||
krk_currentThread.stackTop -= argCount + callableOnStack;
|
||||
krk_push(result);
|
||||
}
|
||||
return 2;
|
||||
@ -862,14 +862,23 @@ int krk_callValue(KrkValue callee, int argCount, int extra) {
|
||||
/**
|
||||
* Takes care of runnext/pop
|
||||
*/
|
||||
KrkValue krk_callSimple(KrkValue value, int argCount, int isMethod) {
|
||||
switch (krk_callValue(value, argCount, isMethod)) {
|
||||
KrkValue krk_callStack(int argCount) {
|
||||
switch (krk_callValue(krk_peek(argCount), argCount, 1)) {
|
||||
case 2: return krk_pop();
|
||||
case 1: return krk_runNext();
|
||||
default:
|
||||
if (!IS_NONE(krk_currentThread.currentException)) return NONE_VAL();
|
||||
default: return NONE_VAL();
|
||||
}
|
||||
}
|
||||
|
||||
KrkValue krk_callDirect(KrkObj * callable, int argCount) {
|
||||
if (unlikely(callable->type != KRK_OBJ_CLOSURE && callable->type != KRK_OBJ_NATIVE)) {
|
||||
return krk_runtimeError(vm.exceptions->typeError, "'%s' is not a function.", krk_typeName(OBJECT_VAL(callable)));
|
||||
}
|
||||
switch (krk_callValue(OBJECT_VAL(callable), argCount, 0)) {
|
||||
case 2: return krk_pop();
|
||||
case 1: return krk_runNext();
|
||||
default: return NONE_VAL();
|
||||
}
|
||||
return krk_runtimeError(vm.exceptions->typeError, "Invalid internal method call: '%s'", krk_typeName(value));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -908,7 +917,7 @@ int krk_bindMethod(KrkClass * _class, KrkString * name) {
|
||||
if (type->_descget) {
|
||||
krk_push(method);
|
||||
krk_swap(1);
|
||||
krk_push(krk_callSimple(OBJECT_VAL(type->_descget), 2, 0));
|
||||
krk_push(krk_callDirect(type->_descget, 2));
|
||||
return 1;
|
||||
}
|
||||
out = method;
|
||||
@ -1011,7 +1020,7 @@ int krk_isFalsey(KrkValue value) {
|
||||
/* If it has a length, and that length is 0, it's Falsey */
|
||||
if (type->_len) {
|
||||
krk_push(value);
|
||||
return !AS_INTEGER(krk_callSimple(OBJECT_VAL(type->_len),1,0));
|
||||
return !AS_INTEGER(krk_callDirect(type->_len,1));
|
||||
}
|
||||
return 0; /* Assume anything else is truthy */
|
||||
}
|
||||
@ -1371,7 +1380,7 @@ static KrkValue tryBind(const char * name, KrkValue a, KrkValue b, const char *
|
||||
krk_push(a);
|
||||
if (krk_bindMethod(type, methodName)) {
|
||||
krk_push(b);
|
||||
value = krk_callSimple(krk_peek(1), 1, 1);
|
||||
value = krk_callStack(1);
|
||||
if (!IS_NOTIMPL(value)) goto _success;
|
||||
krk_pop(); /* name */
|
||||
} else {
|
||||
@ -1386,7 +1395,7 @@ static KrkValue tryBind(const char * name, KrkValue a, KrkValue b, const char *
|
||||
krk_push(b);
|
||||
if (krk_bindMethod(type, methodName)) {
|
||||
krk_push(a);
|
||||
value = krk_callSimple(krk_peek(1), 1, 1);
|
||||
value = krk_callStack(1);
|
||||
if (!IS_NOTIMPL(value)) goto _success;
|
||||
krk_pop(); /* name */
|
||||
} else {
|
||||
@ -1718,7 +1727,7 @@ int krk_loadModule(KrkString * path, KrkValue * moduleOut, KrkString * runAs) {
|
||||
krk_push(krk_valueGetAttribute(OBJECT_VAL(path), "replace"));
|
||||
krk_push(OBJECT_VAL(S(PATH_SEP)));
|
||||
krk_push(OBJECT_VAL(S(".")));
|
||||
krk_push(krk_callSimple(krk_peek(2), 2, 1));
|
||||
krk_push(krk_callStack(2));
|
||||
} else {
|
||||
krk_push(OBJECT_VAL(runAs));
|
||||
}
|
||||
@ -1878,7 +1887,7 @@ static int valueGetProperty(KrkString * name) {
|
||||
|
||||
if (objectClass->_getattr) {
|
||||
krk_push(OBJECT_VAL(name));
|
||||
krk_push(krk_callSimple(OBJECT_VAL(objectClass->_getattr), 2, 0));
|
||||
krk_push(krk_callDirect(objectClass->_getattr, 2));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1953,7 +1962,7 @@ static int trySetDescriptor(KrkValue owner, KrkString * name, KrkValue value) {
|
||||
krk_push(property); /* owner value property */
|
||||
krk_swap(2); /* property value owner */
|
||||
krk_swap(1); /* property owner value */
|
||||
krk_push(krk_callSimple(OBJECT_VAL(type->_descset), 3, 0));
|
||||
krk_push(krk_callDirect(type->_descset, 3));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -2078,7 +2087,7 @@ _resumeHook: (void)0;
|
||||
if (IS_INSTANCE(exceptionObject))
|
||||
krk_tableGet_fast(&AS_INSTANCE(exceptionObject)->fields, S("traceback"), &tracebackEntries);
|
||||
krk_push(tracebackEntries);
|
||||
krk_callSimple(OBJECT_VAL(type->_exit), 4, 0);
|
||||
krk_callDirect(type->_exit, 4);
|
||||
/* Top of stack is now either someone else's problem or a return value */
|
||||
if (!(krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION)) {
|
||||
krk_pop(); /* Handler object */
|
||||
@ -2090,7 +2099,7 @@ _resumeHook: (void)0;
|
||||
krk_push(NONE_VAL());
|
||||
krk_push(NONE_VAL());
|
||||
krk_push(NONE_VAL());
|
||||
krk_callSimple(OBJECT_VAL(type->_exit), 4, 0);
|
||||
krk_callDirect(type->_exit, 4);
|
||||
if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) goto _finishException;
|
||||
}
|
||||
if (AS_HANDLER_TYPE(handler) != OP_RETURN) break;
|
||||
@ -2182,7 +2191,7 @@ _finishReturn: (void)0;
|
||||
case OP_POP: krk_pop(); break;
|
||||
case OP_RAISE: {
|
||||
if (IS_CLASS(krk_peek(0))) {
|
||||
krk_currentThread.currentException = krk_callSimple(krk_peek(0), 0, 1);
|
||||
krk_currentThread.currentException = krk_callStack(0);
|
||||
} else {
|
||||
krk_currentThread.currentException = krk_pop();
|
||||
}
|
||||
@ -2197,9 +2206,9 @@ _finishReturn: (void)0;
|
||||
case OP_INVOKE_GETTER: {
|
||||
KrkClass * type = krk_getType(krk_peek(1));
|
||||
if (likely(type->_getter != NULL)) {
|
||||
krk_push(krk_callSimple(OBJECT_VAL(type->_getter), 2, 0));
|
||||
krk_push(krk_callDirect(type->_getter, 2));
|
||||
} else if (IS_CLASS(krk_peek(1)) && AS_CLASS(krk_peek(1))->_classgetitem) {
|
||||
krk_push(krk_callSimple(OBJECT_VAL(AS_CLASS(krk_peek(1))->_classgetitem), 2, 0));
|
||||
krk_push(krk_callDirect(AS_CLASS(krk_peek(1))->_classgetitem, 2));
|
||||
} else {
|
||||
krk_runtimeError(vm.exceptions->attributeError, "'%s' object is not subscriptable", krk_typeName(krk_peek(1)));
|
||||
}
|
||||
@ -2208,7 +2217,7 @@ _finishReturn: (void)0;
|
||||
case OP_INVOKE_SETTER: {
|
||||
KrkClass * type = krk_getType(krk_peek(2));
|
||||
if (likely(type->_setter != NULL)) {
|
||||
krk_push(krk_callSimple(OBJECT_VAL(type->_setter), 3, 0));
|
||||
krk_push(krk_callDirect(type->_setter, 3));
|
||||
} else {
|
||||
if (type->_getter) {
|
||||
krk_runtimeError(vm.exceptions->attributeError, "'%s' object is not mutable", krk_typeName(krk_peek(2)));
|
||||
@ -2221,7 +2230,7 @@ _finishReturn: (void)0;
|
||||
case OP_INVOKE_GETSLICE: {
|
||||
KrkClass * type = krk_getType(krk_peek(2));
|
||||
if (likely(type->_getslice != NULL)) {
|
||||
krk_push(krk_callSimple(OBJECT_VAL(type->_getslice), 3, 0));
|
||||
krk_push(krk_callDirect(type->_getslice, 3));
|
||||
} else {
|
||||
krk_runtimeError(vm.exceptions->attributeError, "'%s' object is not sliceable", krk_typeName(krk_peek(2)));
|
||||
}
|
||||
@ -2230,7 +2239,7 @@ _finishReturn: (void)0;
|
||||
case OP_INVOKE_SETSLICE: {
|
||||
KrkClass * type = krk_getType(krk_peek(3));
|
||||
if (likely(type->_setslice != NULL)) {
|
||||
krk_push(krk_callSimple(OBJECT_VAL(type->_setslice), 4, 0));
|
||||
krk_push(krk_callDirect(type->_setslice, 4));
|
||||
} else {
|
||||
krk_runtimeError(vm.exceptions->attributeError, "'%s' object is not sliceable", krk_typeName(krk_peek(3)));
|
||||
}
|
||||
@ -2239,7 +2248,7 @@ _finishReturn: (void)0;
|
||||
case OP_INVOKE_DELSLICE: {
|
||||
KrkClass * type = krk_getType(krk_peek(2));
|
||||
if (likely(type->_delslice != NULL)) {
|
||||
krk_callSimple(OBJECT_VAL(type->_delslice), 3, 0);
|
||||
krk_callDirect(type->_delslice, 3);
|
||||
} else {
|
||||
krk_runtimeError(vm.exceptions->attributeError, "'%s' object is not sliceable", krk_typeName(krk_peek(2)));
|
||||
}
|
||||
@ -2248,7 +2257,7 @@ _finishReturn: (void)0;
|
||||
case OP_INVOKE_DELETE: {
|
||||
KrkClass * type = krk_getType(krk_peek(1));
|
||||
if (likely(type->_delitem != NULL)) {
|
||||
krk_callSimple(OBJECT_VAL(type->_delitem), 2, 0);
|
||||
krk_callDirect(type->_delitem, 2);
|
||||
} else {
|
||||
if (type->_getter) {
|
||||
krk_runtimeError(vm.exceptions->attributeError, "'%s' object is not mutable", krk_typeName(krk_peek(1)));
|
||||
@ -2261,7 +2270,7 @@ _finishReturn: (void)0;
|
||||
case OP_INVOKE_ITER: {
|
||||
KrkClass * type = krk_getType(krk_peek(0));
|
||||
if (likely(type->_iter != NULL)) {
|
||||
krk_push(krk_callSimple(OBJECT_VAL(type->_iter), 1, 0));
|
||||
krk_push(krk_callDirect(type->_iter, 1));
|
||||
} else {
|
||||
krk_runtimeError(vm.exceptions->attributeError, "'%s' object is not iterable", krk_typeName(krk_peek(0)));
|
||||
}
|
||||
@ -2271,7 +2280,7 @@ _finishReturn: (void)0;
|
||||
KrkClass * type = krk_getType(krk_peek(0));
|
||||
if (likely(type->_contains != NULL)) {
|
||||
krk_swap(1);
|
||||
krk_push(krk_callSimple(OBJECT_VAL(type->_contains), 2, 0));
|
||||
krk_push(krk_callDirect(type->_contains, 2));
|
||||
} else {
|
||||
krk_runtimeError(vm.exceptions->attributeError, "'%s' object can not be tested for membership", krk_typeName(krk_peek(0)));
|
||||
}
|
||||
@ -2440,7 +2449,7 @@ _finishReturn: (void)0;
|
||||
goto _finishException;
|
||||
}
|
||||
krk_push(contextManager);
|
||||
krk_callSimple(OBJECT_VAL(type->_enter), 1, 0);
|
||||
krk_callDirect(type->_enter, 1);
|
||||
/* Ignore result; don't need to pop */
|
||||
krk_push(NONE_VAL());
|
||||
KrkValue handler = HANDLER_VAL(OP_PUSH_WITH, cleanupTarget);
|
||||
@ -2456,11 +2465,11 @@ _finishReturn: (void)0;
|
||||
if (!IS_NONE(method)) {
|
||||
krk_push(method);
|
||||
krk_swap(1);
|
||||
krk_push(krk_callSimple(krk_peek(1),1,0));
|
||||
krk_push(krk_callStack(1));
|
||||
} else {
|
||||
krk_pop();
|
||||
krk_push(krk_peek(0));
|
||||
krk_push(krk_callSimple(krk_peek(0),0,0));
|
||||
krk_push(krk_callStack(0));
|
||||
}
|
||||
if (!krk_valuesSame(krk_peek(0), krk_peek(1))) {
|
||||
/* Value to yield */
|
||||
@ -2475,7 +2484,7 @@ _finishReturn: (void)0;
|
||||
krk_push(method);
|
||||
krk_swap(1);
|
||||
krk_pop();
|
||||
krk_push(krk_callSimple(krk_peek(0),0,0));
|
||||
krk_push(krk_callStack(0));
|
||||
} else {
|
||||
krk_pop();
|
||||
krk_push(NONE_VAL());
|
||||
@ -2488,7 +2497,7 @@ _finishReturn: (void)0;
|
||||
uint16_t offset = OPERAND;
|
||||
KrkValue iter = krk_peek(0);
|
||||
krk_push(iter);
|
||||
krk_push(krk_callSimple(iter, 0, 1));
|
||||
krk_push(krk_callStack(0));
|
||||
if (krk_valuesSame(iter, krk_peek(0))) frame->ip += offset;
|
||||
break;
|
||||
}
|
||||
@ -2570,16 +2579,14 @@ _finishReturn: (void)0;
|
||||
THREE_BYTE_OPERAND;
|
||||
case OP_SET_LOCAL: {
|
||||
ONE_BYTE_OPERAND;
|
||||
uint32_t slot = OPERAND;
|
||||
krk_currentThread.stack[frame->slots + slot] = krk_peek(0);
|
||||
krk_currentThread.stack[frame->slots + OPERAND] = krk_peek(0);
|
||||
break;
|
||||
}
|
||||
case OP_CALL_LONG:
|
||||
THREE_BYTE_OPERAND;
|
||||
case OP_CALL: {
|
||||
ONE_BYTE_OPERAND;
|
||||
int argCount = OPERAND;
|
||||
if (unlikely(!krk_callValue(krk_peek(argCount), argCount, 1))) goto _finishException;
|
||||
if (unlikely(!krk_callValue(krk_peek(OPERAND), OPERAND, 1))) goto _finishException;
|
||||
frame = &krk_currentThread.frames[krk_currentThread.frameCount - 1];
|
||||
break;
|
||||
}
|
||||
@ -2587,8 +2594,7 @@ _finishReturn: (void)0;
|
||||
THREE_BYTE_OPERAND;
|
||||
case OP_EXPAND_ARGS: {
|
||||
ONE_BYTE_OPERAND;
|
||||
int type = OPERAND;
|
||||
krk_push(KWARGS_VAL(KWARGS_SINGLE-type));
|
||||
krk_push(KWARGS_VAL(KWARGS_SINGLE-OPERAND));
|
||||
break;
|
||||
}
|
||||
case OP_CLOSURE_LONG:
|
||||
@ -2618,16 +2624,14 @@ _finishReturn: (void)0;
|
||||
THREE_BYTE_OPERAND;
|
||||
case OP_GET_UPVALUE: {
|
||||
ONE_BYTE_OPERAND;
|
||||
int slot = OPERAND;
|
||||
krk_push(*UPVALUE_LOCATION(frame->closure->upvalues[slot]));
|
||||
krk_push(*UPVALUE_LOCATION(frame->closure->upvalues[OPERAND]));
|
||||
break;
|
||||
}
|
||||
case OP_SET_UPVALUE_LONG:
|
||||
THREE_BYTE_OPERAND;
|
||||
case OP_SET_UPVALUE: {
|
||||
ONE_BYTE_OPERAND;
|
||||
int slot = OPERAND;
|
||||
*UPVALUE_LOCATION(frame->closure->upvalues[slot]) = krk_peek(0);
|
||||
*UPVALUE_LOCATION(frame->closure->upvalues[OPERAND]) = krk_peek(0);
|
||||
break;
|
||||
}
|
||||
case OP_CLASS_LONG:
|
||||
@ -2883,12 +2887,12 @@ _finishReturn: (void)0;
|
||||
}
|
||||
/* Create the iterator */
|
||||
krk_push(krk_currentThread.stack[stackStart]);
|
||||
krk_push(krk_callSimple(OBJECT_VAL(type->_iter), 1, 0));
|
||||
krk_push(krk_callDirect(type->_iter, 1));
|
||||
|
||||
do {
|
||||
/* Call it until it gives us itself */
|
||||
krk_push(krk_currentThread.stackTop[-1]);
|
||||
krk_push(krk_callSimple(krk_peek(0), 0, 1));
|
||||
krk_push(krk_callStack(0));
|
||||
if (krk_valuesSame(krk_currentThread.stackTop[-2], krk_currentThread.stackTop[-1])) {
|
||||
/* We're done. */
|
||||
krk_pop(); /* The result of iteration */
|
||||
|
@ -36,7 +36,7 @@ int main(int argc, char * argv[]) {
|
||||
KrkClass * type = krk_getType(result);
|
||||
if (type->_reprer) {
|
||||
krk_push(result);
|
||||
result = krk_callSimple(OBJECT_VAL(type->_reprer), 1, 0);
|
||||
result = krk_callDirect(type->_reprer, 1);
|
||||
}
|
||||
if (IS_STRING(result)) {
|
||||
fprintf(stdout, " => %s\n", AS_CSTRING(result));
|
||||
|
@ -105,10 +105,10 @@ static int runSimpleRepl(void) {
|
||||
const char * formatStr = " \033[1;30m=> %s\033[0m\n";
|
||||
if (type->_reprer) {
|
||||
krk_push(result);
|
||||
result = krk_callSimple(OBJECT_VAL(type->_reprer), 1, 0);
|
||||
result = krk_callDirect(type->_reprer, 1);
|
||||
} else if (type->_tostr) {
|
||||
krk_push(result);
|
||||
result = krk_callSimple(OBJECT_VAL(type->_tostr), 1, 0);
|
||||
result = krk_callDirect(type->_tostr, 1);
|
||||
}
|
||||
if (!IS_STRING(result)) {
|
||||
fprintf(stdout, " \033[1;31m=> Unable to produce representation for value.\033[0m\n");
|
||||
|
Loading…
Reference in New Issue
Block a user