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 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!
|
||||||
|
|
59
src/object.c
59
src/object.c
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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++;
|
||||||
|
|
Loading…
Reference in New Issue