WIP: Scopes weren't tracking their content sizes

'print' no longer segfaults from a long chain of indirect memory frees.

It still doesn't work though, which is odd.
This commit is contained in:
2026-04-06 21:50:41 +10:00
parent abae97b6e5
commit 1ae3fcbf73
10 changed files with 12 additions and 219 deletions

View File

@@ -1,29 +0,0 @@
//TODO: Not yet functional
//advent of code thingy
var arr = [
3, 4,
4, 3,
2, 5,
1, 3,
3, 9,
3, 3,
];
var total = 0;
var counter = 0;
while (counter < arr.length) {
var difference = arr[counter] - arr[counter+1];
if (difference < 0) {
difference = -difference;
}
total += difference;
counter += 2;
}
print difference;

View File

@@ -1,17 +0,0 @@
//calculate the nth fibonacci number, and print it
var counter: int = 0;
var first: int = 1;
var second: int = 0;
//This causes integer overflow, but that's fine for now
while (counter < 100_000) {
var third: int = first + second;
first = second;
second = third;
print third;
++counter;
}

View File

@@ -1,100 +0,0 @@
//make sure it works with multiple repititions
//-------------------------
//test break
while (true) {
break;
assert false, "break failed";
}
//test continue
var flag1: bool = true;
while (flag1) {
flag1 = false;
continue;
assert false, "continue failed";
}
print "done";
//-------------------------
//test break
while (true) {
break;
assert false, "break failed";
}
//test continue
var flag2: bool = true;
while (flag2) {
flag2 = false;
continue;
assert false, "continue failed";
}
print "done";
//-------------------------
//test break
while (true) {
break;
assert false, "break failed";
}
//test continue
var flag3: bool = true;
while (flag3) {
flag3 = false;
continue;
assert false, "continue failed";
}
print "done";
//-------------------------
{
//test break
while (true) {
break;
assert false, "break failed";
}
//test continue
var flag4: bool = true;
while (flag4) {
flag4 = false;
continue;
assert false, "continue failed";
}
print "done";
}
//-------------------------
{
//test break
while (true) {
{
break;
}
assert false, "break failed";
}
//test continue
var flag5: bool = true;
while (flag5) {
flag5 = false;
{
continue;
}
assert false, "continue failed";
}
print "done";
}

View File

@@ -1,15 +0,0 @@
//TODO: Not yet functional
//example of the fibonacci sequence
fn fib(n: int) {
if (n < 2) return n;
return fib(n-1) + fib(n-2);
}
//TODO: type coercion syntax hasn't been decided on yet, but it will be needed
for (var i = 1; i <= 10; i++) {
print i .. ":" .. fib(i);
}
//Note to my future self: yes, the base case in 'fib()' is 'n < 2', stop second guessing yourself!
//Note to my past self: don't tell me what to do!

View File

@@ -1,24 +0,0 @@
//standard example, using 'while' instead of 'for', because it's not ready yet
var counter: int = 0;
while (++counter <= 100) {
var result: string = "";
if (counter % 3 == 0) {
result = result .. "fizz";
}
if (counter % 5 == 0) {
result = result .. "buzz";
}
//finally
if (result != "") {
print result;
}
else {
print counter;
}
}

View File

@@ -1,20 +0,0 @@
//TODO: functions are untested
fn makeCounter() {
var counter: int = 0;
fn increment() {
return ++counter;
}
return increment;
}
var tally = makeCounter();
while (true) {
var result = tally();
if (result >= 10_000_000) {
break;
}
}

View File

@@ -1,8 +0,0 @@
//TODO: Not yet functional
//find the leap years
fn isLeapYear(n: int) {
if (n % 400 == 0) return true;
if (n % 100 == 0) return false;
return n % 4 == 0;
}

View File

