Start writing doxygen/javadoc-style doc comments for C API
This commit is contained in:
parent
d112107edc
commit
076b702afa
37
src/debug.h
37
src/debug.h
@ -4,7 +4,44 @@
|
||||
#include "chunk.h"
|
||||
#include "object.h"
|
||||
|
||||
/**
|
||||
* @brief Print a disassembly of 'func' to the stream 'f'.
|
||||
*
|
||||
* Generates and prints a bytecode disassembly of the code object 'func',
|
||||
* writing it to the requested stream.
|
||||
*
|
||||
* @param f Stream to write to.
|
||||
* @param func Code object to disassemble.
|
||||
* @param name Function name to display in disassembly output.
|
||||
*/
|
||||
extern void krk_disassembleChunk(FILE * f, KrkFunction * func, const char * name);
|
||||
|
||||
/**
|
||||
* @brief Print a disassembly of a single opcode instruction.
|
||||
*
|
||||
* Generates and prints a bytecode disassembly for one instruction from
|
||||
* the code object 'func' at byte offset 'offset', printing the result to
|
||||
* the requested stream and returning the size of the instruction.
|
||||
*
|
||||
* @param f Stream to write to.
|
||||
* @param func Code object to disassemble.
|
||||
* @param offset Byte offset of the instruction to disassemble.
|
||||
* @return The size of the instruction in bytes.
|
||||
*/
|
||||
extern size_t krk_disassembleInstruction(FILE * f, KrkFunction * func, size_t offset);
|
||||
|
||||
/**
|
||||
* @brief Obtain the line number for a byte offset into a bytecode chunk.
|
||||
*
|
||||
* Scans the line mapping table for the given chunk to find the
|
||||
* correct line number from the original source file for the instruction
|
||||
* at byte index 'offset'.
|
||||
*
|
||||
* @param chunk Bytecode chunk containing the instruction.
|
||||
* @param offset Byte offset of the instruction to locate.
|
||||
* @return Line number, 1-indexed.
|
||||
*/
|
||||
extern size_t krk_lineNumber(KrkChunk * chunk, size_t offset);
|
||||
|
||||
/* Internal stuff */
|
||||
extern void _createAndBind_disMod(void);
|
||||
|
79
src/object.h
79
src/object.h
@ -221,8 +221,83 @@ static inline int isObjType(KrkValue value, ObjType type) {
|
||||
return IS_OBJECT(value) && AS_OBJECT(value)->type == type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Yield ownership of a C string to the GC and obtain a string object.
|
||||
*
|
||||
* Creates a string object represented by the characters in 'chars' and of
|
||||
* length 'length'. The source string must be nil-terminated and must
|
||||
* remain valid for the lifetime of the object, as its ownership is yielded
|
||||
* to the GC. Useful for strings which were allocated on the heap by
|
||||
* other mechanisms.
|
||||
*
|
||||
* 'chars' must be a nil-terminated C string representing a UTF-8
|
||||
* character sequence.
|
||||
*
|
||||
* @param chars C string to take ownership of.
|
||||
* @param length Length of the C string.
|
||||
* @return A string object.
|
||||
*/
|
||||
extern KrkString * krk_takeString(char * chars, size_t length);
|
||||
|
||||
/**
|
||||
* @brief Obtain a string object representation of the given C string.
|
||||
*
|
||||
* Converts the C string 'chars' into a string object by checking the
|
||||
* string table for it. If the string table does not have an equivalent
|
||||
* string, a new one will be created by copying 'chars'.
|
||||
*
|
||||
* 'chars' must be a nil-terminated C string representing a UTF-8
|
||||
* character sequence.
|
||||
*
|
||||
* @param chars C string to convert to a string object.
|
||||
* @param length Length of the C string.
|
||||
* @return A string object.
|
||||
*/
|
||||
extern KrkString * krk_copyString(const char * chars, size_t length);
|
||||
|
||||
/**
|
||||
* @brief Ensure that a codepoint representation of a string is available.
|
||||
*
|
||||
* Obtain an untyped pointer to the codepoint representation of a string.
|
||||
* If the string does not have a codepoint representation allocated, it will
|
||||
* be generated by this function and remain with the string for the duration
|
||||
* of its lifetime.
|
||||
*
|
||||
* @param string String to obtain the codepoint representation of.
|
||||
* @return A pointer to the bytes of the codepoint representation.
|
||||
*/
|
||||
extern void * krk_unicodeString(KrkString * string);
|
||||
|
||||
/**
|
||||
* @brief Obtain the codepoint at a given index in a string.
|
||||
*
|
||||
* This is a convenience function which ensures that a Unicode codepoint
|
||||
* representation has been generated and returns the codepoint value at
|
||||
* the requested index. If you need to find multiple codepoints, it
|
||||
* is recommended that you use the KRK_STRING_FAST macro after calling
|
||||
* krk_unicodeString instead.
|
||||
*
|
||||
* @note This function does not perform any bounds checking.
|
||||
*
|
||||
* @param string String to index into.
|
||||
* @param index Offset of the codepoint to obtain.
|
||||
* @return Integer representation of the codepoint at the requested index.
|
||||
*/
|
||||
extern uint32_t krk_unicodeCodepoint(KrkString * string, size_t index);
|
||||
|
||||
/**
|
||||
* @brief Convert an integer codepoint to a UTF-8 byte representation.
|
||||
*
|
||||
* Converts a single codepoint to a sequence of bytes containing the
|
||||
* UTF-8 representation. 'out' must be allocated by the caller.
|
||||
*
|
||||
* @param value Codepoint to encode.
|
||||
* @param out Array to write UTF-8 sequence into.
|
||||
* @return The length of the UTF-8 sequence, in bytes.
|
||||
*/
|
||||
extern size_t krk_codepointToBytes(krk_integer_type value, unsigned char * out);
|
||||
|
||||
/* Internal stuff. */
|
||||
extern KrkFunction * krk_newFunction(void);
|
||||
extern KrkNative * krk_newNative(NativeFn function, const char * name, int type);
|
||||
extern KrkClosure * krk_newClosure(KrkFunction * function);
|
||||
@ -233,9 +308,6 @@ extern KrkBoundMethod * krk_newBoundMethod(KrkValue receiver, KrkObj * method);
|
||||
extern KrkTuple * krk_newTuple(size_t length);
|
||||
extern KrkProperty * krk_newProperty(KrkValue method);
|
||||
|
||||
extern void * krk_unicodeString(KrkString * string);
|
||||
extern uint32_t krk_unicodeCodepoint(KrkString * string, size_t index);
|
||||
|
||||
#define KRK_STRING_FAST(string,offset) (uint32_t)\
|
||||
(string->type <= 1 ? ((uint8_t*)string->codes)[offset] : \
|
||||
(string->type == 2 ? ((uint16_t*)string->codes)[offset] : \
|
||||
@ -245,6 +317,5 @@ extern uint32_t krk_unicodeCodepoint(KrkString * string, size_t index);
|
||||
|
||||
extern KrkBytes * krk_newBytes(size_t length, uint8_t * source);
|
||||
extern void krk_bytesUpdateHash(KrkBytes * bytes);
|
||||
extern size_t krk_codepointToBytes(krk_integer_type value, unsigned char * out);
|
||||
|
||||
extern void krk_tupleUpdateHash(KrkTuple * self);
|
||||
|
101
src/table.h
101
src/table.h
@ -23,12 +23,113 @@ typedef struct {
|
||||
KrkTableEntry * entries;
|
||||
} KrkTable;
|
||||
|
||||
/**
|
||||
* @brief Initialize a hash table.
|
||||
*
|
||||
* This should be called for any new hash table, especially ones
|
||||
* initialized in heap or stack space, to set up the capacity, count
|
||||
* and initial entries pointer.
|
||||
*
|
||||
* @param table Hash table to initialize.
|
||||
*/
|
||||
extern void krk_initTable(KrkTable * table);
|
||||
|
||||
/**
|
||||
* @brief Release resources associated with a hash table.
|
||||
*
|
||||
* Frees the entries array for the table and resets count and capacity.
|
||||
*
|
||||
* @param table Hash table to release.
|
||||
*/
|
||||
extern void krk_freeTable(KrkTable * table);
|
||||
|
||||
/**
|
||||
* @brief Add all key-value pairs from 'from' into 'to'.
|
||||
*
|
||||
* Copies each key-value pair from one hash table to another. If a key
|
||||
* from 'from' already exists in 'to', the existing value in 'to' will be
|
||||
* overwritten with the value from 'from'.
|
||||
*
|
||||
* @param from Source table.
|
||||
* @param to Destination table.
|
||||
*/
|
||||
extern void krk_tableAddAll(KrkTable * from, KrkTable * to);
|
||||
|
||||
/**
|
||||
* @brief Find a character sequence in the string interning table.
|
||||
*
|
||||
* Scans through the entries in a given table - usually vm.strings - to find
|
||||
* an entry equivalent to the string specified by the 'chars' and 'length'
|
||||
* parameters, using the 'hash' parameter to speed up lookup.
|
||||
*
|
||||
* @param chars C array of chars representing the string.
|
||||
* @param length Length of the string.
|
||||
* @param hash Precalculated hash value for the string.
|
||||
* @return If the string was found, the string object representation, else NULL.
|
||||
*/
|
||||
extern KrkString * krk_tableFindString(KrkTable * table, const char * chars, size_t length, uint32_t hash);
|
||||
|
||||
/**
|
||||
* @brief Assign a value to a key in a table.
|
||||
*
|
||||
* Inserts the key-value pair specified by 'key' and 'value' into the hash
|
||||
* table 'table', replacing any value that was already preseng with the
|
||||
* same key.
|
||||
*
|
||||
* @param table Table to assign to.
|
||||
* @param key Key to assign.
|
||||
* @param value Value to assign to the key.
|
||||
* @return 0 if the key was already present and has been overwritten, 1 if the key is new to the table.
|
||||
*/
|
||||
extern int krk_tableSet(KrkTable * table, KrkValue key, KrkValue value);
|
||||
|
||||
/**
|
||||
* @brief Obtain the value associated with a key in a table.
|
||||
*
|
||||
* Scans the table 'table' for the key 'key' and, if found, outputs
|
||||
* the associated value to *value. If the key is not found, then
|
||||
* *value will not be changed.
|
||||
*
|
||||
* @param table Table to look up.
|
||||
* @param key Key to look for.
|
||||
* @param value Output pointer to place resulting value in.
|
||||
* @return 0 if the key was not found, 1 if it was.
|
||||
*/
|
||||
extern int krk_tableGet(KrkTable * table, KrkValue key, KrkValue * value);
|
||||
|
||||
/**
|
||||
* @brief Remove a key from a hash table.
|
||||
*
|
||||
* Scans the table 'table' for the key 'key' and, if found, removes
|
||||
* the entry, replacing it with a tombstone value.
|
||||
*
|
||||
* @param table Table to delete from.
|
||||
* @param key Key to delete.
|
||||
* @return 1 if the value was found and deleted, 0 if it was not present.
|
||||
*/
|
||||
extern int krk_tableDelete(KrkTable * table, KrkValue key);
|
||||
|
||||
/**
|
||||
* @brief Internal table scan function.
|
||||
*
|
||||
* Scans through the the entry array 'entries' to find the appropriate entry
|
||||
* for 'key', return a pointer to the entry, which may be or may not have
|
||||
* an associated pair.
|
||||
*
|
||||
* @param entries Table entry array to scan.
|
||||
* @param capacity Size of the table entry array, in entries.
|
||||
* @param key Key to locate.
|
||||
* @return A pointer to the entry for 'key'.
|
||||
*/
|
||||
extern KrkTableEntry * krk_findEntry(KrkTableEntry * entries, size_t capacity, KrkValue key);
|
||||
|
||||
/**
|
||||
* @brief Calculate the hash for a value.
|
||||
*
|
||||
* Retreives or calculates the hash value for 'value'.
|
||||
*
|
||||
* @param value Value to hash.
|
||||
* @return An unsigned 32-bit hash value.
|
||||
*/
|
||||
extern uint32_t krk_hashValue(KrkValue value);
|
||||
|
||||
|
@ -47,7 +47,7 @@ KRK_FUNC(current_thread,{
|
||||
static volatile int _threadLock = 0;
|
||||
static void * _startthread(void * _threadObj) {
|
||||
memset(&krk_currentThread, 0, sizeof(KrkThreadState));
|
||||
krk_currentThread.frames = calloc(FRAMES_MAX,sizeof(CallFrame));
|
||||
krk_currentThread.frames = calloc(KRK_CALL_FRAMES_MAX,sizeof(CallFrame));
|
||||
|
||||
_obtain_lock(_threadLock);
|
||||
if (vm.threads->next) {
|
||||
|
45
src/util.h
45
src/util.h
@ -95,12 +95,21 @@ static inline const char * _method_name(const char * func) {
|
||||
#define BIND_PROP(klass,method) do { krk_defineNativeProperty(&klass->fields, #method, _ ## klass ## _ ## method); } while (0)
|
||||
#define BIND_FUNC(module,func) do { krk_defineNative(&module->fields, #func, _krk_ ## func); } while (0)
|
||||
|
||||
/**
|
||||
* @brief Inline flexible string array.
|
||||
*/
|
||||
struct StringBuilder {
|
||||
size_t capacity;
|
||||
size_t length;
|
||||
char * bytes;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Add a character to the end of a string builder.
|
||||
*
|
||||
* @param sb String builder to append to.
|
||||
* @param c Character to append.
|
||||
*/
|
||||
static inline void pushStringBuilder(struct StringBuilder * sb, char c) {
|
||||
if (sb->capacity < sb->length + 1) {
|
||||
size_t old = sb->capacity;
|
||||
@ -110,6 +119,13 @@ static inline void pushStringBuilder(struct StringBuilder * sb, char c) {
|
||||
sb->bytes[sb->length++] = c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Append a string to the end of a string builder.
|
||||
*
|
||||
* @param sb String builder to append to.
|
||||
* @param str C string to add.
|
||||
* @param len Length of the C string.
|
||||
*/
|
||||
static inline void pushStringBuilderStr(struct StringBuilder * sb, char *str, size_t len) {
|
||||
if (sb->capacity < sb->length + len) {
|
||||
while (sb->capacity < sb->length + len) {
|
||||
@ -123,18 +139,47 @@ static inline void pushStringBuilderStr(struct StringBuilder * sb, char *str, si
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Finalize a string builder into a string object.
|
||||
*
|
||||
* Creates a string object from the contents of the string builder and
|
||||
* frees the space allocated for the builder, returning a value representing
|
||||
* the newly created string object.
|
||||
*
|
||||
* @param sb String builder to finalize.
|
||||
* @return A value representing a string object.
|
||||
*/
|
||||
static inline KrkValue finishStringBuilder(struct StringBuilder * sb) {
|
||||
KrkValue out = OBJECT_VAL(krk_copyString(sb->bytes, sb->length));
|
||||
FREE_ARRAY(char,sb->bytes, sb->capacity);
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Finalize a string builder in a bytes object.
|
||||
*
|
||||
* Converts the contents of a string builder into a bytes object and
|
||||
* frees the space allocated for the builder.
|
||||
*
|
||||
* @param sb String builder to finalize.
|
||||
* @return A value representing a bytes object.
|
||||
*/
|
||||
static inline KrkValue finishStringBuilderBytes(struct StringBuilder * sb) {
|
||||
KrkValue out = OBJECT_VAL(krk_newBytes(sb->length, (uint8_t*)sb->bytes));
|
||||
FREE_ARRAY(char,sb->bytes, sb->capacity);
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Discard the contents of a string builder.
|
||||
*
|
||||
* Frees the resources allocated for the string builder without converting
|
||||
* it to a string or bytes object. Call this when an error has been encountered
|
||||
* and the contents of a string builder are no longer needed.
|
||||
*
|
||||
* @param sb String builder to discard.
|
||||
* @return None, as a convenience.
|
||||
*/
|
||||
static inline KrkValue discardStringBuilder(struct StringBuilder * sb) {
|
||||
FREE_ARRAY(char,sb->bytes, sb->capacity);
|
||||
return NONE_VAL();
|
||||
|
156
src/value.h
156
src/value.h
@ -3,9 +3,24 @@
|
||||
#include <stdio.h>
|
||||
#include "kuroko.h"
|
||||
|
||||
/**
|
||||
* @brief Base structure of all heap objects.
|
||||
*
|
||||
* KrkObj is the base type of all objects stored on the heap and
|
||||
* managed by the garbage collector.
|
||||
*/
|
||||
typedef struct Obj KrkObj;
|
||||
typedef struct ObjString KrkString;
|
||||
|
||||
/**
|
||||
* @brief Tag enum for basic value types.
|
||||
*
|
||||
* Value types are tagged unions of a handful of small
|
||||
* types represented directly on the stack: Integers,
|
||||
* double-precision floating point values, booleans,
|
||||
* exception handler references, complex function argument
|
||||
* processing sentinels, object reference pointers, and None.
|
||||
*/
|
||||
typedef enum {
|
||||
VAL_NONE,
|
||||
VAL_BOOLEAN,
|
||||
@ -14,14 +29,36 @@ typedef enum {
|
||||
VAL_HANDLER,
|
||||
VAL_OBJECT,
|
||||
VAL_KWARGS,
|
||||
/* More here later */
|
||||
} KrkValueType;
|
||||
|
||||
/**
|
||||
* @brief Stack value representation of a 'with' or 'try' block.
|
||||
*
|
||||
* When a 'with' or 'try' block is entered, a handler value is
|
||||
* created on the stack representing the type (with, try) and the
|
||||
* jump target to leave the block (entering the 'except' block of
|
||||
* a 'try', if present, or calling the __exit__ method of an object
|
||||
* __enter__'d by a 'with' block). When the relevant conditions are
|
||||
* triggered in the VM, the stack will be scanned from top to bottom
|
||||
* to look for these values.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned short type;
|
||||
unsigned short target;
|
||||
} KrkJumpTarget;
|
||||
|
||||
/**
|
||||
* @brief Stack reference or primative value.
|
||||
*
|
||||
* This type stores a stack reference to an object, or the contents of
|
||||
* a primitive type. Each VM thread's stack consists of an array of
|
||||
* these values, and they are generally passed around in the VM through
|
||||
* direct copying rather than as pointers, avoiding the need to track
|
||||
* memory used by them.
|
||||
*
|
||||
* Each value is a tagged union with a type (see the enum KrkValueType)
|
||||
* and its contents.
|
||||
*/
|
||||
typedef struct {
|
||||
KrkValueType type;
|
||||
union {
|
||||
@ -33,6 +70,109 @@ typedef struct {
|
||||
} as;
|
||||
} KrkValue;
|
||||
|
||||
/**
|
||||
* @brief Flexible vector of stack references.
|
||||
*
|
||||
* Value Arrays provide a resizable collection of values and are the
|
||||
* backbone of lists and tuples.
|
||||
*/
|
||||
typedef struct {
|
||||
size_t capacity; /**< Available allocated space. */
|
||||
size_t count; /**< Current number of used slots. */
|
||||
KrkValue * values; /**< Pointer to heap-allocated storage. */
|
||||
} KrkValueArray;
|
||||
|
||||
/**
|
||||
* @brief Initialize a value array.
|
||||
*
|
||||
* This should be called for any new value array, especially ones
|
||||
* initialized in heap or stack space, to set up the capacity, count
|
||||
* and initial value pointer.
|
||||
*
|
||||
* @param array Value array to initialize.
|
||||
*/
|
||||
extern void krk_initValueArray(KrkValueArray * array);
|
||||
|
||||
/**
|
||||
* @brief Add a value to a value array.
|
||||
*
|
||||
* Appends 'value' to the end of the given array, adjusting count values
|
||||
* and resizing as necessary.
|
||||
*
|
||||
* @param array Array to append to.
|
||||
* @param value Value to append to array.
|
||||
*/
|
||||
extern void krk_writeValueArray(KrkValueArray * array, KrkValue value);
|
||||
|
||||
/**
|
||||
* @brief Release relesources used by a value array.
|
||||
*
|
||||
* Frees the storage associated with a given value array and resets
|
||||
* its capacity and count. Does not directly free resources associated
|
||||
* with heap objects referenced by the values in this array: The GC
|
||||
* is responsible for taking care of that.
|
||||
*
|
||||
* @param array Array to release.
|
||||
*/
|
||||
extern void krk_freeValueArray(KrkValueArray * array);
|
||||
|
||||
/**
|
||||
* @brief Print a string representation of a value.
|
||||
*
|
||||
* Print a string representation of 'value' to the stream 'f'.
|
||||
* For primitives, performs appropriate formatting. For objects,
|
||||
* this will call __str__ on the object's representative type.
|
||||
* If the type does not have a __str__ method, __repr__ will be
|
||||
* tried before falling back to krk_typeName to directly print
|
||||
* the name of the class with no information on the value.
|
||||
*
|
||||
* This function provides the backend for the print() built-in.
|
||||
*
|
||||
* @param f Stream to write to.
|
||||
* @param value Value to display.
|
||||
*/
|
||||
extern void krk_printValue(FILE * f, KrkValue value);
|
||||
|
||||
/**
|
||||
* @brief Print a value without calling the VM.
|
||||
*
|
||||
* Print a string representation of 'value' to the stream 'f',
|
||||
* avoiding calls to managed code by using simplified representations
|
||||
* where necessary. This is intended for use in debugging code, such
|
||||
* as during disassembly, or when printing values in an untrusted context.
|
||||
*
|
||||
* @note This function will truncate long strings and print them in a form
|
||||
* closer to the 'repr()' representation, with escaped bytes, rather
|
||||
* than directly printing them to the stream.
|
||||
*
|
||||
* @param f Stream to write to.
|
||||
* @param value Value to display.
|
||||
*/
|
||||
extern void krk_printValueSafe(FILE * f, KrkValue value);
|
||||
|
||||
/**
|
||||
* @brief Compare two values for equality.
|
||||
*
|
||||
* Performs a relaxed equality comparison between two values,
|
||||
* check for equivalence by contents. This may call managed
|
||||
* code to run __eq__ methods.
|
||||
*
|
||||
* @return 1 if values are equivalent, 0 otherwise.
|
||||
*/
|
||||
extern int krk_valuesEqual(KrkValue a, KrkValue b);
|
||||
|
||||
/**
|
||||
* @brief Compare two values by identity.
|
||||
*
|
||||
* Performs a strict comparison between two values, comparing
|
||||
* their identities. For primitive values, this is generally
|
||||
* the same as comparing by equality. For objects, this compares
|
||||
* pointer values directly.
|
||||
*
|
||||
* @return 1 if values represent the same object or value, 0 otherwise.
|
||||
*/
|
||||
extern int krk_valuesSame(KrkValue a, KrkValue b);
|
||||
|
||||
#define BOOLEAN_VAL(value) ((KrkValue){VAL_BOOLEAN, {.boolean = value}})
|
||||
#define NONE_VAL(value) ((KrkValue){VAL_NONE, {.integer = 0}})
|
||||
#define INTEGER_VAL(value) ((KrkValue){VAL_INTEGER, {.integer = value}})
|
||||
@ -58,17 +198,3 @@ typedef struct {
|
||||
#define IS_TRY_HANDLER(value) (IS_HANDLER(value) && AS_HANDLER(value).type == OP_PUSH_TRY)
|
||||
#define IS_WITH_HANDLER(value) (IS_HANDLER(value) && AS_HANDLER(value).type == OP_PUSH_WITH)
|
||||
|
||||
typedef struct {
|
||||
size_t capacity;
|
||||
size_t count;
|
||||
KrkValue * values;
|
||||
} KrkValueArray;
|
||||
|
||||
extern void krk_initValueArray(KrkValueArray * array);
|
||||
extern void krk_writeValueArray(KrkValueArray * array, KrkValue value);
|
||||
extern void krk_freeValueArray(KrkValueArray * array);
|
||||
extern void krk_printValue(FILE * f, KrkValue value);
|
||||
extern void krk_printValueSafe(FILE * f, KrkValue value);
|
||||
extern int krk_valuesEqual(KrkValue a, KrkValue b);
|
||||
extern int krk_valuesSame(KrkValue a, KrkValue b);
|
||||
|
||||
|
4
src/vm.c
4
src/vm.c
@ -790,7 +790,7 @@ _finishKwarg:
|
||||
krk_push(KWARGS_VAL(0));
|
||||
argCount++;
|
||||
}
|
||||
if (krk_currentThread.frameCount == FRAMES_MAX) {
|
||||
if (krk_currentThread.frameCount == KRK_CALL_FRAMES_MAX) {
|
||||
krk_runtimeError(vm.exceptions->baseException, "Too many call frames.");
|
||||
return 0;
|
||||
}
|
||||
@ -1118,7 +1118,7 @@ void krk_initVM(int flags) {
|
||||
|
||||
/* Reset current thread */
|
||||
krk_resetStack();
|
||||
krk_currentThread.frames = calloc(FRAMES_MAX,sizeof(CallFrame));
|
||||
krk_currentThread.frames = calloc(KRK_CALL_FRAMES_MAX,sizeof(CallFrame));
|
||||
krk_currentThread.flags = flags & 0x00FF;
|
||||
krk_currentThread.module = NULL;
|
||||
krk_currentThread.watchdog = 0;
|
||||
|
619
src/vm.h
619
src/vm.h
@ -7,16 +7,39 @@
|
||||
#include "table.h"
|
||||
#include "object.h"
|
||||
|
||||
#define FRAMES_MAX 64
|
||||
#define KRK_CALL_FRAMES_MAX 64
|
||||
|
||||
/**
|
||||
* @brief Represents a managed call state in a VM thread.
|
||||
*
|
||||
* For every managed function call, including the top-level module,
|
||||
* a call frame is added to the stack to track the running function,
|
||||
* the current opcode instruction, the offset into the stack, and
|
||||
* the valid globals table.
|
||||
*
|
||||
* Call frames are used directly by the VM as the source of
|
||||
* opcodes and operands during execution, and are used by the exception
|
||||
* handler to roll back execution to the appropriate environment.
|
||||
*/
|
||||
typedef struct {
|
||||
KrkClosure * closure;
|
||||
uint8_t * ip;
|
||||
size_t slots;
|
||||
size_t outSlots;
|
||||
KrkTable * globals;
|
||||
KrkClosure * closure; /**< Pointer to the function object containing the code object for this frame */
|
||||
uint8_t * ip; /**< Instruction pointer within the code object's bytecode data */
|
||||
size_t slots; /**< Offset into the stack at which this function call's arguments begin */
|
||||
size_t outSlots; /**< Offset into the stack at which stackTop will be reset upon return */
|
||||
KrkTable * globals; /**< Pointer to the attribute table containing valud global vairables for this call */
|
||||
} CallFrame;
|
||||
|
||||
/**
|
||||
* @brief Index numbers for always-available interned strings representing important method and member names.
|
||||
*
|
||||
* The VM must look up many methods and members by fixed names. To avoid
|
||||
* continuously having to box and unbox these from C strings to the appropriate
|
||||
* interned KrkString, we keep an array of the KrkString pointers in the global VM state.
|
||||
*
|
||||
* These values are the offsets into that index for each of the relevant
|
||||
* function names (generally with extra underscores removed). For example
|
||||
* METHOD_INIT is the offset for the string value for "__init__".
|
||||
*/
|
||||
typedef enum {
|
||||
METHOD_INIT,
|
||||
METHOD_STR,
|
||||
@ -51,103 +74,131 @@ typedef enum {
|
||||
METHOD__MAX,
|
||||
} KrkSpecialMethods;
|
||||
|
||||
/**
|
||||
* @brief Table of basic exception types.
|
||||
*
|
||||
* These are the core exception types, available in managed code
|
||||
* from the builtin namespace. A single instance of this struct
|
||||
* is attached to the global VM state so that C code can quickly
|
||||
* access these exception types for use with krk_runtimeException.
|
||||
*
|
||||
* @see krk_runtimeException
|
||||
*/
|
||||
struct Exceptions {
|
||||
KrkClass * baseException;
|
||||
KrkClass * typeError;
|
||||
KrkClass * argumentError;
|
||||
KrkClass * indexError;
|
||||
KrkClass * keyError;
|
||||
KrkClass * attributeError;
|
||||
KrkClass * nameError;
|
||||
KrkClass * importError;
|
||||
KrkClass * ioError;
|
||||
KrkClass * valueError;
|
||||
KrkClass * keyboardInterrupt;
|
||||
KrkClass * zeroDivisionError;
|
||||
KrkClass * notImplementedError;
|
||||
KrkClass * syntaxError;
|
||||
KrkClass * baseException; /**< @exception Exception The base exception type. */
|
||||
KrkClass * typeError; /**< @exception TypeError An argument or value was not of the expected type. */
|
||||
KrkClass * argumentError; /**< @exception ArgumentException The number of arguments passed to a function was not as expected. */
|
||||
KrkClass * indexError; /**< @exception IndexError An attempt was made to reference an invalid array index. */
|
||||
KrkClass * keyError; /**< @exception KeyError An attempt was made to reference an invalid mapping key. */
|
||||
KrkClass * attributeError; /**< @exception AttributeError An attempt was made to reference an invalid object property. */
|
||||
KrkClass * nameError; /**< @exception NameError An attempt was made to reference an undeclared global variable. */
|
||||
KrkClass * importError; /**< @exception ImportError An error was encountered when attempting to import a module. */
|
||||
KrkClass * ioError; /**< @exception IOError An error was encountered in operating system's IO library. */
|
||||
KrkClass * valueError; /**< @exception ValueError The value of a parameter or variable is not valid. */
|
||||
KrkClass * keyboardInterrupt; /**< @exception KeyboardInterrupt An interrupt signal was received. */
|
||||
KrkClass * zeroDivisionError; /**< @exception ZeroDivisionError A mathematical function attempted to divide by zero. */
|
||||
KrkClass * notImplementedError; /**< @exception NotImplementedError The method is not implemented, either for the given arguments or in general. */
|
||||
KrkClass * syntaxError; /**< @exception SyntaxError The compiler encountered an unrecognized or invalid source code input. */
|
||||
};
|
||||
|
||||
/**
|
||||
* Be sure not to reorder this, even if it looks better, to maintain
|
||||
* ABI compatibility with existing binaries.
|
||||
* @brief Table of classes for built-in object types.
|
||||
*
|
||||
* For use by C modules and within the VM, an instance of this struct
|
||||
* is attached to the global VM state. At VM initialization, each
|
||||
* built-in class is attached to this table, and the class values
|
||||
* stored here are used for integrated type checking with krk_isInstanceOf.
|
||||
*
|
||||
* @note As this and other tables are used directly by embedders, do not
|
||||
* reorder the layout of the individual class pointers, even if
|
||||
* it looks nicer. The ordering here is part of our library ABI.
|
||||
*/
|
||||
struct BaseClasses {
|
||||
KrkClass * objectClass; /* Root of everything */
|
||||
KrkClass * moduleClass; /* Simple class mostly to provide __repr__ for modules */
|
||||
|
||||
KrkClass * typeClass; /* Class */
|
||||
KrkClass * intClass; /* Integer */
|
||||
KrkClass * floatClass; /* Floating */
|
||||
KrkClass * boolClass; /* Boolean */
|
||||
KrkClass * noneTypeClass; /* None */
|
||||
KrkClass * strClass; /* String */
|
||||
KrkClass * functionClass; /* Functions, Closures */
|
||||
KrkClass * methodClass; /* BoundMethod */
|
||||
KrkClass * tupleClass; /* Tuple */
|
||||
KrkClass * bytesClass; /* Bytes */
|
||||
|
||||
KrkClass * listiteratorClass;
|
||||
KrkClass * rangeClass;
|
||||
KrkClass * rangeiteratorClass;
|
||||
KrkClass * striteratorClass;
|
||||
KrkClass * tupleiteratorClass;
|
||||
|
||||
KrkClass * listClass;
|
||||
KrkClass * dictClass;
|
||||
KrkClass * dictitemsClass;
|
||||
KrkClass * dictkeysClass;
|
||||
|
||||
KrkClass * bytesiteratorClass;
|
||||
KrkClass * objectClass; /**< The base of all classes within the type tree. */
|
||||
KrkClass * moduleClass; /**< A class for representing imported modules, both managed and C. */
|
||||
KrkClass * typeClass; /**< Classes themselves are of this class. */
|
||||
KrkClass * intClass; /**< Primitive integer type. */
|
||||
KrkClass * floatClass; /**< Primitive double-precision floating-point type. */
|
||||
KrkClass * boolClass; /**< Primitive boolean type. */
|
||||
KrkClass * noneTypeClass; /**< The class of the None value. */
|
||||
KrkClass * strClass; /**< Built-in Unicode string type. */
|
||||
KrkClass * functionClass; /**< Represents a code object (KrkFunction) or function object (KrkClosure) */
|
||||
KrkClass * methodClass; /**< Represents a bound method (KrkBoundMethod) */
|
||||
KrkClass * tupleClass; /**< An immutable collection of arbitrary values. */
|
||||
KrkClass * bytesClass; /**< An immutable sequence of bytes. */
|
||||
KrkClass * listiteratorClass; /**< Iterator over lists */
|
||||
KrkClass * rangeClass; /**< An object representing a start and end point for a sequence of integers. */
|
||||
KrkClass * rangeiteratorClass; /**< Iterator over a range of values */
|
||||
KrkClass * striteratorClass; /**< Iterator over characters (by codepoint) in a string */
|
||||
KrkClass * tupleiteratorClass; /**< Iterator over values in a tuple */
|
||||
KrkClass * listClass; /**< Mutable collection of arbitrary values. */
|
||||
KrkClass * dictClass; /**< Mutable mapping of hashable keys to arbitrary values. */
|
||||
KrkClass * dictitemsClass; /**< Iterator over the (key,value) pairs of a dict */
|
||||
KrkClass * dictkeysClass; /**< Iterator over the keys of a dict */
|
||||
KrkClass * bytesiteratorClass; /**< Iterator over the integer byte values of a bytes object. */
|
||||
};
|
||||
|
||||
/**
|
||||
* Thread state represents everything that changes during execution
|
||||
* and isn't a global property of the shared garbage collector.
|
||||
* @brief 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 krk_currentThread
|
||||
*/
|
||||
typedef struct ThreadState {
|
||||
struct ThreadState * next;
|
||||
struct ThreadState * next; /**< Invasive list pointer to next thread. */
|
||||
|
||||
CallFrame * frames;
|
||||
size_t frameCount;
|
||||
size_t stackSize;
|
||||
KrkValue * stack;
|
||||
KrkValue * stackTop;
|
||||
KrkUpvalue * openUpvalues;
|
||||
ssize_t exitOnFrame;
|
||||
CallFrame * frames; /**< Call frame stack for this thread, max KRK_CALL_FRAMES_MAX */
|
||||
size_t frameCount; /**< Number of active call frames. */
|
||||
size_t stackSize; /**< Size of the allocated stack space for this thread. */
|
||||
KrkValue * stack; /**< Pointer to the bottom of the stack for this thread. */
|
||||
KrkValue * stackTop; /**< Pointer to the top of the stack. */
|
||||
KrkUpvalue * openUpvalues; /**< Flexible array of unclosed upvalues. */
|
||||
ssize_t exitOnFrame; /**< When called in a nested context, the frame offset to exit the VM dispatch loop on. */
|
||||
|
||||
KrkInstance * module;
|
||||
KrkValue currentException;
|
||||
int flags;
|
||||
long watchdog;
|
||||
KrkInstance * module; /**< The current module execution context. */
|
||||
KrkValue currentException; /**< When an exception is thrown, it is stored here. */
|
||||
int flags; /**< Thread-local VM flags; each thread inherits the low byte of the global VM flags. */
|
||||
long watchdog; /**< Decrementing watchdog timer for embedding. */
|
||||
|
||||
#define THREAD_SCRATCH_SIZE 3
|
||||
KrkValue scratchSpace[THREAD_SCRATCH_SIZE];
|
||||
KrkValue scratchSpace[THREAD_SCRATCH_SIZE]; /**< A place to store a few values to keep them from being prematurely GC'd. */
|
||||
} KrkThreadState;
|
||||
|
||||
/**
|
||||
* @brief 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.
|
||||
*/
|
||||
typedef struct {
|
||||
int globalFlags; /* Global VM state flags */
|
||||
char * binpath; /* A string representing the name of the interpreter binary. */
|
||||
KrkTable strings; /* Strings table */
|
||||
KrkTable modules; /* Module cache */
|
||||
KrkInstance * builtins; /* '__builtins__' module */
|
||||
KrkInstance * system; /* 'kuroko' module */
|
||||
KrkValue * specialMethodNames; /* Cached strings of important method and function names */
|
||||
struct BaseClasses * baseClasses; /* Pointer to a (static) namespacing struct for the KrkClass*'s of built-in object types */
|
||||
struct Exceptions * exceptions; /* Pointer to a (static) namespacing struct for the KrkClass*'s of basic exception types */
|
||||
int globalFlags; /**< Global VM state flags */
|
||||
char * binpath; /**< A string representing the name of the interpreter binary. */
|
||||
KrkTable strings; /**< Strings table */
|
||||
KrkTable modules; /**< Module cache */
|
||||
KrkInstance * builtins; /**< '__builtins__' module */
|
||||
KrkInstance * system; /**< 'kuroko' module */
|
||||
KrkValue * specialMethodNames; /**< Cached strings of important method and function names */
|
||||
struct BaseClasses * baseClasses; /**< Pointer to a (static) namespacing struct for the KrkClass*'s of built-in object types */
|
||||
struct Exceptions * exceptions; /**< Pointer to a (static) namespacing struct for the KrkClass*'s of basic exception types */
|
||||
|
||||
/* Garbage collector state */
|
||||
KrkObj * objects; /* Linked list of all objects in the GC */
|
||||
size_t bytesAllocated; /* Running total of bytes allocated */
|
||||
size_t nextGC; /* Point at which we should sweep again */
|
||||
size_t grayCount; /* Count of objects marked by scan. */
|
||||
size_t grayCapacity; /* How many objects we can fit in the scan list. */
|
||||
KrkObj** grayStack; /* Scan list */
|
||||
KrkObj * objects; /**< Linked list of all objects in the GC */
|
||||
size_t bytesAllocated; /**< Running total of bytes allocated */
|
||||
size_t nextGC; /**< Point at which we should sweep again */
|
||||
size_t grayCount; /**< Count of objects marked by scan. */
|
||||
size_t grayCapacity; /**< How many objects we can fit in the scan list. */
|
||||
KrkObj** grayStack; /**< Scan list */
|
||||
|
||||
KrkThreadState * threads; /* All the threads. */
|
||||
KrkThreadState * threads; /**< Invasive linked list of all VM threads. */
|
||||
} KrkVM;
|
||||
|
||||
/* Thread-specific flags */
|
||||
/* TODO Should these be in an enum instead? */
|
||||
#define KRK_ENABLE_TRACING (1 << 0)
|
||||
#define KRK_ENABLE_DISASSEMBLY (1 << 1)
|
||||
#define KRK_ENABLE_SCAN_TRACING (1 << 2)
|
||||
@ -165,47 +216,447 @@ extern __thread KrkThreadState krk_currentThread;
|
||||
extern KrkThreadState krk_currentThread;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Singleton instance of the shared VM state.
|
||||
*/
|
||||
extern KrkVM krk_vm;
|
||||
#define vm krk_vm
|
||||
|
||||
/**
|
||||
* @brief Initialize the VM at program startup.
|
||||
*
|
||||
* All library users must call this exactly once on startup to create
|
||||
* the built-in types, modules, and functions for the VM and prepare
|
||||
* the string and module tables. Optionally, callers may set `vm.binpath`
|
||||
* before calling krk_initVM to allow the VM to locate the interpreter
|
||||
* binary and establish the default module paths.
|
||||
*
|
||||
* @param flags Combination of global VM flags and initial thread flags.
|
||||
*/
|
||||
extern void krk_initVM(int flags);
|
||||
|
||||
/**
|
||||
* @brief Release resources from the VM.
|
||||
*
|
||||
* Generally, it is desirable to call this once before the hosting program exits.
|
||||
* If a fresh VM state is needed, krk_freeVM should be called before a further
|
||||
* call to krk_initVM is made. The resources released here can include allocated
|
||||
* heap memory, FILE pointers or descriptors, or various other things which were
|
||||
* initialized by C extension modules.
|
||||
*/
|
||||
extern void krk_freeVM(void);
|
||||
|
||||
/**
|
||||
* @brief Reset the current thread's stack state to the top level.
|
||||
*
|
||||
* In a repl, this can 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 .
|
||||
*/
|
||||
extern void krk_resetStack(void);
|
||||
|
||||
/**
|
||||
* @brief Compile and execute a source code input.
|
||||
*
|
||||
* This is the lowest level call for most usecases, including execution
|
||||
* of commands from a REPL or when executing a file.
|
||||
*
|
||||
* @param src Source code to compile and run.
|
||||
* @param newScope Whether this code should be interpreted in the context of a new module.
|
||||
* @param fromName Name of the function or module being interpreted.
|
||||
* @param fromFile Path to the source file, or a representative string like "<stdin>".
|
||||
* @return When newScope is non-zero, an object representing the globals of the new scope;
|
||||
* otherwise, the returned result of the execution of this code. If an uncaught
|
||||
* exception occurred, this will be None, krk_currentThread.flags should indicate
|
||||
* KRK_HAS_EXCEPTION, and krk_currentThread.currentException should contain the raised
|
||||
* exception value.
|
||||
*/
|
||||
extern KrkValue krk_interpret(const char * src, int newScope, char *, char *);
|
||||
|
||||
/**
|
||||
* @brief 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)
|
||||
*
|
||||
* @param fileName Path to the source file to read and execute.
|
||||
* @param newScope Whether this file should be run in the context of a new module.
|
||||
* @param fromName Value to assign to __name__
|
||||
* @param fromFile Value to assign to __file__
|
||||
* @return As with krk_interpret, an object representing the newly created module,
|
||||
* or the final return value of the VM execution.
|
||||
*/
|
||||
extern KrkValue krk_runfile(const char * fileName, int newScope, char *, char *);
|
||||
|
||||
/**
|
||||
* @brief Load and run a file as a module.
|
||||
*
|
||||
* Similar to krk_runfile, but ensures that execution of the VM returns to the caller
|
||||
* after the file is run. This should be run after calling krk_startModule to initialize
|
||||
* a new module context and is used internally by the import mechanism.
|
||||
*
|
||||
* @param fileName Path to the source file to read and execute.
|
||||
* @param fromName Value to assign to __name__
|
||||
* @param fromFile Value to assign to __file__
|
||||
* @return The object representing the module, or None if execution of the file failed.
|
||||
*/
|
||||
extern KrkValue krk_callfile(const char * fileName, char * fromName, char * fromFile);
|
||||
|
||||
/**
|
||||
* @brief 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.
|
||||
*
|
||||
* @param value Value to push.
|
||||
*/
|
||||
extern void krk_push(KrkValue value);
|
||||
|
||||
/**
|
||||
* @brief 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.
|
||||
*
|
||||
* @return The value previously at the top of the stack.
|
||||
*/
|
||||
extern KrkValue krk_pop(void);
|
||||
|
||||
/**
|
||||
* @brief Peek down from the top of the stack.
|
||||
*
|
||||
* Obtains a value from the current thread's stack without modifying the stack.
|
||||
*
|
||||
* @param distance How far down from the top of the stack to peek (0 = the top)
|
||||
* @return The value from the stack.
|
||||
*/
|
||||
extern KrkValue krk_peek(int distance);
|
||||
|
||||
/**
|
||||
* @brief Get the name of the type of a value.
|
||||
*
|
||||
* Obtains the C string representing the name of the class
|
||||
* associated with the given value. Useful for crafting
|
||||
* exception messages, such as those describing TypeErrors.
|
||||
*
|
||||
* @param value Value to examine
|
||||
* @return Nul-terminated C string of the type of 'value'.
|
||||
*/
|
||||
extern const char * krk_typeName(KrkValue value);
|
||||
|
||||
/**
|
||||
* @brief Attach a native C function to an attribute table.
|
||||
*
|
||||
* Attaches the given native function pointer to an attribute table
|
||||
* while managing the stack shuffling and boxing of both the name and
|
||||
* the function object. If 'name' begins with a '.', the native function
|
||||
* is marked as a method. If 'name' begins with a ':', the native function
|
||||
* is marked as a dynamic property.
|
||||
*
|
||||
* @param table Attribute table to attach to, such as &someInstance->fields
|
||||
* @param name Nil-terminated C string with the name to assign
|
||||
* @param function Native function pointer to attach
|
||||
* @return A pointer to the object representing the attached function.
|
||||
*/
|
||||
extern KrkNative * krk_defineNative(KrkTable * table, const char * name, NativeFn function);
|
||||
|
||||
/**
|
||||
* @brief Attach a native dynamic property to an attribute table.
|
||||
*
|
||||
* Mostly the same as defineNative, but ensures the creation of a dynamic property.
|
||||
* The intention of this function is to replace uses of defineNative with ":" names,
|
||||
* and replace specialized methods with KrkProperty* objects.
|
||||
*
|
||||
* @param table Attribute table to attach to, such as &someInstance->fields
|
||||
* @param name Nil-terminated C string with the name to assign
|
||||
* @param function Native function pointer to attach
|
||||
* @return A pointer to the property object created.
|
||||
*/
|
||||
extern KrkProperty * krk_defineNativeProperty(KrkTable * table, const char * name, NativeFn func);
|
||||
extern void krk_attachNamedObject(KrkTable * table, const char name[], KrkObj * obj);
|
||||
|
||||
/**
|
||||
* @brief Attach a value to an attribute table.
|
||||
*
|
||||
* Manages the stack shuffling and boxing of the name string when attaching
|
||||
* a value to an attribute table. Rather than using krk_tableSet, this is
|
||||
* the preferred method of supplying fields to objects from C code.
|
||||
*
|
||||
* @param table Attribute table to attach to, such as &someInstance->fields
|
||||
* @param name Nil-terminated C string with the name to assign
|
||||
* @param obj Value to attach.
|
||||
*/
|
||||
extern void krk_attachNamedValue(KrkTable * table, const char name[], KrkValue obj);
|
||||
|
||||
/**
|
||||
* @brief Attach an object to an attribute table.
|
||||
*
|
||||
* Manages the stack shuffling and boxing of the name string when attaching
|
||||
* an object to an attribute table. Rather than using krk_tableSet, this is
|
||||
* the preferred method of supplying fields to objects from C code.
|
||||
*
|
||||
* This is a convenience wrapper around krk_attachNamedValue.
|
||||
*
|
||||
* @param table Attribute table to attach to, such as &someInstance->fields
|
||||
* @param name Nil-terminated C string with the name to assign
|
||||
* @param obj Object to attach.
|
||||
*/
|
||||
extern void krk_attachNamedObject(KrkTable * table, const char name[], KrkObj * obj);
|
||||
|
||||
/**
|
||||
* @brief Raise an exception.
|
||||
*
|
||||
* 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 HAS_EXCEPTION flag is set.
|
||||
*
|
||||
* @param type Class pointer for the exception type, eg. vm.exceptions->valueError
|
||||
* @param fmt Format string.
|
||||
* @return As a convenience to C extension authors, returns None.
|
||||
*/
|
||||
extern KrkValue krk_runtimeError(KrkClass * type, const char * fmt, ...);
|
||||
|
||||
/**
|
||||
* @brief 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.
|
||||
*
|
||||
* @return Pointer to current thread's thread state.
|
||||
*/
|
||||
extern KrkThreadState * krk_getCurrentThread(void);
|
||||
|
||||
extern KrkInstance * krk_dictCreate(void);
|
||||
/**
|
||||
* @brief 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.
|
||||
*
|
||||
* @return Value returned by the exit trigger, generally the value
|
||||
* returned by the inner function before the VM returned
|
||||
* to the exit frame.
|
||||
*/
|
||||
extern KrkValue krk_runNext(void);
|
||||
extern KrkClass * krk_getType(KrkValue);
|
||||
|
||||
/**
|
||||
* @brief Get the class representing a value.
|
||||
*
|
||||
* Returns the class object representing the type of a value.
|
||||
* This may be the direct class of an instance, or a pseudoclass
|
||||
* for other value types.
|
||||
*
|
||||
* @param value Reference value to examine.
|
||||
* @return A pointer to the value's type's class object.
|
||||
*/
|
||||
extern KrkClass * krk_getType(KrkValue value);
|
||||
|
||||
/**
|
||||
* @brief Determine if a class is an instance or subclass of a given type.
|
||||
*
|
||||
* Searches the class hierarchy of the given value to determine if it is
|
||||
* a subtype of 'type'. As this chains through the inheritence tree, the
|
||||
* more deeply subclassed 'obj' is, the longer it may take to determine
|
||||
* if it is a subtype of 'type'. All types should eventually be subtypes
|
||||
* of the 'object' type, so this condition should not be checked. For
|
||||
* some types, convenience macros are available. If you need to check if
|
||||
* 'obj' is a specific type, exclusive of subtypes, compare krk_getType
|
||||
* instead of using this function.
|
||||
*
|
||||
* @param obj Value to examine.
|
||||
* @param type Class object to test for membership of.
|
||||
* @return 1 if obj is an instance of type or of a subclass of type
|
||||
*/
|
||||
extern int krk_isInstanceOf(KrkValue obj, KrkClass * type);
|
||||
|
||||
/**
|
||||
* @brief Perform method binding on the stack.
|
||||
*
|
||||
* Performs attribute lookup from the class '_class' for 'name'.
|
||||
* If 'name' is not a valid method, the binding fails.
|
||||
* If 'name' is a valid method, the method will be retrieved and
|
||||
* bound to the instance on the top of the stack, replacing it
|
||||
* with a BoundMethod object.
|
||||
*
|
||||
* @param _class Class object to resolve methods from.
|
||||
* @param name String object with the name of the method to resolve.
|
||||
* @return 1 if the method has been bound, 0 if binding failed.
|
||||
*/
|
||||
extern int krk_bindMethod(KrkClass * _class, KrkString * name);
|
||||
|
||||
/**
|
||||
* @brief Call a callable value in the current stack context.
|
||||
*
|
||||
* Executes the given callable object (function, bound method, object
|
||||
* with a __call__() method, etc.) using 'argCount' arguments from the stack.
|
||||
*
|
||||
* @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.
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @brief Create a list object.
|
||||
*
|
||||
* This is the native function bound to 'listOf'.
|
||||
*/
|
||||
extern KrkValue krk_list_of(int argc, KrkValue argv[], int hasKw);
|
||||
|
||||
/**
|
||||
* @brief Create a dict object.
|
||||
*
|
||||
* This is the native function bound to 'dictOf'
|
||||
*/
|
||||
extern KrkValue krk_dict_of(int argc, KrkValue argv[], int hasKw);
|
||||
|
||||
/**
|
||||
* @brief Create a tuple object.
|
||||
*
|
||||
* This is the native function bound to 'tupleOf'.
|
||||
*/
|
||||
extern KrkValue krk_tuple_of(int argc, KrkValue argv[], int hasKw);
|
||||
|
||||
/**
|
||||
* @brief Call a callable and manage VM state to obtain the return value.
|
||||
*
|
||||
* 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
|
||||
* krk_callValue's 'extra' paramater for details on how 'isMethod' is used.
|
||||
*
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @brief Convenience function for creating new types.
|
||||
*
|
||||
* Creates a class object, output to *_class, setting its name to 'name', inheriting
|
||||
* from 'base', and attaching it with its name to the fields table of the given 'module'.
|
||||
*
|
||||
* @param module Pointer to an instance for a module to attach to, or NULL to skip attaching.
|
||||
* @param _class Output pointer to assign the new class object to.
|
||||
* @param name Name of the new class.
|
||||
* @param base Pointer to class object to inherit from.
|
||||
* @return A pointer to the class object, equivalent to the value assigned to *_class.
|
||||
*/
|
||||
extern KrkClass * krk_makeClass(KrkInstance * module, KrkClass ** _class, const char * name, KrkClass * base);
|
||||
|
||||
/**
|
||||
* @brief Finalize a class by collecting pointers to core methods.
|
||||
*
|
||||
* Scans through the methods table of a class object to find special
|
||||
* methods and assign them to the class object's pointer table so they
|
||||
* can be referenced directly without performing hash lookups.
|
||||
*
|
||||
* @param _class Class object to finalize.
|
||||
*/
|
||||
extern void krk_finalizeClass(KrkClass * _class);
|
||||
|
||||
/**
|
||||
* @brief 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 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__.
|
||||
*/
|
||||
extern void krk_dumpTraceback();
|
||||
|
||||
/**
|
||||
* @brief 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.
|
||||
*
|
||||
* @param name Name of the module, which is assigned to __name__
|
||||
* @return The instance object representing the module.
|
||||
*/
|
||||
extern KrkInstance * krk_startModule(const char * name);
|
||||
|
||||
/**
|
||||
* @brief Obtain a list of properties for an object.
|
||||
*
|
||||
* This is the native function bound to 'object.__dir__'
|
||||
*/
|
||||
extern KrkValue krk_dirObject(int argc, KrkValue argv[], int hasKw);
|
||||
|
||||
/**
|
||||
* @brief Load a module by name.
|
||||
*
|
||||
* This is generally called by the import mechanisms to load a single module.
|
||||
*
|
||||
* @param name Name of the module, used for file lookup.
|
||||
* @param moduleOut Receives a value with the module object.
|
||||
* @param runAs Name to attach to __name__ for this module, different from 'name'.
|
||||
* @return 1 if the module was loaded, 0 if an ImportError occurred.
|
||||
*/
|
||||
extern int krk_loadModule(KrkString * name, KrkValue * moduleOut, KrkString * runAs);
|
||||
|
||||
/* obj_str.h */
|
||||
/**
|
||||
* @brief Load a module from a package.
|
||||
*
|
||||
* Given a package identifier, attempt to the load module
|
||||
* into the module table.
|
||||
*
|
||||
* @param name String object of the dot-separated package path to import.
|
||||
* @return 1 if the module was loaded, 0 if an ImportError occurred.
|
||||
*/
|
||||
extern int krk_doRecursiveModuleLoad(KrkString * name);
|
||||
|
||||
/**
|
||||
* @brief Determine the truth of a value.
|
||||
*
|
||||
* Determines if a value represents a "falsey" value.
|
||||
* Empty collections, 0-length strings, False, numeric 0,
|
||||
* None, etc. are "falsey". Other values are generally "truthy".
|
||||
*
|
||||
* @param value Value to examine.
|
||||
* @return 1 if falsey, 0 if truthy
|
||||
*/
|
||||
extern int krk_isFalsey(KrkValue value);
|
||||
|
||||
/**
|
||||
* @brief 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.
|
||||
*/
|
||||
extern void krk_addObjects(void);
|
||||
|
||||
/**
|
||||
* All of the remaining stuff is internal and shouldn't be used by library users or embedders.
|
||||
* FIXME This stuff needs to be moved to another header! FIXME
|
||||
*/
|
||||
|
||||
extern KrkValue _str___get__(int argc, KrkValue argv[], int hasKw);
|
||||
#define krk_string_get _str___get__
|
||||
extern KrkValue _str___int__(int argc, KrkValue argv[], int hasKw);
|
||||
@ -220,7 +671,6 @@ extern KrkValue _str_format(int argc, KrkValue argv[], int hasKw);
|
||||
/* obj_dict.h */
|
||||
extern KrkValue krk_dict_nth_key_fast(size_t capacity, KrkTableEntry * entries, size_t index);
|
||||
|
||||
extern int krk_isFalsey(KrkValue value);
|
||||
|
||||
extern void _createAndBind_numericClasses(void);
|
||||
extern void _createAndBind_strClass(void);
|
||||
@ -239,7 +689,6 @@ extern void _createAndBind_timeMod(void);
|
||||
extern void _createAndBind_osMod(void);
|
||||
extern void _createAndBind_fileioMod(void);
|
||||
|
||||
extern int krk_doRecursiveModuleLoad(KrkString * name);
|
||||
|
||||
extern KrkValue krk_operator_lt(KrkValue,KrkValue);
|
||||
extern KrkValue krk_operator_gt(KrkValue,KrkValue);
|
||||
|
Loading…
Reference in New Issue
Block a user