diff --git a/src/env.c b/src/env.c index ef14b35..a74d1e4 100644 --- a/src/env.c +++ b/src/env.c @@ -91,7 +91,15 @@ void addToEnv(struct Environment* env, const char* name, const Object obj) addToTable(&env->table, symbol, cloneObject(obj)); } -struct Environment envForLambda(const Object* params, const Object* arg_forms, int paramCount, +/** + * Build the local Environment for a given lambda + * @param params List of symbol objects with the names of lambda params + * @param paramCount Length of params list + * @param arguments Arguments being passed into the lambda where ->forward is the next arg + * @param outer The parent scope + * @return The constructed environment + */ +struct Environment envForLambda(const Object* params, const Object* arguments, int paramCount, struct Environment* outer) { if (outer) { @@ -104,14 +112,14 @@ struct Environment envForLambda(const Object* params, const Object* arg_forms, i .refs = 1, }; - const Object* march = arg_forms; + const Object* argument = arguments; 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); - addToEnv(&env, newObjName, newEnvObj); // Could use eval_forms? + const char* paramName = itemAt(params, i)->string; + // Eval the `argument` list + Object newEnvObj = argument ? eval(argument, outer) : errorWithContext(NOT_ENOUGH_ARGUMENTS, paramName); + addToEnv(&env, paramName, newEnvObj); // Could use eval_forms? cleanObject(&newEnvObj); - march = march ? march->forward : NULL; + argument = argument ? argument->forward : NULL; } env.outer = outer; diff --git a/src/env.h b/src/env.h index 90b4935..c51d7af 100644 --- a/src/env.h +++ b/src/env.h @@ -25,7 +25,7 @@ void setGlobal(struct Environment* env); Object fetchFromEnvironment(const char* name, struct Environment* env); -struct Environment envForLambda(const Object* params, const Object* arg_forms, int paramCount, +struct Environment envForLambda(const Object* params, const Object* arguments, int paramCount, struct Environment* outer); void addToEnv(struct Environment* env, const char* name, Object obj); @@ -56,6 +56,7 @@ void printColored(const char* code); int runTests(int detailed); int getTotalSearchDepth(); + int getTotalSearches(); #define unused __attribute__((unused)) @@ -73,7 +74,7 @@ static const char * const _name ## Symbol = _symbol; \ fnn(_name, _docs, __VA_ARGS__) fn(segfault, "seg", - "Induces a segfault." + "Induces a segfault." ); fn(help, "?", diff --git a/src/hash.c b/src/hash.c index 7759712..a1ad48c 100644 --- a/src/hash.c +++ b/src/hash.c @@ -85,6 +85,7 @@ void extendTable(struct ObjectTable* table) for (size_t i = oldCapacity; i < table->capacity; i++) { table->elements[i].symbol = NULL; } + free(oldElements); } } diff --git a/src/main.c b/src/main.c index c0a8ff1..a04ca3f 100644 --- a/src/main.c +++ b/src/main.c @@ -16,7 +16,7 @@ Object getPrompt(struct Environment* env) return prompt; } Object param = stringFromSlice("", 1); - Object e = listEvalLambda(&prompt, ¶m, 2, env); + Object e = funcyEval(&prompt, ¶m, 1, env); cleanObject(&prompt); cleanObject(¶m); return e; @@ -34,7 +34,7 @@ char* preprocess(char* buf, struct Environment* env) { Object lambda = fetchFromEnvironment("preprocess", env); Object buffer = nullTerminated(buf); - Object s = listEvalLambda(&lambda, &buffer, 2, env); + Object s = funcyEval(&lambda, &buffer, 1, env); size_t length; return stringObj(&s, &length); } diff --git a/src/object.c b/src/object.c index df12bf9..9bc7a52 100644 --- a/src/object.c +++ b/src/object.c @@ -277,7 +277,7 @@ int stringNObj(struct string* s, const Object* obj) inflate(s, 128); if (obj->error->context && obj->error->context[0] != '\0') { s->cursor += sprintf(s->cursor, "%s: %s", errorText[code], - obj->error->context); + obj->error->context); } else if (code >= 0 && code <= INDEX_PAST_END) { s->cursor += sprintf(s->cursor, "%s", errorText[code]); } else { @@ -744,19 +744,17 @@ inline Object constructLambda(const Object* params, const Object* body, struct E o.lambda->body = copyList(body); o.lambda->refs = 1; - if (env) { - Object* dest = &o.lambda->body; - FOR_POINTER_IN_LIST(dest) { - if (POINTER->type == TYPE_SYMBOL) { - Object fetched = fetchFromEnvironment(POINTER->string, env); - // TODO: Figure out why lambdas in particular break when doing this. - if (!isError(fetched, DID_NOT_FIND_SYMBOL) && fetched.type != TYPE_LAMBDA) { - fetched.forward = POINTER->forward; - cleanObject(POINTER); - *POINTER = fetched; - } else { - cleanObject(&fetched); - } + Object* dest = &o.lambda->body; + FOR_POINTER_IN_LIST(dest) { + if (POINTER->type == TYPE_SYMBOL) { + Object fetched = fetchFromEnvironment(POINTER->string, env); + // TODO: Figure out why lambdas in particular break when doing this. + if (!isError(fetched, DID_NOT_FIND_SYMBOL) && fetched.type != TYPE_LAMBDA) { + fetched.forward = POINTER->forward; + cleanObject(POINTER); + *POINTER = fetched; + } else { + cleanObject(&fetched); } } } diff --git a/src/pebblisp.c b/src/pebblisp.c index 4bf5f1d..d12e7c9 100644 --- a/src/pebblisp.c +++ b/src/pebblisp.c @@ -48,13 +48,14 @@ Object evalStructArgs(const Object* symbol, const Object* fields, unused struct return errorObject(NOT_A_LIST); } - struct StructDef def; - def.name = malloc(sizeof(char) * (strlen(name) + 1)); + int fieldCount = listLength(fields); + struct StructDef def = { + .name = malloc(sizeof(char) * (strlen(name) + 1)), + .fieldCount = fieldCount, + .names = malloc(sizeof(char*) * fieldCount), + }; strcpy(def.name, name); - def.fieldCount = listLength(fields); - def.names = malloc(sizeof(char*) * def.fieldCount); - int i = 0; FOR_POINTER_IN_LIST(fields) { def.names[i] = malloc(sizeof(char) * (strlen(POINTER->string) + 1)); @@ -88,7 +89,7 @@ Object mapO(Object* params, int length, struct Environment* env) Object lambda = eval(¶ms[0], env); const Object* inputList = ¶ms[1]; - if (lambda.type != TYPE_LAMBDA) { + if (!isFuncy(lambda)) { return errorObject(BAD_TYPE); } @@ -118,8 +119,8 @@ Object mapO(Object* params, int length, struct Environment* env) * Tries to either apply the function to its parameters, or create a partial * function, if not enough parameters were passed. * - * @param function First element of the paramList, already evaluated to be a function - * @param paramList The parameters to the function + * @param function The object evaluated to be TYPE_FUNC + * @param paramList Ongoing (forward->forward) list of parameters to the function * @param length Length of `paramList` - 1, to exclude the already-evaluated element * @param env The environment to evaluate in */ @@ -145,7 +146,7 @@ Object simpleFuncEval(const Object func, Object arg1, Object arg2, struct Enviro arg2 = cloneObject(arg2); arg1.forward = &arg2; Object first_eval = eval(&func, env); - Object ret = listEvalFunc(&first_eval, &arg1, 2, env); + Object ret = funcyEval(&first_eval, &arg1, 2, env); cleanObject(&first_eval); cleanObject(&arg2); return ret; @@ -157,15 +158,15 @@ Object simpleFuncEval(const Object func, Object arg1, Object arg2, struct Enviro * Tries to apply the lambda to its parameters. Doesn't attempt partial * application. * - * @param lambda First element of the list, already evaluated to be a lambda - * @param remaining The first element after `lambda` + * @param lambda The object evaluated to be TYPE_LAMBDA + * @param passedArguments Ongoing (forward->forward) list of parameters to the lambda * @param env The environment to evaluate in */ -Object listEvalLambda(Object* lambda, const Object* remaining, int evalLength, +Object listEvalLambda(Object* lambda, const Object* passedArguments, int evalLength, struct Environment* env) { struct Environment newEnv = - envForLambda(&lambda->lambda->params, remaining, evalLength - 1, env); + envForLambda(&lambda->lambda->params, passedArguments, evalLength, env); Object ret = eval(&lambda->lambda->body, &newEnv); deleteEnv(&newEnv); cleanObject(lambda); @@ -179,6 +180,24 @@ Object listEvalLambda(Object* lambda, const Object* remaining, int evalLength, return ret; } +Object funcyEval(Object* funcy, const Object* passedArguments, int evalLength, + struct Environment* env) +{ + if (!funcy) { + eprintf("HIGHLY ILLEGAL NULL FUNCY!!!\n"); + return errorObject(BAD_TYPE); + } + switch (funcy->type) { + case TYPE_LAMBDA: + return listEvalLambda(funcy, passedArguments, evalLength, env); + case TYPE_FUNC: + return listEvalFunc(funcy, passedArguments, evalLength, env); + default: + eprintf("HIGHLY ILLEGAL NOT-FUNCY IN funcyEval()!!!\n"); + return errorObject(BAD_TYPE); + } +} + /** * Evaluates a given list, including the application of functions and lambdas * @@ -232,10 +251,10 @@ Object evalList(const Object* obj, struct Environment* env) switch (first_eval.type) { case TYPE_FUNC: // Uses evalLength - 1 because we skip the first form (the function itself) - return listEvalFunc(&first_eval, obj->list->forward, evalLength - 1, env); + return listEvalFunc(&first_eval, first_form->forward, evalLength - 1, env); case TYPE_LAMBDA: - return listEvalLambda(&first_eval, first_form->forward, evalLength, env); + return listEvalLambda(&first_eval, first_form->forward, evalLength - 1, env); default: { // Return list with each element evaluated Object list = listObject(); @@ -253,19 +272,6 @@ Object evalList(const Object* obj, struct Environment* env) } } -#include -Object funcyWithArgs(Object funcy, int count, ...) -{ - va_list ptr; - va_start(ptr, count); - Object args[count]; - for (int i = 0; i < count; i++) { - args[i] = va_arg(ptr, Object); - } - va_end(ptr); - -} - Object eval(const Object* obj, struct Environment* env) { switch (obj->type) { @@ -321,9 +327,8 @@ Result parse(struct Slice* slices) } return r; } else if (token->text[0] == '(') { - // todo check for null rest return readSeq(rest); - } else { // todo error on missing close paren + } else { Result r = parseAtom(token); r.slices = &r.slices[1]; return r; @@ -363,7 +368,7 @@ Result readSeq(struct Slice* tokens) tokens = r.slices; cleanObject(&r.obj); forceString = next->text[0] == '?' - || (strncmp(next->text, "def", 3) == 0); + || (strncmp(next->text, "def", 3) == 0); } } @@ -521,7 +526,8 @@ Object typeCheck(const char* funcName, Object* params, int length, for (int i = 0; i < typeLength - 1; i++) { if (typeChecks[i].checkFunc && !typeChecks[i].checkFunc(params[i])) { char context[128]; - sprintf(context, "When calling (%s), expected %s, but received %s.", funcName, typeChecks[i].name, getTypeName(¶ms[i])); + sprintf(context, "When calling (%s), expected %s, but received %s.", funcName, typeChecks[i].name, + getTypeName(¶ms[i])); return errorWithContextLineNo(BAD_PARAMS, context, 0, NULL); } } diff --git a/src/pebblisp.h b/src/pebblisp.h index a771788..9eb75e6 100644 --- a/src/pebblisp.h +++ b/src/pebblisp.h @@ -77,9 +77,12 @@ Object parseEval(const char* input, struct Environment* env); Object evalList(const Object* obj, struct Environment* env); -Object listEvalLambda(Object* lambda, const Object* remaining, int evalLength, +Object listEvalLambda(Object* lambda, const Object* passedArguments, int evalLength, struct Environment* env); +Object funcyEval(Object* funcy, const Object* passedArguments, int evalLength, + struct Environment* env); + Object simpleFuncEval(Object func, Object arg1, Object arg2, struct Environment* env); Object typeCheck(const char* funcName, Object* params, int length, diff --git a/src/plfunc.c b/src/plfunc.c index 602c1bc..388a20c 100644 --- a/src/plfunc.c +++ b/src/plfunc.c @@ -15,8 +15,14 @@ Object reduce(Object* params, unused int length, struct Environment* env) return simpleFuncEval(func, total, list, env); } + int isFirst = 1; FOR_POINTER_IN_LIST(&list) { + Object oldTotal = total; total = simpleFuncEval(func, total, *POINTER, env); + if (!isFirst) { + cleanObject(&oldTotal); + } + isFirst = 0; } return total; @@ -53,7 +59,7 @@ Object filter(Object* params, unused int length, struct Environment* env) Object cloned = cloneObject(condition); Object first_eval = eval(&cloned, env); Object testee = cloneObject(*POINTER); - Object e = listEvalLambda(&first_eval, &testee, 2, env); + Object e = funcyEval(&first_eval, &testee, 1, env); if (e.number) { nf_addToList(&filtered, testee); // May need to re-clone testee? } diff --git a/src/plfunc.h b/src/plfunc.h index cddb1d2..f389ad5 100644 --- a/src/plfunc.h +++ b/src/plfunc.h @@ -102,7 +102,7 @@ tfn(len, "len", tfn(reduce, "reduce", ({ anyType, expect(isFuncy), anyType, anyType }), - "Performs a simple reduction. Does not currently work with lambdas.\n" + "Performs a simple reduction. Does not currently work with lambdas.\n" // TODO: Still not working "Takes three arguments:\n" " - Values\n" " - A function to apply to each value\n" diff --git a/src/threads.c b/src/threads.c index d89dc5f..3607e76 100644 --- a/src/threads.c +++ b/src/threads.c @@ -55,7 +55,7 @@ void* doAsync(void* args) Object cloned = cloneObject(promise->object); Object first_eval = eval(&cloned, promise->env); - Object e = listEvalLambda(&first_eval, NULL, 1, promise->env); + Object e = funcyEval(&first_eval, NULL, 0, promise->env); promise->object = e; promise->done = 1; diff --git a/src/web.c b/src/web.c index 535105a..ad2c66a 100644 --- a/src/web.c +++ b/src/web.c @@ -101,7 +101,7 @@ answer_to_connection(void* cls, struct MHD_Connection* connection, res.structObject->fields[2] = passwordO; Object route = cloneObject(routes[i].routeAction); - Object result = listEvalLambda(&route, &res, 2, routes[i].env); + Object result = funcyEval(&route, &res, 1, routes[i].env); cleanObject(&res); page = result.string; break;