Add refcount to StaticFunction.

Small appendf() macro for object-stringing.
This commit is contained in:
Sage Vaillancourt 2022-04-18 09:56:57 -04:00 committed by Sage Vaillancourt
parent b0e89cafd4
commit f458b52a17
3 changed files with 45 additions and 31 deletions

View File

@ -174,6 +174,8 @@ size_t inflate(struct string* s, size_t additional)
return s->capacity; return s->capacity;
} }
#define appendf(STRING, ...) (STRING)->cursor += sprintf((STRING)->cursor, __VA_ARGS__)
int stringNObj(struct string* s, const Object* obj); 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) void stringList(struct string* s, const Object* obj)
{ {
s->cursor += sprintf(s->cursor, "("); appendf(s, "(");
FOR_POINTER_IN_LIST(obj) { FOR_POINTER_IN_LIST(obj) {
s->cursor += sprintf(s->cursor, " "); appendf(s, " ");
stringNObj(s, POINTER); stringNObj(s, POINTER);
inflate(s, 0); 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) void stringStruct(struct string* s, const Object* obj)
{ {
struct StructObject* so = obj->structObject; struct StructObject* so = obj->structObject;
s->cursor += sprintf(s->cursor, "{"); appendf(s, "{");
struct StructDef* def = getStructAt(so->definition); struct StructDef* def = getStructAt(so->definition);
for (int i = 0; i < def->fieldCount; i++) { 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; int isString = so->fields[i].type == TYPE_STRING;
if (isString) { if (isString) {
s->cursor += sprintf(s->cursor, "\""); appendf(s, "\"");
} }
stringNObj(s, &so->fields[i]); stringNObj(s, &so->fields[i]);
if (isString) { if (isString) {
s->cursor += sprintf(s->cursor, "\""); appendf(s, "\"");
} }
s->cursor += sprintf(s->cursor, ","); appendf(s, ",");
} }
s->cursor--; 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) 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) { switch (obj->type) {
case TYPE_NUMBER: case TYPE_NUMBER:
s->cursor += sprintf(s->cursor, "%ld", obj->number); appendf(s, "%ld", obj->number);
break; break;
case TYPE_BOOL: case TYPE_BOOL:
s->cursor += sprintf(s->cursor, "%s", obj->number ? "T" : "F"); appendf(s, "%s", obj->number ? "T" : "F");
break; break;
case TYPE_SYMBOL: case TYPE_SYMBOL:
case TYPE_STRING: { case TYPE_STRING: {
size_t stringLen = strlen(obj->string); size_t stringLen = strlen(obj->string);
inflate(s, stringLen); inflate(s, stringLen);
const char* format = obj->type == TYPE_STRING ? "%s" : "`%s`"; const char* format = obj->type == TYPE_STRING ? "%s" : "`%s`";
s->cursor += sprintf(s->cursor, format, obj->string); appendf(s, format, obj->string);
break; break;
} }
case TYPE_STATIC_FUNC: case TYPE_STATIC_FUNC:
s->cursor += sprintf(s->cursor, "STATIC FUNC"); appendf(s, "STATIC FUNC");
break; break;
case TYPE_STRUCT: case TYPE_STRUCT:
stringStruct(s, obj); stringStruct(s, obj);
break; break;
case TYPE_SLIST: case TYPE_SLIST:
s->cursor += sprintf(s->cursor, "'"); appendf(s, "'");
case TYPE_LIST: case TYPE_LIST:
stringList(s, obj); stringList(s, obj);
break; break;
case TYPE_PROMISE: case TYPE_PROMISE:
s->cursor += sprintf(s->cursor, isDone(obj->promise) ? "<DONE>" : "<PENDING>"); appendf(s, isDone(obj->promise) ? "<DONE>" : "<PENDING>");
break; break;
case TYPE_ERROR: { case TYPE_ERROR: {
int code = getErrorCode(*obj); int code = getErrorCode(*obj);
#ifdef SIMPLE_ERRORS #ifdef SIMPLE_ERRORS
s->cursor += sprintf(s->cursor, "E[%d]", (int)code); appendf(s, "E[%d]", (int)code);
#else #else
inflate(s, 128); inflate(s, 128);
if (obj->error->context && obj->error->context[0] != '\0') { 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); obj->error->context);
} else if (code >= 0 && code <= INDEX_PAST_END) { } else if (code >= 0 && code <= INDEX_PAST_END) {
s->cursor += sprintf(s->cursor, "%s", errorText[code]); appendf(s, "%s", errorText[code]);
} else { } else {
s->cursor += sprintf(s->cursor, "BROKEN ERROR CODE: %d", code); appendf(s, "BROKEN ERROR CODE: %d", code);
} }
#endif #endif
break; break;
} }
case TYPE_FUNC: case TYPE_FUNC:
s->cursor += sprintf(s->cursor, "F%ld", obj->number); appendf(s, "F%ld", obj->number);
break; break;
case TYPE_LAMBDA: { case TYPE_LAMBDA: {
#ifdef STANDALONE #ifdef STANDALONE
#ifdef DEBUG #ifdef DEBUG
s->cursor += sprintf(s->cursor, "\\x%d", obj->number); appendf(s, "\\x%d", obj->number);
#endif #endif
char* docString = obj->lambda->params.docString; char* docString = obj->lambda->params.docString;
if (docString) { if (docString) {
inflate(s, strlen(docString)); inflate(s, strlen(docString));
s->cursor += sprintf(s->cursor, "%s\n", docString); appendf(s, "%s\n", docString);
} }
stringNObj(s, &obj->lambda->params); stringNObj(s, &obj->lambda->params);
s->cursor += sprintf(s->cursor, " -> "); appendf(s, " -> ");
stringNObj(s, &obj->lambda->body); stringNObj(s, &obj->lambda->body);
s->cursor += sprintf(s->cursor, ">"); appendf(s, ">");
#else #else
s->cursor += sprintf(s->cursor, "\\x%d", obj->number); appendf(s, "\\x%d", obj->number);
#endif #endif
break; break;
} }
case TYPE_OTHER: case TYPE_OTHER:
s->cursor += sprintf(s->cursor, "%p", obj->other->data); appendf(s, "%p", obj->other->data);
break; break;
} }
if (!isValidType(*obj)) { 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; return 0;
@ -452,7 +454,12 @@ void cleanObject(Object* target)
} }
break; break;
case TYPE_STATIC_FUNC: 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; break;
case TYPE_BOOL: case TYPE_BOOL:
case TYPE_NUMBER: case TYPE_NUMBER:
@ -667,10 +674,11 @@ inline Object cloneObject(const Object src)
return errorWithContext(getErrorCode(src), src.error->context); return errorWithContext(getErrorCode(src), src.error->context);
case TYPE_OTHER: case TYPE_OTHER:
return cloneOther(src); return cloneOther(src);
case TYPE_STATIC_FUNC:
src.staticF->refs += 1;
case TYPE_BOOL: case TYPE_BOOL:
case TYPE_NUMBER: case TYPE_NUMBER:
case TYPE_FUNC: case TYPE_FUNC:
case TYPE_STATIC_FUNC:
return src; return src;
} }

View File

@ -143,6 +143,7 @@ struct StaticFunction {
Object* arguments; Object* arguments;
int argCount; int argCount;
int refs;
}; };
struct Other { struct Other {

View File

@ -279,7 +279,11 @@ Object runStatic(const Object* staticF, struct Environment* env)
for (int i = 0; i < f->argCount; i++) { for (int i = 0; i < f->argCount; i++) {
evaluatedArgs[i] = eval(&f->arguments[i], env); 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) 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[]) Object optimize(Object (* func)(Object*, int, struct Environment*), int argCount, Object args[])
{ {
struct StaticFunction *f = malloc(sizeof(struct StaticFunction) + (sizeof(Object) * argCount)); struct StaticFunction *f = malloc(sizeof(struct StaticFunction) + (sizeof(Object) * argCount));
f->refs = 1;
f->func = func; f->func = func;
f->arguments = (void*) f + sizeof(struct StaticFunction); f->arguments = (void*) f + sizeof(struct StaticFunction);
f->argCount = argCount; f->argCount = argCount;