@@ -26,8 +26,10 @@ static void decrementRefCount(Toy_Scope* scope) {
if (iter->refCount == 0 && iter->data != NULL) { if (iter->refCount == 0 && iter->data != NULL) {
//free the scope entries when this scope is no longer needed //free the scope entries when this scope is no longer needed
for (unsigned int i = 0; i < iter->capacity; i++) { for (unsigned int i = 0; i < iter->capacity; i++) {
Toy_freeString(&(iter->data[i].key)); if (iter->data[i].psl > 0) {
Toy_freeValue(iter->data[i].value); Toy_freeString(&(iter->data[i].key));
Toy_freeValue(iter->data[i].value);
}
} }
free(iter->data); free(iter->data);
} }
@@ -62,7 +64,7 @@ static Toy_ScopeEntry* lookupScopeEntryPtr(Toy_Scope* scope, Toy_String* key, un
void probeAndInsert(Toy_Scope* scope, Toy_String* key, Toy_Value value, Toy_ValueType type, bool constant) { void probeAndInsert(Toy_Scope* scope, Toy_String* key, Toy_Value value, Toy_ValueType type, bool constant) {
//make the entry //make the entry
unsigned int probe = Toy_hashString(key) % scope->capacity; unsigned int probe = Toy_hashString(key) % scope->capacity;
Toy_ScopeEntry entry = (Toy_ScopeEntry){ .key = *key, .value = value, .type = type, .constant = constant, .psl = 0 }; Toy_ScopeEntry entry = (Toy_ScopeEntry){ .key = *key, .value = value, .type = type, .constant = constant, .psl = 1 };
//probe //probe
while (true) { while (true) {
@@ -134,8 +136,11 @@ Toy_Scope* Toy_pushScope(Toy_Bucket** bucketHandle, Toy_Scope* scope) {
Toy_Scope* newScope = (Toy_Scope*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Scope)); Toy_Scope* newScope = (Toy_Scope*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Scope));
newScope->next = scope; newScope->next = scope;
newScope->data = adjustScopeEntries(NULL, TOY_SCOPE_INITIAL_CAPACITY);
newScope->refCount = 0; newScope->refCount = 0;
newScope->data = adjustScopeEntries(NULL, TOY_SCOPE_INITIAL_CAPACITY);
newScope->capacity = TOY_SCOPE_INITIAL_CAPACITY;
newScope->count = 0;
newScope->maxPsl = 0;
incrementRefCount(newScope); incrementRefCount(newScope);

View File

@@ -11,18 +11,18 @@ typedef struct Toy_ScopeEntry {
Toy_String key; Toy_String key;
Toy_Value value; Toy_Value value;
Toy_ValueType type; Toy_ValueType type;
unsigned int psl; //psl '0' means empty
bool constant; bool constant;
unsigned int psl;
} Toy_ScopeEntry; } Toy_ScopeEntry;
//holds a table-like collection of variables TODO: check bitness //holds a table-like collection of variables TODO: check bitness
typedef struct Toy_Scope { typedef struct Toy_Scope {
struct Toy_Scope* next; struct Toy_Scope* next;
unsigned int refCount; unsigned int refCount;
Toy_ScopeEntry* data;
unsigned int capacity; unsigned int capacity;
unsigned int count; unsigned int count;
unsigned int maxPsl; unsigned int maxPsl;
Toy_ScopeEntry* data;
} Toy_Scope; } Toy_Scope;
//handle deep scopes - the scope is stored in the bucket, not the table //handle deep scopes - the scope is stored in the bucket, not the table

View File

@@ -67,6 +67,7 @@ Toy_String* Toy_concatStrings(Toy_Bucket** bucketHandle, Toy_String* left, Toy_S
} }
void Toy_freeString(Toy_String* str) { void Toy_freeString(Toy_String* str) {
assert(str->info.refCount > 0 && "Can't free a string with refcount 0");
//memory is freed when the bucket is //memory is freed when the bucket is
decrementRefCount(str); decrementRefCount(str);
} }