diff --git a/src/object.c b/src/object.c index 48ea975..41f3fd2 100644 --- a/src/object.c +++ b/src/object.c @@ -174,6 +174,8 @@ size_t inflate(struct string* s, size_t additional) return s->capacity; } +#define appendf(STRING, ...) (STRING)->cursor += sprintf((STRING)->cursor, __VA_ARGS__) + int stringNObj(struct string* s, const Object* obj); /** @@ -185,14 +187,14 @@ int stringNObj(struct string* s, const Object* obj); */ void stringList(struct string* s, const Object* obj) { - s->cursor += sprintf(s->cursor, "("); + appendf(s, "("); FOR_POINTER_IN_LIST(obj) { - s->cursor += sprintf(s->cursor, " "); + appendf(s, " "); stringNObj(s, POINTER); inflate(s, 0); } - s->cursor += sprintf(s->cursor, " )"); + appendf(s, " )"); } /** @@ -202,25 +204,25 @@ void stringList(struct string* s, const Object* obj) void stringStruct(struct string* s, const Object* obj) { struct StructObject* so = obj->structObject; - s->cursor += sprintf(s->cursor, "{"); + appendf(s, "{"); struct StructDef* def = getStructAt(so->definition); for (int i = 0; i < def->fieldCount; i++) { - s->cursor += sprintf(s->cursor, " %s: ", def->names[i]); + appendf(s, " %s: ", def->names[i]); int isString = so->fields[i].type == TYPE_STRING; if (isString) { - s->cursor += sprintf(s->cursor, "\""); + appendf(s, "\""); } stringNObj(s, &so->fields[i]); if (isString) { - s->cursor += sprintf(s->cursor, "\""); + appendf(s, "\""); } - s->cursor += sprintf(s->cursor, ","); + appendf(s, ","); } s->cursor--; - s->cursor += sprintf(s->cursor, " }"); + appendf(s, " }"); } /** @@ -241,82 +243,82 @@ void stringStruct(struct string* s, const Object* obj) */ int stringNObj(struct string* s, const Object* obj) { - inflate(s, 16); + inflate(s, 16); // In most cases this is enough to fit the appended string. switch (obj->type) { case TYPE_NUMBER: - s->cursor += sprintf(s->cursor, "%ld", obj->number); + appendf(s, "%ld", obj->number); break; case TYPE_BOOL: - s->cursor += sprintf(s->cursor, "%s", obj->number ? "T" : "F"); + appendf(s, "%s", obj->number ? "T" : "F"); break; case TYPE_SYMBOL: case TYPE_STRING: { size_t stringLen = strlen(obj->string); inflate(s, stringLen); const char* format = obj->type == TYPE_STRING ? "%s" : "`%s`"; - s->cursor += sprintf(s->cursor, format, obj->string); + appendf(s, format, obj->string); break; } case TYPE_STATIC_FUNC: - s->cursor += sprintf(s->cursor, "STATIC FUNC"); + appendf(s, "STATIC FUNC"); break; case TYPE_STRUCT: stringStruct(s, obj); break; case TYPE_SLIST: - s->cursor += sprintf(s->cursor, "'"); + appendf(s, "'"); case TYPE_LIST: stringList(s, obj); break; case TYPE_PROMISE: - s->cursor += sprintf(s->cursor, isDone(obj->promise) ? "" : ""); + appendf(s, isDone(obj->promise) ? "" : ""); break; case TYPE_ERROR: { int code = getErrorCode(*obj); #ifdef SIMPLE_ERRORS - s->cursor += sprintf(s->cursor, "E[%d]", (int)code); + appendf(s, "E[%d]", (int)code); #else inflate(s, 128); if (obj->error->context && obj->error->context[0] != '\0') { - s->cursor += sprintf(s->cursor, "%s: %s", errorText[code], + appendf(s, "%s: %s", errorText[code], obj->error->context); } else if (code >= 0 && code <= INDEX_PAST_END) { - s->cursor += sprintf(s->cursor, "%s", errorText[code]); + appendf(s, "%s", errorText[code]); } else { - s->cursor += sprintf(s->cursor, "BROKEN ERROR CODE: %d", code); + appendf(s, "BROKEN ERROR CODE: %d", code); } #endif break; } case TYPE_FUNC: - s->cursor += sprintf(s->cursor, "F%ld", obj->number); + appendf(s, "F%ld", obj->number); break; case TYPE_LAMBDA: { #ifdef STANDALONE #ifdef DEBUG - s->cursor += sprintf(s->cursor, "\\x%d", obj->number); + appendf(s, "\\x%d", obj->number); #endif char* docString = obj->lambda->params.docString; if (docString) { inflate(s, strlen(docString)); - s->cursor += sprintf(s->cursor, "%s\n", docString); + appendf(s, "%s\n", docString); } stringNObj(s, &obj->lambda->params); - s->cursor += sprintf(s->cursor, " -> "); + appendf(s, " -> "); stringNObj(s, &obj->lambda->body); - s->cursor += sprintf(s->cursor, ">"); + appendf(s, ">"); #else - s->cursor += sprintf(s->cursor, "\\x%d", obj->number); + appendf(s, "\\x%d", obj->number); #endif break; } case TYPE_OTHER: - s->cursor += sprintf(s->cursor, "%p", obj->other->data); + appendf(s, "%p", obj->other->data); break; } if (!isValidType(*obj)) { - s->cursor += sprintf(s->cursor, "BAD_TYPE(%d) X%ld", obj->type, obj->number); + appendf(s, "BAD_TYPE(%d) X%ld", obj->type, obj->number); } return 0; @@ -452,7 +454,12 @@ void cleanObject(Object* target) } break; case TYPE_STATIC_FUNC: - // free(target->staticF); + if ((target->staticF->refs -= 1) == 0) { + for (int i = 0; i < target->staticF->argCount; i++) { + cleanObject(&target->staticF->arguments[i]); + } + free(target->staticF); + } break; case TYPE_BOOL: case TYPE_NUMBER: @@ -667,10 +674,11 @@ inline Object cloneObject(const Object src) return errorWithContext(getErrorCode(src), src.error->context); case TYPE_OTHER: return cloneOther(src); + case TYPE_STATIC_FUNC: + src.staticF->refs += 1; case TYPE_BOOL: case TYPE_NUMBER: case TYPE_FUNC: - case TYPE_STATIC_FUNC: return src; } diff --git a/src/object.h b/src/object.h index fe820c1..c3e2234 100644 --- a/src/object.h +++ b/src/object.h @@ -143,6 +143,7 @@ struct StaticFunction { Object* arguments; int argCount; + int refs; }; struct Other { diff --git a/src/pebblisp.c b/src/pebblisp.c index 2a89585..7f7d21b 100644 --- a/src/pebblisp.c +++ b/src/pebblisp.c @@ -279,7 +279,11 @@ Object runStatic(const Object* staticF, struct Environment* env) for (int i = 0; i < f->argCount; i++) { evaluatedArgs[i] = eval(&f->arguments[i], env); } - return f->func(evaluatedArgs, f->argCount, env); + Object ret = f->func(evaluatedArgs, f->argCount, env); + for (int i = 0; i < f->argCount; i++) { + cleanObject(&evaluatedArgs[i]); + } + return ret; } Object eval(const Object* obj, struct Environment* env) @@ -444,6 +448,7 @@ Object parseNum(int base, const char* text, int length, int (*func)(char)) Object optimize(Object (* func)(Object*, int, struct Environment*), int argCount, Object args[]) { struct StaticFunction *f = malloc(sizeof(struct StaticFunction) + (sizeof(Object) * argCount)); + f->refs = 1; f->func = func; f->arguments = (void*) f + sizeof(struct StaticFunction); f->argCount = argCount;