Add refcount to StaticFunction.
Small appendf() macro for object-stringing.
This commit is contained in:
parent
b0e89cafd4
commit
f458b52a17
68
src/object.c
68
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) ? "<DONE>" : "<PENDING>");
|
||||
appendf(s, isDone(obj->promise) ? "<DONE>" : "<PENDING>");
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -143,6 +143,7 @@ struct StaticFunction {
|
|||
|
||||
Object* arguments;
|
||||
int argCount;
|
||||
int refs;
|
||||
};
|
||||
|
||||
struct Other {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue