mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 14:54:07 +10:00
Wrote a bit of the scope tests, they're still incomplete
This commit is contained in:
@@ -20,7 +20,7 @@ static void decrementRefCount(Toy_Scope* scope) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Toy_Value* lookupScope(Toy_Scope* scope, Toy_Value key, unsigned int hash, bool recursive) {
|
static Toy_Value* lookupScope(Toy_Scope* scope, Toy_String* key, unsigned int hash, bool recursive) {
|
||||||
//terminate
|
//terminate
|
||||||
if (scope == NULL) {
|
if (scope == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -31,11 +31,11 @@ static Toy_Value* lookupScope(Toy_Scope* scope, Toy_Value key, unsigned int hash
|
|||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
//found the entry
|
//found the entry
|
||||||
if (TOY_VALUES_ARE_EQUAL(scope->table->data[probe].key, key)) {
|
if (Toy_compareStrings(TOY_VALUE_AS_STRING(scope->table->data[probe].key), key)) {
|
||||||
return &(scope->table->data[probe].value);
|
return &(scope->table->data[probe].value);
|
||||||
}
|
}
|
||||||
|
|
||||||
//if its an empty slot
|
//if its an empty slot (didn't find it here)
|
||||||
if (TOY_VALUE_IS_NULL(scope->table->data[probe].key)) {
|
if (TOY_VALUE_IS_NULL(scope->table->data[probe].key)) {
|
||||||
return recursive ? lookupScope(scope->next, key, hash, recursive) : NULL;
|
return recursive ? lookupScope(scope->next, key, hash, recursive) : NULL;
|
||||||
}
|
}
|
||||||
@@ -69,8 +69,15 @@ Toy_Scope* Toy_popScope(Toy_Scope* scope) {
|
|||||||
return scope->next;
|
return scope->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_Scope* deepCopyScope(Toy_Bucket** bucketHandle, Toy_Scope* scope) {
|
Toy_Scope* Toy_deepCopyScope(Toy_Bucket** bucketHandle, Toy_Scope* scope) {
|
||||||
Toy_Scope* newScope = Toy_pushScope(bucketHandle, scope->next);
|
//copy/pasted from pushScope, so I can allocate the table manually
|
||||||
|
Toy_Scope* newScope = Toy_partitionBucket(bucketHandle, sizeof(Toy_Scope));
|
||||||
|
|
||||||
|
newScope->next = scope->next;
|
||||||
|
newScope->table = Toy_private_adjustTableCapacity(NULL, scope->table->capacity);
|
||||||
|
newScope->refCount = 0;
|
||||||
|
|
||||||
|
incrementRefCount(newScope);
|
||||||
|
|
||||||
//forcibly copy the contents
|
//forcibly copy the contents
|
||||||
for (int i = 0; i < scope->table->capacity; i++) {
|
for (int i = 0; i < scope->table->capacity; i++) {
|
||||||
@@ -82,36 +89,36 @@ Toy_Scope* deepCopyScope(Toy_Bucket** bucketHandle, Toy_Scope* scope) {
|
|||||||
return newScope;
|
return newScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Toy_declareScope(Toy_Bucket** bucketHandle, Toy_Scope* scope, Toy_String key, Toy_Value value) {
|
void Toy_declareScope(Toy_Bucket** bucketHandle, Toy_Scope* scope, Toy_String* key, Toy_Value value) {
|
||||||
if (key.type != TOY_STRING_NAME) {
|
if (key->type != TOY_STRING_NAME) {
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Toy_Scope only allows name strings as keys\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Toy_Scope only allows name strings as keys\n" TOY_CC_RESET);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_Value* valuePtr = lookupScope(scope, key, Toy_hashValue(key), false);
|
Toy_Value* valuePtr = lookupScope(scope, key, Toy_hashString(key), false);
|
||||||
|
|
||||||
if (valuePtr != NULL) {
|
if (valuePtr != NULL) {
|
||||||
|
|
||||||
char buffer[key.length + 256];
|
char buffer[key->length + 256];
|
||||||
snprintf(buffer, "Can't redefine a variable: %s", key.as.name.data);
|
sprintf(buffer, "Can't redefine a variable: %s", key->as.name.data);
|
||||||
Toy_error(buffer);
|
Toy_error(buffer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_insertTable(&scope->table, key, value);
|
Toy_insertTable(&scope->table, TOY_VALUE_FROM_STRING(Toy_copyString(bucketHandle, key)), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Toy_assignScope(Toy_Bucket** bucketHandle, Toy_Scope* scope, Toy_String key, Toy_Value value) {
|
void Toy_assignScope(Toy_Bucket** bucketHandle, Toy_Scope* scope, Toy_String* key, Toy_Value value) {
|
||||||
if (key.type != TOY_STRING_NAME) {
|
if (key->type != TOY_STRING_NAME) {
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Toy_Scope only allows name strings as keys\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Toy_Scope only allows name strings as keys\n" TOY_CC_RESET);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_Value* valuePtr = lookupScope(scope, key, Toy_hashValue(key), true);
|
Toy_Value* valuePtr = lookupScope(scope, key, Toy_hashString(key), true);
|
||||||
|
|
||||||
if (valuePtr == NULL) {
|
if (valuePtr == NULL) {
|
||||||
char buffer[key.length + 256];
|
char buffer[key->length + 256];
|
||||||
snprintf(buffer, "Undefined variable: %s", key.as.name.data);
|
sprintf(buffer, "Undefined variable: %s", key->as.name.data);
|
||||||
Toy_error(buffer);
|
Toy_error(buffer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -119,31 +126,31 @@ void Toy_assignScope(Toy_Bucket** bucketHandle, Toy_Scope* scope, Toy_String key
|
|||||||
*valuePtr = value;
|
*valuePtr = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_Value Toy_accessScope(Toy_Bucket** bucketHandle, Toy_Scope* scope, Toy_String key) {
|
Toy_Value Toy_accessScope(Toy_Bucket** bucketHandle, Toy_Scope* scope, Toy_String* key) {
|
||||||
if (key.type != TOY_STRING_NAME) {
|
if (key->type != TOY_STRING_NAME) {
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Toy_Scope only allows name strings as keys\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Toy_Scope only allows name strings as keys\n" TOY_CC_RESET);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_Value* valuePtr = lookupScope(scope, key, Toy_hashValue(key), true);
|
Toy_Value* valuePtr = lookupScope(scope, key, Toy_hashString(key), true);
|
||||||
|
|
||||||
if (valuePtr == NULL) {
|
if (valuePtr == NULL) {
|
||||||
char buffer[key.length + 256];
|
char buffer[key->length + 256];
|
||||||
snprintf(buffer, "Undefined variable: %s", key.as.name.data);
|
sprintf(buffer, "Undefined variable: %s", key->as.name.data);
|
||||||
Toy_error(buffer);
|
Toy_error(buffer);
|
||||||
return;
|
return TOY_VALUE_FROM_NULL();
|
||||||
}
|
}
|
||||||
|
|
||||||
return *valuePtr;
|
return *valuePtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Toy_isDeclaredScope(Toy_Bucket** bucketHandle, Toy_Scope* scope, Toy_String key) {
|
bool Toy_isDeclaredScope(Toy_Bucket** bucketHandle, Toy_Scope* scope, Toy_String* key) {
|
||||||
if (key.type != TOY_STRING_NAME) {
|
if (key->type != TOY_STRING_NAME) {
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Toy_Scope only allows name strings as keys\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Toy_Scope only allows name strings as keys\n" TOY_CC_RESET);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_Value* valuePtr = lookupScope(scope, key, Toy_hashValue(key), true);
|
Toy_Value* valuePtr = lookupScope(scope, key, Toy_hashString(key), true);
|
||||||
|
|
||||||
return valuePtr != NULL;
|
return valuePtr != NULL;
|
||||||
}
|
}
|
||||||
@@ -14,15 +14,15 @@ typedef struct Toy_Scope {
|
|||||||
unsigned int refCount;
|
unsigned int refCount;
|
||||||
} Toy_Scope;
|
} Toy_Scope;
|
||||||
|
|
||||||
//handle deep scopes
|
//handle deep scopes - the scope is stored in the bucket, not the table
|
||||||
TOY_API Toy_Scope* Toy_pushScope(Toy_Bucket** bucketHandle, Toy_Scope* scope);
|
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* deepCopyScope(Toy_Bucket** bucketHandle, Toy_Scope* scope);
|
TOY_API Toy_Scope* Toy_deepCopyScope(Toy_Bucket** bucketHandle, Toy_Scope* scope);
|
||||||
|
|
||||||
//manage the contents
|
//manage the contents
|
||||||
TOY_API void Toy_declareScope(Toy_Bucket** bucketHandle, Toy_Scope* scope, Toy_String key, Toy_Value value);
|
TOY_API void Toy_declareScope(Toy_Bucket** bucketHandle, Toy_Scope* scope, Toy_String* key, Toy_Value value);
|
||||||
TOY_API void Toy_assignScope(Toy_Bucket** bucketHandle, Toy_Scope* scope, Toy_String key, Toy_Value value);
|
TOY_API void Toy_assignScope(Toy_Bucket** bucketHandle, Toy_Scope* scope, Toy_String* key, Toy_Value value);
|
||||||
TOY_API Toy_Value Toy_accessScope(Toy_Bucket** bucketHandle, Toy_Scope* scope, Toy_String key);
|
TOY_API Toy_Value Toy_accessScope(Toy_Bucket** bucketHandle, Toy_Scope* scope, Toy_String* key);
|
||||||
|
|
||||||
TOY_API bool Toy_isDeclaredScope(Toy_Bucket** bucketHandle, Toy_Scope* scope, Toy_String key);
|
TOY_API bool Toy_isDeclaredScope(Toy_Bucket** bucketHandle, Toy_Scope* scope, Toy_String* key);
|
||||||
@@ -54,7 +54,8 @@ static void probeAndInsert(Toy_Table** tableHandle, Toy_Value key, Toy_Value val
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Toy_Table* adjustTableCapacity(Toy_Table* oldTable, unsigned int newCapacity) {
|
//exposed functions
|
||||||
|
Toy_Table* Toy_private_adjustTableCapacity(Toy_Table* oldTable, unsigned int newCapacity) {
|
||||||
//allocate and zero a new table in memory
|
//allocate and zero a new table in memory
|
||||||
Toy_Table* newTable = malloc(newCapacity * sizeof(Toy_TableEntry) + sizeof(Toy_Table));
|
Toy_Table* newTable = malloc(newCapacity * sizeof(Toy_TableEntry) + sizeof(Toy_Table));
|
||||||
|
|
||||||
@@ -86,9 +87,8 @@ static Toy_Table* adjustTableCapacity(Toy_Table* oldTable, unsigned int newCapac
|
|||||||
return newTable;
|
return newTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
//exposed functions
|
|
||||||
Toy_Table* Toy_allocateTable() {
|
Toy_Table* Toy_allocateTable() {
|
||||||
return adjustTableCapacity(NULL, MIN_CAPACITY);
|
return Toy_private_adjustTableCapacity(NULL, MIN_CAPACITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Toy_freeTable(Toy_Table* table) {
|
void Toy_freeTable(Toy_Table* table) {
|
||||||
@@ -104,7 +104,7 @@ void Toy_insertTable(Toy_Table** tableHandle, Toy_Value key, Toy_Value value) {
|
|||||||
|
|
||||||
//expand the capacity
|
//expand the capacity
|
||||||
if ((*tableHandle)->count > (*tableHandle)->capacity * 0.8) {
|
if ((*tableHandle)->count > (*tableHandle)->capacity * 0.8) {
|
||||||
(*tableHandle) = adjustTableCapacity((*tableHandle), (*tableHandle)->capacity * 2);
|
(*tableHandle) = Toy_private_adjustTableCapacity((*tableHandle), (*tableHandle)->capacity * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
probeAndInsert(tableHandle, key, value);
|
probeAndInsert(tableHandle, key, value);
|
||||||
|
|||||||
@@ -26,3 +26,5 @@ TOY_API void Toy_insertTable(Toy_Table** tableHandle, Toy_Value key, Toy_Value v
|
|||||||
TOY_API Toy_Value Toy_lookupTable(Toy_Table** tableHandle, Toy_Value key);
|
TOY_API Toy_Value Toy_lookupTable(Toy_Table** tableHandle, Toy_Value key);
|
||||||
TOY_API void Toy_removeTable(Toy_Table** tableHandle, Toy_Value key);
|
TOY_API void Toy_removeTable(Toy_Table** tableHandle, Toy_Value key);
|
||||||
|
|
||||||
|
//NOTE: exposed to skip unnecessary allocations within Toy_Scope
|
||||||
|
TOY_API Toy_Table* Toy_private_adjustTableCapacity(Toy_Table* oldTable, unsigned int newCapacity);
|
||||||
|
|||||||
327
tests/cases/test_scope.c
Normal file
327
tests/cases/test_scope.c
Normal file
@@ -0,0 +1,327 @@
|
|||||||
|
#include "toy_scope.h"
|
||||||
|
#include "toy_console_colors.h"
|
||||||
|
|
||||||
|
#include "toy_bucket.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int test_scope_allocation() {
|
||||||
|
//allocate and free a scope
|
||||||
|
{
|
||||||
|
//setup
|
||||||
|
Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL);
|
||||||
|
|
||||||
|
Toy_Scope* scope = Toy_pushScope(&bucket, NULL);
|
||||||
|
|
||||||
|
//check
|
||||||
|
if (scope == NULL ||
|
||||||
|
scope->next != NULL ||
|
||||||
|
scope->table == NULL ||
|
||||||
|
scope->table->capacity != 16 ||
|
||||||
|
scope->refCount != 1 ||
|
||||||
|
|
||||||
|
false)
|
||||||
|
{
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to allocate a Toy_Scope\n" TOY_CC_RESET);
|
||||||
|
Toy_popScope(scope);
|
||||||
|
Toy_freeBucket(&bucket);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
Toy_popScope(scope);
|
||||||
|
Toy_freeBucket(&bucket);
|
||||||
|
}
|
||||||
|
|
||||||
|
//allocate and free a list of scopes
|
||||||
|
{
|
||||||
|
//setup
|
||||||
|
Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL);
|
||||||
|
|
||||||
|
//run
|
||||||
|
Toy_Scope* scope = NULL;
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
scope = Toy_pushScope(&bucket, scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
//check
|
||||||
|
if (
|
||||||
|
scope == NULL ||
|
||||||
|
scope->next == NULL ||
|
||||||
|
scope->table == NULL ||
|
||||||
|
scope->table->capacity != 16 ||
|
||||||
|
scope->refCount != 1 ||
|
||||||
|
|
||||||
|
scope->next->next == NULL ||
|
||||||
|
scope->next->table == NULL ||
|
||||||
|
scope->next->table->capacity != 16 ||
|
||||||
|
scope->next->refCount != 2 ||
|
||||||
|
|
||||||
|
scope->next->next->next == NULL ||
|
||||||
|
scope->next->next->table == NULL ||
|
||||||
|
scope->next->next->table->capacity != 16 ||
|
||||||
|
scope->next->next->refCount != 3 ||
|
||||||
|
|
||||||
|
scope->next->next->next->next == NULL ||
|
||||||
|
scope->next->next->next->table == NULL ||
|
||||||
|
scope->next->next->next->table->capacity != 16 ||
|
||||||
|
scope->next->next->next->refCount != 4 ||
|
||||||
|
|
||||||
|
scope->next->next->next->next->next != NULL ||
|
||||||
|
scope->next->next->next->next->table == NULL ||
|
||||||
|
scope->next->next->next->next->table->capacity != 16 ||
|
||||||
|
scope->next->next->next->next->refCount != 5 || //refCount includes all ancestors
|
||||||
|
|
||||||
|
false)
|
||||||
|
{
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to allocate a list of Toy_Scope\n" TOY_CC_RESET);
|
||||||
|
while (scope) {
|
||||||
|
scope = Toy_popScope(scope);
|
||||||
|
}
|
||||||
|
Toy_freeBucket(&bucket);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
while (scope) {
|
||||||
|
scope = Toy_popScope(scope);
|
||||||
|
}
|
||||||
|
Toy_freeBucket(&bucket);
|
||||||
|
}
|
||||||
|
|
||||||
|
//ensure pops work correctly
|
||||||
|
{
|
||||||
|
//setup
|
||||||
|
Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL);
|
||||||
|
|
||||||
|
//run
|
||||||
|
Toy_Scope* scope = NULL;
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
scope = Toy_pushScope(&bucket, scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
scope = Toy_popScope(scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
//check
|
||||||
|
if (
|
||||||
|
scope == NULL ||
|
||||||
|
scope->next == NULL ||
|
||||||
|
scope->table == NULL ||
|
||||||
|
scope->table->capacity != 16 ||
|
||||||
|
scope->refCount != 1 ||
|
||||||
|
|
||||||
|
scope->next->next == NULL ||
|
||||||
|
scope->next->table == NULL ||
|
||||||
|
scope->next->table->capacity != 16 ||
|
||||||
|
scope->next->refCount != 2 ||
|
||||||
|
|
||||||
|
scope->next->next->next != NULL ||
|
||||||
|
scope->next->next->table == NULL ||
|
||||||
|
scope->next->next->table->capacity != 16 ||
|
||||||
|
scope->next->next->refCount != 3 ||
|
||||||
|
|
||||||
|
false)
|
||||||
|
{
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to allocate and free a list of Toy_Scope\n" TOY_CC_RESET);
|
||||||
|
while (scope) {
|
||||||
|
scope = Toy_popScope(scope);
|
||||||
|
}
|
||||||
|
Toy_freeBucket(&bucket);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
while (scope) {
|
||||||
|
scope = Toy_popScope(scope);
|
||||||
|
}
|
||||||
|
Toy_freeBucket(&bucket);
|
||||||
|
}
|
||||||
|
|
||||||
|
//branched scope references
|
||||||
|
{
|
||||||
|
//setup
|
||||||
|
Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL);
|
||||||
|
|
||||||
|
//run
|
||||||
|
Toy_Scope* scopeBase = Toy_pushScope(&bucket, NULL);
|
||||||
|
Toy_Scope* scopeA = Toy_pushScope(&bucket, scopeBase);
|
||||||
|
Toy_Scope* scopeB = Toy_pushScope(&bucket, scopeBase);
|
||||||
|
|
||||||
|
//check
|
||||||
|
if (
|
||||||
|
scopeBase == NULL ||
|
||||||
|
scopeBase->next != NULL ||
|
||||||
|
scopeBase->table == NULL ||
|
||||||
|
scopeBase->table->capacity != 16 ||
|
||||||
|
scopeBase->refCount != 3 ||
|
||||||
|
|
||||||
|
scopeA == NULL ||
|
||||||
|
scopeA->next != scopeBase ||
|
||||||
|
scopeA->table == NULL ||
|
||||||
|
scopeA->table->capacity != 16 ||
|
||||||
|
scopeA->refCount != 1 ||
|
||||||
|
|
||||||
|
scopeB == NULL ||
|
||||||
|
scopeB->next != scopeBase ||
|
||||||
|
scopeB->table == NULL ||
|
||||||
|
scopeB->table->capacity != 16 ||
|
||||||
|
scopeB->refCount != 1 ||
|
||||||
|
|
||||||
|
scopeA->next != scopeB->next || //double check
|
||||||
|
|
||||||
|
false)
|
||||||
|
{
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to allocate branched scopes\n" TOY_CC_RESET);
|
||||||
|
Toy_popScope(scopeB);
|
||||||
|
Toy_popScope(scopeA);
|
||||||
|
Toy_popScope(scopeBase);
|
||||||
|
Toy_freeBucket(&bucket);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
Toy_popScope(scopeB);
|
||||||
|
Toy_popScope(scopeA);
|
||||||
|
Toy_popScope(scopeBase);
|
||||||
|
|
||||||
|
Toy_freeBucket(&bucket);
|
||||||
|
}
|
||||||
|
|
||||||
|
//deallocate ancestors correctly
|
||||||
|
{
|
||||||
|
//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* scopeC = Toy_pushScope(&bucket, scopeB);
|
||||||
|
|
||||||
|
Toy_popScope(scopeB);
|
||||||
|
|
||||||
|
//check
|
||||||
|
if (
|
||||||
|
scopeA == NULL ||
|
||||||
|
scopeA->next != NULL ||
|
||||||
|
scopeA->table == NULL ||
|
||||||
|
scopeA->table->capacity != 16 ||
|
||||||
|
scopeA->refCount != 2 ||
|
||||||
|
|
||||||
|
//scopeB still exists in memory until scopeC is popped
|
||||||
|
scopeB == NULL ||
|
||||||
|
scopeB->next != scopeA ||
|
||||||
|
scopeB->table == NULL ||
|
||||||
|
scopeB->table->capacity != 16 ||
|
||||||
|
scopeB->refCount != 1 ||
|
||||||
|
|
||||||
|
scopeC == NULL ||
|
||||||
|
scopeC->next != scopeB ||
|
||||||
|
scopeC->table == NULL ||
|
||||||
|
scopeC->table->capacity != 16 ||
|
||||||
|
scopeC->refCount != 1 ||
|
||||||
|
|
||||||
|
false)
|
||||||
|
{
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to deallocate ancestors scopes correctly\n" TOY_CC_RESET);
|
||||||
|
Toy_popScope(scopeC);
|
||||||
|
Toy_popScope(scopeA);
|
||||||
|
Toy_freeBucket(&bucket);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
Toy_popScope(scopeC);
|
||||||
|
Toy_popScope(scopeA);
|
||||||
|
|
||||||
|
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 != 16 ||
|
||||||
|
scopeA->refCount != 3 ||
|
||||||
|
|
||||||
|
scopeB == NULL ||
|
||||||
|
scopeB->next != scopeA ||
|
||||||
|
scopeB->table == NULL ||
|
||||||
|
scopeB->table->capacity != 16 ||
|
||||||
|
scopeB->refCount != 1 ||
|
||||||
|
|
||||||
|
scopeB == NULL ||
|
||||||
|
scopeB->next != scopeA ||
|
||||||
|
scopeB->table == NULL ||
|
||||||
|
scopeB->table->capacity != 16 ||
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_scope_elements() {
|
||||||
|
//TODO: Ensure the scope's primary function of handling key-value pairs works correctly.
|
||||||
|
printf(TOY_CC_WARN "'test_scope_elements()' not yet implemented\n" TOY_CC_RESET);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
//run each test set, returning the total errors given
|
||||||
|
int total = 0, res = 0;
|
||||||
|
|
||||||
|
{
|
||||||
|
res = test_scope_allocation();
|
||||||
|
if (res == 0) {
|
||||||
|
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||||
|
}
|
||||||
|
total += res;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
res = test_scope_elements();
|
||||||
|
if (res == 0) {
|
||||||
|
// printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
|
||||||
|
}
|
||||||
|
total += res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
@@ -23,7 +23,7 @@ TEST_OBJDIR=obj
|
|||||||
|
|
||||||
#file names
|
#file names
|
||||||
TEST_SOURCEFILES=$(wildcard $(TEST_SOURCEDIR)/*.c)
|
TEST_SOURCEFILES=$(wildcard $(TEST_SOURCEDIR)/*.c)
|
||||||
TEST_CASESFILES=$(wildcard $(TEST_CASESDIR)/*.c)
|
TEST_CASESFILES=$(wildcard $(TEST_CASESDIR)/test_*.c)
|
||||||
|
|
||||||
#build the object files, compile the test cases, and run
|
#build the object files, compile the test cases, and run
|
||||||
all: clean build-source build-cases build-link build-run
|
all: clean build-source build-cases build-link build-run
|
||||||
|
|||||||
Reference in New Issue
Block a user