WIP bad approach, read more

I build a self-referential system, then tried to copy only parts. I need
to step back and adjust my approach.

'Toy_private_deepCopyValue' and 'Toy_private_deepCopyScope' need to be
ripped out, and I need to simply accept there will be only one instance
of 'Toy_Bucket' that isn't freed until the top-level VM is.

I need an hour's break before I'll tackle this again.

See #163
This commit is contained in:
2025-02-18 13:06:15 +11:00
parent 3a82593e4d
commit 9fe6d6b218
7 changed files with 44 additions and 83 deletions

View File

@@ -1,29 +1,3 @@
/*
fn name(param1: int, param2: float, param3: string, param4) {
print param1;
print param2;
print param3;
print param4;
}
name(42, 3.14, "hello world", -1);
fn output(arg) {
print arg;
}
output(null);
output(true);
output(42);
output(3.1415);
output("woot!");
output([1, 23, 3]);
output(["key":1]);
output(name);
*/
//TODO: Not yet functional //TODO: Not yet functional
fn makeCounter() { fn makeCounter() {
var counter: int = 0; var counter: int = 0;

View File

@@ -94,9 +94,9 @@ Toy_Scope* Toy_popScope(Toy_Scope* scope) {
return scope->next; return scope->next;
} }
Toy_Scope* Toy_deepCopyScope(Toy_Bucket** bucketHandle, Toy_Scope* scope) { Toy_Scope* Toy_private_deepCopyScope(Toy_Bucket** scopeBucketHandle, Toy_Bucket** literalBucketHandle, Toy_Scope* scope) {
//copy/pasted from pushScope, so I can allocate the table manually //copy/pasted from pushScope, so I can allocate the table manually
Toy_Scope* newScope = (Toy_Scope*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Scope)); Toy_Scope* newScope = (Toy_Scope*)Toy_partitionBucket(scopeBucketHandle, sizeof(Toy_Scope));
newScope->next = scope->next; newScope->next = scope->next;
newScope->table = scope->table != NULL ? Toy_private_adjustTableCapacity(NULL, scope->table->capacity) : NULL; newScope->table = scope->table != NULL ? Toy_private_adjustTableCapacity(NULL, scope->table->capacity) : NULL;
@@ -108,7 +108,7 @@ Toy_Scope* Toy_deepCopyScope(Toy_Bucket** bucketHandle, Toy_Scope* scope) {
//forcibly copy the contents //forcibly copy the contents
for (unsigned int i = 0; i < scope->table->capacity; i++) { for (unsigned int i = 0; i < scope->table->capacity; i++) {
if (!TOY_VALUE_IS_NULL(scope->table->data[i].key)) { if (!TOY_VALUE_IS_NULL(scope->table->data[i].key)) {
Toy_insertTable(&newScope->table, Toy_copyValue(scope->table->data[i].key), Toy_copyValue(scope->table->data[i].value)); Toy_insertTable(&newScope->table, Toy_private_deepCopyValue(scopeBucketHandle, literalBucketHandle, scope->table->data[i].key), Toy_private_deepCopyValue(scopeBucketHandle, literalBucketHandle, scope->table->data[i].value));
} }
} }
} }

View File

@@ -19,7 +19,7 @@ TOY_API Toy_Scope* Toy_pushScope(Toy_Bucket** bucketHandle, Toy_Scope* scope);
TOY_API Toy_Scope* Toy_popScope(Toy_Scope* scope); TOY_API Toy_Scope* Toy_popScope(Toy_Scope* scope);
TOY_API Toy_Scope* Toy_private_pushDummyScope(Toy_Bucket** bucketHandle, Toy_Scope* scope); //doesn't delcare a table for storage TOY_API Toy_Scope* Toy_private_pushDummyScope(Toy_Bucket** bucketHandle, Toy_Scope* scope); //doesn't delcare a table for storage
TOY_API Toy_Scope* Toy_deepCopyScope(Toy_Bucket** bucketHandle, Toy_Scope* scope); TOY_API Toy_Scope* Toy_private_deepCopyScope(Toy_Bucket** scopeBucketHandle, Toy_Bucket** literalBucketHandle, Toy_Scope* scope);
//manage the contents //manage the contents
TOY_API void Toy_declareScope(Toy_Scope* scope, Toy_String* key, Toy_Value value); TOY_API void Toy_declareScope(Toy_Scope* scope, Toy_String* key, Toy_Value value);

View File

@@ -104,41 +104,9 @@ Toy_Value Toy_copyValue(Toy_Value value) {
return TOY_VALUE_FROM_STRING(Toy_copyString(value.as.string)); return TOY_VALUE_FROM_STRING(Toy_copyString(value.as.string));
} }
case TOY_VALUE_ARRAY: { case TOY_VALUE_ARRAY:
//arrays probably won't get copied much case TOY_VALUE_TABLE:
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->capacity = ptr->capacity;
result->count = ptr->count;
return TOY_VALUE_FROM_ARRAY(result);
}
case TOY_VALUE_TABLE: {
//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->capacity = ptr->capacity;
result->count = ptr->count;
return TOY_VALUE_FROM_TABLE(result);
}
case TOY_VALUE_FUNCTION: case TOY_VALUE_FUNCTION:
// return value; //URGENT: concerning
case TOY_VALUE_OPAQUE: case TOY_VALUE_OPAQUE:
case TOY_VALUE_ANY: case TOY_VALUE_ANY:
case TOY_VALUE_REFERENCE: case TOY_VALUE_REFERENCE:
@@ -151,7 +119,7 @@ Toy_Value Toy_copyValue(Toy_Value value) {
return TOY_VALUE_FROM_NULL(); return TOY_VALUE_FROM_NULL();
} }
Toy_Value Toy_deepCopyValue(struct Toy_Bucket** bucketHandle, Toy_Value value) { Toy_Value Toy_private_deepCopyValue(Toy_Bucket** scopeBucketHandle, Toy_Bucket** literalBucketHandle, Toy_Value value) {
//this should be the same as Toy_copyValue(), but it forces a deep copy for the strings //this should be the same as Toy_copyValue(), but it forces a deep copy for the strings
MAYBE_UNWRAP(value); MAYBE_UNWRAP(value);
@@ -163,7 +131,7 @@ Toy_Value Toy_deepCopyValue(struct Toy_Bucket** bucketHandle, Toy_Value value) {
return value; return value;
case TOY_VALUE_STRING: { case TOY_VALUE_STRING: {
return TOY_VALUE_FROM_STRING(Toy_deepCopyString(bucketHandle, value.as.string)); return TOY_VALUE_FROM_STRING(Toy_deepCopyString(literalBucketHandle, value.as.string));
} }
case TOY_VALUE_ARRAY: { case TOY_VALUE_ARRAY: {
@@ -172,7 +140,7 @@ Toy_Value Toy_deepCopyValue(struct Toy_Bucket** bucketHandle, Toy_Value value) {
Toy_Array* result = Toy_resizeArray(NULL, ptr->capacity); Toy_Array* result = Toy_resizeArray(NULL, ptr->capacity);
for (unsigned int i = 0; i < ptr->count; i++) { for (unsigned int i = 0; i < ptr->count; i++) {
result->data[i] = Toy_deepCopyValue(bucketHandle, ptr->data[i]); result->data[i] = Toy_private_deepCopyValue(scopeBucketHandle, literalBucketHandle, ptr->data[i]);
} }
result->capacity = ptr->capacity; result->capacity = ptr->capacity;
@@ -188,8 +156,8 @@ Toy_Value Toy_deepCopyValue(struct Toy_Bucket** bucketHandle, Toy_Value value) {
for (unsigned int i = 0; i < ptr->capacity; i++) { for (unsigned int i = 0; i < ptr->capacity; i++) {
if (TOY_VALUE_IS_NULL(ptr->data[i].key) != true) { if (TOY_VALUE_IS_NULL(ptr->data[i].key) != true) {
result->data[i].key = Toy_deepCopyValue(bucketHandle, ptr->data[i].key); result->data[i].key = Toy_private_deepCopyValue(scopeBucketHandle, literalBucketHandle, ptr->data[i].key);
result->data[i].value = Toy_deepCopyValue(bucketHandle, ptr->data[i].value); result->data[i].value = Toy_private_deepCopyValue(scopeBucketHandle, literalBucketHandle, ptr->data[i].value);
} }
} }
@@ -199,8 +167,27 @@ Toy_Value Toy_deepCopyValue(struct Toy_Bucket** bucketHandle, Toy_Value value) {
return TOY_VALUE_FROM_TABLE(result); return TOY_VALUE_FROM_TABLE(result);
} }
case TOY_VALUE_FUNCTION: { case TOY_VALUE_FUNCTION: {
Toy_Function* fn = Toy_createModuleFunction(bucketHandle, TOY_VALUE_AS_FUNCTION(value)->module.module); //URGENT: concerning if (TOY_VALUE_AS_FUNCTION(value)->type == TOY_FUNCTION_MODULE) {
return TOY_VALUE_FROM_FUNCTION(fn); Toy_Function* fn = Toy_createModuleFunction(literalBucketHandle, TOY_VALUE_AS_FUNCTION(value)->module.module);
//BUGFIX: rewire any and all strings within the function's ancestors
if (fn->module.module.parentScope != NULL && fn->module.module.parentScope->next != NULL) {
//break the loop to prevent infinite loops...???
//URGENT: fuck
Toy_Scope* tmp = fn->module.module.parentScope;
fn->module.module.parentScope = NULL;
Toy_Scope* duplicate = Toy_private_deepCopyScope(scopeBucketHandle, literalBucketHandle, tmp->next);
fn->module.module.parentScope = Toy_private_pushDummyScope(scopeBucketHandle, duplicate); //insert a new dummy
}
return TOY_VALUE_FROM_FUNCTION(fn);
}
fprintf(stderr, TOY_CC_ERROR "ERROR: Can't deep-copy an unknown function type value, exiting\n" TOY_CC_RESET);
exit(-1);
break;
} }
case TOY_VALUE_OPAQUE: case TOY_VALUE_OPAQUE:

View File

@@ -51,7 +51,7 @@ typedef struct Toy_Value { //32 | 64 BITNESS
#define TOY_VALUE_IS_STRING(value) ((value).type == TOY_VALUE_STRING) #define TOY_VALUE_IS_STRING(value) ((value).type == TOY_VALUE_STRING)
#define TOY_VALUE_IS_ARRAY(value) ((value).type == TOY_VALUE_ARRAY || (TOY_VALUE_IS_REFERENCE(value) && Toy_unwrapValue(value).type == TOY_VALUE_ARRAY)) #define TOY_VALUE_IS_ARRAY(value) ((value).type == TOY_VALUE_ARRAY || (TOY_VALUE_IS_REFERENCE(value) && Toy_unwrapValue(value).type == TOY_VALUE_ARRAY))
#define TOY_VALUE_IS_TABLE(value) ((value).type == TOY_VALUE_TABLE || (TOY_VALUE_IS_REFERENCE(value) && Toy_unwrapValue(value).type == TOY_VALUE_TABLE)) #define TOY_VALUE_IS_TABLE(value) ((value).type == TOY_VALUE_TABLE || (TOY_VALUE_IS_REFERENCE(value) && Toy_unwrapValue(value).type == TOY_VALUE_TABLE))
#define TOY_VALUE_IS_FUNCTION(value) ((value).type == TOY_VALUE_FUNCTION) #define TOY_VALUE_IS_FUNCTION(value) ((value).type == TOY_VALUE_FUNCTION || (TOY_VALUE_IS_REFERENCE(value) && Toy_unwrapValue(value).type == TOY_VALUE_FUNCTION))
#define TOY_VALUE_IS_OPAQUE(value) ((value).type == TOY_VALUE_OPAQUE) #define TOY_VALUE_IS_OPAQUE(value) ((value).type == TOY_VALUE_OPAQUE)
#define TOY_VALUE_IS_TYPE(value) ((value).type == TOY_VALUE_TYPE) #define TOY_VALUE_IS_TYPE(value) ((value).type == TOY_VALUE_TYPE)
#define TOY_VALUE_IS_REFERENCE(value) ((value).type == TOY_VALUE_REFERENCE) #define TOY_VALUE_IS_REFERENCE(value) ((value).type == TOY_VALUE_REFERENCE)
@@ -62,7 +62,7 @@ typedef struct Toy_Value { //32 | 64 BITNESS
#define TOY_VALUE_AS_STRING(value) ((value).as.string) #define TOY_VALUE_AS_STRING(value) ((value).as.string)
#define TOY_VALUE_AS_ARRAY(value) ((TOY_VALUE_IS_REFERENCE(value) ? Toy_unwrapValue(value) : value).as.array) #define TOY_VALUE_AS_ARRAY(value) ((TOY_VALUE_IS_REFERENCE(value) ? Toy_unwrapValue(value) : value).as.array)
#define TOY_VALUE_AS_TABLE(value) ((TOY_VALUE_IS_REFERENCE(value) ? Toy_unwrapValue(value) : value).as.table) #define TOY_VALUE_AS_TABLE(value) ((TOY_VALUE_IS_REFERENCE(value) ? Toy_unwrapValue(value) : value).as.table)
#define TOY_VALUE_AS_FUNCTION(value) ((value).as.function) #define TOY_VALUE_AS_FUNCTION(value) ((TOY_VALUE_IS_REFERENCE(value) ? Toy_unwrapValue(value) : value).as.function)
//TODO: more //TODO: more
#define TOY_VALUE_FROM_NULL() ((Toy_Value){{ .integer = 0 }, TOY_VALUE_NULL}) #define TOY_VALUE_FROM_NULL() ((Toy_Value){{ .integer = 0 }, TOY_VALUE_NULL})
@@ -82,7 +82,7 @@ TOY_API Toy_Value Toy_unwrapValue(Toy_Value value);
TOY_API unsigned int Toy_hashValue(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(Toy_Value value);
TOY_API Toy_Value Toy_deepCopyValue(struct Toy_Bucket** bucketHandle, Toy_Value value); //don't use refcounting TOY_API Toy_Value Toy_private_deepCopyValue(struct Toy_Bucket** scopeBucketHandle, struct Toy_Bucket** literalBucketHandle, Toy_Value value); //don't use refcounting
TOY_API void Toy_freeValue(Toy_Value value); TOY_API void Toy_freeValue(Toy_Value value);
TOY_API bool Toy_checkValueIsTruthy(Toy_Value value); TOY_API bool Toy_checkValueIsTruthy(Toy_Value value);

View File

@@ -273,7 +273,7 @@ static void processAssignCompound(Toy_VM* vm) {
} }
//in the event of a certain subset of types, create references instead (these should only exist on the stack) //in the event of a certain subset of types, create references instead (these should only exist on the stack)
if (TOY_VALUE_IS_REFERENCE(*valuePtr) || TOY_VALUE_IS_ARRAY(*valuePtr) || TOY_VALUE_IS_TABLE(*valuePtr)) { if (TOY_VALUE_IS_REFERENCE(*valuePtr) || TOY_VALUE_IS_ARRAY(*valuePtr) || TOY_VALUE_IS_TABLE(*valuePtr) || TOY_VALUE_IS_FUNCTION(*valuePtr)) {
target = TOY_REFERENCE_FROM_POINTER(valuePtr); target = TOY_REFERENCE_FROM_POINTER(valuePtr);
} }
else { else {
@@ -363,7 +363,7 @@ static void processAccess(Toy_VM* vm) {
//URGENT: should I loop functions into the reference system? //URGENT: should I loop functions into the reference system?
//in the event of a certain subset of types, create references instead (these should only exist on the stack) //in the event of a certain subset of types, create references instead (these should only exist on the stack)
if (TOY_VALUE_IS_REFERENCE(*valuePtr) || TOY_VALUE_IS_ARRAY(*valuePtr) || TOY_VALUE_IS_TABLE(*valuePtr)) { if (TOY_VALUE_IS_REFERENCE(*valuePtr) || TOY_VALUE_IS_ARRAY(*valuePtr) || TOY_VALUE_IS_TABLE(*valuePtr) || TOY_VALUE_IS_FUNCTION(*valuePtr)) {
Toy_Value ref = TOY_REFERENCE_FROM_POINTER(valuePtr); Toy_Value ref = TOY_REFERENCE_FROM_POINTER(valuePtr);
Toy_pushStack(&vm->stack, ref); Toy_pushStack(&vm->stack, ref);
} }
@@ -415,7 +415,7 @@ static void processInvoke(Toy_VM* vm) {
//spin up a new sub-vm //spin up a new sub-vm
Toy_VM subVM; Toy_VM subVM;
Toy_initVM(&subVM); Toy_inheritVM(&subVM, vm);
Toy_bindVM(&subVM, &module, false); Toy_bindVM(&subVM, &module, false);
//inject params, backwards from the stack //inject params, backwards from the stack
@@ -440,7 +440,7 @@ static void processInvoke(Toy_VM* vm) {
//extract and store any results //extract and store any results
if (resultCount > 0) { if (resultCount > 0) {
Toy_Array* results = Toy_extractResultsFromVM(&vm->literalBucket, &subVM, resultCount); Toy_Array* results = Toy_extractResultsFromVM(&vm->scopeBucket, &vm->literalBucket, &subVM, resultCount);
for (unsigned int i = 0; i < results->count; i++) { 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 //NOTE: since the results array is being immediately freed, just push each element without a call to copy
@@ -899,7 +899,7 @@ static void processIndex(Toy_VM* vm) {
} }
//in the event of a certain subset of types, create references instead (these should only exist on the stack) //in the event of a certain subset of types, create references instead (these should only exist on the stack)
if (TOY_VALUE_IS_REFERENCE(array->data[i]) || TOY_VALUE_IS_ARRAY(array->data[i]) || TOY_VALUE_IS_TABLE(array->data[i])) { if (TOY_VALUE_IS_REFERENCE(array->data[i]) || TOY_VALUE_IS_ARRAY(array->data[i]) || TOY_VALUE_IS_TABLE(array->data[i]) || TOY_VALUE_IS_FUNCTION(array->data[i])) {
Toy_Value ref = TOY_REFERENCE_FROM_POINTER(&(array->data[i])); Toy_Value ref = TOY_REFERENCE_FROM_POINTER(&(array->data[i]));
Toy_pushStack(&vm->stack, ref); Toy_pushStack(&vm->stack, ref);
} }
@@ -932,7 +932,7 @@ static void processIndex(Toy_VM* vm) {
} }
//in the event of a certain subset of types, create references instead (these should only exist on the stack) //in the event of a certain subset of types, create references instead (these should only exist on the stack)
if (TOY_VALUE_IS_REFERENCE(entry->value) || TOY_VALUE_IS_ARRAY(entry->value) || TOY_VALUE_IS_TABLE(entry->value)) { if (TOY_VALUE_IS_REFERENCE(entry->value) || TOY_VALUE_IS_ARRAY(entry->value) || TOY_VALUE_IS_TABLE(entry->value) || TOY_VALUE_IS_FUNCTION(entry->value)) {
Toy_Value ref = TOY_REFERENCE_FROM_POINTER(&(entry->value)); Toy_Value ref = TOY_REFERENCE_FROM_POINTER(&(entry->value));
Toy_pushStack(&vm->stack, ref); Toy_pushStack(&vm->stack, ref);
} }
@@ -1162,7 +1162,7 @@ void Toy_freeVM(Toy_VM* vm) {
} }
} }
Toy_Array* Toy_extractResultsFromVM(Toy_Bucket** bucketHandle, Toy_VM* subVM, unsigned int resultCount) { Toy_Array* Toy_extractResultsFromVM(Toy_Bucket** scopeBucketHandle, Toy_Bucket** literalBucketHandle, Toy_VM* subVM, unsigned int resultCount) {
if (subVM->stack->count < resultCount) { if (subVM->stack->count < resultCount) {
fprintf(stderr, TOY_CC_ERROR "ERROR: Too many results requested from VM, exiting\n" TOY_CC_RESET); fprintf(stderr, TOY_CC_ERROR "ERROR: Too many results requested from VM, exiting\n" TOY_CC_RESET);
exit(-1); exit(-1);
@@ -1173,7 +1173,7 @@ Toy_Array* Toy_extractResultsFromVM(Toy_Bucket** bucketHandle, Toy_VM* subVM, un
const unsigned int offset = subVM->stack->count - resultCount; //first element to extract const unsigned int offset = subVM->stack->count - resultCount; //first element to extract
for (/* EMPTY */; results->count < resultCount; results->count++) { for (/* EMPTY */; results->count < resultCount; results->count++) {
results->data[results->count] = Toy_deepCopyValue(bucketHandle, subVM->stack->data[offset + results->count]); results->data[results->count] = Toy_private_deepCopyValue(scopeBucketHandle, literalBucketHandle, subVM->stack->data[offset + results->count]);
} }
return results; return results;

View File

@@ -53,6 +53,6 @@ TOY_API void Toy_bindVM(Toy_VM* vm, Toy_Module* module, bool preserveScope);
TOY_API unsigned int Toy_runVM(Toy_VM* vm); TOY_API unsigned int Toy_runVM(Toy_VM* vm);
TOY_API void Toy_freeVM(Toy_VM* vm); TOY_API void Toy_freeVM(Toy_VM* vm);
TOY_API Toy_Array* Toy_extractResultsFromVM(Toy_Bucket** bucketHandle, Toy_VM* subVM, unsigned int resultCount); TOY_API Toy_Array* Toy_extractResultsFromVM(Toy_Bucket** scopeBucketHandle, Toy_Bucket** literalBucketHandle, Toy_VM* subVM, unsigned int resultCount);
//TODO: inject extra data (hook system for external libraries) //TODO: inject extra data (hook system for external libraries)