diff --git a/src/env.c b/src/env.c index 906d84c..56366cf 100644 --- a/src/env.c +++ b/src/env.c @@ -8,13 +8,27 @@ #include "web.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) { if (!env) { return errorObject(NULL_ENV); } - if (env->size == 0) { + if (env->capacity == 0) { if (env->outer) { return fetchFromEnvironment(name, env->outer); } 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); break; } @@ -53,9 +67,7 @@ struct Environment envForLambda(const Object* params, const Object* arg_forms, struct Environment env = { .outer = outer, - .structCount = 0, - .structCapacity = 0, - .size = paramCount, + .capacity = paramCount, .refs = 1, }; @@ -75,10 +87,10 @@ struct Environment envForLambda(const Object* params, const Object* arg_forms, for (int i = 0; i < paramCount; i++) { const char* newObjName = itemAt(params, i)->string; // Eval the `march` list - Object newEnvObj = eval(march, outer); - addToEnv(&env, newObjName, newEnvObj); // Could use eval_forms? + Object newEnvObj = march ? eval(march, outer) : errorObject(NOT_ENOUGH_ARGUMENTS); + addToEnv(&env, newObjName, newEnvObj); // Could use eval_forms? cleanObject(&newEnvObj); - march = march->forward; + march = march ? march->forward : NULL; } return env; @@ -95,7 +107,7 @@ void addToEnv(struct Environment* env, const char* name, const Object obj) { struct Environment* temp_env = 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) { // Add *new* item to env only if we're in the original scope if (temp_env == env) { @@ -115,10 +127,10 @@ void addToEnv(struct Environment* env, const char* name, const Object obj) printd("Reallocating environment\n"); const int inc = 5; - const int old_size = env->size; - env->size += inc; - env->strings = realloc(env->strings, sizeof(char*) * env->size); - env->objects = realloc(env->objects, sizeof(Object) * env->size); + const int old_size = env->capacity; + env->capacity += inc; + env->strings = realloc(env->strings, sizeof(char*) * env->capacity); + env->objects = realloc(env->objects, sizeof(Object) * env->capacity); for (int j = 0; j < inc; j++) { env->strings[old_size + j] = NULL; @@ -133,8 +145,8 @@ void printEnv(struct Environment* env) printf("NULL env\n"); return; } - printf("env->size = %d\n", env->size); - for (int i = 0; i < env->size; i++) { + printf("env->capacity = %d\n", env->capacity); + for (int i = 0; i < env->capacity; i++) { if (env->strings[i] == NULL) { printf("env[%d]: NULL %p\n", i, env->strings[i]); break; @@ -176,15 +188,18 @@ void deleteEnv(struct Environment* e) free(e->strings); free(e->objects); } +} - for (int i = 0; i < e->structCount; i++) { - free(e->structDefs[i].name); - for (int j = 0; j < e->structDefs[i].fieldCount; j++) { - free(e->structDefs[i].names[j]); +void shredDictionary() +{ + for (int i = 0; i < dictionary.structCount; i++) { + 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 { @@ -353,14 +368,19 @@ int runTests(int detailed) struct Environment defaultEnv() { + if (!helpInitialized) { + dictionary = (struct Dictionary) { + .structCount = 0, + .structCapacity = 8, + .structDefs = malloc(sizeof(struct StructDef) * 8), + }; + } + struct Environment e = { .outer = NULL, .strings = calloc(sizeof(char*), MAX_ENV_ELM), .objects = malloc(sizeof(Object) * MAX_ENV_ELM), - .size = MAX_ENV_ELM, - .structCount = 0, - .structCapacity = 8, - .structDefs = malloc(sizeof(struct StructDef) * 8), + .capacity = MAX_ENV_ELM, .refs = 1, }; @@ -421,24 +441,34 @@ struct Environment defaultEnv() return e; } -int getStructIndex(struct Environment* env, const char* name) +int getStructIndex(const char* name) { - for (int i = 0; i < env->structCount; i++) { - if (strcmp(name, env->structDefs[i].name) == 0) { + for (int i = 0; i < dictionary.structCount; i++) { + if (strcmp(name, dictionary.structDefs[i].name) == 0) { return i; } } return -1; } -struct Environment* globalEnv; - -struct Environment* global() +struct StructDef* getStructAt(int i) { - return globalEnv; + return &dictionary.structDefs[i]; } -void setGlobal(struct Environment* env) +void addStructDef(struct StructDef def) { - globalEnv = env; -} \ No newline at end of file + 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); + } + +} diff --git a/src/env.h b/src/env.h index f745740..827dbab 100644 --- a/src/env.h +++ b/src/env.h @@ -8,13 +8,15 @@ struct Environment { char** strings; Object* objects; struct Environment* outer; - int size; + int capacity; + int refs; +}; + +struct Dictionary { int structCount; int structCapacity; struct StructDef* structDefs; - - int refs; }; struct Environment* global(); @@ -37,9 +39,15 @@ void addFunc(const char* name, void deleteEnv(struct Environment* e); +void shredDictionary(); + 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! char* getHelp(const char* symbol); diff --git a/src/object.c b/src/object.c index 67d9ba8..16cefc0 100644 --- a/src/object.c +++ b/src/object.c @@ -181,7 +181,7 @@ static const char* errorText[] = {"MISMATCHED_PARENS", "LISTS_NOT_SAME_SIZE", "BAD_NUMBER", "UNSUPPORTED_NUMBER_TYPE", - "ONLY_ONE_ARGUMENT", + "NOT_ENOUGH_ARGUMENTS", "NOT_A_LIST", "SCRIPT_NOT_FOUND", "NO_CLONE_SPECIFIED", @@ -225,8 +225,9 @@ int stringStruct(char* dest, const Object* obj) const char* initial = dest; dest += sprintf(dest, "{"); - for (int i = 0; i < global()->structDefs[so->definition].fieldCount; i++) { - dest += sprintf(dest, " %s: ", global()->structDefs[so->definition].names[i]); + struct StructDef* def = getStructAt(so->definition); + for (int i = 0; i < def->fieldCount; i++) { + dest += sprintf(dest, " %s: ", def->names[i]); int isString = so->fields[i].type == TYPE_STRING; if (isString) { dest += sprintf(dest, "\""); @@ -453,7 +454,7 @@ void cleanObject(Object* target) } break; 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]); } free(target->structObject->fields); @@ -587,7 +588,7 @@ inline Object structObject(int definition) Object structo = newObject(TYPE_STRUCT); structo.structObject = malloc(sizeof(struct StructObject)); 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; } @@ -685,7 +686,7 @@ Object cloneStruct(const Object src) { Object structo = structObject(src.structObject->definition); 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]); } return structo; diff --git a/src/object.h b/src/object.h index 0ba8f92..7acfa9c 100644 --- a/src/object.h +++ b/src/object.h @@ -53,7 +53,7 @@ enum errorCode { LISTS_NOT_SAME_SIZE, BAD_NUMBER, UNSUPPORTED_NUMBER_TYPE, - ONLY_ONE_ARGUMENT, + NOT_ENOUGH_ARGUMENTS, NOT_A_LIST, SCRIPT_NOT_FOUND, NO_CLONE_SPECIFIED, diff --git a/src/pebblisp.c b/src/pebblisp.c index dc2d3ae..8a4a232 100644 --- a/src/pebblisp.c +++ b/src/pebblisp.c @@ -76,20 +76,7 @@ Object evalStructArgs(const Object* symbol, const Object* fields, struct Environ } } - env = global(); - - 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); - } + addStructDef(def); return boolObject(1); } @@ -269,19 +256,17 @@ Object evalList(const Object* obj, struct Environment* env) return builtIn; } - struct Environment* outerEnv = global(); - for (int i = 0; i < outerEnv->structCount; i++) { - if (strcmp(first_form->string, outerEnv->structDefs[i].name) == 0) { - Object structo = structObject(i); - int s = 0; - FOR_POINTER_IN_LIST(obj) { - if (s != 0) { // Skip the field name - structo.structObject->fields[s - 1] = eval(POINTER, env); - } - s++; + int i = getStructIndex(first_form->string); + if (i >= 0) { + Object structo = structObject(i); + int s = 0; + FOR_POINTER_IN_LIST(obj) { + if (s != 0) { // Skip the field name + structo.structObject->fields[s - 1] = eval(POINTER, env); } - return structo; + s++; } + return structo; } } @@ -360,9 +345,9 @@ Object possessive(Object* params, int length, struct Environment* env) return errorObject(NULL_PARSE); } - struct StructDef structDef = global()->structDefs[structo.structObject->definition]; - for (int i = 0; i < structDef.fieldCount; i++) { - if (strcmp(field.string, structDef.names[i]) == 0) { + struct StructDef* structDef = getStructAt(structo.structObject->definition); + for (int i = 0; i < structDef->fieldCount; i++) { + if (strcmp(field.string, structDef->names[i]) == 0) { return cloneObject(structo.structObject->fields[i]); } } @@ -696,6 +681,7 @@ int main(int argc, const char* argv[]) } } if (ret != -1) { + shredDictionary(); deleteEnv(global()); return ret; } @@ -727,6 +713,7 @@ int main(int argc, const char* argv[]) repl(&env); } deleteEnv(&env); + shredDictionary(); // printf("TOTAL ALLOCATIONS: %d\n", getAllocations()); // printf("TOTAL BYTES: %d\n", getBytes()); } diff --git a/src/plfunc.c b/src/plfunc.c index 49f8153..68dcceb 100644 --- a/src/plfunc.c +++ b/src/plfunc.c @@ -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, struct Environment* env) { - if (isError(*obj2, ONLY_ONE_ARGUMENT)) { + if (isError(*obj2, NOT_ENOUGH_ARGUMENTS)) { return *obj2; } diff --git a/src/web.c b/src/web.c index 634c869..1be2033 100644 --- a/src/web.c +++ b/src/web.c @@ -119,7 +119,7 @@ void initialize() if (!initialized) { Object o = parseEval("(struct Request (queryParams))", global()); cleanObject(&o); - requestDefinition = getStructIndex(global(), "Request"); + requestDefinition = getStructIndex("Request"); } initialized = 1; }