Simplify Environment struct.

Fill in envForLambda with errorObjects if not enough are provided.
Move addStructDef() into env.c
Add dedicated Dictionary struct to env.c
env->size -> env->capacity
This commit is contained in:
Sage Vaillancourt 2022-03-27 18:52:56 -04:00
parent 69cf9212d7
commit 34032cb1c6
7 changed files with 102 additions and 76 deletions

100
src/env.c
View File

@ -8,13 +8,27 @@
#include "web.h" #include "web.h"
#include "plfunc.h" #include "plfunc.h"
struct Environment* globalEnv;
struct Environment* global()
{
return globalEnv;
}
void setGlobal(struct Environment* env)
{
globalEnv = env;
}
struct Dictionary dictionary;
Object fetchFromEnvironment(const char* name, struct Environment* env) Object fetchFromEnvironment(const char* name, struct Environment* env)
{ {
if (!env) { if (!env) {
return errorObject(NULL_ENV); return errorObject(NULL_ENV);
} }
if (env->size == 0) { if (env->capacity == 0) {
if (env->outer) { if (env->outer) {
return fetchFromEnvironment(name, env->outer); return fetchFromEnvironment(name, env->outer);
} else { } else {
@ -22,7 +36,7 @@ Object fetchFromEnvironment(const char* name, struct Environment* env)
} }
} }
for (int i = 0; i < env->size; i++) { for (int i = 0; i < env->capacity; i++) {
if (env->strings[i] == NULL) { printd("Try %d (NULL)\n", i); if (env->strings[i] == NULL) { printd("Try %d (NULL)\n", i);
break; break;
} }
@ -53,9 +67,7 @@ struct Environment envForLambda(const Object* params, const Object* arg_forms,
struct Environment env = { struct Environment env = {
.outer = outer, .outer = outer,
.structCount = 0, .capacity = paramCount,
.structCapacity = 0,
.size = paramCount,
.refs = 1, .refs = 1,
}; };
@ -75,10 +87,10 @@ struct Environment envForLambda(const Object* params, const Object* arg_forms,
for (int i = 0; i < paramCount; i++) { for (int i = 0; i < paramCount; i++) {
const char* newObjName = itemAt(params, i)->string; const char* newObjName = itemAt(params, i)->string;
// Eval the `march` list // Eval the `march` list
Object newEnvObj = eval(march, outer); Object newEnvObj = march ? eval(march, outer) : errorObject(NOT_ENOUGH_ARGUMENTS);
addToEnv(&env, newObjName, newEnvObj); // Could use eval_forms? addToEnv(&env, newObjName, newEnvObj); // Could use eval_forms?
cleanObject(&newEnvObj); cleanObject(&newEnvObj);
march = march->forward; march = march ? march->forward : NULL;
} }
return env; return env;
@ -95,7 +107,7 @@ void addToEnv(struct Environment* env, const char* name, const Object obj)
{ {
struct Environment* temp_env = env; struct Environment* temp_env = env;
while (temp_env) { while (temp_env) {
for (int i = 0; i < temp_env->size; i++) { for (int i = 0; i < temp_env->capacity; i++) {
if (temp_env->strings[i] == NULL) { if (temp_env->strings[i] == NULL) {
// Add *new* item to env only if we're in the original scope // Add *new* item to env only if we're in the original scope
if (temp_env == env) { if (temp_env == env) {
@ -115,10 +127,10 @@ void addToEnv(struct Environment* env, const char* name, const Object obj)
printd("Reallocating environment\n"); printd("Reallocating environment\n");
const int inc = 5; const int inc = 5;
const int old_size = env->size; const int old_size = env->capacity;
env->size += inc; env->capacity += inc;
env->strings = realloc(env->strings, sizeof(char*) * env->size); env->strings = realloc(env->strings, sizeof(char*) * env->capacity);
env->objects = realloc(env->objects, sizeof(Object) * env->size); env->objects = realloc(env->objects, sizeof(Object) * env->capacity);
for (int j = 0; j < inc; j++) { for (int j = 0; j < inc; j++) {
env->strings[old_size + j] = NULL; env->strings[old_size + j] = NULL;
@ -133,8 +145,8 @@ void printEnv(struct Environment* env)
printf("NULL env\n"); printf("NULL env\n");
return; return;
} }
printf("env->size = %d\n", env->size); printf("env->capacity = %d\n", env->capacity);
for (int i = 0; i < env->size; i++) { for (int i = 0; i < env->capacity; i++) {
if (env->strings[i] == NULL) { if (env->strings[i] == NULL) {
printf("env[%d]: NULL %p\n", i, env->strings[i]); printf("env[%d]: NULL %p\n", i, env->strings[i]);
break; break;
@ -176,15 +188,18 @@ void deleteEnv(struct Environment* e)
free(e->strings); free(e->strings);
free(e->objects); free(e->objects);
} }
}
for (int i = 0; i < e->structCount; i++) { void shredDictionary()
free(e->structDefs[i].name); {
for (int j = 0; j < e->structDefs[i].fieldCount; j++) { for (int i = 0; i < dictionary.structCount; i++) {
free(e->structDefs[i].names[j]); free(dictionary.structDefs[i].name);
for (int j = 0; j < dictionary.structDefs[i].fieldCount; j++) {
free(dictionary.structDefs[i].names[j]);
} }
free(e->structDefs[i].names); free(dictionary.structDefs[i].names);
} }
free(e->structDefs); free(dictionary.structDefs);
} }
struct symFunc { struct symFunc {
@ -353,14 +368,19 @@ int runTests(int detailed)
struct Environment defaultEnv() struct Environment defaultEnv()
{ {
if (!helpInitialized) {
dictionary = (struct Dictionary) {
.structCount = 0,
.structCapacity = 8,
.structDefs = malloc(sizeof(struct StructDef) * 8),
};
}
struct Environment e = { struct Environment e = {
.outer = NULL, .outer = NULL,
.strings = calloc(sizeof(char*), MAX_ENV_ELM), .strings = calloc(sizeof(char*), MAX_ENV_ELM),
.objects = malloc(sizeof(Object) * MAX_ENV_ELM), .objects = malloc(sizeof(Object) * MAX_ENV_ELM),
.size = MAX_ENV_ELM, .capacity = MAX_ENV_ELM,
.structCount = 0,
.structCapacity = 8,
.structDefs = malloc(sizeof(struct StructDef) * 8),
.refs = 1, .refs = 1,
}; };
@ -421,24 +441,34 @@ struct Environment defaultEnv()
return e; return e;
} }
int getStructIndex(struct Environment* env, const char* name) int getStructIndex(const char* name)
{ {
for (int i = 0; i < env->structCount; i++) { for (int i = 0; i < dictionary.structCount; i++) {
if (strcmp(name, env->structDefs[i].name) == 0) { if (strcmp(name, dictionary.structDefs[i].name) == 0) {
return i; return i;
} }
} }
return -1; return -1;
} }
struct Environment* globalEnv; struct StructDef* getStructAt(int i)
struct Environment* global()
{ {
return globalEnv; return &dictionary.structDefs[i];
} }
void setGlobal(struct Environment* env) void addStructDef(struct StructDef def)
{ {
globalEnv = env; dictionary.structDefs[dictionary.structCount] = def;
} dictionary.structCount += 1;
if (dictionary.structCount == dictionary.structCapacity) {
struct StructDef* prev = dictionary.structDefs;
int prevCapacity = dictionary.structCapacity;
dictionary.structCapacity *= 2;
dictionary.structDefs = malloc(sizeof(struct StructDef) * dictionary.structCapacity);
for (int i = 0; i < prevCapacity; i++) {
dictionary.structDefs[i] = prev[i];
}
free(prev);
}
}

View File

@ -8,13 +8,15 @@ struct Environment {
char** strings; char** strings;
Object* objects; Object* objects;
struct Environment* outer; struct Environment* outer;
int size; int capacity;
int refs;
};
struct Dictionary {
int structCount; int structCount;
int structCapacity; int structCapacity;
struct StructDef* structDefs; struct StructDef* structDefs;
int refs;
}; };
struct Environment* global(); struct Environment* global();
@ -37,9 +39,15 @@ void addFunc(const char* name,
void deleteEnv(struct Environment* e); void deleteEnv(struct Environment* e);
void shredDictionary();
struct Environment defaultEnv(); struct Environment defaultEnv();
int getStructIndex(struct Environment* env, const char* name); int getStructIndex(const char* name);
struct StructDef* getStructAt(int i);
void addStructDef(struct StructDef def);
/// Needs to be freed! /// Needs to be freed!
char* getHelp(const char* symbol); char* getHelp(const char* symbol);

View File

@ -181,7 +181,7 @@ static const char* errorText[] = {"MISMATCHED_PARENS",
"LISTS_NOT_SAME_SIZE", "LISTS_NOT_SAME_SIZE",
"BAD_NUMBER", "BAD_NUMBER",
"UNSUPPORTED_NUMBER_TYPE", "UNSUPPORTED_NUMBER_TYPE",
"ONLY_ONE_ARGUMENT", "NOT_ENOUGH_ARGUMENTS",
"NOT_A_LIST", "NOT_A_LIST",
"SCRIPT_NOT_FOUND", "SCRIPT_NOT_FOUND",
"NO_CLONE_SPECIFIED", "NO_CLONE_SPECIFIED",
@ -225,8 +225,9 @@ int stringStruct(char* dest, const Object* obj)
const char* initial = dest; const char* initial = dest;
dest += sprintf(dest, "{"); dest += sprintf(dest, "{");
for (int i = 0; i < global()->structDefs[so->definition].fieldCount; i++) { struct StructDef* def = getStructAt(so->definition);
dest += sprintf(dest, " %s: ", global()->structDefs[so->definition].names[i]); for (int i = 0; i < def->fieldCount; i++) {
dest += sprintf(dest, " %s: ", def->names[i]);
int isString = so->fields[i].type == TYPE_STRING; int isString = so->fields[i].type == TYPE_STRING;
if (isString) { if (isString) {
dest += sprintf(dest, "\""); dest += sprintf(dest, "\"");
@ -453,7 +454,7 @@ void cleanObject(Object* target)
} }
break; break;
case TYPE_STRUCT: case TYPE_STRUCT:
for (int i = 0; i < global()->structDefs[target->structObject->definition].fieldCount; i++) { for (int i = 0; i < getStructAt(target->structObject->definition)->fieldCount; i++) {
cleanObject(&target->structObject->fields[i]); cleanObject(&target->structObject->fields[i]);
} }
free(target->structObject->fields); free(target->structObject->fields);
@ -587,7 +588,7 @@ inline Object structObject(int definition)
Object structo = newObject(TYPE_STRUCT); Object structo = newObject(TYPE_STRUCT);
structo.structObject = malloc(sizeof(struct StructObject)); structo.structObject = malloc(sizeof(struct StructObject));
structo.structObject->definition = definition; structo.structObject->definition = definition;
structo.structObject->fields = malloc(sizeof(Object) * global()->structDefs[definition].fieldCount); structo.structObject->fields = malloc(sizeof(Object) * getStructAt(definition)->fieldCount);
return structo; return structo;
} }
@ -685,7 +686,7 @@ Object cloneStruct(const Object src)
{ {
Object structo = structObject(src.structObject->definition); Object structo = structObject(src.structObject->definition);
struct StructObject* so = structo.structObject; struct StructObject* so = structo.structObject;
for (int i = 0; i < global()->structDefs[so->definition].fieldCount; i++) { for (int i = 0; i < getStructAt(so->definition)->fieldCount; i++) {
so->fields[i] = cloneObject(src.structObject->fields[i]); so->fields[i] = cloneObject(src.structObject->fields[i]);
} }
return structo; return structo;

View File

@ -53,7 +53,7 @@ enum errorCode {
LISTS_NOT_SAME_SIZE, LISTS_NOT_SAME_SIZE,
BAD_NUMBER, BAD_NUMBER,
UNSUPPORTED_NUMBER_TYPE, UNSUPPORTED_NUMBER_TYPE,
ONLY_ONE_ARGUMENT, NOT_ENOUGH_ARGUMENTS,
NOT_A_LIST, NOT_A_LIST,
SCRIPT_NOT_FOUND, SCRIPT_NOT_FOUND,
NO_CLONE_SPECIFIED, NO_CLONE_SPECIFIED,

View File

@ -76,20 +76,7 @@ Object evalStructArgs(const Object* symbol, const Object* fields, struct Environ
} }
} }
env = global(); addStructDef(def);
env->structDefs[env->structCount] = def;
env->structCount += 1;
if (env->structCount == env->structCapacity) {
struct StructDef* prev = env->structDefs;
int prevCapacity = env->structCapacity;
env->structCapacity *= 2;
env->structDefs = malloc(sizeof(struct StructDef) * env->structCapacity);
for (int i = 0; i < prevCapacity; i++) {
env->structDefs[i] = prev[i];
}
free(prev);
}
return boolObject(1); return boolObject(1);
} }
@ -269,19 +256,17 @@ Object evalList(const Object* obj, struct Environment* env)
return builtIn; return builtIn;
} }
struct Environment* outerEnv = global(); int i = getStructIndex(first_form->string);
for (int i = 0; i < outerEnv->structCount; i++) { if (i >= 0) {
if (strcmp(first_form->string, outerEnv->structDefs[i].name) == 0) { Object structo = structObject(i);
Object structo = structObject(i); int s = 0;
int s = 0; FOR_POINTER_IN_LIST(obj) {
FOR_POINTER_IN_LIST(obj) { if (s != 0) { // Skip the field name
if (s != 0) { // Skip the field name structo.structObject->fields[s - 1] = eval(POINTER, env);
structo.structObject->fields[s - 1] = eval(POINTER, env);
}
s++;
} }
return structo; s++;
} }
return structo;
} }
} }
@ -360,9 +345,9 @@ Object possessive(Object* params, int length, struct Environment* env)
return errorObject(NULL_PARSE); return errorObject(NULL_PARSE);
} }
struct StructDef structDef = global()->structDefs[structo.structObject->definition]; struct StructDef* structDef = getStructAt(structo.structObject->definition);
for (int i = 0; i < structDef.fieldCount; i++) { for (int i = 0; i < structDef->fieldCount; i++) {
if (strcmp(field.string, structDef.names[i]) == 0) { if (strcmp(field.string, structDef->names[i]) == 0) {
return cloneObject(structo.structObject->fields[i]); return cloneObject(structo.structObject->fields[i]);
} }
} }
@ -696,6 +681,7 @@ int main(int argc, const char* argv[])
} }
} }
if (ret != -1) { if (ret != -1) {
shredDictionary();
deleteEnv(global()); deleteEnv(global());
return ret; return ret;
} }
@ -727,6 +713,7 @@ int main(int argc, const char* argv[])
repl(&env); repl(&env);
} }
deleteEnv(&env); deleteEnv(&env);
shredDictionary();
// printf("TOTAL ALLOCATIONS: %d\n", getAllocations()); // printf("TOTAL ALLOCATIONS: %d\n", getAllocations());
// printf("TOTAL BYTES: %d\n", getBytes()); // printf("TOTAL BYTES: %d\n", getBytes());
} }

View File

@ -269,7 +269,7 @@ Object _basicOp(const Object* obj1, const Object* obj2, const char op,
Object basicOp(const Object* obj1, const Object* obj2, const char op, Object basicOp(const Object* obj1, const Object* obj2, const char op,
struct Environment* env) struct Environment* env)
{ {
if (isError(*obj2, ONLY_ONE_ARGUMENT)) { if (isError(*obj2, NOT_ENOUGH_ARGUMENTS)) {
return *obj2; return *obj2;
} }

View File

@ -119,7 +119,7 @@ void initialize()
if (!initialized) { if (!initialized) {
Object o = parseEval("(struct Request (queryParams))", global()); Object o = parseEval("(struct Request (queryParams))", global());
cleanObject(&o); cleanObject(&o);
requestDefinition = getStructIndex(global(), "Request"); requestDefinition = getStructIndex("Request");
} }
initialized = 1; initialized = 1;
} }