Use stripped Objects in hash.c

These lack the unused .forward field, reducing table memory by ~25%.
Also bump Object.number up to a long, and add a generic Object.data field.
This commit is contained in:
Sage Vaillancourt 2022-04-08 11:49:02 -04:00 committed by Sage Vaillancourt
parent 13d1168401
commit 85fb91b4ed
7 changed files with 66 additions and 29 deletions

View File

@ -57,10 +57,10 @@ struct symFunc {
#define pf(_func) buildFuncSym(_func ## Symbol, &(_func))
#endif
Object* fetch(const char* name, struct Environment* env)
struct StrippedObject* fetch(const char* name, struct Environment* env)
{
while (env) {
Object* object = getFromTable(&env->table, name);
struct StrippedObject* object = getFromTable(&env->table, name);
if (object) {
return object;
}
@ -71,19 +71,23 @@ Object* fetch(const char* name, struct Environment* env)
Object fetchFromEnvironment(const char* name, struct Environment* env)
{
Object* object = fetch(name, env);
struct StrippedObject* object = fetch(name, env);
if (object) {
return cloneObject(*object);
Object o = deStrip(*object);
return cloneObject(o);
}
return errorWithContext(DID_NOT_FIND_SYMBOL, name);
}
void addToEnv(struct Environment* env, const char* name, const Object obj)
{
Object* existing = fetch(name, env);
struct StrippedObject* existing = fetch(name, env);
if (existing) {
cleanObject(existing);
*existing = cloneObject(obj);
Object o = deStrip(*existing);
cleanObject(&o);
o = cloneObject(obj);
existing->type = o.type;
existing->data = o.data;
return;
}
char* symbol = malloc(sizeof(char) * (strlen(name) + 1));
@ -252,7 +256,8 @@ void printEnv(struct Environment* env, int printPointers)
printf("Native");
} else {
size_t length;
char* s = stringObj(&env->table.elements[i].object, &length);
// SAFETY: Casting to Object is fine because stringObj() doesn't touch .forward
char* s = stringObj((Object *) &env->table.elements[i].object, &length);
printColored(s);
if (env->table.elements[i].object.type == TYPE_STRING) {
printf("\"");
@ -410,10 +415,11 @@ Object help(Object* params, int length, struct Environment* env)
}
}
Object* object = fetch(symbol, env);
struct StrippedObject* object = fetch(symbol, env);
if (object) {
size_t len = 0;
char* string = stringObj(object, &len);
// SAFETY: Casting to Object is fine because stringObj() doesn't touch .forward
char* string = stringObj((Object*) object, &len);
Object text = stringFromSlice(string, len);
free(string);
return text;

View File

@ -4,9 +4,14 @@
#include "object.h"
#include "hash.h"
struct StrippedObject {
Type type;
void* data;
};
struct EnvElement {
char* symbol;
Object object;
struct StrippedObject object;
};
struct Environment;
@ -19,6 +24,8 @@ struct Environment {
int refs;
};
Object deStrip(struct StrippedObject object);
struct Environment* global();
void setGlobal(struct Environment* env);

View File

@ -3,6 +3,19 @@
#include <string.h>
void addStripped(struct ObjectTable* table, char* name, struct StrippedObject object);
Object deStrip(struct StrippedObject object)
{
// Garbage .forward data may be safe here, but since usage of that data is
// currently in flux, it should take the more cautious route for now.
return (Object) {
.type = object.type,
.string = object.data,
.forward = NULL,
};
}
struct ObjectTable buildTable(size_t capacity)
{
struct ObjectTable table = {
@ -21,7 +34,8 @@ void deleteTable(struct ObjectTable* table)
for (int i = 0; i < table->capacity; i++) {
if (table->elements[i].symbol) {
free(table->elements[i].symbol);
cleanObject(&table->elements[i].object);
Object deStripped = deStrip(table->elements[i].object);
cleanObject(&deStripped);
}
}
free(table->elements);
@ -47,7 +61,7 @@ void extendTable(struct ObjectTable* table)
struct ObjectTable newTable = buildTable(table->capacity ? table->capacity * 2 : 4);
for (int i = 0; i < table->capacity; i++) {
if (table->elements[i].symbol) {
addToTable(&newTable, table->elements[i].symbol, table->elements[i].object);
addStripped(&newTable, table->elements[i].symbol, table->elements[i].object);
}
}
free(table->elements);
@ -55,7 +69,7 @@ void extendTable(struct ObjectTable* table)
}
}
Object* getFromTable(struct ObjectTable* table, const char* name)
struct StrippedObject* getFromTable(struct ObjectTable* table, const char* name)
{
if (table->capacity == 0) {
return NULL;
@ -106,11 +120,7 @@ static unsigned long hash(unused const char* str, struct ObjectTable* table)
#endif
///
/// \param table
/// \param name Should be a new allocation
/// \param object Should already be cloned
void addToTable(struct ObjectTable* table, char* name, Object object)
void addStripped(struct ObjectTable* table, char* name, struct StrippedObject object)
{
extendTable(table);
size_t h = hash(name, table);
@ -121,3 +131,15 @@ void addToTable(struct ObjectTable* table, char* name, Object object)
table->elements[h].object = object;
table->count += 1;
}
///
/// \param table
/// \param name Should be a new allocation
/// \param object Should already be cloned
void addToTable(struct ObjectTable* table, char* name, Object object)
{
addStripped(table, name, (struct StrippedObject) {
.data = object.data,
.type = object.type,
});
}

View File

@ -13,7 +13,7 @@ struct ObjectTable buildTable(size_t capacity);
void addToTable(struct ObjectTable* table, char* name, Object object);
Object* getFromTable(struct ObjectTable* table, const char* name);
struct StrippedObject* getFromTable(struct ObjectTable* table, const char* name);
void deleteTable(struct ObjectTable* table);

View File

@ -245,7 +245,7 @@ int stringNObj(struct string* s, const Object* obj)
inflate(s, 16);
switch (obj->type) {
case TYPE_NUMBER:
s->cursor += sprintf(s->cursor, "%d", obj->number);
s->cursor += sprintf(s->cursor, "%ld", obj->number);
break;
case TYPE_BOOL:
s->cursor += sprintf(s->cursor, "%s", obj->number ? "T" : "F");
@ -287,7 +287,7 @@ int stringNObj(struct string* s, const Object* obj)
break;
}
case TYPE_FUNC:
s->cursor += sprintf(s->cursor, "F%d", obj->number);
s->cursor += sprintf(s->cursor, "F%ld", obj->number);
break;
case TYPE_LAMBDA: {
#ifdef STANDALONE
@ -314,7 +314,7 @@ int stringNObj(struct string* s, const Object* obj)
}
if (!isValidType(*obj)) {
s->cursor += sprintf(s->cursor, "BAD_TYPE(%d) X%d", obj->type, obj->number);
s->cursor += sprintf(s->cursor, "BAD_TYPE(%d) X%ld", obj->type, obj->number);
}
return 0;
@ -422,8 +422,8 @@ void cleanObject(Object* target)
if (!target->lambda->refs) {
cleanObject(&target->lambda->params);
cleanObject(&target->lambda->body);
free(target->lambda);
free(target->lambda->params.docString);
free(target->lambda);
}
break;
case TYPE_STRUCT:

View File

@ -89,7 +89,7 @@ struct Object {
Type type;
union {
int number;
long number;
Object* list;
char* string;
@ -104,6 +104,7 @@ struct Object {
#else
struct Error* error;
#endif
void* data;
};
union {

View File

@ -184,7 +184,7 @@ Object funcyEval(Object* funcy, const Object* passedArguments, int evalLength,
struct Environment* env)
{
if (!funcy) {
eprintf("HIGHLY ILLEGAL NULL FUNCY!!!\n");
eprintf("HIGHLY ILLEGAL NULL FUNC-LIKE!!!\n");
return errorObject(BAD_TYPE);
}
switch (funcy->type) {
@ -193,7 +193,7 @@ Object funcyEval(Object* funcy, const Object* passedArguments, int evalLength,
case TYPE_FUNC:
return listEvalFunc(funcy, passedArguments, evalLength, env);
default:
eprintf("HIGHLY ILLEGAL NOT-FUNCY IN funcyEval()!!!\n");
eprintf("HIGHLY ILLEGAL NOT-FUNC IN funcyEval()!!!\n");
return errorObject(BAD_TYPE);
}
}
@ -229,8 +229,9 @@ Object evalList(const Object* obj, struct Environment* env)
Object* doc = NULL;
Object* body = NULL;
if (params) {
doc = params->forward && params->forward->forward ? params->forward : NULL;
body = doc ? params->forward->forward : params->forward;
int twoParams = params->forward && params->forward->forward;
doc = twoParams ? params->forward : NULL;
body = twoParams ? params->forward->forward : params->forward;
}
return constructLambda(params, doc, body, env);
} else if (strcmp(first_form->string, "struct") == 0) {