More doc comments
This commit is contained in:
parent
076b702afa
commit
c567204f65
62
src/chunk.h
62
src/chunk.h
@ -4,11 +4,21 @@
|
||||
#include "value.h"
|
||||
|
||||
/**
|
||||
* Opcodes
|
||||
* @brief Instruction opcode values
|
||||
*
|
||||
* These are pretty much entirely based on the clox opcodes from the book.
|
||||
* There's not really much else to add here, since the VM is sufficient for
|
||||
* our needs. Most of the interesting changes happen in the compiler.
|
||||
* The instruction opcode table is divided in four parts. The high two bits of each
|
||||
* opcode encodes the number of operands to pull from the codeobject and thus the
|
||||
* size (generally) of the instruction (note that OP_CLOSURE(_LONG) has additional
|
||||
* arguments depending on the function it points to).
|
||||
*
|
||||
* 0-operand opcodes are "simple" instructions that generally only deal with stack
|
||||
* values and require no additional arguments.
|
||||
*
|
||||
* 1- and 3- operand opcodes are paired as 'short' and 'long'. While the VM does not
|
||||
* currently depend on these instructions having the same values in the lower 6 bits,
|
||||
* it is recommended that this property remain true.
|
||||
*
|
||||
* 2-operand opcodes are generally jump instructions.
|
||||
*/
|
||||
typedef enum {
|
||||
OP_ADD = 1,
|
||||
@ -111,13 +121,32 @@ typedef enum {
|
||||
OP_UNPACK_LONG,
|
||||
} KrkOpCode;
|
||||
|
||||
/**
|
||||
* @brief Map entry of instruction offsets to line numbers.
|
||||
*
|
||||
* Each code object contains an array of line mappings, indicating
|
||||
* the start offset of each line. Since a line typically maps to
|
||||
* multiple opcodes, and spans of many lines may map to no opcodes
|
||||
* in the case of blank lines or docstrings, this array is stored
|
||||
* as a sequence of <starOffset, line> pairs rather than a simple
|
||||
* array of one or the other.
|
||||
*/
|
||||
typedef struct {
|
||||
size_t startOffset;
|
||||
size_t line;
|
||||
} KrkLineMap;
|
||||
|
||||
/**
|
||||
* Bytecode chunks
|
||||
* @brief Opcode chunk of a code object.
|
||||
*
|
||||
* Opcode chunks are internal to code objects and I'm not really
|
||||
* sure why we're still separating them from the KrkFunction objects.
|
||||
*
|
||||
* Stores four flexible arrays using three different formats:
|
||||
* - Code, representing opcodes and operands.
|
||||
* - Lines, representing offset-to-line mappings.
|
||||
* - Filename, the string name of the source file.
|
||||
* - Constants, an array of values referenced by the code object.
|
||||
*/
|
||||
typedef struct {
|
||||
size_t count;
|
||||
@ -132,9 +161,32 @@ typedef struct {
|
||||
KrkValueArray constants;
|
||||
} KrkChunk;
|
||||
|
||||
/**
|
||||
* @brief Initialize an opcode chunk.
|
||||
*/
|
||||
extern void krk_initChunk(KrkChunk * chunk);
|
||||
|
||||
/**
|
||||
* @brief Append a byte to an opcode chunk.
|
||||
*/
|
||||
extern void krk_writeChunk(KrkChunk * chunk, uint8_t byte, size_t line);
|
||||
|
||||
/**
|
||||
* @brief Release the resources allocated to an opcode chunk.
|
||||
*/
|
||||
extern void krk_freeChunk(KrkChunk * chunk);
|
||||
|
||||
/**
|
||||
* @brief Add a new constant value to an opcode chunk.
|
||||
*/
|
||||
extern size_t krk_addConstant(KrkChunk * chunk, KrkValue value);
|
||||
|
||||
/**
|
||||
* @brief Write an OP_CONSTANT(_LONG) instruction.
|
||||
*/
|
||||
extern void krk_emitConstant(KrkChunk * chunk, size_t ind, size_t line);
|
||||
|
||||
/**
|
||||
* @brief Add a new constant and write an instruction for it.
|
||||
*/
|
||||
extern size_t krk_writeConstant(KrkChunk * chunk, KrkValue value, size_t line);
|
||||
|
@ -2,5 +2,19 @@
|
||||
|
||||
#include "object.h"
|
||||
|
||||
/**
|
||||
* @brief Compile a string to a code object.
|
||||
*
|
||||
* Compiles the source string 'src' into a code object.
|
||||
*
|
||||
* @param src Source code string to compile.
|
||||
* @param newScope Whether the compiler should treat the source as a new module.
|
||||
* @param fileName Path name of the source file or a representative string like "<stdin>"
|
||||
* @return The code object resulting from the compilation, or NULL if compilation failed.
|
||||
*/
|
||||
extern KrkFunction * krk_compile(const char * src, int newScope, char * fileName);
|
||||
|
||||
/**
|
||||
* @brief Mark objects owned by the compiler as in use.
|
||||
*/
|
||||
extern void krk_markCompilerRoots(void);
|
||||
|
@ -239,7 +239,7 @@ void krk_markTable(KrkTable * table) {
|
||||
}
|
||||
}
|
||||
|
||||
void krk_tableRemoveWhite(KrkTable * table) {
|
||||
static void tableRemoveWhite(KrkTable * table) {
|
||||
for (size_t i = 0; i < table->capacity; ++i) {
|
||||
KrkTableEntry * entry = &table->entries[i];
|
||||
if (IS_OBJECT(entry->key) && !(AS_OBJECT(entry->key))->isMarked) {
|
||||
@ -287,7 +287,7 @@ static void markRoots() {
|
||||
size_t krk_collectGarbage(void) {
|
||||
markRoots();
|
||||
traceReferences();
|
||||
krk_tableRemoveWhite(&vm.strings);
|
||||
tableRemoveWhite(&vm.strings);
|
||||
size_t out = sweep();
|
||||
vm.nextGC = vm.bytesAllocated * 2;
|
||||
return out;
|
||||
|
60
src/memory.h
60
src/memory.h
@ -12,10 +12,66 @@
|
||||
|
||||
#define ALLOCATE(type, count) (type*)krk_reallocate(NULL,0,sizeof(type)*(count))
|
||||
|
||||
extern void * krk_reallocate(void *, size_t, size_t);
|
||||
/**
|
||||
* @brief Resize an allocated heap object.
|
||||
*
|
||||
* Allocates or reallocates the heap object 'ptr', tracking changes
|
||||
* in sizes from 'old' to 'new'. If 'ptr' is NULL, 'old' should be 0,
|
||||
* and a new pointer will be allocated of size 'new'.
|
||||
*
|
||||
* @param ptr Heap object to resize.
|
||||
* @param old Current size of the object.
|
||||
* @param new New size of the object.
|
||||
* @return New pointer for heap object.
|
||||
*/
|
||||
extern void * krk_reallocate(void * ptr, size_t old, size_t new);
|
||||
|
||||
/**
|
||||
* @brief Release all objects.
|
||||
*
|
||||
* Generally called automatically by krk_freeVM(); releases all of
|
||||
* the GC-tracked heap objects.
|
||||
*/
|
||||
extern void krk_freeObjects(void);
|
||||
|
||||
/**
|
||||
* @brief Run a cycle of the garbage collector.
|
||||
*
|
||||
* Runs one scan-sweep cycle of the garbage collector, potentially
|
||||
* freeing unused resources and advancing potentially-unused
|
||||
* resources to the next stage of removal.
|
||||
*
|
||||
* @return The number of bytes released by this collection cycle.
|
||||
*/
|
||||
extern size_t krk_collectGarbage(void);
|
||||
|
||||
/**
|
||||
* @brief During a GC scan cycle, mark a value as used.
|
||||
*
|
||||
* When defining a new type in a C extension, this function should
|
||||
* be used by the type's _ongcscan callback to mark any values not
|
||||
* already tracked by the garbage collector.
|
||||
*
|
||||
* @param value The value to mark.
|
||||
*/
|
||||
extern void krk_markValue(KrkValue value);
|
||||
|
||||
/**
|
||||
* @brief During a GC scan cycle, mark an object as used.
|
||||
*
|
||||
* Equivalent to krk_markValue but operates directly on an object.
|
||||
*
|
||||
* @param object The object to mark.
|
||||
*/
|
||||
extern void krk_markObject(KrkObj * object);
|
||||
|
||||
/**
|
||||
* @brief During a GC scan cycle, mark the contents of a table as used.
|
||||
*
|
||||
* Marks all keys and values in a table as used. Generally applied
|
||||
* to the internal storage of mapping types.
|
||||
*
|
||||
* @param table The table to mark.
|
||||
*/
|
||||
extern void krk_markTable(KrkTable * table);
|
||||
extern void krk_tableRemoveWhite(KrkTable * table);
|
||||
|
||||
|
@ -99,6 +99,12 @@ typedef enum {
|
||||
TOKEN_EOF,
|
||||
} KrkTokenType;
|
||||
|
||||
/**
|
||||
* @brief A token from the scanner.
|
||||
*
|
||||
* Represents a single scanned item from the scanner, such as a keyword,
|
||||
* string literal, numeric literal, identifier, etc.
|
||||
*/
|
||||
typedef struct {
|
||||
KrkTokenType type;
|
||||
const char * start;
|
||||
@ -109,6 +115,12 @@ typedef struct {
|
||||
size_t literalWidth;
|
||||
} KrkToken;
|
||||
|
||||
/**
|
||||
* @brief Token scanner state.
|
||||
*
|
||||
* Stores the state of the compiler's scanner, reading from a source
|
||||
* character string and tracking the current line.
|
||||
*/
|
||||
typedef struct {
|
||||
const char * start;
|
||||
const char * cur;
|
||||
@ -119,8 +131,48 @@ typedef struct {
|
||||
KrkToken unget;
|
||||
} KrkScanner;
|
||||
|
||||
/**
|
||||
* @brief Initialize the compiler to scan tokens from 'src'.
|
||||
*
|
||||
* FIXME: There is currently only a single static scanner state;
|
||||
* along with making the compiler re-entrant, the scanner
|
||||
* needs to also be re-entrant; there's really no reason
|
||||
* these can't all just take a KrkScanner* argument.
|
||||
*/
|
||||
extern void krk_initScanner(const char * src);
|
||||
|
||||
/**
|
||||
* @brief Read the next token from the scanner.
|
||||
*
|
||||
* FIXME: Or, maybe the scanner shouldn't even be available outside
|
||||
* of the compiler, that would make some sense as well, as it's
|
||||
* a low-level detail, but we use it for tab completion in the
|
||||
* main repl, so I'm not sure that's feasible right now.
|
||||
*/
|
||||
extern KrkToken krk_scanToken(void);
|
||||
|
||||
/**
|
||||
* @brief Push a token back to the scanner to be reprocessed.
|
||||
*
|
||||
* Pushes a previously-scanned token back to the scanner.
|
||||
* Used to implement small backtracking operations at the
|
||||
* end of block constructs like 'if' and 'try'.
|
||||
*/
|
||||
extern void krk_ungetToken(KrkToken token);
|
||||
|
||||
/**
|
||||
* @brief Rewind the scanner to a previous state.
|
||||
*
|
||||
* Resets the current scanner to the state in 'to'. Used by
|
||||
* the compiler to implement comprehensions, which would otherwise
|
||||
* not be possible in a single-pass compiler.
|
||||
*/
|
||||
extern void krk_rewindScanner(KrkScanner to);
|
||||
|
||||
/**
|
||||
* @brief Retreive a copy of the current scanner state.
|
||||
*
|
||||
* Used with krk_rewindScanner() to implement rescanning
|
||||
* for comprehensions.
|
||||
*/
|
||||
extern KrkScanner krk_tellScanner(void);
|
||||
|
Loading…
Reference in New Issue
Block a user