Reference count LAMBDAS.

Remove more unused code/checks.
Simplify evalList (though it could use more work).
This commit is contained in:
Sage Vaillancourt 2022-03-26 19:51:52 -04:00
parent 03920147d4
commit 158c21f441
5 changed files with 31 additions and 104 deletions

View File

@ -38,8 +38,6 @@ void deleteEnv(struct Environment* e);
struct Environment defaultEnv(); struct Environment defaultEnv();
struct StructDef getStructDef(struct Environment* env, const char* name);
int getStructIndex(struct Environment* env, const char* name); int getStructIndex(struct Environment* env, const char* name);
/// Needs to be freed! /// Needs to be freed!

View File

@ -59,9 +59,6 @@ Object* itemAt(const Object* listObj, int n)
} }
FOR_POINTER_IN_LIST(listObj) { FOR_POINTER_IN_LIST(listObj) {
if (POINTER == NULL) {
return NULL;
}
if (n-- == 0) { if (n-- == 0) {
return POINTER; return POINTER;
} }
@ -179,7 +176,6 @@ void nf_addToList(Object* dest, const Object src)
static const char* errorText[] = {"MISMATCHED_PARENS", static const char* errorText[] = {"MISMATCHED_PARENS",
"NULL_ENV", "NULL_ENV",
"EMPTY_ENV", "EMPTY_ENV",
"BUILT_IN_NOT_FOUND",
"NULL_PARSE", "NULL_PARSE",
"NULL_LAMBDA_LIST", "NULL_LAMBDA_LIST",
"NULL_MAP_ARGS", "NULL_MAP_ARGS",
@ -189,7 +185,6 @@ static const char* errorText[] = {"MISMATCHED_PARENS",
"LISTS_NOT_SAME_SIZE", "LISTS_NOT_SAME_SIZE",
"BAD_NUMBER", "BAD_NUMBER",
"UNSUPPORTED_NUMBER_TYPE", "UNSUPPORTED_NUMBER_TYPE",
"NOT_A_SYMBOL",
"ONLY_ONE_ARGUMENT", "ONLY_ONE_ARGUMENT",
"NOT_A_LIST", "NOT_A_LIST",
"SCRIPT_NOT_FOUND", "SCRIPT_NOT_FOUND",
@ -279,9 +274,6 @@ int stringStruct(char* dest, const Object* obj)
int stringNObj(char* dest, const Object* obj, const size_t len) int stringNObj(char* dest, const Object* obj, const size_t len)
{ {
const char* initial = dest; const char* initial = dest;
if (!dest || !obj) {
return 0;
}
switch (obj->type) { switch (obj->type) {
case TYPE_NUMBER: case TYPE_NUMBER:
@ -396,8 +388,6 @@ void printType(const Object* obj)
} }
} }
void nestedPrintList(const Object* list, int newline);
void _printObj(const Object* obj, int newline) void _printObj(const Object* obj, int newline)
{ {
#ifdef DEBUG #ifdef DEBUG
@ -440,29 +430,12 @@ inline void printObj(const Object* obj)
_printObj(obj, 1); _printObj(obj, 1);
} }
void nestedPrintList(const Object* list, int newline)
{
printf("(");
if (list && isListy(*list)) {
FOR_POINTER_IN_LIST(list) {
printf(" ");
_printObj(POINTER, 0);
}
}
printf(" )");
if (newline) {
printf("\n");
}
}
#endif #endif
/** /**
* Performs appropriate free() on a given Object and NULLs its ->forward * Performs appropriate free() on a given Object and NULLs its ->forward
* Returns immediately if param is NULL
* *
* Strings: The Object's ->string is freed and NULLed * Strings: The Object's ->string is freed
* Lists: deleteList() is called on the Object (may recurse) * Lists: deleteList() is called on the Object (may recurse)
* Lambdas: The body and params are cleaned, and the lambda itself is freed * Lambdas: The body and params are cleaned, and the lambda itself is freed
* *
@ -470,24 +443,22 @@ void nestedPrintList(const Object* list, int newline)
*/ */
void cleanObject(Object* target) void cleanObject(Object* target)
{ {
if (target == NULL) {
return;
}
switch (target->type) { switch (target->type) {
case TYPE_STRING: case TYPE_STRING:
case TYPE_SYMBOL: case TYPE_SYMBOL:
free(target->string); free(target->string);
target->string = NULL;
break; break;
case TYPE_LIST: case TYPE_LIST:
case TYPE_SLIST: case TYPE_SLIST:
deleteList(target); deleteList(target);
break; break;
case TYPE_LAMBDA: case TYPE_LAMBDA:
cleanObject(&target->lambda->params); target->lambda->refs -= 1;
cleanObject(&target->lambda->body); if (!target->lambda->refs) {
free(target->lambda); cleanObject(&target->lambda->params);
cleanObject(&target->lambda->body);
free(target->lambda);
}
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 < global()->structDefs[target->structObject->definition].fieldCount; i++) {
@ -495,14 +466,12 @@ void cleanObject(Object* target)
} }
free(target->structObject->fields); free(target->structObject->fields);
free(target->structObject); free(target->structObject);
target->structObject = NULL;
break; break;
case TYPE_ERROR: case TYPE_ERROR:
#ifndef SIMPLE_ERRORS #ifndef SIMPLE_ERRORS
free(target->error->plContext); free(target->error->plContext);
free(target->error->context); free(target->error->context);
free(target->error); free(target->error);
target->error = NULL;
#endif #endif
break; break;
case TYPE_OTHER: case TYPE_OTHER:
@ -515,8 +484,6 @@ void cleanObject(Object* target)
case TYPE_FUNC: case TYPE_FUNC:
break; break;
} }
target->forward = NULL;
} }
/** /**
@ -553,18 +520,10 @@ void deleteList(Object* dest)
cleanObject(prevMarch); cleanObject(prevMarch);
free(prevMarch); free(prevMarch);
} }
dest->list = NULL;
} }
void _copyList(Object* dest, const Object* src, int delete) void _copyList(Object* dest, const Object* src, int delete)
{ {
if (!dest || !src) { printd("NULL\n");
return;
}
if (!isListy(*dest) || !isListy(*src)) { printd("NOT A LIST\n");
return;
}
if (delete) { if (delete) {
deleteList(dest); deleteList(dest);
} }
@ -684,7 +643,8 @@ inline int isValidType(const Object test)
*/ */
inline Object cloneLambda(const Object old) inline Object cloneLambda(const Object old)
{ {
return constructLambda(&old.lambda->params, &old.lambda->body, NULL); old.lambda->refs += 1;
return old;
} }
Object cloneString(Object obj) Object cloneString(Object obj)
@ -796,6 +756,7 @@ inline Object constructLambda(const Object* params, const Object* body, struct E
o.lambda = malloc(sizeof(struct Lambda)); o.lambda = malloc(sizeof(struct Lambda));
o.lambda->params = listObject(); o.lambda->params = listObject();
o.lambda->body = listObject(); o.lambda->body = listObject();
o.lambda->refs = 1;
copyList(&o.lambda->params, params); copyList(&o.lambda->params, params);
copyList(&o.lambda->body, body); copyList(&o.lambda->body, body);

View File

@ -44,7 +44,6 @@ enum errorCode {
MISMATCHED_PARENS, MISMATCHED_PARENS,
NULL_ENV, NULL_ENV,
EMPTY_ENV, EMPTY_ENV,
BUILT_IN_NOT_FOUND,
NULL_PARSE, NULL_PARSE,
NULL_LAMBDA_LIST, NULL_LAMBDA_LIST,
NULL_MAP_ARGS, NULL_MAP_ARGS,
@ -54,7 +53,6 @@ enum errorCode {
LISTS_NOT_SAME_SIZE, LISTS_NOT_SAME_SIZE,
BAD_NUMBER, BAD_NUMBER,
UNSUPPORTED_NUMBER_TYPE, UNSUPPORTED_NUMBER_TYPE,
NOT_A_SYMBOL,
ONLY_ONE_ARGUMENT, ONLY_ONE_ARGUMENT,
NOT_A_LIST, NOT_A_LIST,
SCRIPT_NOT_FOUND, SCRIPT_NOT_FOUND,
@ -120,11 +118,11 @@ struct StructDef {
struct StructObject { struct StructObject {
int definition; int definition;
//struct StructDef *definition;
struct Object* fields; // Order should match that in the definition. struct Object* fields; // Order should match that in the definition.
}; };
struct Lambda { struct Lambda {
int refs;
Object params; Object params;
Object body; Object body;
}; };

View File

@ -39,17 +39,6 @@ Object evalDefArgs(const Object* symbol, const Object* value,
{ {
const char* name = symbol->string; const char* name = symbol->string;
// Handles multi-definitions
if (bothAre(TYPE_LIST, symbol, value) &&
listLength(symbol) == listLength(value)) {
FOR_POINTERS_IN_LISTS(symbol, value) {
Object finalValue = eval(P2, env);
addToEnv(env, P1->string, finalValue);
cleanObject(&finalValue);
}
return cloneObject(*symbol);
}
Object finalValue = eval(value, env); Object finalValue = eval(value, env);
addToEnv(env, name, finalValue); addToEnv(env, name, finalValue);
@ -87,9 +76,7 @@ Object evalStructArgs(const Object* symbol, const Object* fields, struct Environ
} }
} }
while (env->outer) { env = global();
env = env->outer;
}
env->structDefs[env->structCount] = def; env->structDefs[env->structCount] = def;
env->structCount += 1; env->structCount += 1;
@ -157,12 +144,9 @@ Object evalMapArgs(const Object* argForms, struct Environment* env)
} }
Object evalBuiltIns(const Object* first, const Object* rest, Object evalBuiltIns(const Object* first, const Object* rest,
struct Environment* env) struct Environment* env, int* found)
{ {
if (first->type != TYPE_SYMBOL) { *found = 1;
return errorObject(NOT_A_SYMBOL);
}
if (strcmp(first->string, "def") == 0) { if (strcmp(first->string, "def") == 0) {
return evalDefArgs(rest, rest->forward, env); return evalDefArgs(rest, rest->forward, env);
#ifndef LOW_MEM #ifndef LOW_MEM
@ -182,7 +166,8 @@ Object evalBuiltIns(const Object* first, const Object* rest,
return evalStructArgs(rest, rest->forward, env); return evalStructArgs(rest, rest->forward, env);
} }
return errorObject(BUILT_IN_NOT_FOUND); *found = 0;
return *first;
} }
/** /**
@ -296,37 +281,28 @@ Object evalList(const Object* obj, struct Environment* env)
} }
Object* first_form = obj->list; Object* first_form = obj->list;
{ // Try to eval built-ins if (first_form->type == TYPE_SYMBOL) {
Object builtIn = evalBuiltIns(first_form, first_form->forward, env); int found;
Object builtIn = evalBuiltIns(first_form, first_form->forward, env, &found);
if (!isError(builtIn, BUILT_IN_NOT_FOUND) && if (found) {
!isError(builtIn, NOT_A_SYMBOL)) {
return builtIn; return builtIn;
} }
cleanObject(&builtIn);
}
int def = -1;
if (first_form->type == TYPE_SYMBOL) {
struct Environment* outerEnv = global(); struct Environment* outerEnv = global();
for (int i = 0; i < outerEnv->structCount; i++) { for (int i = 0; i < outerEnv->structCount; i++) {
if (strcmp(first_form->string, outerEnv->structDefs[i].name) == 0) { if (strcmp(first_form->string, outerEnv->structDefs[i].name) == 0) {
def = i; Object structo = structObject(i);
break; int s = 0;
FOR_POINTER_IN_LIST(obj) {
if (s != 0) { // Skip the field name
structo.structObject->fields[s - 1] = eval(POINTER, env);
}
s++;
}
return structo;
} }
} }
} }
if (def >= 0) {
Object structo = structObject(def);
int i = 0;
FOR_POINTER_IN_LIST(obj) {
if (i != 0) {
structo.structObject->fields[i - 1] = eval(POINTER, env);
}
i++;
}
return structo;
}
// Evaluate the list based on the first element's type // Evaluate the list based on the first element's type
Object first_eval = eval(first_form, env); Object first_eval = eval(first_form, env);
@ -338,7 +314,7 @@ Object evalList(const Object* obj, struct Environment* env)
case TYPE_LAMBDA: case TYPE_LAMBDA:
return listEvalLambda(&first_eval, first_form->forward, env); return listEvalLambda(&first_eval, first_form->forward, env);
default: { // Return list with each element evaluated default: { // Return list with each element evaluated
Object list = listObject(); Object list = listObject();
int i = 0; int i = 0;
nf_addToList(&list, first_eval); nf_addToList(&list, first_eval);
@ -597,7 +573,7 @@ Object parseEval(const char* input, struct Environment* env)
cleanObject(&obj); cleanObject(&obj);
Object parsed = parse(tok).obj; Object parsed = parse(tok).obj;
if (parsed.type == TYPE_ERROR) { if (parsed.type == TYPE_ERROR) {
obj = parsed; // TODO Check necessity obj = parsed; // TODO Check necessity
obj.error->plContext = malloc(sizeof(struct Slice)); obj.error->plContext = malloc(sizeof(struct Slice));
*obj.error->plContext = *lastOpen; *obj.error->plContext = *lastOpen;
break; break;
@ -749,10 +725,6 @@ int main(int argc, const char* argv[])
action.sa_sigaction = handler; action.sa_sigaction = handler;
sigaction(SIGSEGV, &action, NULL); sigaction(SIGSEGV, &action, NULL);
// struct Environment* e = &env;
// e += 10000;
// printEnv(e);
readFile(SCRIPTDIR "/lib.pbl", &env); readFile(SCRIPTDIR "/lib.pbl", &env);
if (argc >= 2) { if (argc >= 2) {
FILE* file = fopen(argv[1], "r"); FILE* file = fopen(argv[1], "r");

View File

@ -65,8 +65,6 @@ struct Slice* nf_tokenize(const char* input, struct Error* err)
int parens = 0; int parens = 0;
while (input[i] != '\0') { while (input[i] != '\0') {
int l = 1; int l = 1;
// printd("input: '%c'\n", input[i]);
if (isWhitespace(input[i]) || input[i] == ';') { if (isWhitespace(input[i]) || input[i] == ';') {
if (input[i] == '\n') { if (input[i] == '\n') {
lineNumber++; lineNumber++;