Reference count LAMBDAS.
Remove more unused code/checks. Simplify evalList (though it could use more work).
This commit is contained in:
parent
03920147d4
commit
158c21f441
|
@ -38,8 +38,6 @@ void deleteEnv(struct Environment* e);
|
|||
|
||||
struct Environment defaultEnv();
|
||||
|
||||
struct StructDef getStructDef(struct Environment* env, const char* name);
|
||||
|
||||
int getStructIndex(struct Environment* env, const char* name);
|
||||
|
||||
/// Needs to be freed!
|
||||
|
|
59
src/object.c
59
src/object.c
|
@ -59,9 +59,6 @@ Object* itemAt(const Object* listObj, int n)
|
|||
}
|
||||
|
||||
FOR_POINTER_IN_LIST(listObj) {
|
||||
if (POINTER == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (n-- == 0) {
|
||||
return POINTER;
|
||||
}
|
||||
|
@ -179,7 +176,6 @@ void nf_addToList(Object* dest, const Object src)
|
|||
static const char* errorText[] = {"MISMATCHED_PARENS",
|
||||
"NULL_ENV",
|
||||
"EMPTY_ENV",
|
||||
"BUILT_IN_NOT_FOUND",
|
||||
"NULL_PARSE",
|
||||
"NULL_LAMBDA_LIST",
|
||||
"NULL_MAP_ARGS",
|
||||
|
@ -189,7 +185,6 @@ static const char* errorText[] = {"MISMATCHED_PARENS",
|
|||
"LISTS_NOT_SAME_SIZE",
|
||||
"BAD_NUMBER",
|
||||
"UNSUPPORTED_NUMBER_TYPE",
|
||||
"NOT_A_SYMBOL",
|
||||
"ONLY_ONE_ARGUMENT",
|
||||
"NOT_A_LIST",
|
||||
"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)
|
||||
{
|
||||
const char* initial = dest;
|
||||
if (!dest || !obj) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (obj->type) {
|
||||
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)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
|
@ -440,29 +430,12 @@ inline void printObj(const Object* obj)
|
|||
_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
|
||||
|
||||
/**
|
||||
* 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)
|
||||
* 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)
|
||||
{
|
||||
if (target == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (target->type) {
|
||||
case TYPE_STRING:
|
||||
case TYPE_SYMBOL:
|
||||
free(target->string);
|
||||
target->string = NULL;
|
||||
break;
|
||||
case TYPE_LIST:
|
||||
case TYPE_SLIST:
|
||||
deleteList(target);
|
||||
break;
|
||||
case TYPE_LAMBDA:
|
||||
cleanObject(&target->lambda->params);
|
||||
cleanObject(&target->lambda->body);
|
||||
free(target->lambda);
|
||||
target->lambda->refs -= 1;
|
||||
if (!target->lambda->refs) {
|
||||
cleanObject(&target->lambda->params);
|
||||
cleanObject(&target->lambda->body);
|
||||
free(target->lambda);
|
||||
}
|
||||
break;
|
||||
case TYPE_STRUCT:
|
||||
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);
|
||||
target->structObject = NULL;
|
||||
break;
|
||||
case TYPE_ERROR:
|
||||
#ifndef SIMPLE_ERRORS
|
||||
free(target->error->plContext);
|
||||
free(target->error->context);
|
||||
free(target->error);
|
||||
target->error = NULL;
|
||||
#endif
|
||||
break;
|
||||
case TYPE_OTHER:
|
||||
|
@ -515,8 +484,6 @@ void cleanObject(Object* target)
|
|||
case TYPE_FUNC:
|
||||
break;
|
||||
}
|
||||
|
||||
target->forward = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -553,18 +520,10 @@ void deleteList(Object* dest)
|
|||
cleanObject(prevMarch);
|
||||
free(prevMarch);
|
||||
}
|
||||
dest->list = NULL;
|
||||
}
|
||||
|
||||
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) {
|
||||
deleteList(dest);
|
||||
}
|
||||
|
@ -684,7 +643,8 @@ inline int isValidType(const Object test)
|
|||
*/
|
||||
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)
|
||||
|
@ -796,6 +756,7 @@ inline Object constructLambda(const Object* params, const Object* body, struct E
|
|||
o.lambda = malloc(sizeof(struct Lambda));
|
||||
o.lambda->params = listObject();
|
||||
o.lambda->body = listObject();
|
||||
o.lambda->refs = 1;
|
||||
copyList(&o.lambda->params, params);
|
||||
copyList(&o.lambda->body, body);
|
||||
|
||||
|
|
|
@ -44,7 +44,6 @@ enum errorCode {
|
|||
MISMATCHED_PARENS,
|
||||
NULL_ENV,
|
||||
EMPTY_ENV,
|
||||
BUILT_IN_NOT_FOUND,
|
||||
NULL_PARSE,
|
||||
NULL_LAMBDA_LIST,
|
||||
NULL_MAP_ARGS,
|
||||
|
@ -54,7 +53,6 @@ enum errorCode {
|
|||
LISTS_NOT_SAME_SIZE,
|
||||
BAD_NUMBER,
|
||||
UNSUPPORTED_NUMBER_TYPE,
|
||||
NOT_A_SYMBOL,
|
||||
ONLY_ONE_ARGUMENT,
|
||||
NOT_A_LIST,
|
||||
SCRIPT_NOT_FOUND,
|
||||
|
@ -120,11 +118,11 @@ struct StructDef {
|
|||
|
||||
struct StructObject {
|
||||
int definition;
|
||||
//struct StructDef *definition;
|
||||
struct Object* fields; // Order should match that in the definition.
|
||||
};
|
||||
|
||||
struct Lambda {
|
||||
int refs;
|
||||
Object params;
|
||||
Object body;
|
||||
};
|
||||
|
|
|
@ -39,17 +39,6 @@ Object evalDefArgs(const Object* symbol, const Object* value,
|
|||
{
|
||||
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);
|
||||
|
||||
addToEnv(env, name, finalValue);
|
||||
|
@ -87,9 +76,7 @@ Object evalStructArgs(const Object* symbol, const Object* fields, struct Environ
|
|||
}
|
||||
}
|
||||
|
||||
while (env->outer) {
|
||||
env = env->outer;
|
||||
}
|
||||
env = global();
|
||||
|
||||
env->structDefs[env->structCount] = def;
|
||||
env->structCount += 1;
|
||||
|
@ -157,12 +144,9 @@ Object evalMapArgs(const Object* argForms, struct Environment* env)
|
|||
}
|
||||
|
||||
Object evalBuiltIns(const Object* first, const Object* rest,
|
||||
struct Environment* env)
|
||||
struct Environment* env, int* found)
|
||||
{
|
||||
if (first->type != TYPE_SYMBOL) {
|
||||
return errorObject(NOT_A_SYMBOL);
|
||||
}
|
||||
|
||||
*found = 1;
|
||||
if (strcmp(first->string, "def") == 0) {
|
||||
return evalDefArgs(rest, rest->forward, env);
|
||||
#ifndef LOW_MEM
|
||||
|
@ -182,7 +166,8 @@ Object evalBuiltIns(const Object* first, const Object* rest,
|
|||
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;
|
||||
{ // Try to eval built-ins
|
||||
Object builtIn = evalBuiltIns(first_form, first_form->forward, env);
|
||||
|
||||
if (!isError(builtIn, BUILT_IN_NOT_FOUND) &&
|
||||
!isError(builtIn, NOT_A_SYMBOL)) {
|
||||
if (first_form->type == TYPE_SYMBOL) {
|
||||
int found;
|
||||
Object builtIn = evalBuiltIns(first_form, first_form->forward, env, &found);
|
||||
if (found) {
|
||||
return builtIn;
|
||||
}
|
||||
cleanObject(&builtIn);
|
||||
}
|
||||
|
||||
int def = -1;
|
||||
if (first_form->type == TYPE_SYMBOL) {
|
||||
struct Environment* outerEnv = global();
|
||||
for (int i = 0; i < outerEnv->structCount; i++) {
|
||||
if (strcmp(first_form->string, outerEnv->structDefs[i].name) == 0) {
|
||||
def = i;
|
||||
break;
|
||||
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++;
|
||||
}
|
||||
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
|
||||
Object first_eval = eval(first_form, env);
|
||||
|
@ -338,7 +314,7 @@ Object evalList(const Object* obj, struct Environment* env)
|
|||
case TYPE_LAMBDA:
|
||||
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();
|
||||
int i = 0;
|
||||
nf_addToList(&list, first_eval);
|
||||
|
@ -597,7 +573,7 @@ Object parseEval(const char* input, struct Environment* env)
|
|||
cleanObject(&obj);
|
||||
Object parsed = parse(tok).obj;
|
||||
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 = *lastOpen;
|
||||
break;
|
||||
|
@ -749,10 +725,6 @@ int main(int argc, const char* argv[])
|
|||
action.sa_sigaction = handler;
|
||||
sigaction(SIGSEGV, &action, NULL);
|
||||
|
||||
// struct Environment* e = &env;
|
||||
// e += 10000;
|
||||
// printEnv(e);
|
||||
|
||||
readFile(SCRIPTDIR "/lib.pbl", &env);
|
||||
if (argc >= 2) {
|
||||
FILE* file = fopen(argv[1], "r");
|
||||
|
|
|
@ -65,8 +65,6 @@ struct Slice* nf_tokenize(const char* input, struct Error* err)
|
|||
int parens = 0;
|
||||
while (input[i] != '\0') {
|
||||
int l = 1;
|
||||
// printd("input: '%c'\n", input[i]);
|
||||
|
||||
if (isWhitespace(input[i]) || input[i] == ';') {
|
||||
if (input[i] == '\n') {
|
||||
lineNumber++;
|
||||
|
|
Loading…
Reference in New Issue