From 9fe6d6b2183af2b18779553450747803255a091c Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Tue, 18 Feb 2025 13:06:15 +1100 Subject: [PATCH] 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 --- scripts/funky.toy | 26 ----------------- source/toy_scope.c | 6 ++-- source/toy_scope.h | 2 +- source/toy_value.c | 69 +++++++++++++++++++--------------------------- source/toy_value.h | 6 ++-- source/toy_vm.c | 16 +++++------ source/toy_vm.h | 2 +- 7 files changed, 44 insertions(+), 83 deletions(-) diff --git a/scripts/funky.toy b/scripts/funky.toy index 5b41ee4..03e6b59 100644 --- a/scripts/funky.toy +++ b/scripts/funky.toy @@ -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 fn makeCounter() { var counter: int = 0; diff --git a/source/toy_scope.c b/source/toy_scope.c index 746c654..06a56ed 100644 --- a/source/toy_scope.c +++ b/source/toy_scope.c @@ -94,9 +94,9 @@ Toy_Scope* Toy_popScope(Toy_Scope* scope) { 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 - 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->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 for (unsigned int i = 0; i < scope->table->capacity; i++) { 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)); } } } diff --git a/source/toy_scope.h b/source/toy_scope.h index 9766cf3..dfa085b 100644 --- a/source/toy_scope.h +++ b/source/toy_scope.h @@ -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_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 TOY_API void Toy_declareScope(Toy_Scope* scope, Toy_String* key, Toy_Value value); diff --git a/source/toy_value.c b/source/toy_value.c index 1452185..84aa3a7 100644 --- a/source/toy_value.c +++ b/source/toy_value.c @@ -104,41 +104,9 @@ Toy_Value Toy_copyValue(Toy_Value value) { return TOY_VALUE_FROM_STRING(Toy_copyString(value.as.string)); } - case TOY_VALUE_ARRAY: { - //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->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_ARRAY: + case TOY_VALUE_TABLE: case TOY_VALUE_FUNCTION: - // return value; //URGENT: concerning - case TOY_VALUE_OPAQUE: case TOY_VALUE_ANY: case TOY_VALUE_REFERENCE: @@ -151,7 +119,7 @@ Toy_Value Toy_copyValue(Toy_Value value) { 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 MAYBE_UNWRAP(value); @@ -163,7 +131,7 @@ Toy_Value Toy_deepCopyValue(struct Toy_Bucket** bucketHandle, Toy_Value value) { return value; 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: { @@ -172,7 +140,7 @@ Toy_Value Toy_deepCopyValue(struct Toy_Bucket** bucketHandle, Toy_Value value) { Toy_Array* result = Toy_resizeArray(NULL, ptr->capacity); 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; @@ -188,8 +156,8 @@ Toy_Value Toy_deepCopyValue(struct Toy_Bucket** bucketHandle, Toy_Value value) { for (unsigned int i = 0; i < ptr->capacity; i++) { if (TOY_VALUE_IS_NULL(ptr->data[i].key) != true) { - result->data[i].key = Toy_deepCopyValue(bucketHandle, ptr->data[i].key); - result->data[i].value = Toy_deepCopyValue(bucketHandle, ptr->data[i].value); + result->data[i].key = Toy_private_deepCopyValue(scopeBucketHandle, literalBucketHandle, ptr->data[i].key); + 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); } case TOY_VALUE_FUNCTION: { - Toy_Function* fn = Toy_createModuleFunction(bucketHandle, TOY_VALUE_AS_FUNCTION(value)->module.module); //URGENT: concerning - return TOY_VALUE_FROM_FUNCTION(fn); + if (TOY_VALUE_AS_FUNCTION(value)->type == TOY_FUNCTION_MODULE) { + 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: diff --git a/source/toy_value.h b/source/toy_value.h index a2bf5a7..b7ed49c 100644 --- a/source/toy_value.h +++ b/source/toy_value.h @@ -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_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_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_TYPE(value) ((value).type == TOY_VALUE_TYPE) #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_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_FUNCTION(value) ((value).as.function) +#define TOY_VALUE_AS_FUNCTION(value) ((TOY_VALUE_IS_REFERENCE(value) ? Toy_unwrapValue(value) : value).as.function) //TODO: more #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 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 bool Toy_checkValueIsTruthy(Toy_Value value); diff --git a/source/toy_vm.c b/source/toy_vm.c index 9bc426e..d78a42f 100644 --- a/source/toy_vm.c +++ b/source/toy_vm.c @@ -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) - 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); } else { @@ -363,7 +363,7 @@ static void processAccess(Toy_VM* vm) { //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) - 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_pushStack(&vm->stack, ref); } @@ -415,7 +415,7 @@ static void processInvoke(Toy_VM* vm) { //spin up a new sub-vm Toy_VM subVM; - Toy_initVM(&subVM); + Toy_inheritVM(&subVM, vm); Toy_bindVM(&subVM, &module, false); //inject params, backwards from the stack @@ -440,7 +440,7 @@ static void processInvoke(Toy_VM* vm) { //extract and store any results 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++) { //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) - 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_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) - 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_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) { fprintf(stderr, TOY_CC_ERROR "ERROR: Too many results requested from VM, exiting\n" TOY_CC_RESET); 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 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; diff --git a/source/toy_vm.h b/source/toy_vm.h index 4d612a5..44d6daa 100644 --- a/source/toy_vm.h +++ b/source/toy_vm.h @@ -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 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)