Core API for the bytecode virtual machine. More...
#include <stdarg.h>
#include <sys/types.h>
#include "kuroko.h"
#include "value.h"
#include "table.h"
#include "object.h"
Go to the source code of this file.
Data Structures | |
struct | KrkCallFrame |
Represents a managed call state in a VM thread. More... | |
struct | Exceptions |
Table of basic exception types. More... | |
struct | BaseClasses |
Table of classes for built-in object types. More... | |
struct | KrkThreadState |
Execution state of a VM thread. More... | |
struct | KrkVM |
Global VM state. More... | |
Macros | |
#define | KRK_CALL_FRAMES_MAX 1000 |
Maximum depth of the call stack in managed-code function calls. | |
#define | KRK_THREAD_SCRATCH_SIZE 3 |
Extra space for each thread to store a set of working values safe from the GC. More... | |
#define | KRK_THREAD_ENABLE_TRACING (1 << 0) |
#define | KRK_THREAD_ENABLE_DISASSEMBLY (1 << 1) |
#define | KRK_THREAD_HAS_EXCEPTION (1 << 3) |
#define | KRK_THREAD_SINGLE_STEP (1 << 4) |
#define | KRK_THREAD_SIGNALLED (1 << 5) |
#define | KRK_THREAD_DEFER_STACK_FREE (1 << 6) |
#define | KRK_GLOBAL_ENABLE_STRESS_GC (1 << 8) |
#define | KRK_GLOBAL_GC_PAUSED (1 << 9) |
#define | KRK_GLOBAL_CLEAN_OUTPUT (1 << 10) |
#define | KRK_GLOBAL_REPORT_GC_COLLECTS (1 << 12) |
#define | KRK_GLOBAL_THREADS (1 << 13) |
#define | KRK_GLOBAL_NO_DEFAULT_MODULES (1 << 14) |
#define | krk_threadLocal __thread |
#define | vm krk_vm |
Convenience macro for namespacing. | |
Typedefs | |
typedef struct KrkThreadState | KrkThreadState |
Execution state of a VM thread. More... | |
typedef struct KrkVM | KrkVM |
Global VM state. More... | |
Functions | |
void | krk_resetStack (void) |
Reset the current thread's stack state to the top level. More... | |
KrkValue | krk_interpret (const char *src, const char *fromFile) |
Compile and execute a source code input. More... | |
KrkValue | krk_runfile (const char *fileName, const char *fromFile) |
Load and run a source file and return when execution completes. More... | |
void | krk_push (KrkValue value) |
Push a stack value. More... | |
KrkValue | krk_pop (void) |
Pop the top of the stack. More... | |
KrkValue | krk_peek (int distance) |
Peek down from the top of the stack. More... | |
void | krk_swap (int distance) |
Swap the top of the stack of the value distance slots down. More... | |
KrkValue | krk_runtimeError (KrkClass *type, const char *fmt,...) |
Produce and raise an exception with a formatted message. More... | |
void | krk_raiseException (KrkValue base, KrkValue cause) |
Raise an exception value. More... | |
void | krk_attachInnerException (KrkValue innerException) |
Attach an inner exception to the current exception object. More... | |
KrkThreadState * | krk_getCurrentThread (void) |
Get a pointer to the current thread state. More... | |
KrkValue | krk_runNext (void) |
Continue VM execution until the next exit trigger. More... | |
KrkValue | krk_callStack (int argCount) |
Call a callable on the stack with argCount arguments. More... | |
KrkValue | krk_callDirect (KrkObj *callable, int argCount) |
Call a closure or native function with argCount arguments. More... | |
void | krk_dumpTraceback (void) |
If there is an active exception, print a traceback to stderr . More... | |
KrkInstance * | krk_startModule (const char *name) |
Set up a new module object in the current thread. More... | |
KrkValue | krk_dirObject (int argc, const KrkValue argv[], int hasKw) |
Obtain a list of properties for an object. More... | |
int | krk_loadModule (KrkString *path, KrkValue *moduleOut, KrkString *runAs, KrkValue parent) |
Load a module from a file with a specified name. More... | |
int | krk_doRecursiveModuleLoad (KrkString *name) |
Load a module by a dotted name. More... | |
int | krk_importModule (KrkString *name, KrkString *runAs) |
Load the dotted name name with the final element as runAs . More... | |
KrkValue | krk_valueGetAttribute_default (KrkValue value, char *name, KrkValue defaultVal) |
See krk_valueGetAttribute. | |
void | krk_addObjects (void) |
Concatenate two strings. More... | |
KrkValue | krk_operator_lt (KrkValue, KrkValue) |
Compare two values, returning True if the left is less than the right. More... | |
KrkValue | krk_operator_gt (KrkValue, KrkValue) |
Compare to values, returning True if the left is greater than the right. More... | |
KrkValue | krk_operator_le (KrkValue, KrkValue) |
Compare two values, returning True if the left is less than or equal to the right. More... | |
KrkValue | krk_operator_ge (KrkValue, KrkValue) |
Compare to values, returning True if the left is greater than or equal to the right. More... | |
void | krk_setMaximumRecursionDepth (size_t maxDepth) |
Set the maximum recursion call depth. More... | |
KrkValue | krk_callNativeOnStack (size_t argCount, const KrkValue *stackArgs, int hasKw, NativeFn native) |
Call a native function using a reference to stack arguments safely. More... | |
KrkValue | krk_instanceSetAttribute_wrapper (KrkValue owner, KrkString *name, KrkValue to) |
Set an attribute of an instance object, bypassing __setattr__. More... | |
int | krk_getAttribute (KrkString *name) |
Implementation of the GET_PROPERTY instruction. More... | |
int | krk_setAttribute (KrkString *name) |
Implementation of the SET_PROPERTY instruction. More... | |
int | krk_delAttribute (KrkString *name) |
Implementation of the DEL_PROPERTY instruction. More... | |
void | krk_module_init_kuroko (void) |
Initialize the built-in 'kuroko' module. More... | |
void | krk_module_init_threading (void) |
Initialize the built-in 'threading' module. More... | |
Variables | |
krk_threadLocal KrkThreadState | krk_currentThread |
Thread-local VM state. More... | |
KrkVM | krk_vm |
Singleton instance of the shared VM state. | |
Detailed Description
Core API for the bytecode virtual machine.
Functions and structures declared here make up the bulk of the public C API for Kuroko, including initializing the VM and passing code to be interpreted.
Definition in file vm.h.
Macro Definition Documentation
◆ KRK_THREAD_SCRATCH_SIZE
#define KRK_THREAD_SCRATCH_SIZE 3 |
Extra space for each thread to store a set of working values safe from the GC.
Various operations require threads to remove values from the stack but ensure they are not lost to garbage collection. This space allows each thread to keep a few things around during those operations.
Typedef Documentation
◆ KrkThreadState
typedef struct KrkThreadState KrkThreadState |
Execution state of a VM thread.
Each thread in the VM has its own local thread state, which contains the thread's stack, stack pointer, call frame stack, a thread-specific VM flags bitarray, and an exception state.
- See also
- krk_currentThread
◆ KrkVM
Global VM state.
This state is shared by all VM threads and stores the path to the VM binary, global execution flags, the string and module tables, tables of builtin types, and the state of the (shared) garbage collector.
Function Documentation
◆ krk_addObjects()
void krk_addObjects | ( | void | ) |
Concatenate two strings.
This is a convenience function which calls str.__add__
on the top stack values. Generally, this should be avoided - use StringBuilder
instead.
◆ krk_attachInnerException()
void krk_attachInnerException | ( | KrkValue | innerException | ) |
Attach an inner exception to the current exception object.
Sets the __context__
of the current exception object.
There must be a current exception, and it must be an instance object.
- Parameters
-
innerException __context__ to set.
Definition at line 423 of file exceptions.c.
◆ krk_callDirect()
Call a closure or native function with argCount
arguments.
Calls the closure or native callable
with arguments from the top of the stack. argCount
arguments are popped from the stack and the return value of the call is returned.
- Parameters
-
callable Closure or native function. argCount Arguments to collect from the stack.
- Returns
- The return value of the function.
◆ krk_callNativeOnStack()
|
inline |
Call a native function using a reference to stack arguments safely.
Passing the address of the stack to a native function directly would be unsafe: the stack can be reallocated at any time through pushes. To allow for native functions to be called with arguments from the stack safely, this wrapper holds on to a reference to the stack at the call time, unless one was already held by an outer call; if a held stack is reallocated, it will be freed when execution returns to the call to krk_callNativeOnStack
that holds it.
Make a call to a native function using values on the stack without moving them. If the stack is reallocated within this call, the old stack will not be freed until all such nested calls through krk_callNativeOnStack have returned.
If someone is already preserving this stack, we can just call directly.
◆ krk_callStack()
KrkValue krk_callStack | ( | int | argCount | ) |
Call a callable on the stack with argCount
arguments.
Calls the callable argCount
stack entries down from the top of the stack, passing argCount
arguments. Resumes execution of the VM for managed calls until they are completed. Pops all arguments and the callable from the stack and returns the return value of the call.
- Parameters
-
argCount Arguments to collect from the stack.
- Returns
- The return value of the function.
Takes care of runnext/pop
◆ krk_delAttribute()
int krk_delAttribute | ( | KrkString * | name | ) |
Implementation of the DEL_PROPERTY instruction.
Attempts to delete the attribute specified by name
from the value at the top of the stack, returning 1 and reducing the stack by one on success. If the attribute is not found or attribute deletion is not meaningful, 0 is returned and the stack remains unmodified, but no exception is raised.
- Warning
- Currently, no __delattr__ mechanism is available.
- Parameters
-
name Name of the attribute to delete.
- Returns
- 1 if the attribute was found and can be deleted, 0 otherwise.
◆ krk_dirObject()
Obtain a list of properties for an object.
This is the native function bound to object.__dir__
Definition at line 13 of file builtins.c.
◆ krk_doRecursiveModuleLoad()
int krk_doRecursiveModuleLoad | ( | KrkString * | name | ) |
Load a module by a dotted name.
Given a package identifier, attempt to the load module into the module table. This is a thin wrapper around krk_importModule()
.
- Parameters
-
name String object of the dot-separated package path to import.
- Returns
- 1 if the module was loaded, 0 if an ImportError occurred.
◆ krk_dumpTraceback()
void krk_dumpTraceback | ( | void | ) |
If there is an active exception, print a traceback to stderr
.
This function is exposed as a convenience for repl developers. Normally, the VM will call krk_dumpTraceback()
itself if an exception is unhandled and no exit trigger is current set. The traceback is obtained from the exception object. If the exception object does not have a traceback, only the exception itself will be printed. The traceback printer will attempt to open source files to print faulting lines and may call into the VM if the exception object has a managed implementation of __str__
.
Display a traceback by scanning up the stack / call frames. The format of the output here is modeled after the output given by CPython, so we display the outermost call first and then move inwards; on each call frame we try to open the source file and print the corresponding line.
Definition at line 366 of file exceptions.c.
◆ krk_getAttribute()
int krk_getAttribute | ( | KrkString * | name | ) |
Implementation of the GET_PROPERTY instruction.
Retrieves the attribute specifed by name
from the value at the top of the stack. The top of the stack will be replaced with the resulting attribute value, if one is found, and 1 will be returned. Otherwise, 0 is returned and the stack remains unchanged. No exception is raised if the property is not found, allowing this function to be used in context where a default value is desired, but note that exceptions may be raised __getattr__ methods or by descriptor __get__ methods.
- Parameters
-
name Name of the attribute to look up.
- Returns
- 1 if the attribute was found, 0 otherwise.
◆ krk_getCurrentThread()
KrkThreadState* krk_getCurrentThread | ( | void | ) |
Get a pointer to the current thread state.
Generally equivalent to &krk_currentThread
, though krk_currentThread
itself may be implemented as a macro that calls this function depending on the platform's thread support.
- Returns
- Pointer to current thread's thread state.
◆ krk_importModule()
Load the dotted name name
with the final element as runAs
.
If name
was imported previously with a name different from runAs
, it will be imported again with the new name; this may result in unexpected behaviour. Generally, runAs
is used to specify that the module should be run as __main__
.
- Parameters
-
name Dotted path name of a module. runAs Alternative name to attach to __name__
for the module.
- Returns
- 1 on success, 0 on failure.
For relative imports, we canonicalize the import name based on the current package, and then trying importModule again with the fully qualified name.
from .. import ... or from ..something import ...
If there n dots, there are n-1 components to pop from the end of the package name, as '..' is "go up one" and '...' is "go up two".
To import foo.bar.baz
- import foo as foo
- import foo/bar as foo.bar
- import foo/bar/baz as foo.bar.baz
◆ krk_instanceSetAttribute_wrapper()
Set an attribute of an instance object, bypassing __setattr__.
This can be used to emulate the behavior of super(object).__setattr__ for types that derive from KrkInstance and have a fields table, and is the internal mechanism by which object.__setattr__() performs this task.
Does not bypass descriptors.
- Parameters
-
owner Instance object to set an attribute on. name Name of the attribute to New value for the attribute
- Returns
- The value set, which is likely
to
but may be the returned value of a descriptor __set__ method.
◆ krk_interpret()
KrkValue krk_interpret | ( | const char * | src, |
const char * | fromFile | ||
) |
Compile and execute a source code input.
Compiles and executes the source code in src
and returns the result of execution - generally the return value of a function body or the last value on the stack in a REPL expression. This is the lowest level call for most usecases, including execution of commands from a REPL or when executing a file.
The string provided in fromFile
is used in exception tracebacks.
- Parameters
-
src Source code to compile and run. fromFile Path to the source file, or a representative string like "<stdin>".
- Returns
- The value of the executed code, which is either the value of an explicit 'return' statement, or the last expression value from an executed statement. If an uncaught exception occurred, this will be
None
andkrk_currentThread.flags
should indicateKRK_THREAD_HAS_EXCEPTION
andkrk_currentThread.currentException
should contain the raised exception value.
◆ krk_loadModule()
Load a module from a file with a specified name.
This is generally called by the import mechanisms to load a single module and will establish a module context internally to load the new module into, return a KrkValue representing that module context through the moduleOut
parameter.
- Parameters
-
path Dotted path of the module, used for file lookup. moduleOut Receives a value with the module object. runAs Name to attach to __name__
for this module, different frompath
parent Parent module object, if loaded from a package.
- Returns
- 1 if the module was loaded, 0 if an ImportError occurred.
Load a module.
The module search path is stored in builtins.module_paths and should be a list of directories (with trailing forward-slash) to look at, in order, to resolve module names. krk source files will always take priority, so if a later search path has a krk source and an earlier search path has a shared object module, the later search path will still win.
◆ krk_module_init_kuroko()
void krk_module_init_kuroko | ( | void | ) |
◆ krk_module_init_threading()
void krk_module_init_threading | ( | void | ) |
◆ krk_operator_ge()
Compare to values, returning True if the left is greater than or equal to the right.
This is equivalent to the opcode instruction OP_GREATER_EQUAL.
◆ krk_operator_gt()
Compare to values, returning True if the left is greater than the right.
This is equivalent to the opcode instruction OP_GREATER.
◆ krk_operator_le()
Compare two values, returning True if the left is less than or equal to the right.
This is equivalent to the opcode instruction OP_LESS_EQUAL.
◆ krk_operator_lt()
Compare two values, returning True if the left is less than the right.
This is equivalent to the opcode instruction OP_LESS.
◆ krk_peek()
|
inline |
◆ krk_pop()
|
inline |
Pop the top of the stack.
Removes and returns the value at the top of current thread's stack. Generally, it is preferably to leave values on the stack and use krk_peek if the value is desired, as removing a value from the stack may result in it being garbage collected.
- Returns
- The value previously at the top of the stack.
Pop the top of the stack. We never reclaim space used by the stack, so anything that is popped can be safely pushed back on without the stack moving, and you an also generally rely on a popped item still being where it was if you don't allocate anything in between; the repl relies on this it expects to be able to get the last pushed value and display it (if it's not None).
◆ krk_push()
|
inline |
Push a stack value.
Pushes a value onto the current thread's stack, triggering a stack resize if there is not enough space to hold the new value.
- Parameters
-
value Value to push.
Push a value onto the stack, and grow the stack if necessary. Note that growing the stack can involve the stack moving, so do not rely on the memory offset of a stack value if you expect the stack to grow - eg. if you are calling into managed code to do anything, or if you are pushing anything.
◆ krk_raiseException()
Raise an exception value.
Implementation of the OP_RAISE
and OP_RAISE_FROM
instructions.
If either of base
or cause
is a class, the class will be called to produce an instance, so exception classes may be used directly if desired.
If cause
is not None
it will be attached as __cause__
to the resulting exception object.
A traceback is automatically attached.
- Parameters
-
base Exception object or class to raise. cause Exception cause object or class to attach.
Definition at line 435 of file exceptions.c.
◆ krk_resetStack()
void krk_resetStack | ( | void | ) |
Reset the current thread's stack state to the top level.
In a repl, this should be called before or after each iteration to clean up any remnant stack entries from an uncaught exception. It should not be called during normal execution by C extensions. Values on the stack may be lost to garbage collection after a call to krk_resetStack
.
Reset the stack pointers, frame, upvalue list, clear the exception flag and current exception; happens on startup (twice) and after an exception.
◆ krk_runfile()
KrkValue krk_runfile | ( | const char * | fileName, |
const char * | fromFile | ||
) |
Load and run a source file and return when execution completes.
Loads and runs a source file. Can be used by interpreters to run scripts, either in the context of a new a module or as if they were continuations of the current module state (eg. as if they were lines entered on a repl)
- Parameters
-
fileName Path to the source file to read and execute. fromFile Value to assign to __file__
- Returns
- As with
krk_interpret
, an object representing the newly created module, or the final return value of the VM execution.
◆ krk_runNext()
KrkValue krk_runNext | ( | void | ) |
Continue VM execution until the next exit trigger.
Resumes the VM dispatch loop, returning to the caller when the next exit trigger event happens. Generally, callers will want to set the current thread's exitOnFrame before calling krk_runNext
. Alternatively, see krk_callValue
which manages exit triggers automatically when calling function objects.
- Returns
- Value returned by the exit trigger, generally the value returned by the inner function before the VM returned to the exit frame.
Run the VM until it returns from the current call frame; used by native methods to call into managed methods. Returns the value returned by the RETURN instruction that exited the call frame. Should be nestable so a managed method can call a native method can call a managed can call a native and so on (hopefully).
◆ krk_runtimeError()
Produce and raise an exception with a formatted message.
Creates an instance of the given exception type, passing a formatted string to the initializer. All of the core exception types take an option string value to attach to the exception, but third-party exception types may have different initializer signatures and need separate initialization.
The created exception object is attached to the current thread state and the KRK_THREAD_HAS_EXCEPTION
flag is set.
If the format string is exactly "%V", the first format argument will be attached the exception as the 'msg' attribute.
No field width or precisions are supported on any conversion specifiers.
Standard conversion specifiers 'c', 's', 'd', 'u' are available, and the 'd' and 'u' specifiers may have length modifiers of l, L, or z.
Additional format specifiers are as follows:
S
- Accepts one KrkString* to be printed in its entirety. R
- Accepts one KrkValue and calls repr on it. T
- Accepts one KrkValue and emits the name of its type.
- Parameters
-
type Class pointer for the exception type, eg. vm.exceptions->valueError
fmt Format string.
- Returns
- As a convenience to C extension authors, returns
None
Raise an exception. Creates an exception object of the requested type and formats a message string to attach to it. Exception classes are found in vm.exceptions and are initialized on startup.
Definition at line 460 of file exceptions.c.
◆ krk_setAttribute()
int krk_setAttribute | ( | KrkString * | name | ) |
Implementation of the SET_PROPERTY instruction.
Sets the attribute specifed by name
on the value second from top of the stack to the value at the top of the stack. Upon successful completion, 1 is returned the stack is reduced by one slot, and the top of the stack is the value set, which may be the result of a descriptor __set__ method. If the owner object does not allow for attributes to be set, and no descriptor object is present, 0 will be returned and the stack remains unmodified. No exception is raised in this case, though exceptions may still be raised by __setattr__ methods or descriptor __set__ methods.
- Parameters
-
name Name of the attribute to set.
- Returns
- 1 if the attribute could be set, 0 otherwise.
◆ krk_setMaximumRecursionDepth()
void krk_setMaximumRecursionDepth | ( | size_t | maxDepth | ) |
◆ krk_startModule()
KrkInstance* krk_startModule | ( | const char * | name | ) |
Set up a new module object in the current thread.
Creates a new instance of the module type and attaches a __builtins__
reference to its fields. The module becomes the current thread's main module, but is not directly attached to the module table.
- Parameters
-
name Name of the module, which is assigned to __name__
- Returns
- The instance object representing the module.
◆ krk_swap()
|
inline |
Swap the top of the stack of the value distance
slots down.
Exchanges the values at the top of the stack and distance
slots from the top without removing or shuffling anything in between.
- Parameters
-
distance How from down from the top of the stack to swap (0 = the top)
Variable Documentation
◆ krk_currentThread
|
extern |
Thread-local VM state.
See KrkThreadState
for more information.