Use reference counting for identifiers

This commit is contained in:
2026-06-17 10:11:15 +10:00
parent 6d35acbe60
commit b4e481ed9c
16 changed files with 112 additions and 156 deletions

View File

@@ -38,6 +38,8 @@ typedef struct GroundError GroundError;
// --- Helper types --- // --- Helper types ---
typedef struct GroundIdentifier GroundIdentifier;
typedef struct GroundFunctionArg GroundFunctionArg; typedef struct GroundFunctionArg GroundFunctionArg;
typedef struct GroundObjectField GroundObjectField; typedef struct GroundObjectField GroundObjectField;
@@ -113,7 +115,7 @@ struct GroundType {
struct GroundFunctionArg { struct GroundFunctionArg {
union { union {
char* id; GroundIdentifier* id;
GroundType type; GroundType type;
} as; } as;
}; };
@@ -143,7 +145,7 @@ enum GroundArgType {
struct GroundArg { struct GroundArg {
enum GroundArgType type; enum GroundArgType type;
union { union {
char* ref; GroundIdentifier* ref;
GroundValue value; GroundValue value;
} as; } as;
@@ -247,6 +249,11 @@ struct GroundState {
size_t _size; size_t _size;
}; };
struct GroundIdentifier {
char* string;
size_t referenceCount;
};
// //
// INTERFACE // INTERFACE
// //
@@ -277,12 +284,12 @@ struct _Ground {
struct { struct {
GroundArg (*Value) (GroundValue value); GroundArg (*Value) (GroundValue value);
GroundArg (*ValueRef) (const char* ref); GroundArg (*ValueRef) (GroundIdentifier* ref);
GroundArg (*DirectRef) (const char* ref); GroundArg (*DirectRef) (GroundIdentifier* ref);
GroundArg (*LineRef) (const char* ref); GroundArg (*LineRef) (GroundIdentifier* ref);
GroundArg (*LabelRef) (const char* ref); GroundArg (*LabelRef) (GroundIdentifier* ref);
GroundArg (*FunctionRef) (const char* ref); GroundArg (*FunctionRef) (GroundIdentifier* ref);
GroundArg (*TypeRef) (const char* ref); GroundArg (*TypeRef) (GroundIdentifier* ref);
} Arg; } Arg;
GroundList (*List) (); GroundList (*List) ();
@@ -298,6 +305,8 @@ struct _Ground {
GroundProgram (*Program) (); GroundProgram (*Program) ();
GroundType (*Type) (enum GroundTypeType type, ...); GroundType (*Type) (enum GroundTypeType type, ...);
GroundIdentifier* (*Identifier) (const char* id);
} New; } New;
// Frees the memory held by the specified struct // Frees the memory held by the specified struct
@@ -313,6 +322,8 @@ struct _Ground {
void (*Instruction) (GroundInstruction* in); void (*Instruction) (GroundInstruction* in);
void (*Program) (GroundProgram* in); void (*Program) (GroundProgram* in);
void (*State) (GroundState* state); void (*State) (GroundState* state);
void (*Identifier) (GroundIdentifier* identifier);
} Free; } Free;
// Creates a copy of the memory held by the specified struct // Creates a copy of the memory held by the specified struct
@@ -328,6 +339,8 @@ struct _Ground {
GroundInstruction (*Instruction) (GroundInstruction* in); GroundInstruction (*Instruction) (GroundInstruction* in);
GroundProgram (*Program) (GroundProgram* in); GroundProgram (*Program) (GroundProgram* in);
GroundState (*State) (GroundState* in); GroundState (*State) (GroundState* in);
GroundIdentifier* (*Identifier) (GroundIdentifier* in);
} Copy; } Copy;
struct { struct {

View File

@@ -14,6 +14,8 @@ sources = files(
'src/Copy/Struct.c', 'src/Copy/Struct.c',
'src/Copy/Value.c', 'src/Copy/Value.c',
'src/Copy/Identifier.c',
'src/Free/Function.c', 'src/Free/Function.c',
'src/Free/List.c', 'src/Free/List.c',
'src/Free/Object.c', 'src/Free/Object.c',
@@ -26,6 +28,8 @@ sources = files(
'src/Free/Program.c', 'src/Free/Program.c',
'src/Free/State.c', 'src/Free/State.c',
'src/Free/Identifier.c',
'src/Function/appendInstruction.c', 'src/Function/appendInstruction.c',
'src/Function/appendArg.c', 'src/Function/appendArg.c',
@@ -58,6 +62,8 @@ sources = files(
'src/New/String.c', 'src/New/String.c',
'src/New/Struct.c', 'src/New/Struct.c',
'src/New/Identifier.c',
'src/New/NativeFunction.c', 'src/New/NativeFunction.c',
'src/New/Instruction.c', 'src/New/Instruction.c',

View File

@@ -25,17 +25,19 @@ GroundFunction _GroundCopyFunction(GroundFunction* in) {
*newFunction.closure = Ground.Copy.State(in->closure); *newFunction.closure = Ground.Copy.State(in->closure);
newFunction.args.at = malloc(sizeof(char*) * in->args.capacity); newFunction.args.at = malloc(sizeof(GroundFunctionArg) * in->args.capacity);
if (newFunction.args.at == NULL) {
Ground.Log.Error("malloc failed in Ground.Copy.Function()");
Ground.Flags.error = true;
return newFunction;
}
for (size_t i = 0; i < in->args.count; i++) { for (size_t i = 0; i < in->args.count; i++) {
size_t len = strlen(in->args.at[i].as.id);
newFunction.args.at = malloc(sizeof(char) * (len + 1));
if (newFunction.args.at == NULL) { if (newFunction.args.at == NULL) {
Ground.Log.Error("malloc failed in Ground.Copy.Function()"); Ground.Log.Error("malloc failed in Ground.Copy.Function()");
Ground.Flags.error = true; Ground.Flags.error = true;
return newFunction; return newFunction;
} }
newFunction.args.at->as.id = Ground.Copy.Identifier(in->args.at[i].as.id);
strcpy(newFunction.args.at[i].as.id, in->args.at[i].as.id);
} }
return newFunction; return newFunction;

6
src/Copy/Identifier.c Normal file
View File

@@ -0,0 +1,6 @@
#include "../../include/ground.h"
GroundIdentifier* _GroundCopyIdentifier(GroundIdentifier* identifier) {
identifier->referenceCount++;
return identifier;
}

View File

@@ -4,7 +4,6 @@ void _GroundFreeArg(GroundArg* in) {
if (in->type == GroundArg_Value) { if (in->type == GroundArg_Value) {
Ground.Free.Value(&in->as.value); Ground.Free.Value(&in->as.value);
} else { } else {
// FIXME - double free for arg Ground.Free.Identifier(in->as.ref);
// free(in->as.ref);
} }
} }

9
src/Free/Identifier.c Normal file
View File

@@ -0,0 +1,9 @@
#include "../../include/ground.h"
void _GroundFreeIdentifier(GroundIdentifier* identifier) {
identifier->referenceCount--;
if (identifier->referenceCount == 0) {
free(identifier->string);
free(identifier);
}
}

View File

@@ -1,7 +1,6 @@
#include "../../include/ground.h" #include "../../include/ground.h"
#include <string.h>
void _GroundFunctionAppendArg(GroundFunction* function, const char* argName) { void _GroundFunctionAppendArg(GroundFunction* function, GroundIdentifier* argName) {
if (function->isNativeFunction) { if (function->isNativeFunction) {
Ground.Log.Error("Cannot add arg to native function in Ground.Function.appendArg()"); Ground.Log.Error("Cannot add arg to native function in Ground.Function.appendArg()");
Ground.Flags.error = true; Ground.Flags.error = true;
@@ -19,14 +18,6 @@ void _GroundFunctionAppendArg(GroundFunction* function, const char* argName) {
function->args.capacity *= 2; function->args.capacity *= 2;
} }
size_t len = strlen(argName); function->args.at[function->args.count].as.id = Ground.Copy.Identifier(argName);
function->args.at[function->args.count].as.id = malloc(sizeof(char) * (len + 1));
if (function->args.at[function->args.count].as.id == NULL) {
Ground.Log.Error("malloc failed in Ground.Function.appendArg()");
Ground.Flags.error = true;
return;
}
strcpy(function->args.at[function->args.count].as.id, argName);
function->args.count++; function->args.count++;
} }

View File

@@ -12,7 +12,7 @@ static inline void doLabels(GroundProgram* program, GroundState* state) {
if (instruction->args.len > 0) { if (instruction->args.len > 0) {
GroundArg* arg = &instruction->args.at[0]; GroundArg* arg = &instruction->args.at[0];
GroundLabel* label = NULL; GroundLabel* label = NULL;
HASH_FIND_STR(state->labels, arg->as.ref, label); HASH_FIND_STR(state->labels, arg->as.ref->string, label);
if (label == NULL) { if (label == NULL) {
label = malloc(sizeof(GroundLabel)); label = malloc(sizeof(GroundLabel));
@@ -21,7 +21,7 @@ static inline void doLabels(GroundProgram* program, GroundState* state) {
Ground.Flags.error = true; Ground.Flags.error = true;
return; return;
} }
strncpy(label->name, arg->as.ref, 2047); strncpy(label->name, arg->as.ref->string, 2047);
label->name[2047] = '\0'; label->name[2047] = '\0';
label->lineNum = i; label->lineNum = i;
HASH_ADD_STR(state->labels, name, label); HASH_ADD_STR(state->labels, name, label);
@@ -34,10 +34,10 @@ static inline void doLabels(GroundProgram* program, GroundState* state) {
GroundInstruction* instruction = &program->at[i]; GroundInstruction* instruction = &program->at[i];
if (instruction->type == GroundInstruction_JUMP) { if (instruction->type == GroundInstruction_JUMP) {
GroundArg* arg = &instruction->args.at[0]; GroundArg* arg = &instruction->args.at[0];
size_t* line = Ground.State.findLabel(state, arg->as.ref); size_t* line = Ground.State.findLabel(state, arg->as.ref->string);
if (line == NULL) { if (line == NULL) {
char buf[2048]; char buf[2048];
snprintf(buf, 2047, "couldn't find label '%s' (instruction JUMP at %zu) in Ground.Internal.Run()", arg->as.ref, i); snprintf(buf, 2047, "couldn't find label '%s' (instruction JUMP at %zu) in Ground.Internal.Run()", arg->as.ref->string, i);
Ground.Log.Error(buf); Ground.Log.Error(buf);
Ground.Flags.error = true; Ground.Flags.error = true;
return; return;
@@ -47,10 +47,10 @@ static inline void doLabels(GroundProgram* program, GroundState* state) {
} else if (instruction->type == GroundInstruction_IF) { } else if (instruction->type == GroundInstruction_IF) {
GroundArg* arg = &instruction->args.at[1]; GroundArg* arg = &instruction->args.at[1];
size_t* line = Ground.State.findLabel(state, arg->as.ref); size_t* line = Ground.State.findLabel(state, arg->as.ref->string);
if (line == NULL) { if (line == NULL) {
char buf[2048]; char buf[2048];
snprintf(buf, 2047, "couldn't find label '%s' (instruction IF at %zu) in Ground.Internal.Run()", arg->as.ref, i); snprintf(buf, 2047, "couldn't find label '%s' (instruction IF at %zu) in Ground.Internal.Run()", arg->as.ref->string, i);
Ground.Log.Error(buf); Ground.Log.Error(buf);
Ground.Flags.error = true; Ground.Flags.error = true;
return; return;
@@ -60,10 +60,10 @@ static inline void doLabels(GroundProgram* program, GroundState* state) {
} else if (instruction->type == GroundInstruction_CATCH) { } else if (instruction->type == GroundInstruction_CATCH) {
GroundArg* arg = &instruction->args.at[1]; GroundArg* arg = &instruction->args.at[1];
size_t* line = Ground.State.findLabel(state, arg->as.ref); size_t* line = Ground.State.findLabel(state, arg->as.ref->string);
if (line == NULL) { if (line == NULL) {
char buf[2048]; char buf[2048];
snprintf(buf, 2047, "couldn't find label '%s' (instruction CATCH at %zu) in Ground.Internal.Run()", arg->as.ref, i); snprintf(buf, 2047, "couldn't find label '%s' (instruction CATCH at %zu) in Ground.Internal.Run()", arg->as.ref->string, i);
Ground.Log.Error(buf); Ground.Log.Error(buf);
Ground.Flags.error = true; Ground.Flags.error = true;
return; return;
@@ -92,7 +92,7 @@ static inline size_t doOffsets(GroundProgram* program, GroundState* state) {
) continue; ) continue;
GroundVariable* item = NULL; GroundVariable* item = NULL;
HASH_FIND_STR(state->variables, arg->as.ref, item); HASH_FIND_STR(state->variables, arg->as.ref->string, item);
if (item == NULL) { if (item == NULL) {
item = malloc(sizeof(GroundVariable)); item = malloc(sizeof(GroundVariable));
@@ -102,7 +102,7 @@ static inline size_t doOffsets(GroundProgram* program, GroundState* state) {
return 0; return 0;
} }
item->value = Ground.New.Value.Int(0); item->value = Ground.New.Value.Int(0);
strncpy(item->name, arg->as.ref, 2047); strncpy(item->name, arg->as.ref->string, 2047);
item->_offset = size++; item->_offset = size++;
HASH_ADD_STR(state->variables, name, item); HASH_ADD_STR(state->variables, name, item);
} }

View File

@@ -1,25 +1,8 @@
#include "../../../include/ground.h" #include "../../../include/ground.h"
#include <string.h> GroundArg _GroundNewArgDirectRef(GroundIdentifier* ref) {
#include <stdlib.h>
GroundArg _GroundNewArgDirectRef(const char* ref) {
size_t len = strlen(ref);
char* copy = malloc(len + 1);
if (copy == NULL) {
Ground.Log.Error("malloc failed in Ground.New.Arg.DirectRef()");
Ground.Flags.error = true;
return (GroundArg) {
.type = GroundArg_DirectRef,
.as.ref = ""
};
}
strcpy(copy, ref);
return (GroundArg) { return (GroundArg) {
.type = GroundArg_DirectRef, .type = GroundArg_DirectRef,
.as.ref = copy .as.ref = Ground.Copy.Identifier(ref)
}; };
} }

View File

@@ -1,25 +1,8 @@
#include "../../../include/ground.h" #include "../../../include/ground.h"
#include <string.h> GroundArg _GroundNewArgFunctionRef(GroundIdentifier* ref) {
#include <stdlib.h>
GroundArg _GroundNewArgFunctionRef(const char* ref) {
size_t len = strlen(ref);
char* copy = malloc(len + 1);
if (copy == NULL) {
Ground.Log.Error("malloc failed in Ground.New.Arg.FunctionRef()");
Ground.Flags.error = true;
return (GroundArg) {
.type = GroundArg_DirectRef,
.as.ref = ""
};
}
strcpy(copy, ref);
return (GroundArg) { return (GroundArg) {
.type = GroundArg_FunctionRef, .type = GroundArg_FunctionRef,
.as.ref = copy .as.ref = Ground.Copy.Identifier(ref)
}; };
} }

View File

@@ -1,26 +1,9 @@
#include "../../../include/ground.h" #include "../../../include/ground.h"
#include <string.h> GroundArg _GroundNewArgLabelRef(GroundIdentifier* ref) {
#include <stdlib.h>
GroundArg _GroundNewArgLabelRef(const char* ref) {
size_t len = strlen(ref);
char* copy = malloc(len + 1);
if (copy == NULL) {
Ground.Log.Error("malloc failed in Ground.New.Arg.LabelRef()");
Ground.Flags.error = true;
return (GroundArg) {
.type = GroundArg_DirectRef,
.as.ref = ""
};
}
strcpy(copy, ref);
return (GroundArg) { return (GroundArg) {
.type = GroundArg_Label, .type = GroundArg_Label,
.as.ref = copy .as.ref = Ground.Copy.Identifier(ref)
}; };
} }

View File

@@ -1,25 +1,8 @@
#include "../../../include/ground.h" #include "../../../include/ground.h"
#include <string.h> GroundArg _GroundNewArgLineRef(GroundIdentifier* ref) {
#include <stdlib.h>
GroundArg _GroundNewArgLineRef(const char* ref) {
size_t len = strlen(ref);
char* copy = malloc(len + 1);
if (copy == NULL) {
Ground.Log.Error("malloc failed in Ground.New.Arg.LineRef()");
Ground.Flags.error = true;
return (GroundArg) {
.type = GroundArg_DirectRef,
.as.ref = ""
};
}
strcpy(copy, ref);
return (GroundArg) { return (GroundArg) {
.type = GroundArg_LineRef, .type = GroundArg_LineRef,
.as.ref = copy .as.ref = Ground.Copy.Identifier(ref)
}; };
} }

View File

@@ -1,26 +1,9 @@
#include "../../../include/ground.h" #include "../../../include/ground.h"
#include <string.h> GroundArg _GroundNewArgTypeRef(GroundIdentifier* ref) {
#include <stdlib.h>
GroundArg _GroundNewArgTypeRef(const char* ref) {
size_t len = strlen(ref);
char* copy = malloc(len + 1);
if (copy == NULL) {
Ground.Log.Error("malloc failed in Ground.New.Arg.TypeRef()");
Ground.Flags.error = true;
return (GroundArg) {
.type = GroundArg_DirectRef,
.as.ref = ""
};
}
strcpy(copy, ref);
return (GroundArg) { return (GroundArg) {
.type = GroundArg_TypeRef, .type = GroundArg_TypeRef,
.as.ref = copy .as.ref = Ground.Copy.Identifier(ref)
}; };
} }

View File

@@ -1,26 +1,9 @@
#include "../../../include/ground.h" #include "../../../include/ground.h"
#include <string.h> GroundArg _GroundNewArgValueRef(GroundIdentifier* ref) {
#include <stdlib.h>
GroundArg _GroundNewArgValueRef(const char* ref) {
size_t len = strlen(ref);
char* copy = malloc(len + 1);
if (copy == NULL) {
Ground.Log.Error("malloc failed in Ground.New.Arg.ValueRef()");
Ground.Flags.error = true;
return (GroundArg) {
.type = GroundArg_DirectRef,
.as.ref = ""
};
}
strcpy(copy, ref);
return (GroundArg) { return (GroundArg) {
.type = GroundArg_ValueRef, .type = GroundArg_ValueRef,
.as.ref = copy .as.ref = Ground.Copy.Identifier(ref)
}; };
} }

22
src/New/Identifier.c Normal file
View File

@@ -0,0 +1,22 @@
#include "../../include/ground.h"
GroundIdentifier* _GroundNewIdentifier(const char* id) {
GroundIdentifier* identifier = malloc(sizeof(GroundIdentifier));
if (identifier == NULL) {
Ground.Log.Error("malloc failed in Ground.New.Identifier");
Ground.Flags.error = true;
return NULL;
}
identifier->string = malloc(sizeof(char) * (strlen(id) + 1));
if (identifier->string == NULL) {
Ground.Log.Error("malloc failed in Ground.New.Identifier");
Ground.Flags.error = true;
return NULL;
}
strcpy(identifier->string, id);
identifier->referenceCount = 1;
return identifier;
}

View File

@@ -11,12 +11,12 @@ GroundValue _GroundNewValueStruct(GroundStruct in);
GroundValue _GroundNewValueObject(GroundObject in); GroundValue _GroundNewValueObject(GroundObject in);
GroundArg _GroundNewArgValue(GroundValue value); GroundArg _GroundNewArgValue(GroundValue value);
GroundArg _GroundNewArgValueRef(const char* ref); GroundArg _GroundNewArgValueRef(GroundIdentifier* ref);
GroundArg _GroundNewArgDirectRef(const char* ref); GroundArg _GroundNewArgDirectRef(GroundIdentifier* ref);
GroundArg _GroundNewArgLineRef(const char* ref); GroundArg _GroundNewArgLineRef(GroundIdentifier* ref);
GroundArg _GroundNewArgLabelRef(const char* ref); GroundArg _GroundNewArgLabelRef(GroundIdentifier* ref);
GroundArg _GroundNewArgFunctionRef(const char* ref); GroundArg _GroundNewArgFunctionRef(GroundIdentifier* ref);
GroundArg _GroundNewArgTypeRef(const char* ref); GroundArg _GroundNewArgTypeRef(GroundIdentifier* ref);
GroundList _GroundNewList(); GroundList _GroundNewList();
GroundString _GroundNewString(const char* in); GroundString _GroundNewString(const char* in);
@@ -30,6 +30,7 @@ GroundInstruction _GroundNewInstruction(enum GroundInstructionType type);
GroundProgram _GroundNewProgram(); GroundProgram _GroundNewProgram();
GroundType _GroundNewType(enum GroundTypeType type, ...); GroundType _GroundNewType(enum GroundTypeType type, ...);
GroundIdentifier* _GroundNewIdentifier(const char* id);
void _GroundFreeValue(GroundValue* in); void _GroundFreeValue(GroundValue* in);
void _GroundFreeList(GroundList* in); void _GroundFreeList(GroundList* in);
@@ -43,6 +44,8 @@ void _GroundFreeInstruction(GroundInstruction* in);
void _GroundFreeProgram(GroundProgram* in); void _GroundFreeProgram(GroundProgram* in);
void _GroundFreeState(GroundState* in); void _GroundFreeState(GroundState* in);
void _GroundFreeIdentifier(GroundIdentifier* identifier);
GroundValue _GroundCopyValue(GroundValue* in); GroundValue _GroundCopyValue(GroundValue* in);
GroundList _GroundCopyList(GroundList* in); GroundList _GroundCopyList(GroundList* in);
@@ -56,6 +59,8 @@ GroundInstruction _GroundCopyInstruction(GroundInstruction* in);
GroundProgram _GroundCopyProgram(GroundProgram* in); GroundProgram _GroundCopyProgram(GroundProgram* in);
GroundState _GroundCopyState(GroundState* in); GroundState _GroundCopyState(GroundState* in);
GroundIdentifier* _GroundCopyIdentifier(GroundIdentifier* identifier);
void _GroundListAppend(GroundList* list, GroundValue value); void _GroundListAppend(GroundList* list, GroundValue value);
@@ -129,6 +134,8 @@ struct _Ground Ground = {
.Instruction = _GroundNewInstruction, .Instruction = _GroundNewInstruction,
.Program = _GroundNewProgram, .Program = _GroundNewProgram,
.Type = _GroundNewType, .Type = _GroundNewType,
.Identifier = _GroundNewIdentifier,
}, },
.Free = { .Free = {
@@ -143,6 +150,8 @@ struct _Ground Ground = {
.Instruction = _GroundFreeInstruction, .Instruction = _GroundFreeInstruction,
.Program = _GroundFreeProgram, .Program = _GroundFreeProgram,
.State = _GroundFreeState, .State = _GroundFreeState,
.Identifier = _GroundFreeIdentifier,
}, },
.Copy = { .Copy = {
@@ -158,6 +167,7 @@ struct _Ground Ground = {
.Program = _GroundCopyProgram, .Program = _GroundCopyProgram,
.State = _GroundCopyState, .State = _GroundCopyState,
.Identifier = _GroundCopyIdentifier,
}, },
.List = { .List = {