Expanded bytecode inspector, added functions to Toy_copyValue

This commit is contained in:
2026-04-17 11:55:46 +10:00
parent 81c95ff69d
commit 5b101d763e
12 changed files with 175 additions and 77 deletions

View File

@@ -1222,10 +1222,13 @@ static void writeBytecodeBody(Toy_Bytecode* mb, Toy_Ast* ast) {
writeBytecodeFromAst(&mb, ast);
EMIT_BYTE(&mb, code, TOY_OPCODE_RETURN); //end terminator
EMIT_BYTE(&mb, code, 0); //4-byte alignment
EMIT_BYTE(&mb, code, 0);
EMIT_BYTE(&mb, code, 0);
//append an extra return if needed
if (mb->codeCount <= 4 || mb->code[mb->codeCount - 4] != TOY_OPCODE_RETURN) { //if empty or no return statement
EMIT_BYTE(&mb, code, TOY_OPCODE_RETURN); //end terminator
EMIT_BYTE(&mb, code, 0); //4-byte alignment
EMIT_BYTE(&mb, code, 0);
EMIT_BYTE(&mb, code, 0);
}
}
static unsigned char* collateBytecodeBody(Toy_Bytecode* mb) {

View File

@@ -20,6 +20,23 @@ Toy_Function* Toy_createFunctionFromCallback(Toy_Bucket** bucketHandle, Toy_nati
return fn;
}
Toy_Function* Toy_copyFunction(Toy_Bucket** bucketHandle, Toy_Function* original) {
Toy_Function* fn = (Toy_Function*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Function));
if (original->type == TOY_FUNCTION_CUSTOM) {
fn->type = original->type;
fn->bytecode.code = original->bytecode.code;
fn->bytecode.parentScope = original->bytecode.parentScope;
Toy_private_incrementScopeRefCount(fn->bytecode.parentScope);
}
else if (fn->type == TOY_FUNCTION_NATIVE) {
fn->type = original->type;
fn->native.callback = original->native.callback;
}
return fn;
}
TOY_API void Toy_freeFunction(Toy_Function* fn) {
if (fn->type == TOY_FUNCTION_CUSTOM) {
Toy_private_decrementScopeRefCount(fn->bytecode.parentScope);

View File

@@ -34,4 +34,5 @@ typedef union Toy_Function_t {
TOY_API Toy_Function* Toy_createFunctionFromBytecode(Toy_Bucket** bucketHandle, unsigned char* bytecode, Toy_Scope* parentScope);
TOY_API Toy_Function* Toy_createFunctionFromCallback(Toy_Bucket** bucketHandle, Toy_nativeCallback callback);
TOY_API Toy_Function* Toy_copyFunction(Toy_Bucket** bucketHandle, Toy_Function* fn);
TOY_API void Toy_freeFunction(Toy_Function* fn);

View File

@@ -90,7 +90,7 @@ unsigned int Toy_hashValue(Toy_Value value) {
return 0;
}
Toy_Value Toy_copyValue(Toy_Value value) {
Toy_Value Toy_copyValue(Toy_Bucket** bucketHandle, Toy_Value value) {
MAYBE_UNWRAP(value);
switch(value.type) {
@@ -104,13 +104,13 @@ Toy_Value Toy_copyValue(Toy_Value value) {
return TOY_VALUE_FROM_STRING(Toy_copyString(value.as.string));
}
case TOY_VALUE_ARRAY: {
case TOY_VALUE_ARRAY: { //TODO: switch to buckets
//arrays probably won't get copied much
Toy_Array* ptr = value.as.array;
Toy_Array* result = Toy_resizeArray(NULL, ptr->capacity);
for (unsigned int i = 0; i < ptr->count; i++) {
result->data[i] = Toy_copyValue(ptr->data[i]);
result->data[i] = Toy_copyValue(bucketHandle, ptr->data[i]);
}
result->capacity = ptr->capacity;
@@ -119,15 +119,15 @@ Toy_Value Toy_copyValue(Toy_Value value) {
return TOY_VALUE_FROM_ARRAY(result);
}
case TOY_VALUE_TABLE: {
case TOY_VALUE_TABLE: { //TODO: switch to buckets
//tables probably won't get copied much
Toy_Table* ptr = value.as.table;
Toy_Table* result = Toy_private_adjustTableCapacity(NULL, ptr->capacity);
for (unsigned int i = 0; i < ptr->capacity; i++) {
if (TOY_VALUE_IS_NULL(ptr->data[i].key) != true) {
result->data[i].key = Toy_copyValue(ptr->data[i].key);
result->data[i].value = Toy_copyValue(ptr->data[i].value);
result->data[i].key = Toy_copyValue(bucketHandle, ptr->data[i].key);
result->data[i].value = Toy_copyValue(bucketHandle, ptr->data[i].value);
}
}
@@ -137,9 +137,8 @@ Toy_Value Toy_copyValue(Toy_Value value) {
return TOY_VALUE_FROM_TABLE(result);
}
case TOY_VALUE_FUNCTION: //TODO: implement function duplication elsewhere
fprintf(stderr, TOY_CC_ERROR "ERROR: Can't copy a function (use a reference instead), exiting\n" TOY_CC_RESET);
exit(-1);
case TOY_VALUE_FUNCTION:
return TOY_VALUE_FROM_FUNCTION(Toy_copyFunction(bucketHandle, value.as.function));
case TOY_VALUE_OPAQUE:
case TOY_VALUE_ANY:

View File

@@ -2,9 +2,9 @@
#include "toy_common.h"
#include "toy_print.h"
#include "toy_bucket.h"
//forward declarations
struct Toy_Bucket;
union Toy_String_t;
struct Toy_Array;
struct Toy_Table;
@@ -79,7 +79,7 @@ typedef struct Toy_Value { //32 | 64 BITNESS
TOY_API Toy_Value Toy_unwrapValue(Toy_Value value);
TOY_API unsigned int Toy_hashValue(Toy_Value value);
TOY_API Toy_Value Toy_copyValue(Toy_Value value);
TOY_API Toy_Value Toy_copyValue(struct Toy_Bucket** bucketHandle, Toy_Value value);
TOY_API void Toy_freeValue(Toy_Value value);
TOY_API bool Toy_checkValueIsTruthy(Toy_Value value);

View File

@@ -159,7 +159,7 @@ static void processRead(Toy_VM* vm) {
unsigned int addr = (unsigned int)READ_INT(vm);
//create and push the function value
Toy_Function* function = Toy_createFunctionFromBytecode(&vm->memoryBucket, vm->code + vm->subsAddr + addr, vm->scope);
Toy_Function* function = Toy_createFunctionFromBytecode(&vm->memoryBucket, vm->code + vm->subsAddr + addr, vm->scope); //BUG: functions don't have the jumps indirection?
value = TOY_VALUE_FROM_FUNCTION(function);
break;
@@ -227,7 +227,7 @@ static void processAssign(Toy_VM* vm) {
//in case of chaining, leave a copy on the stack
bool chainedAssignment = READ_BYTE(vm);
if (chainedAssignment) {
Toy_pushStack(&vm->stack, Toy_copyValue(value));
Toy_pushStack(&vm->stack, Toy_copyValue(&vm->memoryBucket, value));
}
//cleanup
@@ -253,7 +253,7 @@ static void processAssignCompound(Toy_VM* vm) {
target = TOY_REFERENCE_FROM_POINTER(valuePtr);
}
else {
target = Toy_copyValue(*valuePtr);
target = Toy_copyValue(&vm->memoryBucket, *valuePtr);
}
}
@@ -280,12 +280,12 @@ static void processAssignCompound(Toy_VM* vm) {
}
//set the value
array->data[index] = Toy_copyValue(TOY_VALUE_IS_REFERENCE(value) ? Toy_unwrapValue(value) : value);
array->data[index] = Toy_copyValue(&vm->memoryBucket, TOY_VALUE_IS_REFERENCE(value) ? Toy_unwrapValue(value) : value);
//in case of chaining, leave a copy on the stack
bool chainedAssignment = READ_BYTE(vm);
if (chainedAssignment) {
Toy_pushStack(&vm->stack, Toy_copyValue(value));
Toy_pushStack(&vm->stack, Toy_copyValue(&vm->memoryBucket, value));
}
//cleanup
@@ -296,12 +296,12 @@ static void processAssignCompound(Toy_VM* vm) {
Toy_Table* table = TOY_VALUE_AS_TABLE(target);
//set the value
Toy_insertTable(&table, Toy_copyValue(TOY_VALUE_IS_REFERENCE(key) ? Toy_unwrapValue(key) : key), Toy_copyValue(TOY_VALUE_IS_REFERENCE(value) ? Toy_unwrapValue(value) : value));
Toy_insertTable(&table, Toy_copyValue(&vm->memoryBucket, TOY_VALUE_IS_REFERENCE(key) ? Toy_unwrapValue(key) : key), Toy_copyValue(&vm->memoryBucket, TOY_VALUE_IS_REFERENCE(value) ? Toy_unwrapValue(value) : value));
//in case of chaining, leave a copy on the stack
bool chainedAssignment = READ_BYTE(vm);
if (chainedAssignment) {
Toy_pushStack(&vm->stack, Toy_copyValue(value));
Toy_pushStack(&vm->stack, Toy_copyValue(&vm->memoryBucket, value));
}
//cleanup
@@ -335,7 +335,7 @@ static void processAccess(Toy_VM* vm) {
Toy_pushStack(&vm->stack, ref);
}
else {
Toy_pushStack(&vm->stack, Toy_copyValue(*valuePtr));
Toy_pushStack(&vm->stack, Toy_copyValue(&vm->memoryBucket, *valuePtr));
}
//cleanup
@@ -403,7 +403,7 @@ static void processInvoke(Toy_VM* vm) {
//extract and store any results
if (resultCount > 0) {
Toy_Array* results = Toy_extractResultsFromVM(&subVM, resultCount);
Toy_Array* results = Toy_extractResultsFromVM(vm, &subVM, resultCount);
for (unsigned int i = 0; i < results->count; i++) {
//NOTE: since the results array is being immediately freed, just push each element without a call to copy
@@ -432,7 +432,7 @@ static void processInvoke(Toy_VM* vm) {
}
static void processDuplicate(Toy_VM* vm) {
Toy_Value value = Toy_copyValue(Toy_peekStack(&vm->stack));
Toy_Value value = Toy_copyValue(&vm->memoryBucket, Toy_peekStack(&vm->stack));
Toy_pushStack(&vm->stack, value);
//check for compound assignments
@@ -878,7 +878,7 @@ static void processIndex(Toy_VM* vm) {
Toy_pushStack(&vm->stack, ref);
}
else {
Toy_pushStack(&vm->stack, Toy_copyValue(array->data[i]));
Toy_pushStack(&vm->stack, Toy_copyValue(&vm->memoryBucket, array->data[i]));
}
}
@@ -911,7 +911,7 @@ static void processIndex(Toy_VM* vm) {
Toy_pushStack(&vm->stack, ref);
}
else {
Toy_pushStack(&vm->stack, Toy_copyValue(entry->value));
Toy_pushStack(&vm->stack, Toy_copyValue(&vm->memoryBucket, entry->value));
}
}
@@ -1146,7 +1146,7 @@ void Toy_freeVM(Toy_VM* vm) {
}
}
Toy_Array* Toy_extractResultsFromVM(Toy_VM* subVM, unsigned int resultCount) {
Toy_Array* Toy_extractResultsFromVM(Toy_VM* parentVM, Toy_VM* subVM, unsigned int resultCount) {
if (subVM->stack->count < resultCount) {
fprintf(stderr, TOY_CC_ERROR "ERROR: Too many results requested from VM, exiting\n" TOY_CC_RESET);
exit(-1);
@@ -1156,8 +1156,8 @@ Toy_Array* Toy_extractResultsFromVM(Toy_VM* subVM, unsigned int resultCount) {
const unsigned int offset = subVM->stack->count - resultCount; //first element to extract
for (/* EMPTY */; results->count < resultCount; results->count++) {
results->data[results->count] = Toy_copyValue(subVM->stack->data[offset + results->count]);
for (/* EMPTY */; results->count < resultCount; results->count++) { //TODO: make sure the parent bucket adopts the child bucket's responsibilities
results->data[results->count] = Toy_copyValue(&parentVM->memoryBucket, subVM->stack->data[offset + results->count]);
}
return results;

View File

@@ -51,6 +51,6 @@ void Toy_bindVM(Toy_VM* vm, unsigned char* bytecode, Toy_Scope* parentScope);
TOY_API unsigned int Toy_runVM(Toy_VM* vm);
TOY_API void Toy_freeVM(Toy_VM* vm);
TOY_API Toy_Array* Toy_extractResultsFromVM(Toy_VM* subVM, unsigned int resultCount);
TOY_API Toy_Array* Toy_extractResultsFromVM(Toy_VM* parentVM, Toy_VM* subVM, unsigned int resultCount);
//TODO: inject extra data (hook system for external libraries)