Small optimizations and cleanup.
This commit is contained in:
parent
158c21f441
commit
9a454e6a30
90
src/env.c
90
src/env.c
|
@ -53,8 +53,6 @@ struct Environment envForLambda(const Object* params, const Object* arg_forms,
|
|||
|
||||
struct Environment env = {
|
||||
.outer = outer,
|
||||
.strings = NULL,
|
||||
.objects = NULL,
|
||||
.structCount = 0,
|
||||
.structCapacity = 0,
|
||||
.size = paramCount,
|
||||
|
@ -62,7 +60,12 @@ struct Environment envForLambda(const Object* params, const Object* arg_forms,
|
|||
};
|
||||
|
||||
if (paramCount == 0) {
|
||||
return outer ? *outer : env;
|
||||
if (outer) {
|
||||
return *outer;
|
||||
}
|
||||
env.strings = NULL;
|
||||
env.objects = NULL;
|
||||
return env;
|
||||
}
|
||||
|
||||
env.strings = calloc(sizeof(char*), paramCount + 1);
|
||||
|
@ -81,29 +84,22 @@ struct Environment envForLambda(const Object* params, const Object* arg_forms,
|
|||
return env;
|
||||
}
|
||||
|
||||
// TODO Maybe extend environment using a new outer, instead of realloc
|
||||
void addToEnvAt(int i, struct Environment* env, const char* name, const Object obj)
|
||||
{
|
||||
env->strings[i] = malloc(sizeof(char) * strlen(name) + 1);
|
||||
strcpy(env->strings[i], name);
|
||||
env->objects[i] = cloneObject(obj);
|
||||
}
|
||||
|
||||
void addToEnv(struct Environment* env, const char* name, const Object obj)
|
||||
{
|
||||
// int sym_pos = findInEnv(&env, name);
|
||||
// if(sym_pos != -1) {
|
||||
// Object o = cloneObject(obj);
|
||||
// cleanObject(&env->objects[sym_pos]);
|
||||
// env->objects[sym_pos] = o;
|
||||
// return;
|
||||
// }
|
||||
|
||||
int i;
|
||||
struct Environment* temp_env = env;
|
||||
int is_local = 1;
|
||||
while (temp_env) {
|
||||
for (i = 0; i < temp_env->size; i++) {
|
||||
// Add *new* item to env only if we're in the local scope
|
||||
for (int i = 0; i < temp_env->size; i++) {
|
||||
if (temp_env->strings[i] == NULL) {
|
||||
if (is_local) {
|
||||
temp_env->strings[i] =
|
||||
calloc(sizeof(char), strlen(name) + 1);
|
||||
strcpy(temp_env->strings[i], name);
|
||||
temp_env->objects[i] = cloneObject(obj);
|
||||
// Add *new* item to env only if we're in the original scope
|
||||
if (temp_env == env) {
|
||||
addToEnvAt(i, env, name, obj);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
@ -115,7 +111,6 @@ void addToEnv(struct Environment* env, const char* name, const Object obj)
|
|||
}
|
||||
}
|
||||
temp_env = temp_env->outer;
|
||||
is_local = 0;
|
||||
}
|
||||
|
||||
printd("Reallocating environment\n");
|
||||
|
@ -129,9 +124,7 @@ void addToEnv(struct Environment* env, const char* name, const Object obj)
|
|||
env->strings[old_size + j] = NULL;
|
||||
}
|
||||
|
||||
env->strings[old_size] = malloc(strlen(name) + 1);
|
||||
strcpy(env->strings[old_size], name);
|
||||
env->objects[old_size] = cloneObject(obj);
|
||||
addToEnvAt(old_size, env, name, obj);
|
||||
}
|
||||
|
||||
void printEnv(struct Environment* env)
|
||||
|
@ -155,11 +148,12 @@ void printEnv(struct Environment* env)
|
|||
|
||||
void addFunc(const char* name,
|
||||
Object (* func)(Object*, int, struct Environment*),
|
||||
struct Environment* env)
|
||||
struct Environment* env,
|
||||
int i)
|
||||
{
|
||||
Object o = newObject(TYPE_FUNC);
|
||||
o.func = func;
|
||||
addToEnv(env, name, o);
|
||||
addToEnvAt(i, env, name, o);
|
||||
}
|
||||
|
||||
void deleteEnv(struct Environment* e)
|
||||
|
@ -180,9 +174,7 @@ void deleteEnv(struct Environment* e)
|
|||
i++;
|
||||
}
|
||||
free(e->strings);
|
||||
e->strings = NULL;
|
||||
free(e->objects);
|
||||
e->objects = NULL;
|
||||
}
|
||||
|
||||
for (int i = 0; i < e->structCount; i++) {
|
||||
|
@ -201,18 +193,6 @@ struct symFunc {
|
|||
Object (* func)(Object*, int, struct Environment*);
|
||||
};
|
||||
|
||||
struct Environment* globalEnv;
|
||||
|
||||
struct Environment* global()
|
||||
{
|
||||
return globalEnv;
|
||||
}
|
||||
|
||||
void setGlobal(struct Environment* env)
|
||||
{
|
||||
globalEnv = env;
|
||||
}
|
||||
|
||||
struct helpText {
|
||||
const char* symbol;
|
||||
const char* help;
|
||||
|
@ -225,6 +205,8 @@ struct helpText helpTexts[100];
|
|||
#define pfn(_func) buildFuncSym(_func ## Symbol, &(_func), _func ## Doc, NULL)
|
||||
#define pf(_name, _func) buildFuncSym(_name, &(_func), _func ## Doc, _func ## Tests, array_length(_func ## Tests))
|
||||
|
||||
/// For any instances (e.g. segfault recovery) where defaultEnv() may be called
|
||||
/// multiple times.
|
||||
int helpInitialized = 0;
|
||||
|
||||
struct symFunc buildFuncSym(const char* symbol, Object (* func)(Object*, int, struct Environment*), const char* help,
|
||||
|
@ -371,15 +353,11 @@ int runTests(int detailed)
|
|||
|
||||
struct Environment defaultEnv()
|
||||
{
|
||||
char** strings = calloc(sizeof(char*), MAX_ENV_ELM);
|
||||
Object* objects = malloc(sizeof(Object) * MAX_ENV_ELM);
|
||||
char size = MAX_ENV_ELM;
|
||||
|
||||
struct Environment e = {
|
||||
.outer = NULL,
|
||||
.strings = strings,
|
||||
.objects = objects,
|
||||
.size = size,
|
||||
.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),
|
||||
|
@ -435,8 +413,8 @@ struct Environment defaultEnv()
|
|||
#endif
|
||||
};
|
||||
|
||||
for (unsigned i = 0; i < sizeof(symFuncs) / sizeof(symFuncs[0]); i++) {
|
||||
addFunc(symFuncs[i].sym, symFuncs[i].func, &e);
|
||||
for (int i = 0; i < sizeof(symFuncs) / sizeof(symFuncs[0]); i++) {
|
||||
addFunc(symFuncs[i].sym, symFuncs[i].func, &e, i);
|
||||
}
|
||||
|
||||
helpInitialized = 1;
|
||||
|
@ -452,3 +430,15 @@ int getStructIndex(struct Environment* env, const char* name)
|
|||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct Environment* globalEnv;
|
||||
|
||||
struct Environment* global()
|
||||
{
|
||||
return globalEnv;
|
||||
}
|
||||
|
||||
void setGlobal(struct Environment* env)
|
||||
{
|
||||
globalEnv = env;
|
||||
}
|
|
@ -32,7 +32,8 @@ void printEnv(struct Environment* env);
|
|||
|
||||
void addFunc(const char* name,
|
||||
Object (* func)(Object*, int, struct Environment*),
|
||||
struct Environment* env);
|
||||
struct Environment* env,
|
||||
int i);
|
||||
|
||||
void deleteEnv(struct Environment* e);
|
||||
|
||||
|
|
|
@ -170,42 +170,6 @@ Object evalBuiltIns(const Object* first, const Object* rest,
|
|||
return *first;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk evaluator of Objects in a given list. Puts the results in a given array
|
||||
*
|
||||
* Note that `destArr` is a raw array, not an Object list, and that `start` is
|
||||
* not itself a list, but the first element *in* a list to be evaluated. This
|
||||
* allows more speed and flexibility in what should be evaluated.
|
||||
*
|
||||
* @param destArr The raw array to put the results into. Not an Object list!
|
||||
* @param start The Object element to start with
|
||||
* @param env The environment to use while evaluating
|
||||
*/
|
||||
void evalForms(Object* destArr, const Object* start, struct Environment* env)
|
||||
{
|
||||
int i = 0;
|
||||
while (start) {
|
||||
destArr[i] = eval(start, env);
|
||||
start = start->forward;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
Object listEvalFunc(const Object* list, const Object* function,
|
||||
int length, struct Environment* env);
|
||||
|
||||
Object simpleFuncEval(const Object func, Object arg1, Object arg2, struct Environment* env)
|
||||
{
|
||||
Object funcList = startList(func);
|
||||
nf_addToList(&funcList, arg1);
|
||||
Object current = cloneObject(arg2);
|
||||
nf_addToList(&funcList, current);
|
||||
Object first_eval = eval(funcList.list, env);
|
||||
arg1 = listEvalFunc(&funcList, &first_eval, 2, env);
|
||||
cleanObject(&funcList);
|
||||
return arg1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates a list whose first element is a function, applying that function
|
||||
*
|
||||
|
@ -221,7 +185,12 @@ Object listEvalFunc(const Object* list, const Object* function,
|
|||
const int length, struct Environment* env)
|
||||
{
|
||||
Object rest[length];
|
||||
evalForms(rest, list->list->forward, env);
|
||||
|
||||
const Object* start = list->list->forward;
|
||||
for (int i = 0; i < length; i++) {
|
||||
rest[i] = eval(start, env);
|
||||
start = start->forward;
|
||||
}
|
||||
|
||||
Object result = function->func(rest, length, env);
|
||||
for (int i = 0; i < length; i++) {
|
||||
|
@ -230,6 +199,18 @@ Object listEvalFunc(const Object* list, const Object* function,
|
|||
return result;
|
||||
}
|
||||
|
||||
Object simpleFuncEval(const Object func, Object arg1, Object arg2, struct Environment* env)
|
||||
{
|
||||
Object funcList = startList(func);
|
||||
nf_addToList(&funcList, arg1);
|
||||
Object current = cloneObject(arg2);
|
||||
nf_addToList(&funcList, current);
|
||||
Object first_eval = eval(funcList.list, env);
|
||||
arg1 = listEvalFunc(&funcList, &first_eval, 2, env);
|
||||
cleanObject(&funcList);
|
||||
return arg1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates a list whose first element is a lambda, applying that lambda
|
||||
*
|
||||
|
|
|
@ -49,8 +49,6 @@ Object parseEval(const char* input, struct Environment* env);
|
|||
|
||||
Object evalList(const Object* obj, struct Environment* env);
|
||||
|
||||
void evalForms(Object* destList, const Object* src, struct Environment* env);
|
||||
|
||||
void copySlice(char* dest, struct Slice* src);
|
||||
|
||||
Object evalLambdaArgs(const Object* arg_forms, struct Environment* env);
|
||||
|
|
Loading…
Reference in New Issue