vm.c
164 KrkClass * krk_makeClass(KrkInstance * module, KrkClass ** _class, const char * name, KrkClass * base) {
211 if (krk_tableGet_fast(&_base->methods, AS_STRING(vm.specialMethodNames[entry->index]), &tmp)) break;
214 if (_base && (IS_CLOSURE(tmp) || IS_NATIVE(tmp)) && (!(AS_OBJECT(tmp)->flags & KRK_OBJ_FLAGS_FUNCTION_IS_STATIC_METHOD) || entry->index == METHOD_NEW)) {
310 (destination < closure->function->potentialPositionals ? AS_STRING(closure->function->positionalArgNames.values[destination]) :
311 (destination - closure->function->potentialPositionals < closure->function->keywordArgs ? AS_STRING(closure->function->keywordArgNames.values[destination - closure->function->potentialPositionals]) :
333 positionals->values = KRK_GROW_ARRAY(KrkValue, positionals->values, old, positionals->capacity);
343 int krk_processComplexArguments(int argCount, KrkValueArray * positionals, KrkTable * keywords, const char * name) {
354 size_t startOfExtras = &krk_currentThread.stackTop[-kwargsCount * 2 - TOP_ARGS] - krk_currentThread.stack;
375 krk_runtimeError(vm.exceptions->typeError, "%s() got multiple values for argument '%S'", name, AS_STRING(entry->key));
385 krk_runtimeError(vm.exceptions->typeError, "%s() got multiple values for argument '%S'", name, AS_STRING(key));
421 /* This processes the existing argument list into a ValueArray and a Table with the args and keywords */
422 if (!krk_processComplexArguments(argCount, positionals, keywords, closure->function->name ? closure->function->name->chars : "<unnamed>")) return 0;
438 if ((positionals->count > potentialPositionalArgs) && !(closure->function->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_COLLECTS_ARGS)) {
466 size_t count = (positionals->count > potentialPositionalArgs) ? (positionals->count - potentialPositionalArgs) : 0;
500 if (!IS_KWARGS(krk_currentThread.stackTop[-argCount + j + closure->function->potentialPositionals + !!(closure->function->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_COLLECTS_ARGS)])) {
504 krk_currentThread.stackTop[-argCount + j + closure->function->potentialPositionals + !!(closure->function->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_COLLECTS_ARGS)] = value;
548 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));
549 } else if ((size_t)argCount > potentialPositionalArgs && (closure->function->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_COLLECTS_ARGS)) {
567 if (unlikely(closure->function->obj.flags & (KRK_OBJ_FLAGS_CODEOBJECT_IS_GENERATOR | KRK_OBJ_FLAGS_CODEOBJECT_IS_COROUTINE))) {
568 KrkInstance * gen = krk_buildGenerator(closure, krk_currentThread.stackTop - argCount, argCount);
601 inline KrkValue krk_callNativeOnStack(size_t argCount, const KrkValue *stackArgs, int hasKw, NativeFn native) {
632 memmove(&krk_currentThread.stackTop[-argCount],&krk_currentThread.stackTop[-argCount-1],sizeof(KrkValue) * argCount);
637 size_t stackOffsetAfterCall = (krk_currentThread.stackTop - krk_currentThread.stack) - argCount - returnDepth;
648 if (unlikely(!krk_processComplexArguments(argCount, AS_LIST(myList), AS_DICT(myDict), callee->name))) return 0;
653 /* Also add a list for storing references that get removed from the kwargs dict during mutation. */
717 return (_class->_call->type == KRK_OBJ_CLOSURE) ? _callManaged((KrkClosure*)_class->_call, argCount, returnDepth) : _callNative((KrkNative*)_class->_call, argCount, returnDepth);
776 #define UPVALUE_LOCATION(upvalue) (upvalue->location == -1 ? &upvalue->closed : &upvalue->owner->stack[upvalue->location])
783 while (krk_currentThread.openUpvalues != NULL && krk_currentThread.openUpvalues->location >= last) {
1007 static KrkValue _bin_op(size_t methodOffset, size_t invOffset, const char * operator, KrkValue a, KrkValue b) {
1065 return krk_runtimeError(vm.exceptions->typeError, "bad operand type for unary %s: '%T'", operator, value);
1090 int exitSlot = (krk_currentThread.exitOnFrame >= 0) ? krk_currentThread.frames[krk_currentThread.exitOnFrame].outSlots : 0;
1122 for (frameOffset = krk_currentThread.frameCount - 1; frameOffset >= 0 && (int)krk_currentThread.frames[frameOffset].slots > stackOffset; frameOffset--);
1146 int krk_loadModule(KrkString * path, KrkValue * moduleOut, KrkString * runAs, KrkValue parent) {
1165 krk_runtimeError(vm.exceptions->importError, "kuroko.module_paths must be a list, not '%T'", modulePaths);
1219 krk_runtimeError(vm.exceptions->importError, "No module named '%S'; '%S' is a package and cannot be executed directly",
1273 if (IS_INSTANCE(parent) && krk_tableGet_fast(&AS_INSTANCE(parent)->fields, S("__name__"), &parentName) && IS_STRING(parentName)) {
1400 if (!krk_tableGet_fast(&krk_currentThread.module->fields, S("__package__"), &packageName) || !IS_STRING(packageName)) {
1402 krk_runtimeError(vm.exceptions->importError, "attempted relative import without a package context");
1452 krk_runtimeError(vm.exceptions->importError, "attempted relative import beyond top-level package");
1507 KrkValue listOut = krk_string_split(3,(KrkValue[]){krk_currentThread.stack[argBase+3], krk_currentThread.stack[argBase+4], INTEGER_VAL(1)}, 0);
1535 if (!krk_loadModule(AS_STRING(krk_currentThread.stack[argBase+1]), ¤t, runAs, krk_currentThread.stack[argBase-1])) return 0;
1540 krk_tableSet(&AS_INSTANCE(krk_currentThread.stack[argBase-1])->fields, krk_currentThread.stack[argBase+0], krk_peek(0));
1546 if (!krk_loadModule(AS_STRING(krk_currentThread.stack[argBase+1]), ¤t, AS_STRING(krk_currentThread.stack[argBase+2]),NONE_VAL())) return 0;
1549 krk_tableSet(&AS_INSTANCE(krk_currentThread.stack[argBase-1])->fields, krk_currentThread.stack[argBase+0], krk_peek(0));
1553 if (!krk_tableGet_fast(&AS_INSTANCE(current)->fields, S("__ispackage__"), &tmp) || !IS_BOOLEAN(tmp) || AS_BOOLEAN(tmp) != 1) {
1554 krk_runtimeError(vm.exceptions->importError, "'%S' is not a package", AS_STRING(krk_currentThread.stack[argBase+2]));
1633 } else if (IS_NONE(krk_peek(0)) || (AS_OBJECT(method)->flags & KRK_OBJ_FLAGS_FUNCTION_IS_STATIC_METHOD)) {
1684 if ((IS_NATIVE(value) || IS_CLOSURE(value)) && (AS_OBJECT(value)->flags & KRK_OBJ_FLAGS_FUNCTION_IS_CLASS_METHOD)) {
1755 KrkValue o = OBJECT_VAL(krk_newBoundMethod(krk_currentThread.stackTop[-2], AS_OBJECT(krk_currentThread.stackTop[-1])));
1773 return krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%s'", krk_peek(0), name);
1833 return krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%s'", krk_peek(0), name);
1855 static KrkValue setAttr_wrapper(KrkValue owner, KrkClass * _class, KrkTable * fields, KrkString * name, KrkValue to) {
1863 return setAttr_wrapper(owner, AS_INSTANCE(owner)->_class, &AS_INSTANCE(owner)->fields, name, to);
1912 return krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%s'", krk_peek(1), name);
1931 if (likely(IS_INTEGER(a) && IS_INTEGER(b))) a = krk_int_op_ ## op (AS_INTEGER(a), AS_INTEGER(b)); \
1936 #define LIKELY_INT_COMPARE_OP(op,operator) { KrkValue b = krk_peek(0); KrkValue a = krk_peek(1); \
1937 if (likely(IS_INTEGER(a) && IS_INTEGER(b))) a = BOOLEAN_VAL(AS_INTEGER(a) operator AS_INTEGER(b)); \
1987 KrkValue collection = krk_callNativeOnStack(count, &krk_currentThread.stackTop[-count], 0, func);
2047 krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%s'", krk_peek(1), "__format__");
2084 if (unlikely(krk_currentThread.flags & (KRK_THREAD_ENABLE_TRACING | KRK_THREAD_SINGLE_STEP | KRK_THREAD_SIGNALLED))) {
2113 /* Only GCC lets us put these on empty statements; just hope clang doesn't start complaining */
2120 #define TWO_BYTE_OPERAND { OPERAND = OPERAND | (frame->ip[0] << 8) | frame->ip[1]; frame->ip += 2; }
2121 #define THREE_BYTE_OPERAND { OPERAND = (frame->ip[0] << 16) | (frame->ip[1] << 8); frame->ip += 2; } FALLTHROUGH
2127 /* Top of stack is a HANDLER that should have had something loaded into it if it was still valid */
2191 if (frame->closure->function->obj.flags & (KRK_OBJ_FLAGS_CODEOBJECT_IS_GENERATOR | KRK_OBJ_FLAGS_CODEOBJECT_IS_COROUTINE)) {
2262 commonMethodInvoke(offsetof(KrkClass,_setter), 3, "'%T' object doesn't support item assignment");
2266 commonMethodInvoke(offsetof(KrkClass,_delitem), 2, "'%T' object doesn't support item deletion");
2276 commonMethodInvoke(offsetof(KrkClass,_contains), 2, "'%T' object can not be tested for membership");
2295 /* We either entered the @c finally without an exception, or the exception was handled by an @c except */
2413 /* Overlong jumps replace 2-byte operand jump instructions with a zero-operand instruction that
2429 krk_tableGet_fast(&vm.builtins->fields, AS_STRING(vm.specialMethodNames[METHOD_BLDCLS]), &build_class);
2439 if (krk_valuesSame(krk_peek(0), BOOLEAN_VAL(0)) || krk_isFalsey(krk_peek(0))) frame->ip += OPERAND;
2445 if (krk_valuesSame(krk_peek(0), BOOLEAN_VAL(0)) || krk_isFalsey(krk_peek(0))) frame->ip += OPERAND;
2557 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]))) {
2753 if (!krk_tableGet(&AS_INSTANCE(krk_peek(0))->fields, vm.specialMethodNames[METHOD_NAME], &moduleName)) {
2754 krk_runtimeError(vm.exceptions->importError, "Can not import '%S' from non-module '%T' object", name, krk_peek(0));
2764 krk_runtimeError(vm.exceptions->importError, "Can not import '%S' from '%S'", name, AS_STRING(moduleName));
2777 krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%S'", krk_peek(0), name);
2788 krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%S'", krk_peek(0), name);
2799 krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%S'", krk_peek(1), name);
2812 commonMethodInvoke(offsetof(KrkClass,_setter), 3, "'%T' object doesn't support item assignment");
2821 commonMethodInvoke(offsetof(KrkClass,_getter), 2, "'%T' object doesn't support item assignment");
2858 KrkClass * superclass = AS_CLASS(baseClass)->base ? AS_CLASS(baseClass)->base : vm.baseClasses->objectClass;
2881 krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%S'", krk_peek(0), name);
3037 krk_runtimeError(vm.exceptions->valueError, "not enough values to unpack (expected %u, got %zu)", OPERAND, values->values.count);
3118 krk_runtimeError(vm.exceptions->typeError, "not enough values to unpack (expected at least %u, got %zu)",
3128 krk_runtimeError(vm.exceptions->typeError, "not enough values to unpack (expected at least %u, got %zu)",
3214 krk_attachNamedObject(&module->fields, "__name__", (KrkObj*)krk_copyString(name,strlen(name)));
3227 krk_attachNamedObject(&krk_currentThread.module->fields, "__file__", (KrkObj*)function->chunk.filename);
KrkCodeObject * krk_compile(const char *src, const char *fileName)
Compile a source string to bytecode.
Definition: compiler.c:4129
Exported methods for the source compiler.
Functions for debugging bytecode execution.
void krk_debug_init(void)
Initialize debugger state. Call exactly once per VM.
Definition: debug.c:699
int krk_debugBreakpointHandler(void)
Called by the VM when a breakpoint is encountered.
Definition: debug.c:663
size_t krk_disassembleInstruction(FILE *f, KrkCodeObject *func, size_t offset)
Print a disassembly of a single opcode instruction.
Definition: debug.c:415
void krk_debug_dumpStack(FILE *f, KrkCallFrame *frame)
Print the elements on the stack.
Definition: debug.c:125
_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:423
void krk_raiseException(KrkValue base, KrkValue cause)
Raise an exception value.
Definition: exceptions.c:435
KrkValue krk_runtimeError(KrkClass *type, const char *fmt,...)
Produce and raise an exception with a formatted message.
Definition: exceptions.c:460
void krk_dumpTraceback(void)
If there is an active exception, print a traceback to stderr.
Definition: exceptions.c:366
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:295
KrkBoundMethod * krk_newBoundMethod(KrkValue receiver, KrkObj *method)
Create a new bound method.
Definition: object.c:350
Definition: vm.c:1577
KrkObj * _descget
__get__ Called when a descriptor object is bound as a property
Definition: object.h:242
KrkClass * krk_newClass(KrkString *name, KrkClass *base)
Create a new class object.
Definition: object.c:324
KrkObj * _reprer
__repr__ Called to create a reproducible string representation of an instance
Definition: object.h:229
KrkObj * _len
__len__ Generally called by len() but may be used to determine truthiness
Definition: object.h:234
KrkClass * krk_makeClass(KrkInstance *module, KrkClass **_class, const char *name, KrkClass *base)
Convenience function for creating new types.
Definition: vm.c:164
KrkObj * _descset
__set__ Called when a descriptor object is assigned to as a property
Definition: object.h:243
void krk_finalizeClass(KrkClass *_class)
Finalize a class by collecting pointers to core methods.
Definition: vm.c:189
int krk_bindMethod(KrkClass *_class, KrkString *name)
Perform method binding on the stack.
Definition: vm.c:1655
KrkObj * _hash
__hash__ Called when an instance is a key in a dict or an entry in a set
Definition: object.h:245
int krk_bindMethodSuper(KrkClass *baseClass, KrkString *name, KrkClass *realClass)
Bind a method with super() semantics.
Definition: vm.c:1626
KrkCodeObject * function
The codeobject containing the bytecode run when this function is called.
Definition: object.h:197
KrkClosure * krk_newClosure(KrkCodeObject *function, KrkValue globals)
Create a new function object.
Definition: object.c:290
KrkUpvalue ** upvalues
Array of upvalues collected from the surrounding context when the closure was created.
Definition: object.h:198
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:167
KrkValueArray positionalArgNames
Array of names for positional arguments (and *args)
Definition: object.h:173
KrkLocalEntry * localNames
Stores the names of local variables used in the function, for debugging.
Definition: object.h:177
KrkValueArray keywordArgNames
Array of names for keyword-only arguments (and **kwargs)
Definition: object.h:174
unsigned short totalArguments
Total argument cells we can fill in complex argument processing.
Definition: object.h:168
KrkValue krk_dict_of(int argc, const KrkValue argv[], int hasKw)
Create a dict object.
Definition: obj_dict.c:19
KrkInstance * krk_newInstance(KrkClass *_class)
Create a new instance of the given class.
Definition: object.c:343
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:281
uint32_t instructionOffset
Instruction (operand offset) this jump target applies to.
Definition: object.h:152
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:224
int krk_tableGet(KrkTable *table, KrkValue key, KrkValue *value)
Obtain the value associated with a key in a table.
Definition: table.c:211
int krk_tableDelete(KrkTable *table, KrkValue key)
Remove a key from a hash table.
Definition: table.c:238
int krk_tableSet(KrkTable *table, KrkValue key, KrkValue value)
Assign a value to a key in a table.
Definition: table.c:148
void krk_attachNamedObject(KrkTable *table, const char name[], KrkObj *obj)
Attach an object to an attribute table.
Definition: vm.c:808
KrkNative * krk_defineNative(KrkTable *table, const char *name, NativeFn function)
Attach a native C function to an attribute table.
Definition: vm.c:155
void krk_attachNamedValue(KrkTable *table, const char name[], KrkValue obj)
Attach a value to an attribute table.
Definition: vm.c:794
void krk_tableAddAll(KrkTable *from, KrkTable *to)
Add all key-value pairs from 'from' into 'to'.
Definition: table.c:202
void krk_freeTable(KrkTable *table)
Release resources associated with a hash table.
Definition: table.c:41
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:219
int krk_tableSetIfExists(KrkTable *table, KrkValue key, KrkValue value)
Update the value of a table entry only if it is found.
Definition: table.c:194
KrkValueArray values
Stores the length, capacity, and actual values of the tuple.
Definition: object.h:325
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:691
KrkValue krk_valueSetAttribute(KrkValue owner, char *name, KrkValue to)
Set a property of an object by name.
Definition: vm.c:1907
int krk_isInstanceOf(KrkValue obj, const KrkClass *type)
Determine if a class is an instance or subclass of a given type.
Definition: vm.c:282
KrkValue krk_valueDelAttribute(KrkValue owner, char *name)
Delete a property of an object by name.
Definition: vm.c:1829
static int krk_valuesSame(KrkValue a, KrkValue b)
Compare two values by identity.
Definition: value.h:141
KrkValue krk_valueGetAttribute(KrkValue value, char *name)
Obtain a property of an object by name.
Definition: vm.c:1769
KrkValue krk_set_of(int argc, const KrkValue argv[], int hasKw)
Create a set object.
Definition: obj_set.c:343
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:387
Core API for the bytecode virtual machine.
int krk_getAttribute(KrkString *name)
Implementation of the GET_PROPERTY instruction.
Definition: vm.c:1765
int krk_importModule(KrkString *name, KrkString *runAs)
Load the dotted name name with the final element as runAs.
Definition: vm.c:1378
void krk_resetStack(void)
Reset the current thread's stack state to the top level.
Definition: vm.c:85
int krk_setAttribute(KrkString *name)
Implementation of the SET_PROPERTY instruction.
Definition: vm.c:1903
void krk_module_init_threading(void)
Initialize the built-in 'threading' module.
Definition: threads.c:207
KrkValue krk_callStack(int argCount)
Call a callable on the stack with argCount arguments.
Definition: vm.c:732
KrkThreadState * krk_getCurrentThread(void)
Get a pointer to the current thread state.
int krk_delAttribute(KrkString *name)
Implementation of the DEL_PROPERTY instruction.
Definition: vm.c:1825
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:601
int krk_loadModule(KrkString *path, KrkValue *moduleOut, KrkString *runAs, KrkValue parent)
Load a module from a file with a specified name.
Definition: vm.c:1146
KrkValue krk_valueGetAttribute_default(KrkValue value, char *name, KrkValue defaultVal)
See krk_valueGetAttribute.
Definition: vm.c:1780
void krk_setMaximumRecursionDepth(size_t maxDepth)
Set the maximum recursion call depth.
Definition: vm.c:863
void krk_swap(int distance)
Swap the top of the stack of the value distance slots down.
Definition: vm.c:145
KrkValue krk_interpret(const char *src, const char *fromFile)
Compile and execute a source code input.
Definition: vm.c:3219
KrkValue krk_runfile(const char *fileName, const char *fromFile)
Load and run a source file and return when execution completes.
Definition: vm.c:3236
KrkInstance * krk_startModule(const char *name)
Set up a new module object in the current thread.
Definition: vm.c:3209
KrkValue krk_callDirect(KrkObj *callable, int argCount)
Call a closure or native function with argCount arguments.
Definition: vm.c:740
KrkValue krk_instanceSetAttribute_wrapper(KrkValue owner, KrkString *name, KrkValue to)
Set an attribute of an instance object, bypassing __setattr__.
Definition: vm.c:1862
#define KRK_CALL_FRAMES_MAX
Maximum depth of the call stack in managed-code function calls.
Definition: vm.h:20