From b4e481ed9c303dbd6ef54c778509eb8777c84fa6 Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Wed, 17 Jun 2026 10:11:15 +1000 Subject: [PATCH] Use reference counting for identifiers --- include/ground.h | 29 +++++++++++++++++++++-------- meson.build | 6 ++++++ src/Copy/Function.c | 12 +++++++----- src/Copy/Identifier.c | 6 ++++++ src/Free/Arg.c | 3 +-- src/Free/Identifier.c | 9 +++++++++ src/Function/appendArg.c | 13 ++----------- src/Internal/run.c | 20 ++++++++++---------- src/New/Arg/DirectRef.c | 21 ++------------------- src/New/Arg/FunctionRef.c | 21 ++------------------- src/New/Arg/LabelRef.c | 21 ++------------------- src/New/Arg/LineRef.c | 21 ++------------------- src/New/Arg/TypeRef.c | 21 ++------------------- src/New/Arg/ValueRef.c | 21 ++------------------- src/New/Identifier.c | 22 ++++++++++++++++++++++ src/libmain.c | 22 ++++++++++++++++------ 16 files changed, 112 insertions(+), 156 deletions(-) create mode 100644 src/Copy/Identifier.c create mode 100644 src/Free/Identifier.c create mode 100644 src/New/Identifier.c diff --git a/include/ground.h b/include/ground.h index 5f11ca2..7efeb91 100644 --- a/include/ground.h +++ b/include/ground.h @@ -38,6 +38,8 @@ typedef struct GroundError GroundError; // --- Helper types --- +typedef struct GroundIdentifier GroundIdentifier; + typedef struct GroundFunctionArg GroundFunctionArg; typedef struct GroundObjectField GroundObjectField; @@ -113,7 +115,7 @@ struct GroundType { struct GroundFunctionArg { union { - char* id; + GroundIdentifier* id; GroundType type; } as; }; @@ -143,7 +145,7 @@ enum GroundArgType { struct GroundArg { enum GroundArgType type; union { - char* ref; + GroundIdentifier* ref; GroundValue value; } as; @@ -247,6 +249,11 @@ struct GroundState { size_t _size; }; +struct GroundIdentifier { + char* string; + size_t referenceCount; +}; + // // INTERFACE // @@ -277,12 +284,12 @@ struct _Ground { struct { GroundArg (*Value) (GroundValue value); - GroundArg (*ValueRef) (const char* ref); - GroundArg (*DirectRef) (const char* ref); - GroundArg (*LineRef) (const char* ref); - GroundArg (*LabelRef) (const char* ref); - GroundArg (*FunctionRef) (const char* ref); - GroundArg (*TypeRef) (const char* ref); + GroundArg (*ValueRef) (GroundIdentifier* ref); + GroundArg (*DirectRef) (GroundIdentifier* ref); + GroundArg (*LineRef) (GroundIdentifier* ref); + GroundArg (*LabelRef) (GroundIdentifier* ref); + GroundArg (*FunctionRef) (GroundIdentifier* ref); + GroundArg (*TypeRef) (GroundIdentifier* ref); } Arg; GroundList (*List) (); @@ -298,6 +305,8 @@ struct _Ground { GroundProgram (*Program) (); GroundType (*Type) (enum GroundTypeType type, ...); + GroundIdentifier* (*Identifier) (const char* id); + } New; // Frees the memory held by the specified struct @@ -313,6 +322,8 @@ struct _Ground { void (*Instruction) (GroundInstruction* in); void (*Program) (GroundProgram* in); void (*State) (GroundState* state); + + void (*Identifier) (GroundIdentifier* identifier); } Free; // Creates a copy of the memory held by the specified struct @@ -328,6 +339,8 @@ struct _Ground { GroundInstruction (*Instruction) (GroundInstruction* in); GroundProgram (*Program) (GroundProgram* in); GroundState (*State) (GroundState* in); + + GroundIdentifier* (*Identifier) (GroundIdentifier* in); } Copy; struct { diff --git a/meson.build b/meson.build index 9d9d940..dd74707 100644 --- a/meson.build +++ b/meson.build @@ -14,6 +14,8 @@ sources = files( 'src/Copy/Struct.c', 'src/Copy/Value.c', + 'src/Copy/Identifier.c', + 'src/Free/Function.c', 'src/Free/List.c', 'src/Free/Object.c', @@ -26,6 +28,8 @@ sources = files( 'src/Free/Program.c', 'src/Free/State.c', + 'src/Free/Identifier.c', + 'src/Function/appendInstruction.c', 'src/Function/appendArg.c', @@ -58,6 +62,8 @@ sources = files( 'src/New/String.c', 'src/New/Struct.c', + 'src/New/Identifier.c', + 'src/New/NativeFunction.c', 'src/New/Instruction.c', diff --git a/src/Copy/Function.c b/src/Copy/Function.c index af9130b..9adfbe5 100644 --- a/src/Copy/Function.c +++ b/src/Copy/Function.c @@ -25,17 +25,19 @@ GroundFunction _GroundCopyFunction(GroundFunction* in) { *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++) { - size_t len = strlen(in->args.at[i].as.id); - newFunction.args.at = malloc(sizeof(char) * (len + 1)); if (newFunction.args.at == NULL) { Ground.Log.Error("malloc failed in Ground.Copy.Function()"); Ground.Flags.error = true; return newFunction; } - - strcpy(newFunction.args.at[i].as.id, in->args.at[i].as.id); + newFunction.args.at->as.id = Ground.Copy.Identifier(in->args.at[i].as.id); } return newFunction; diff --git a/src/Copy/Identifier.c b/src/Copy/Identifier.c new file mode 100644 index 0000000..fa99479 --- /dev/null +++ b/src/Copy/Identifier.c @@ -0,0 +1,6 @@ +#include "../../include/ground.h" + +GroundIdentifier* _GroundCopyIdentifier(GroundIdentifier* identifier) { + identifier->referenceCount++; + return identifier; +} diff --git a/src/Free/Arg.c b/src/Free/Arg.c index 89e210e..87ace8d 100644 --- a/src/Free/Arg.c +++ b/src/Free/Arg.c @@ -4,7 +4,6 @@ void _GroundFreeArg(GroundArg* in) { if (in->type == GroundArg_Value) { Ground.Free.Value(&in->as.value); } else { - // FIXME - double free for arg - // free(in->as.ref); + Ground.Free.Identifier(in->as.ref); } } diff --git a/src/Free/Identifier.c b/src/Free/Identifier.c new file mode 100644 index 0000000..565d612 --- /dev/null +++ b/src/Free/Identifier.c @@ -0,0 +1,9 @@ +#include "../../include/ground.h" + +void _GroundFreeIdentifier(GroundIdentifier* identifier) { + identifier->referenceCount--; + if (identifier->referenceCount == 0) { + free(identifier->string); + free(identifier); + } +} diff --git a/src/Function/appendArg.c b/src/Function/appendArg.c index 84855d9..d2028df 100644 --- a/src/Function/appendArg.c +++ b/src/Function/appendArg.c @@ -1,7 +1,6 @@ #include "../../include/ground.h" -#include -void _GroundFunctionAppendArg(GroundFunction* function, const char* argName) { +void _GroundFunctionAppendArg(GroundFunction* function, GroundIdentifier* argName) { if (function->isNativeFunction) { Ground.Log.Error("Cannot add arg to native function in Ground.Function.appendArg()"); Ground.Flags.error = true; @@ -19,14 +18,6 @@ void _GroundFunctionAppendArg(GroundFunction* function, const char* argName) { function->args.capacity *= 2; } - size_t len = strlen(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.at[function->args.count].as.id = Ground.Copy.Identifier(argName); function->args.count++; } diff --git a/src/Internal/run.c b/src/Internal/run.c index b37cdff..3f3eda8 100644 --- a/src/Internal/run.c +++ b/src/Internal/run.c @@ -12,7 +12,7 @@ static inline void doLabels(GroundProgram* program, GroundState* state) { if (instruction->args.len > 0) { GroundArg* arg = &instruction->args.at[0]; 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) { label = malloc(sizeof(GroundLabel)); @@ -21,7 +21,7 @@ static inline void doLabels(GroundProgram* program, GroundState* state) { Ground.Flags.error = true; return; } - strncpy(label->name, arg->as.ref, 2047); + strncpy(label->name, arg->as.ref->string, 2047); label->name[2047] = '\0'; label->lineNum = i; HASH_ADD_STR(state->labels, name, label); @@ -34,10 +34,10 @@ static inline void doLabels(GroundProgram* program, GroundState* state) { GroundInstruction* instruction = &program->at[i]; if (instruction->type == GroundInstruction_JUMP) { 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) { 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.Flags.error = true; return; @@ -47,10 +47,10 @@ static inline void doLabels(GroundProgram* program, GroundState* state) { } else if (instruction->type == GroundInstruction_IF) { 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) { 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.Flags.error = true; return; @@ -60,10 +60,10 @@ static inline void doLabels(GroundProgram* program, GroundState* state) { } else if (instruction->type == GroundInstruction_CATCH) { 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) { 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.Flags.error = true; return; @@ -92,7 +92,7 @@ static inline size_t doOffsets(GroundProgram* program, GroundState* state) { ) continue; 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) { item = malloc(sizeof(GroundVariable)); @@ -102,7 +102,7 @@ static inline size_t doOffsets(GroundProgram* program, GroundState* state) { return 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++; HASH_ADD_STR(state->variables, name, item); } diff --git a/src/New/Arg/DirectRef.c b/src/New/Arg/DirectRef.c index 03e60ed..54d4ea1 100644 --- a/src/New/Arg/DirectRef.c +++ b/src/New/Arg/DirectRef.c @@ -1,25 +1,8 @@ #include "../../../include/ground.h" -#include -#include - -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); - +GroundArg _GroundNewArgDirectRef(GroundIdentifier* ref) { return (GroundArg) { .type = GroundArg_DirectRef, - .as.ref = copy + .as.ref = Ground.Copy.Identifier(ref) }; } diff --git a/src/New/Arg/FunctionRef.c b/src/New/Arg/FunctionRef.c index 4855fba..922a692 100644 --- a/src/New/Arg/FunctionRef.c +++ b/src/New/Arg/FunctionRef.c @@ -1,25 +1,8 @@ #include "../../../include/ground.h" -#include -#include - -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); - +GroundArg _GroundNewArgFunctionRef(GroundIdentifier* ref) { return (GroundArg) { .type = GroundArg_FunctionRef, - .as.ref = copy + .as.ref = Ground.Copy.Identifier(ref) }; } diff --git a/src/New/Arg/LabelRef.c b/src/New/Arg/LabelRef.c index d371eca..42121d7 100644 --- a/src/New/Arg/LabelRef.c +++ b/src/New/Arg/LabelRef.c @@ -1,26 +1,9 @@ #include "../../../include/ground.h" -#include -#include - -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); - +GroundArg _GroundNewArgLabelRef(GroundIdentifier* ref) { return (GroundArg) { .type = GroundArg_Label, - .as.ref = copy + .as.ref = Ground.Copy.Identifier(ref) }; } diff --git a/src/New/Arg/LineRef.c b/src/New/Arg/LineRef.c index dc21833..14ac45e 100644 --- a/src/New/Arg/LineRef.c +++ b/src/New/Arg/LineRef.c @@ -1,25 +1,8 @@ #include "../../../include/ground.h" -#include -#include - -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); - +GroundArg _GroundNewArgLineRef(GroundIdentifier* ref) { return (GroundArg) { .type = GroundArg_LineRef, - .as.ref = copy + .as.ref = Ground.Copy.Identifier(ref) }; } diff --git a/src/New/Arg/TypeRef.c b/src/New/Arg/TypeRef.c index a98f4f4..4c5cb4e 100644 --- a/src/New/Arg/TypeRef.c +++ b/src/New/Arg/TypeRef.c @@ -1,26 +1,9 @@ #include "../../../include/ground.h" -#include -#include - -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); - +GroundArg _GroundNewArgTypeRef(GroundIdentifier* ref) { return (GroundArg) { .type = GroundArg_TypeRef, - .as.ref = copy + .as.ref = Ground.Copy.Identifier(ref) }; } diff --git a/src/New/Arg/ValueRef.c b/src/New/Arg/ValueRef.c index 557ffed..23cefec 100644 --- a/src/New/Arg/ValueRef.c +++ b/src/New/Arg/ValueRef.c @@ -1,26 +1,9 @@ #include "../../../include/ground.h" -#include -#include - -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); - +GroundArg _GroundNewArgValueRef(GroundIdentifier* ref) { return (GroundArg) { .type = GroundArg_ValueRef, - .as.ref = copy + .as.ref = Ground.Copy.Identifier(ref) }; } diff --git a/src/New/Identifier.c b/src/New/Identifier.c new file mode 100644 index 0000000..000dd83 --- /dev/null +++ b/src/New/Identifier.c @@ -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; +} diff --git a/src/libmain.c b/src/libmain.c index 9e345fc..daa91ce 100644 --- a/src/libmain.c +++ b/src/libmain.c @@ -11,12 +11,12 @@ GroundValue _GroundNewValueStruct(GroundStruct in); GroundValue _GroundNewValueObject(GroundObject in); GroundArg _GroundNewArgValue(GroundValue value); -GroundArg _GroundNewArgValueRef(const char* ref); -GroundArg _GroundNewArgDirectRef(const char* ref); -GroundArg _GroundNewArgLineRef(const char* ref); -GroundArg _GroundNewArgLabelRef(const char* ref); -GroundArg _GroundNewArgFunctionRef(const char* ref); -GroundArg _GroundNewArgTypeRef(const char* ref); +GroundArg _GroundNewArgValueRef(GroundIdentifier* ref); +GroundArg _GroundNewArgDirectRef(GroundIdentifier* ref); +GroundArg _GroundNewArgLineRef(GroundIdentifier* ref); +GroundArg _GroundNewArgLabelRef(GroundIdentifier* ref); +GroundArg _GroundNewArgFunctionRef(GroundIdentifier* ref); +GroundArg _GroundNewArgTypeRef(GroundIdentifier* ref); GroundList _GroundNewList(); GroundString _GroundNewString(const char* in); @@ -30,6 +30,7 @@ GroundInstruction _GroundNewInstruction(enum GroundInstructionType type); GroundProgram _GroundNewProgram(); GroundType _GroundNewType(enum GroundTypeType type, ...); +GroundIdentifier* _GroundNewIdentifier(const char* id); void _GroundFreeValue(GroundValue* in); void _GroundFreeList(GroundList* in); @@ -43,6 +44,8 @@ void _GroundFreeInstruction(GroundInstruction* in); void _GroundFreeProgram(GroundProgram* in); void _GroundFreeState(GroundState* in); +void _GroundFreeIdentifier(GroundIdentifier* identifier); + GroundValue _GroundCopyValue(GroundValue* in); GroundList _GroundCopyList(GroundList* in); @@ -56,6 +59,8 @@ GroundInstruction _GroundCopyInstruction(GroundInstruction* in); GroundProgram _GroundCopyProgram(GroundProgram* in); GroundState _GroundCopyState(GroundState* in); +GroundIdentifier* _GroundCopyIdentifier(GroundIdentifier* identifier); + void _GroundListAppend(GroundList* list, GroundValue value); @@ -129,6 +134,8 @@ struct _Ground Ground = { .Instruction = _GroundNewInstruction, .Program = _GroundNewProgram, .Type = _GroundNewType, + + .Identifier = _GroundNewIdentifier, }, .Free = { @@ -143,6 +150,8 @@ struct _Ground Ground = { .Instruction = _GroundFreeInstruction, .Program = _GroundFreeProgram, .State = _GroundFreeState, + + .Identifier = _GroundFreeIdentifier, }, .Copy = { @@ -158,6 +167,7 @@ struct _Ground Ground = { .Program = _GroundCopyProgram, .State = _GroundCopyState, + .Identifier = _GroundCopyIdentifier, }, .List = {