diff --git a/src/env.c b/src/env.c index c433f90..ef14b35 100644 --- a/src/env.c +++ b/src/env.c @@ -57,8 +57,6 @@ struct symFunc { #define pf(_func) buildFuncSym(_func ## Symbol, &(_func)) #endif -#ifndef HASHLESS_ENV // Hash-based env - Object* fetch(const char* name, struct Environment* env) { while (env) { @@ -261,281 +259,6 @@ void printEnv(struct Environment* env, int printPointers) } } -#else -Object fetchFromEnvironment(const char* name, struct Environment* env) -{ - if (!env) { - return errorObject(NULL_ENV); - } - - if (env->capacity == 0) { - if (env->outer) { - return fetchFromEnvironment(name, env->outer); - } else { - return errorObject(EMPTY_ENV); - } - } - - for (int i = 0; i < env->capacity; i++) { - if (env->elements[i].symbol == NULL) { - printd("Try %d (NULL)\n", i); - break; - } - - printd("Try %d (%s)\n", i, env->strings[i]); - if (strcmp(name, env->elements[i].symbol) == 0) { - printd("Returning!\n"); - return cloneObject(env->elements[i].object); - } - } - - printd("Trying outer %p\n", env->outer); - if (env->outer) { - return fetchFromEnvironment(name, env->outer); - } - - return errorWithContext(DID_NOT_FIND_SYMBOL, name); -} - -void addToEnvAt(int i, struct Environment* env, const char* name, const Object obj) -{ - env->elements[i].symbol = malloc(sizeof(char) * strlen(name) + 1); - strcpy(env->elements[i].symbol, name); - env->elements[i].object = cloneObject(obj); -} - -struct Environment envForLambda(const Object* params, const Object* arg_forms, int paramCount, - struct Environment* outer) -{ - if (outer) { - outer->refs += 1; - } - - struct Environment env = { - .outer = outer, - .capacity = paramCount, - .refs = 1, - }; - - if (paramCount == 0) { - if (outer) { - outer->refs += 1; - return *outer; - } - env.elements = NULL; - return env; - } - - env.elements = malloc(sizeof(struct EnvElement) * (paramCount + 1)); - - const Object* march = arg_forms; - for (int i = 0; i < paramCount; i++) { - const char* newObjName = itemAt(params, i)->string; - // Eval the `march` list - Object newEnvObj = march ? eval(march, outer) : errorWithContext(NOT_ENOUGH_ARGUMENTS, newObjName); - addToEnvAt(i, &env, newObjName, newEnvObj); // Could use eval_forms? - cleanObject(&newEnvObj); - march = march ? march->forward : NULL; - } - env.elements[paramCount].symbol = NULL; - - return env; -} - -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->capacity; i++) { - if (temp_env->elements[i].symbol == NULL) { - // Add *new* item to env only if we're in the original scope, - // otherwise keep searching - if (temp_env == env) { - addToEnvAt(i, env, name, obj); - return; - } - break; - } else if (strcmp(temp_env->elements[i].symbol, name) == 0) { - Object o = cloneObject(obj); - cleanObject(&temp_env->elements[i].object); - temp_env->elements[i].object = o; - return; - } - } - temp_env = temp_env->outer; - } - - printd("Reallocating environment\n"); - const int inc = 5; - const int old_size = env->capacity; - env->capacity += inc; - env->elements = realloc(env->elements, sizeof(struct EnvElement) * env->capacity); - - for (int j = 0; j < inc; j++) { - env->elements[old_size + j].symbol = NULL; - } - - addToEnvAt(old_size, env, name, obj); -} - -void deleteEnv(struct Environment* e) -{ - e->refs -= 1; - if (e->refs) { - return; - } - if (e->outer) { - deleteEnv(e->outer); - } - - if (e->elements) { - int i = 0; - while (e->elements[i].symbol) { - free(e->elements[i].symbol); - cleanObject(&e->elements[i].object); - i++; - } - free(e->elements); - } -} - -struct Environment defaultEnvPreAllocated(struct EnvElement* elements) -{ -#ifndef STANDALONE - int helpInitialized = 0; -#endif - if (!helpInitialized) { - dictionary = (struct Dictionary) { - .structCount = 0, - .structCapacity = 8, - .structDefs = malloc(sizeof(struct StructDef) * 8), - }; - } - - struct Environment e = { - .elements = elements, - .outer = NULL, - .capacity = MAX_ENV_ELM, - .refs = 1, - }; - - struct symFunc symFuncs[] = { - pf(def), - pf(add), - pf(sub), - pf(mul), - pf(dvi), - pf(mod), - pf(equ), - pf(greaterThan), - pf(lessThan), - pf(and), - pf(or), - pf(catObjects), - pf(filter), - pf(len), - pf(append), - pf(prepend), - pf(reduce), - pf(mapO), - pf(at), -#ifndef PBL_PLATFORM_APLITE - pf(rest), - pf(charAt), - pf(chars), - pf(matches), - pf(slen), - pf(substring), - pf(isNum), - pf(isList), - pf(isString), - pf(isErr), - pf(charVal), - pf(parseEvalO), -#endif - pf(structAccess), - pf(getTime), -#ifndef LOW_MEM - pf(reverse), -#endif -#ifdef WEBSERVER - pf(addGetRoute), - pf(addPostRoute), - pf(startServer), -#endif -#ifdef STANDALONE - pf(segfault), - pf(print), - pf(numToChar), - pf(printEnvO), - pf(systemCall), - pf(loadFile), - pf(cd), - pf(cwd), - pf(takeInput), - pf(readFileToObject), - pf(getEnvVar), - pf(async), - pf(await), - pf(help) -#endif - }; - - unsigned i; - for (i = 0; i < sizeof(symFuncs) / sizeof(symFuncs[0]); i++) { - addFunc(symFuncs[i].sym, symFuncs[i].func, &e, i); - } - for (int j = i; j < e.capacity; j++) { - e.elements[j].symbol = NULL; - } - - helpInitialized = 1; - return e; -} - -struct Environment defaultEnv() -{ - return defaultEnvPreAllocated(malloc(sizeof(struct EnvElement) * MAX_ENV_ELM)); -} - -void printEnv(struct Environment* env, int printPointers) -{ - if (!env) { - printf("NULL env\n"); - return; - } - printf("env->capacity = %d\n", env->capacity); - for (int i = 0; i < env->capacity; i++) { - printf(""); - if (env->elements[i].symbol == NULL) { - printf("[%d]: NULL - End of Environment\n", i); - break; - } - if (printPointers) { - printf("[%d]: `%s` %p :: ", i, env->elements[i].symbol, env->elements[i].symbol); - } else { - printf("[%d]: `%s` :: ", i, env->elements[i].symbol); - } - printf(""); - if (env->elements[i].object.type == TYPE_STRING) { - printf("\""); - } - if (env->elements[i].object.type == TYPE_FUNC && !printPointers) { - printf("Native"); - } else { - size_t length; - char* s = stringObj(&env->elements[i].object, &length); - printColored(s); - if (env->elements[i].object.type == TYPE_STRING) { - printf("\""); - } - free(s); - } - printf("\n"); - } -} -#endif - void addFunc(const char* name, Object (* func)(Object*, int, struct Environment*), struct Environment* env, diff --git a/src/hash.c b/src/hash.c index d7564bf..7759712 100644 --- a/src/hash.c +++ b/src/hash.c @@ -3,18 +3,6 @@ #include -static unsigned long hash(const char *str) -{ - unsigned long hash = 5381; - int c; - - while ((c = *str++)) { - hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ - } - - return hash; -} - struct ObjectTable buildTable(size_t capacity) { struct ObjectTable table = { @@ -28,11 +16,32 @@ struct ObjectTable buildTable(size_t capacity) return table; } -/// -/// \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 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); + } + } + free(table->elements); +} + +#ifndef HASHLESS_ENV + +static unsigned long hash(const char* str, struct ObjectTable* table) +{ + unsigned long hash = 5381; + int c; + + while ((c = *str++)) { + hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + } + + return hash % table->capacity; +} + +void extendTable(struct ObjectTable* table) { if (table->capacity < (table->count + 1) * 2) { struct ObjectTable newTable = buildTable(table->capacity ? table->capacity * 2 : 4); @@ -44,14 +53,6 @@ void addToTable(struct ObjectTable* table, char* name, Object object) free(table->elements); *table = newTable; } - - size_t h = hash(name) % table->capacity; - while(table->elements[h].symbol) { - h = (h + 1) % table->capacity; - } - table->elements[h].symbol = name; - table->elements[h].object = object; - table->count += 1; } Object* getFromTable(struct ObjectTable* table, const char* name) @@ -59,8 +60,8 @@ Object* getFromTable(struct ObjectTable* table, const char* name) if (table->capacity == 0) { return NULL; } - size_t h = hash(name) % table->capacity; - while(table->elements[h].symbol) { + size_t h = hash(name, table); + while (table->elements[h].symbol) { if (strcmp(name, table->elements[h].symbol) == 0) { return &table->elements[h].object; } @@ -69,13 +70,53 @@ Object* getFromTable(struct ObjectTable* table, const char* name) return NULL; } -void deleteTable(struct ObjectTable* table) +#else + +void extendTable(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); + if (table->count == (table->capacity - 1)) { + struct EnvElement* oldElements = table->elements; + size_t oldCapacity = table->capacity; + table->capacity *= 2; + table->elements = malloc(sizeof(struct EnvElement) * table->capacity); + for (int i = 0; i < oldCapacity; i++) { + table->elements[i] = oldElements[i]; + } + for (size_t i = oldCapacity; i < table->capacity; i++) { + table->elements[i].symbol = NULL; } } - free(table->elements); -} \ No newline at end of file +} + +Object* getFromTable(struct ObjectTable* table, const char* name) +{ + for (size_t i = 0; i < table->count; i++) { + if (strcmp(name, table->elements[i].symbol) == 0) { + return &table->elements[i].object; + } + } + return NULL; +} + +static unsigned long hash(unused const char* str, struct ObjectTable* table) +{ + return table->count; +} + +#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) +{ + extendTable(table); + size_t h = hash(name, table); + while (table->elements[h].symbol) { + h = (h + 1) % table->capacity; + } + table->elements[h].symbol = name; + table->elements[h].object = object; + table->count += 1; +}