diff --git a/scripts/funky.toy b/scripts/funky.toy index 03e6b59..0786824 100644 --- a/scripts/funky.toy +++ b/scripts/funky.toy @@ -1,9 +1,9 @@ -//TODO: Not yet functional +//TODO: functions are untested fn makeCounter() { var counter: int = 0; fn increment() { - return counter++; + return ++counter; } return increment; @@ -11,6 +11,10 @@ fn makeCounter() { var tally = makeCounter(); -print tally(); -print tally(); -print tally(); \ No newline at end of file +while (true) { + var result = tally(); + + if (result >= 10_000_000) { + break; + } +} diff --git a/source/toy_scope.c b/source/toy_scope.c index 06a56ed..69ac7d5 100644 --- a/source/toy_scope.c +++ b/source/toy_scope.c @@ -94,28 +94,6 @@ Toy_Scope* Toy_popScope(Toy_Scope* scope) { return scope->next; } -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(scopeBucketHandle, sizeof(Toy_Scope)); - - newScope->next = scope->next; - newScope->table = scope->table != NULL ? Toy_private_adjustTableCapacity(NULL, scope->table->capacity) : NULL; - newScope->refCount = 0; - - incrementRefCount(newScope); - - if (newScope->table != NULL) { - //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_private_deepCopyValue(scopeBucketHandle, literalBucketHandle, scope->table->data[i].key), Toy_private_deepCopyValue(scopeBucketHandle, literalBucketHandle, scope->table->data[i].value)); - } - } - } - - return newScope; -} - void Toy_declareScope(Toy_Scope* scope, Toy_String* key, Toy_Value value) { if (key->info.type != TOY_STRING_NAME) { fprintf(stderr, TOY_CC_ERROR "ERROR: Toy_Scope only allows name strings as keys\n" TOY_CC_RESET); diff --git a/source/toy_scope.h b/source/toy_scope.h index dfa085b..5793a90 100644 --- a/source/toy_scope.h +++ b/source/toy_scope.h @@ -19,8 +19,6 @@ 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_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); TOY_API void Toy_assignScope(Toy_Scope* scope, Toy_String* key, Toy_Value value); diff --git a/source/toy_value.c b/source/toy_value.c index 84aa3a7..f7ba2df 100644 --- a/source/toy_value.c +++ b/source/toy_value.c @@ -104,43 +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_TABLE: - case TOY_VALUE_FUNCTION: - case TOY_VALUE_OPAQUE: - case TOY_VALUE_ANY: - case TOY_VALUE_REFERENCE: - case TOY_VALUE_UNKNOWN: - fprintf(stderr, TOY_CC_ERROR "ERROR: Can't copy an unknown value type, exiting\n" TOY_CC_RESET); - exit(-1); - } - - //dummy return - return TOY_VALUE_FROM_NULL(); -} - -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); - - switch(value.type) { - case TOY_VALUE_NULL: - case TOY_VALUE_BOOLEAN: - case TOY_VALUE_INTEGER: - case TOY_VALUE_FLOAT: - return value; - - case TOY_VALUE_STRING: { - return TOY_VALUE_FROM_STRING(Toy_deepCopyString(literalBucketHandle, 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_private_deepCopyValue(scopeBucketHandle, literalBucketHandle, ptr->data[i]); + result->data[i] = Toy_copyValue(ptr->data[i]); } result->capacity = ptr->capacity; @@ -156,8 +126,8 @@ Toy_Value Toy_private_deepCopyValue(Toy_Bucket** scopeBucketHandle, Toy_Bucket** for (unsigned int i = 0; i < ptr->capacity; i++) { if (TOY_VALUE_IS_NULL(ptr->data[i].key) != true) { - 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); + result->data[i].key = Toy_copyValue(ptr->data[i].key); + result->data[i].value = Toy_copyValue(ptr->data[i].value); } } @@ -166,35 +136,15 @@ Toy_Value Toy_private_deepCopyValue(Toy_Bucket** scopeBucketHandle, Toy_Bucket** return TOY_VALUE_FROM_TABLE(result); } - case TOY_VALUE_FUNCTION: { - 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_FUNCTION: + return value; //URGENT: concerning case TOY_VALUE_OPAQUE: case TOY_VALUE_ANY: case TOY_VALUE_REFERENCE: case TOY_VALUE_UNKNOWN: - fprintf(stderr, TOY_CC_ERROR "ERROR: Can't deep-copy an unknown value type, exiting\n" TOY_CC_RESET); + fprintf(stderr, TOY_CC_ERROR "ERROR: Can't copy an unknown value type, exiting\n" TOY_CC_RESET); exit(-1); } diff --git a/source/toy_value.h b/source/toy_value.h index b7ed49c..45bac77 100644 --- a/source/toy_value.h +++ b/source/toy_value.h @@ -82,7 +82,6 @@ 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_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 d78a42f..6004081 100644 --- a/source/toy_vm.c +++ b/source/toy_vm.c @@ -73,12 +73,12 @@ static void processRead(Toy_VM* vm) { //build a string from the data section if (stringType == TOY_STRING_LEAF) { - value = TOY_VALUE_FROM_STRING(Toy_createString(&vm->literalBucket, cstring)); + value = TOY_VALUE_FROM_STRING(Toy_createString(&vm->memoryBucket, cstring)); } else if (stringType == TOY_STRING_NAME) { Toy_ValueType valueType = TOY_VALUE_UNKNOWN; - value = TOY_VALUE_FROM_STRING(Toy_createNameStringLength(&vm->literalBucket, cstring, len, valueType, false)); + value = TOY_VALUE_FROM_STRING(Toy_createNameStringLength(&vm->memoryBucket, cstring, len, valueType, false)); } else { Toy_error("Invalid string type found in opcode read"); @@ -162,10 +162,10 @@ static void processRead(Toy_VM* vm) { unsigned int addr = (unsigned int)READ_INT(vm); Toy_Module module = Toy_parseModule(vm->code + vm->subsAddr + addr); - module.parentScope = Toy_private_pushDummyScope(&vm->scopeBucket, vm->scope); + module.parentScope = Toy_private_pushDummyScope(&vm->memoryBucket, vm->scope); //create and push the function value - Toy_Function* function = Toy_createModuleFunction(&vm->literalBucket, module); + Toy_Function* function = Toy_createModuleFunction(&vm->memoryBucket, module); value = TOY_VALUE_FROM_FUNCTION(function); break; @@ -210,7 +210,7 @@ static void processDeclare(Toy_VM* vm) { char* cstring = (char*)(vm->code + vm->dataAddr + jump); //build the name string - Toy_String* name = Toy_createNameStringLength(&vm->literalBucket, cstring, len, type, constant); + Toy_String* name = Toy_createNameStringLength(&vm->memoryBucket, cstring, len, type, constant); //get the value Toy_Value value = Toy_popStack(&vm->stack); @@ -430,7 +430,7 @@ static void processInvoke(Toy_VM* vm) { const char* cstr = ((char*)(module.code + module.dataAddr)) + paramAddr; //as a name string - Toy_String* name = Toy_createNameStringLength(&subVM.literalBucket, cstr, strlen(cstr), paramType, true); + Toy_String* name = Toy_createNameStringLength(&subVM.memoryBucket, cstr, strlen(cstr), paramType, true); Toy_declareScope(subVM.scope, name, argValue); } @@ -440,7 +440,7 @@ static void processInvoke(Toy_VM* vm) { //extract and store any results if (resultCount > 0) { - Toy_Array* results = Toy_extractResultsFromVM(&vm->scopeBucket, &vm->literalBucket, &subVM, resultCount); + Toy_Array* results = Toy_extractResultsFromVM(&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 @@ -723,7 +723,7 @@ static void processAssert(Toy_VM* vm) { //determine the args if (count == 1) { - message = TOY_VALUE_FROM_STRING(Toy_createString(&vm->literalBucket, "assertion failed")); //TODO: needs a better default message + message = TOY_VALUE_FROM_STRING(Toy_createString(&vm->memoryBucket, "assertion failed")); //TODO: needs a better default message value = Toy_popStack(&vm->stack); } else if (count == 2) { @@ -738,7 +738,7 @@ static void processAssert(Toy_VM* vm) { //do the check if (TOY_VALUE_IS_NULL(value) || Toy_checkValueIsTruthy(value) != true) { //on a failure, print the message - Toy_String* string = Toy_stringifyValue(&vm->literalBucket, message); + Toy_String* string = Toy_stringifyValue(&vm->memoryBucket, message); char* buffer = Toy_getStringRawBuffer(string); Toy_assertFailure(buffer); @@ -756,7 +756,7 @@ static void processAssert(Toy_VM* vm) { static void processPrint(Toy_VM* vm) { //print the value on top of the stack, popping it Toy_Value value = Toy_popStack(&vm->stack); - Toy_String* string = Toy_stringifyValue(&vm->literalBucket, value); + Toy_String* string = Toy_stringifyValue(&vm->memoryBucket, value); char* buffer = Toy_getStringRawBuffer(string); //TODO: check string type to skip this call Toy_print(buffer); @@ -779,7 +779,7 @@ static void processConcat(Toy_VM* vm) { } //all good - Toy_String* result = Toy_concatStrings(&vm->literalBucket, TOY_VALUE_AS_STRING(left), TOY_VALUE_AS_STRING(right)); + Toy_String* result = Toy_concatStrings(&vm->memoryBucket, TOY_VALUE_AS_STRING(left), TOY_VALUE_AS_STRING(right)); Toy_pushStack(&vm->stack, TOY_VALUE_FROM_STRING(result)); } @@ -847,11 +847,11 @@ static void processIndex(Toy_VM* vm) { //extract cstring, based on type if (str->info.type == TOY_STRING_LEAF) { const char* cstr = str->leaf.data; - result = Toy_createStringLength(&vm->literalBucket, cstr + i, l); + result = Toy_createStringLength(&vm->memoryBucket, cstr + i, l); } else if (str->info.type == TOY_STRING_NODE) { char* cstr = Toy_getStringRawBuffer(str); - result = Toy_createStringLength(&vm->literalBucket, cstr + i, l); + result = Toy_createStringLength(&vm->memoryBucket, cstr + i, l); free(cstr); } else { @@ -1031,7 +1031,7 @@ static unsigned int process(Toy_VM* vm) { break; case TOY_OPCODE_SCOPE_PUSH: - vm->scope = Toy_pushScope(&vm->scopeBucket, vm->scope); + vm->scope = Toy_pushScope(&vm->memoryBucket, vm->scope); break; case TOY_OPCODE_SCOPE_POP: @@ -1095,10 +1095,9 @@ void Toy_initVM(Toy_VM* vm) { //create persistent memory vm->scope = NULL; vm->stack = Toy_allocateStack(); - vm->literalBucket = Toy_allocateBucket(TOY_BUCKET_IDEAL); - vm->scopeBucket = Toy_allocateBucket(TOY_BUCKET_IDEAL); + vm->memoryBucket = Toy_allocateBucket(TOY_BUCKET_IDEAL); - vm->scopeBucketHandle = NULL; //not used + vm->parentBucketHandle = NULL; Toy_resetVM(vm, true); } @@ -1107,10 +1106,9 @@ void Toy_inheritVM(Toy_VM* vm, Toy_VM* parent) { //inherent persistent memory vm->scope = NULL; vm->stack = Toy_allocateStack(); - vm->literalBucket = Toy_allocateBucket(TOY_BUCKET_IDEAL); - vm->scopeBucket = parent->scopeBucket; + vm->memoryBucket = parent->memoryBucket; - vm->scopeBucketHandle = &parent->scopeBucket; //track this to update it later + vm->parentBucketHandle = &parent->memoryBucket; //track this to update it later Toy_resetVM(vm, true); } @@ -1130,7 +1128,7 @@ void Toy_bindVM(Toy_VM* vm, Toy_Module* module, bool preserveScope) { vm->subsAddr = module->subsAddr; if (preserveScope == false) { - vm->scope = Toy_pushScope(&vm->scopeBucket, module->parentScope); + vm->scope = Toy_pushScope(&vm->memoryBucket, module->parentScope); } } @@ -1152,17 +1150,16 @@ void Toy_freeVM(Toy_VM* vm) { //clear the persistent memory Toy_freeStack(vm->stack); - Toy_freeBucket(&vm->literalBucket); - if (vm->scopeBucketHandle != NULL) { - *(vm->scopeBucketHandle) = vm->scopeBucket; //re-adjust the parent's scopeBucket pointer, in case it was expanded + if (vm->parentBucketHandle != NULL) { + *(vm->parentBucketHandle) = vm->memoryBucket; //update the outter VM, if there is one } else { - Toy_freeBucket(&vm->scopeBucket); + Toy_freeBucket(&vm->memoryBucket); } } -Toy_Array* Toy_extractResultsFromVM(Toy_Bucket** scopeBucketHandle, Toy_Bucket** literalBucketHandle, Toy_VM* subVM, unsigned int resultCount) { +Toy_Array* Toy_extractResultsFromVM(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 +1170,7 @@ Toy_Array* Toy_extractResultsFromVM(Toy_Bucket** scopeBucketHandle, Toy_Bucket** const unsigned int offset = subVM->stack->count - resultCount; //first element to extract for (/* EMPTY */; results->count < resultCount; results->count++) { - results->data[results->count] = Toy_private_deepCopyValue(scopeBucketHandle, literalBucketHandle, subVM->stack->data[offset + results->count]); + results->data[results->count] = Toy_copyValue(subVM->stack->data[offset + results->count]); } return results; diff --git a/source/toy_vm.h b/source/toy_vm.h index 44d6daa..ee8e92e 100644 --- a/source/toy_vm.h +++ b/source/toy_vm.h @@ -39,9 +39,8 @@ typedef struct Toy_VM { Toy_Stack* stack; //easy access to memory - Toy_Bucket* literalBucket; //stores the value literals (strings, functions, etc.) - Toy_Bucket* scopeBucket; //stores the scope instances - Toy_Bucket** scopeBucketHandle; //for reusing the scope bucket to save on alloc/free + Toy_Bucket* memoryBucket; + Toy_Bucket** parentBucketHandle; } Toy_VM; TOY_API void Toy_resetVM(Toy_VM* vm, bool preserveScope); @@ -53,6 +52,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** scopeBucketHandle, Toy_Bucket** literalBucketHandle, Toy_VM* subVM, unsigned int resultCount); +TOY_API Toy_Array* Toy_extractResultsFromVM(Toy_VM* subVM, unsigned int resultCount); //TODO: inject extra data (hook system for external libraries) diff --git a/tests/cases/test_scope.c b/tests/cases/test_scope.c index 2db5e23..9fbb340 100644 --- a/tests/cases/test_scope.c +++ b/tests/cases/test_scope.c @@ -244,56 +244,6 @@ int test_scope_allocation(void) { Toy_freeBucket(&bucket); } - //deep copy - { - //setup - Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL); - - //run - Toy_Scope* scopeA = Toy_pushScope(&bucket, NULL); - Toy_Scope* scopeB = Toy_pushScope(&bucket, scopeA); - Toy_Scope* scopeCopy = Toy_deepCopyScope(&bucket, scopeB); - - //check - if ( - scopeA == NULL || - scopeA->next != NULL || - scopeA->table == NULL || - scopeA->table->capacity != 8 || - scopeA->refCount != 3 || - - scopeB == NULL || - scopeB->next != scopeA || - scopeB->table == NULL || - scopeB->table->capacity != 8 || - scopeB->refCount != 1 || - - scopeB == NULL || - scopeB->next != scopeA || - scopeB->table == NULL || - scopeB->table->capacity != 8 || - scopeB->refCount != 1 || - - scopeB == scopeCopy || - - false) - { - fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to deep copy a scope\n" TOY_CC_RESET); - Toy_popScope(scopeCopy); - Toy_popScope(scopeB); - Toy_popScope(scopeA); - Toy_freeBucket(&bucket); - return -1; - } - - //cleanup - Toy_popScope(scopeCopy); - Toy_popScope(scopeB); - Toy_popScope(scopeA); - - Toy_freeBucket(&bucket); - } - return 0; }