vm.c
77 KrkCallFrame * caller = krk_currentThread.frameCount > 1 ? &krk_currentThread.frames[krk_currentThread.frameCount-2] : NULL;
92 caller ? (caller->closure->function->qualname ? caller->closure->function->qualname->chars : caller->closure->function->name->chars) : "(root)",
94 caller ? ((int)krk_lineNumber(&caller->closure->function->chunk, caller->ip - caller->closure->function->chunk.code)) : 1,
96 frame->closure->function->qualname ? frame->closure->function->qualname->chars : frame->closure->function->name->chars,
101 # define FRAME_IN(frame) if (unlikely(vm.globalFlags & KRK_GLOBAL_CALLGRIND)) { _frame_in(frame); }
102 # define FRAME_OUT(frame) if (unlikely(vm.globalFlags & KRK_GLOBAL_CALLGRIND)) { _frame_out(frame); }
203 KrkClass * krk_makeClass(KrkInstance * module, KrkClass ** _class, const char * name, KrkClass * base) {
253 if (_base && (IS_CLOSURE(tmp) || IS_NATIVE(tmp)) && (!(AS_OBJECT(tmp)->flags & KRK_OBJ_FLAGS_FUNCTION_IS_STATIC_METHOD) || entry->index == METHOD_NEW)) {
345 (destination < closure->function->potentialPositionals ? AS_STRING(closure->function->positionalArgNames.values[destination]) :
346 (destination - closure->function->potentialPositionals < closure->function->keywordArgs ? AS_STRING(closure->function->keywordArgNames.values[destination - closure->function->potentialPositionals]) :
378 int krk_processComplexArguments(int argCount, KrkValueArray * positionals, KrkTable * keywords, const char * name) {
389 size_t startOfExtras = &krk_currentThread.stackTop[-kwargsCount * 2 - TOP_ARGS] - krk_currentThread.stack;
410 krk_runtimeError(vm.exceptions->typeError, "%s() got multiple values for argument '%S'", name, AS_STRING(entry->key));
420 krk_runtimeError(vm.exceptions->typeError, "%s() got multiple values for argument '%S'", name, AS_STRING(key));
456 /* This processes the existing argument list into a ValueArray and a Table with the args and keywords */
457 if (!krk_processComplexArguments(argCount, positionals, keywords, closure->function->name ? closure->function->name->chars : "<unnamed>")) return 0;
473 if ((positionals->count > potentialPositionalArgs) && !(closure->function->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_COLLECTS_ARGS)) {
501 size_t count = (positionals->count > potentialPositionalArgs) ? (positionals->count - potentialPositionalArgs) : 0;
535 if (!IS_KWARGS(krk_currentThread.stackTop[-argCount + j + closure->function->potentialPositionals + !!(closure->function->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_COLLECTS_ARGS)])) {
539 krk_currentThread.stackTop[-argCount + j + closure->function->potentialPositionals + !!(closure->function->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_COLLECTS_ARGS)] = value;
583 argCountX = argCount - closure->function->keywordArgs - (!!(closure->function->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_COLLECTS_ARGS) + !!(closure->function->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_COLLECTS_KWS));
584 } else if ((size_t)argCount > potentialPositionalArgs && (closure->function->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_COLLECTS_ARGS)) {
602 if (unlikely(closure->function->obj.flags & (KRK_OBJ_FLAGS_CODEOBJECT_IS_GENERATOR | KRK_OBJ_FLAGS_CODEOBJECT_IS_COROUTINE))) {
603 KrkInstance * gen = krk_buildGenerator(closure, krk_currentThread.stackTop - argCount, argCount);
637 inline KrkValue krk_callNativeOnStack(size_t argCount, const KrkValue *stackArgs, int hasKw, NativeFn native) {
668 memmove(&krk_currentThread.stackTop[-argCount],&krk_currentThread.stackTop[-argCount-1],sizeof(KrkValue) * argCount);
673 size_t stackOffsetAfterCall = (krk_currentThread.stackTop - krk_currentThread.stack) - argCount - returnDepth;
684 if (unlikely(!krk_processComplexArguments(argCount, AS_LIST(myList), AS_DICT(myDict), callee->name))) return 0;
748 return (_class->_call->type == KRK_OBJ_CLOSURE) ? _callManaged((KrkClosure*)_class->_call, argCount, returnDepth) : _callNative((KrkNative*)_class->_call, argCount, returnDepth);
807 #define UPVALUE_LOCATION(upvalue) (upvalue->location == -1 ? &upvalue->closed : &upvalue->owner->stack[upvalue->location])
814 while (krk_currentThread.openUpvalues != NULL && krk_currentThread.openUpvalues->location >= last) {
1046 static KrkValue _bin_op(size_t methodOffset, size_t invOffset, const char * operator, KrkValue a, KrkValue b) {
1104 return krk_runtimeError(vm.exceptions->typeError, "bad operand type for unary %s: '%T'", operator, value);
1129 int exitSlot = (krk_currentThread.exitOnFrame >= 0) ? krk_currentThread.frames[krk_currentThread.exitOnFrame].outSlots : 0;
1159 for (frameOffset = krk_currentThread.frameCount - 1; frameOffset >= 0 && (int)krk_currentThread.frames[frameOffset].slots > stackOffset; frameOffset--);
1183 int krk_loadModule(KrkString * path, KrkValue * moduleOut, KrkString * runAs, KrkValue parent) {
1202 krk_runtimeError(vm.exceptions->importError, "kuroko.module_paths must be a list, not '%T'", modulePaths);
1256 krk_runtimeError(vm.exceptions->importError, "No module named '%S'; '%S' is a package and cannot be executed directly",
1310 if (IS_INSTANCE(parent) && krk_tableGet_fast(&AS_INSTANCE(parent)->fields, S("__name__"), &parentName) && IS_STRING(parentName)) {
1436 if (!krk_tableGet_fast(&krk_currentThread.module->fields, S("__package__"), &packageName) || !IS_STRING(packageName)) {
1438 krk_runtimeError(vm.exceptions->importError, "attempted relative import without a package context");
1488 krk_runtimeError(vm.exceptions->importError, "attempted relative import beyond top-level package");
1543 KrkValue listOut = krk_string_split(3,(KrkValue[]){krk_currentThread.stack[argBase+3], krk_currentThread.stack[argBase+4], INTEGER_VAL(1)}, 0);
1571 if (!krk_loadModule(AS_STRING(krk_currentThread.stack[argBase+1]), ¤t, runAs, krk_currentThread.stack[argBase-1])) return 0;
1576 krk_tableSet(&AS_INSTANCE(krk_currentThread.stack[argBase-1])->fields, krk_currentThread.stack[argBase+0], krk_peek(0));
1582 if (!krk_loadModule(AS_STRING(krk_currentThread.stack[argBase+1]), ¤t, AS_STRING(krk_currentThread.stack[argBase+2]),NONE_VAL())) return 0;
1585 krk_tableSet(&AS_INSTANCE(krk_currentThread.stack[argBase-1])->fields, krk_currentThread.stack[argBase+0], krk_peek(0));
1589 if (!krk_tableGet_fast(&AS_INSTANCE(current)->fields, S("__ispackage__"), &tmp) || !IS_BOOLEAN(tmp) || AS_BOOLEAN(tmp) != 1) {
1590 krk_runtimeError(vm.exceptions->importError, "'%S' is not a package", AS_STRING(krk_currentThread.stack[argBase+2]));
1669 } else if (IS_NONE(krk_peek(0)) || (AS_OBJECT(method)->flags & KRK_OBJ_FLAGS_FUNCTION_IS_STATIC_METHOD)) {
1720 if ((IS_NATIVE(value) || IS_CLOSURE(value)) && (AS_OBJECT(value)->flags & KRK_OBJ_FLAGS_FUNCTION_IS_CLASS_METHOD)) {
1791 krk_currentThread.stackTop[-2] = OBJECT_VAL(krk_newBoundMethod(krk_currentThread.stackTop[-2], AS_OBJECT(krk_currentThread.stackTop[-1])));
1807 return krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%s'", krk_peek(0), name);
1867 return krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%s'", krk_peek(0), name);
1889 static KrkValue setAttr_wrapper(KrkValue owner, KrkClass * _class, KrkTable * fields, KrkString * name, KrkValue to) {
1897 return setAttr_wrapper(owner, AS_INSTANCE(owner)->_class, &AS_INSTANCE(owner)->fields, name, to);
1911 krk_currentThread.stackTop[-1] = setAttr_wrapper(owner,type,&AS_INSTANCE(owner)->fields, name, value);
1913 krk_currentThread.stackTop[-1] = setAttr_wrapper(owner,type,&AS_CLASS(owner)->methods, name, value);
1920 krk_currentThread.stackTop[-1] = setAttr_wrapper(owner,type,&AS_CLOSURE(owner)->fields, name, value);
1943 return krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%s'", krk_peek(1), name);
1962 if (likely(IS_INTEGER(a) && IS_INTEGER(b))) a = krk_int_op_ ## op (AS_INTEGER(a), AS_INTEGER(b)); \
1967 #define LIKELY_INT_COMPARE_OP(op,operator) { KrkValue b = krk_peek(0); KrkValue a = krk_peek(1); \
1968 if (likely(IS_INTEGER(a) && IS_INTEGER(b))) a = BOOLEAN_VAL(AS_INTEGER(a) operator AS_INTEGER(b)); \
2018 KrkValue collection = krk_callNativeOnStack(count, &krk_currentThread.stackTop[-count], 0, func);
2078 krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%s'", krk_peek(1), "__format__");
2115 if (unlikely(krk_currentThread.flags & (KRK_THREAD_ENABLE_TRACING | KRK_THREAD_SINGLE_STEP | KRK_THREAD_SIGNALLED))) {
2144 /* Only GCC lets us put these on empty statements; just hope clang doesn't start complaining */
2152 #define THREE_BYTE_OPERAND { OPERAND = (frame->ip[0] << 16) | (frame->ip[1] << 8); frame->ip += 2; } FALLTHROUGH
2157 /* Top of stack is a HANDLER that should have had something loaded into it if it was still valid */
2220 if (frame->closure->function->obj.flags & (KRK_OBJ_FLAGS_CODEOBJECT_IS_GENERATOR | KRK_OBJ_FLAGS_CODEOBJECT_IS_COROUTINE)) {
2290 commonMethodInvoke(offsetof(KrkClass,_setter), 3, "'%T' object doesn't support item assignment");
2294 commonMethodInvoke(offsetof(KrkClass,_delitem), 2, "'%T' object doesn't support item deletion");
2304 commonMethodInvoke(offsetof(KrkClass,_contains), 2, "'%T' object can not be tested for membership");
2326 if (IS_CLASS(AS_TUPLE(krk_peek(0))->values.values[i]) && krk_isInstanceOf(krk_peek(2), AS_CLASS(AS_TUPLE(krk_peek(0))->values.values[i]))) {
2737 if (!krk_tableGet(&AS_INSTANCE(krk_peek(0))->fields, vm.specialMethodNames[METHOD_NAME], &moduleName)) {
2738 krk_runtimeError(vm.exceptions->importError, "Can not import '%S' from non-module '%T' object", name, krk_peek(0));
2748 krk_runtimeError(vm.exceptions->importError, "Can not import '%S' from '%S'", name, AS_STRING(moduleName));
2761 krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%S'", krk_peek(0), name);
2772 krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%S'", krk_peek(0), name);
2783 krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%S'", krk_peek(1), name);
2796 commonMethodInvoke(offsetof(KrkClass,_setter), 3, "'%T' object doesn't support item assignment");
2805 commonMethodInvoke(offsetof(KrkClass,_getter), 2, "'%T' object doesn't support item assignment");
2842 KrkClass * superclass = AS_CLASS(baseClass)->base ? AS_CLASS(baseClass)->base : vm.baseClasses->objectClass;
2865 krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%S'", krk_peek(0), name);
3019 krk_runtimeError(vm.exceptions->valueError, "not enough values to unpack (expected %u, got %zu)", OPERAND, values->values.count);
3100 krk_runtimeError(vm.exceptions->typeError, "not enough values to unpack (expected at least %u, got %zu)",
3110 krk_runtimeError(vm.exceptions->typeError, "not enough values to unpack (expected at least %u, got %zu)",
3185 krk_attachNamedObject(&module->fields, "__name__", (KrkObj*)krk_copyString(name,strlen(name)));
3198 krk_attachNamedObject(&krk_currentThread.module->fields, "__file__", (KrkObj*)function->chunk.filename);
KrkCodeObject * krk_compile(const char *src, char *fileName)
Compile a source string to bytecode.
Definition: compiler.c:3986
Exported methods for the source compiler.
Functions for debugging bytecode execution.
int krk_debugBreakpointHandler(void)
Called by the VM when a breakpoint is encountered.
Definition: debug.c:583
size_t krk_disassembleInstruction(FILE *f, KrkCodeObject *func, size_t offset)
Print a disassembly of a single opcode instruction.
Definition: debug.c:248
void krk_debug_dumpStack(FILE *f, KrkCallFrame *frame)
Print the elements on the stack.
Definition: debug.c:22
_noexport void _createAndBind_exceptions(void)
Bind native methods and classes for exceptions.
Definition: exceptions.c:184
void krk_attachInnerException(KrkValue innerException)
Attach an inner exception to the current exception object.
Definition: exceptions.c:408
void krk_raiseException(KrkValue base, KrkValue cause)
Raise an exception value.
Definition: exceptions.c:420
KrkValue krk_runtimeError(KrkClass *type, const char *fmt,...)
Produce and raise an exception with a formatted message.
Definition: exceptions.c:445
void krk_dumpTraceback(void)
If there is an active exception, print a traceback to stderr.
Definition: exceptions.c:351
Functions for dealing with garbage collection and memory allocation.
Struct definitions for core object types.
Internal header.
KrkSpecialMethods
Index numbers for always-available interned strings representing important method and member names.
Definition: private.h:38
A function that has been attached to an object to serve as a method.
Definition: object.h:269
KrkBoundMethod * krk_newBoundMethod(KrkValue receiver, KrkObj *method)
Create a new bound method.
Definition: object.c:346
size_t krk_lineNumber(KrkChunk *chunk, size_t offset)
Obtain the line number for a byte offset into a bytecode chunk.
Definition: chunk.c:74
Definition: vm.c:1613
KrkObj * _descget
__get__ Called when a descriptor object is bound as a property
Definition: object.h:216
KrkClass * krk_newClass(KrkString *name, KrkClass *base)
Create a new class object.
Definition: object.c:320
KrkObj * _reprer
__repr__ Called to create a reproducible string representation of an instance
Definition: object.h:203
KrkObj * _len
__len__ Generally called by len() but may be used to determine truthiness
Definition: object.h:208
KrkClass * krk_makeClass(KrkInstance *module, KrkClass **_class, const char *name, KrkClass *base)
Convenience function for creating new types.
Definition: vm.c:203
KrkObj * _descset
__set__ Called when a descriptor object is assigned to as a property
Definition: object.h:217
void krk_finalizeClass(KrkClass *_class)
Finalize a class by collecting pointers to core methods.
int krk_bindMethod(KrkClass *_class, KrkString *name)
Perform method binding on the stack.
Definition: vm.c:1691
KrkObj * _hash
__hash__ Called when an instance is a key in a dict or an entry in a set
Definition: object.h:219
int krk_bindMethodSuper(KrkClass *baseClass, KrkString *name, KrkClass *realClass)
Bind a method with super() semantics.
Definition: vm.c:1662
KrkCodeObject * function
The codeobject containing the bytecode run when this function is called.
Definition: object.h:171
KrkClosure * krk_newClosure(KrkCodeObject *function, KrkValue globals)
Create a new function object.
Definition: object.c:286
KrkUpvalue ** upvalues
Array of upvalues collected from the surrounding context when the closure was created.
Definition: object.h:172
KrkInstance * krk_buildGenerator(KrkClosure *function, KrkValue *arguments, size_t argCount)
Convert a function into a generator with the given arguments.
Definition: obj_gen.c:82
unsigned short potentialPositionals
Precalculated positional arguments for complex argument processing.
Definition: object.h:148
KrkValueArray positionalArgNames
Array of names for positional arguments (and *args)
Definition: object.h:154
KrkLocalEntry * localNames
Stores the names of local variables used in the function, for debugging.
Definition: object.h:158
KrkValueArray keywordArgNames
Array of names for keyword-only arguments (and **kwargs)
Definition: object.h:155
unsigned short totalArguments
Total argument cells we can fill in complex argument processing.
Definition: object.h:149
KrkValue krk_dict_of(int argc, const KrkValue argv[], int hasKw)
Create a dict object.
Definition: obj_dict.c:11
KrkInstance * krk_newInstance(KrkClass *_class)
Create a new instance of the given class.
Definition: object.c:339
KrkValue krk_list_of(int argc, const KrkValue argv[], int hasKw)
Create a list object.
Definition: obj_list.c:30
KrkNative * krk_newNative(NativeFn function, const char *name, int type)
Create a native function binding object.
Definition: object.c:277
KrkValue krk_slice_of(int argc, const KrkValue argv[], int hasKw)
Create a slice object.
Definition: obj_slice.c:14
KrkString * krk_copyString(const char *chars, size_t length)
Obtain a string object representation of the given C string.
Definition: object.c:221
int krk_tableGet(KrkTable *table, KrkValue key, KrkValue *value)
Obtain the value associated with a key in a table.
Definition: table.c:178
int krk_tableDelete(KrkTable *table, KrkValue key)
Remove a key from a hash table.
Definition: table.c:208
int krk_tableSet(KrkTable *table, KrkValue key, KrkValue value)
Assign a value to a key in a table.
Definition: table.c:145
void krk_attachNamedObject(KrkTable *table, const char name[], KrkObj *obj)
Attach an object to an attribute table.
Definition: vm.c:839
KrkNative * krk_defineNative(KrkTable *table, const char *name, NativeFn function)
Attach a native C function to an attribute table.
Definition: vm.c:194
void krk_attachNamedValue(KrkTable *table, const char name[], KrkValue obj)
Attach a value to an attribute table.
Definition: vm.c:825
void krk_tableAddAll(KrkTable *from, KrkTable *to)
Add all key-value pairs from 'from' into 'to'.
Definition: table.c:169
void krk_freeTable(KrkTable *table)
Release resources associated with a hash table.
Definition: table.c:20
int krk_tableGet_fast(KrkTable *table, struct KrkString *str, KrkValue *value)
Obtain the value associated with a string key in a table.
Definition: table.c:189
int krk_tableSetIfExists(KrkTable *table, KrkValue key, KrkValue value)
Update the value of a table entry only if it is found.
Definition: table.c:159
KrkValueArray values
Stores the length, capacity, and actual values of the tuple.
Definition: object.h:299
KrkValue krk_tuple_of(int argc, const KrkValue argv[], int hasKw)
Create a tuple object.
Definition: obj_tuple.c:40
void krk_writeValueArray(KrkValueArray *array, KrkValue value)
Add a value to a value array.
Definition: value.c:17
Stack reference or primative value.
int krk_callValue(KrkValue callee, int argCount, int callableOnStack)
Call a callable value in the current stack context.
Definition: vm.c:722
KrkValue krk_valueSetAttribute(KrkValue owner, char *name, KrkValue to)
Set a property of an object by name.
Definition: vm.c:1938
int krk_isInstanceOf(KrkValue obj, const KrkClass *type)
Determine if a class is an instance or subclass of a given type.
Definition: vm.c:317
int krk_valuesEqual(KrkValue a, KrkValue b)
Compare two values for equality.
KrkValue krk_valueDelAttribute(KrkValue owner, char *name)
Delete a property of an object by name.
Definition: vm.c:1863
KrkValue krk_valueGetAttribute(KrkValue value, char *name)
Obtain a property of an object by name.
Definition: vm.c:1803
KrkValue krk_set_of(int argc, const KrkValue argv[], int hasKw)
Create a set object.
Definition: obj_set.c:346
Implementation of a generic hash table.
Utilities for creating native bindings.
int krk_unpackIterable(KrkValue iterable, void *context, int callback(void *, const KrkValue *, size_t))
Unpack an iterable.
Definition: builtins.c:380
Core API for the bytecode virtual machine.
int krk_getAttribute(KrkString *name)
Implementation of the GET_PROPERTY instruction.
Definition: vm.c:1799
int krk_importModule(KrkString *name, KrkString *runAs)
Load the dotted name name with the final element as runAs.
Definition: vm.c:1414
void krk_resetStack(void)
Reset the current thread's stack state to the top level.
Definition: vm.c:124
int krk_setAttribute(KrkString *name)
Implementation of the SET_PROPERTY instruction.
Definition: vm.c:1934
void krk_module_init_threading(void)
Initialize the built-in 'threading' module.
Definition: threads.c:202
KrkValue krk_callStack(int argCount)
Call a callable on the stack with argCount arguments.
Definition: vm.c:763
KrkThreadState * krk_getCurrentThread(void)
Get a pointer to the current thread state.
Definition: vm.c:115
int krk_delAttribute(KrkString *name)
Implementation of the DEL_PROPERTY instruction.
Definition: vm.c:1859
KrkValue krk_callNativeOnStack(size_t argCount, const KrkValue *stackArgs, int hasKw, NativeFn native)
Call a native function using a reference to stack arguments safely.
Definition: vm.c:637
int krk_loadModule(KrkString *path, KrkValue *moduleOut, KrkString *runAs, KrkValue parent)
Load a module from a file with a specified name.
Definition: vm.c:1183
KrkValue krk_valueGetAttribute_default(KrkValue value, char *name, KrkValue defaultVal)
See krk_valueGetAttribute.
Definition: vm.c:1814
void krk_setMaximumRecursionDepth(size_t maxDepth)
Set the maximum recursion call depth.
Definition: vm.c:894
void krk_swap(int distance)
Swap the top of the stack of the value distance slots down.
Definition: vm.c:184
KrkValue krk_runfile(const char *fileName, char *fromFile)
Load and run a source file and return when execution completes.
Definition: vm.c:3207
KrkInstance * krk_startModule(const char *name)
Set up a new module object in the current thread.
Definition: vm.c:3180
KrkValue krk_callDirect(KrkObj *callable, int argCount)
Call a closure or native function with argCount arguments.
Definition: vm.c:771
KrkValue krk_instanceSetAttribute_wrapper(KrkValue owner, KrkString *name, KrkValue to)
Set an attribute of an instance object, bypassing __setattr__.
Definition: vm.c:1896
#define KRK_CALL_FRAMES_MAX
Maximum depth of the call stack in managed-code function calls.
Definition: vm.h:22
KrkValue krk_interpret(const char *src, char *fromFile)
Compile and execute a source code input.
Definition: vm.c:3190