From e22e022cd8e70ebc7f6b37fa685fcd5c79d78665 Mon Sep 17 00:00:00 2001 From: Sage Vaillancourt Date: Mon, 28 Mar 2022 09:56:24 -0400 Subject: [PATCH] Reference count strings. --- src/Makefile | 2 +- src/env.c | 2 ++ src/object.c | 26 ++++++++++++++++++-------- src/object.h | 2 ++ src/pebblisp.c | 4 ++-- src/plfunc.c | 17 +++++++---------- 6 files changed, 32 insertions(+), 21 deletions(-) diff --git a/src/Makefile b/src/Makefile index 37c64a3..72a2b82 100644 --- a/src/Makefile +++ b/src/Makefile @@ -32,7 +32,7 @@ run: install: cp -pf ./$(exe) $(BINPREFIX) mkdir -p $(SCRIPTDIR) - cp ./examples/* $(SCRIPTDIR) + cp -r ./examples/* $(SCRIPTDIR) uninstall: rm $(BINPREFIX)/$(exe) diff --git a/src/env.c b/src/env.c index 56366cf..cdb1c45 100644 --- a/src/env.c +++ b/src/env.c @@ -363,6 +363,8 @@ int runTests(int detailed) printf(""); } printf("%d tests failed!\n", failureCount); + // fprintf(stderr, "TOTAL ALLOCATIONS: %d\n", getAllocations()); + // fprintf(stderr, "TOTAL BYTES: %zu\n", getBytes()); return failureCount; } diff --git a/src/object.c b/src/object.c index 41ce58a..3a03e4d 100644 --- a/src/object.c +++ b/src/object.c @@ -207,7 +207,7 @@ int stringList(char* dest, const Object* obj) dest += sprintf(dest, "("); FOR_POINTER_IN_LIST(obj) { - char tok[90] = ""; + char tok[256] = ""; stringObj(tok, POINTER); dest += sprintf(dest, " %s", tok); } @@ -439,7 +439,9 @@ void cleanObject(Object* target) switch (target->type) { case TYPE_STRING: case TYPE_SYMBOL: - free(target->string); + if (!(target->string[-1] -= 1)) { + free(target->string - 1); + } break; case TYPE_LIST: case TYPE_SLIST: @@ -642,9 +644,7 @@ inline Object cloneLambda(const Object old) Object cloneString(Object obj) { - const char* string = obj.string; - obj.string = malloc(sizeof(char) * (strlen(string) + 1)); - strcpy(obj.string, string); + obj.string[-1] += 1; return obj; } @@ -721,9 +721,19 @@ inline Object stringFromSlice(const char* string, int len) inline Object symFromSlice(const char* string, int len) { - Object o = newObject(TYPE_SYMBOL); - o.string = calloc(sizeof(char), len + 1); - strncpy(o.string, string, len); + Object o = withLen(len, TYPE_SYMBOL); + snprintf(o.string, len + 1, "%s", string); + return o; +} + +/// Creates a stringy object with room for a reference-count prefix and trailing null byte. +/// Thus, withLen(3, TYPE_STRING) will actually allocate a 5-byte "string". +inline Object withLen(int len, enum Type type) +{ + Object o = newObject(type); + o.string = malloc(sizeof(char) * (len + 2)); + o.string[0] = 1; + o.string += 1; return o; } diff --git a/src/object.h b/src/object.h index 7acfa9c..0d80522 100644 --- a/src/object.h +++ b/src/object.h @@ -201,6 +201,8 @@ Object stringFromSlice(const char* string, int len); Object symFromSlice(const char* string, int len); +Object withLen(int len, enum Type type); + Object boolObject(int b); Object numberObject(int num); diff --git a/src/pebblisp.c b/src/pebblisp.c index 8a4a232..8a7dedc 100644 --- a/src/pebblisp.c +++ b/src/pebblisp.c @@ -714,8 +714,8 @@ int main(int argc, const char* argv[]) } deleteEnv(&env); shredDictionary(); - // printf("TOTAL ALLOCATIONS: %d\n", getAllocations()); - // printf("TOTAL BYTES: %d\n", getBytes()); + // fprintf(stderr, "TOTAL ALLOCATIONS: %d\n", getAllocations()); + // fprintf(stderr, "TOTAL BYTES: %zu\n", getBytes()); } #endif diff --git a/src/plfunc.c b/src/plfunc.c index 68dcceb..4724047 100644 --- a/src/plfunc.c +++ b/src/plfunc.c @@ -25,20 +25,18 @@ Object charAt(Object* params, int length, struct Environment* env) Object string = params[0]; Object at = params[1]; - char* c = malloc(sizeof(char) * 2); - c[1] = '\0'; + Object c = withLen(1, string.type); + c.string[1] = '\0'; for (int i = 0; i < at.number; i++) { if (string.string[i] == '\0') { - c[0] = '\0'; - string.string = c; - return string; + c.string[0] = '\0'; + return c; } } - c[0] = string.string[at.number]; - string.string = c; - return string; + c.string[0] = string.string[at.number]; + return c; } Object filter(Object* params, int length, struct Environment* env) @@ -216,8 +214,7 @@ Object _catObjects(Object obj1, Object obj2, struct Environment* env) cleanObject(&evalObj1); cleanObject(&evalObj2); - Object o = newObject(TYPE_STRING); - o.string = malloc(sizeof(char) * length + 1); + Object o = withLen(length, TYPE_STRING); sprintf(o.string, "%s%s", str1, str2); return o;