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;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -143,6 +143,7 @@ struct StaticFunction {
|
||||||
|
|
||||||
Object* arguments;
|
Object* arguments;
|
||||||
int argCount;
|
int argCount;
|
||||||
|
int refs;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Other {
|
struct Other {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue