265 lines
5.6 KiB
C
265 lines
5.6 KiB
C
#include "object.h"
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
#ifndef STANDALONE
|
|
#define printf(...) stringObj(NULL, NULL)
|
|
#endif
|
|
|
|
int listLength(const Object *listObj)
|
|
{
|
|
if(!listObj || listObj->type != TYPE_LIST)
|
|
return -1;
|
|
|
|
Object *t = listObj->list;
|
|
if(t == NULL)
|
|
return 0;
|
|
|
|
int len = 1;
|
|
while(t->forward != NULL) {
|
|
t = t->forward;
|
|
len++;
|
|
}
|
|
return len;
|
|
}
|
|
|
|
Object *itemAt(const Object *listObj, int n)
|
|
{
|
|
if(!listObj || listObj->type != TYPE_LIST)
|
|
return NULL;
|
|
|
|
Object *march = listObj->list;
|
|
for(int i = 0; i < n; i++) {
|
|
march = march->forward;
|
|
|
|
if(march == NULL)
|
|
return NULL;
|
|
}
|
|
return march;
|
|
}
|
|
|
|
// Returns last object in list (->forward == NULL)
|
|
Object *tail(const Object *listObj)
|
|
{
|
|
if(!listObj || listObj->type != TYPE_LIST)
|
|
return NULL;
|
|
|
|
Object *t = listObj->list;
|
|
while(t->forward != NULL) {
|
|
t = t->forward;
|
|
}
|
|
return t;
|
|
}
|
|
|
|
// Adds an object to the end of a list object
|
|
void addToList(Object *dest, const Object src)
|
|
{
|
|
if(!dest || dest->type != TYPE_LIST)
|
|
return;
|
|
|
|
if(dest->list == NULL) {
|
|
dest->list = malloc(sizeof(struct Object));
|
|
*dest->list = src;
|
|
dest->list->forward = NULL;
|
|
return;
|
|
}
|
|
|
|
Object *end = tail(dest);
|
|
end->forward = malloc(sizeof(struct Object));
|
|
*end->forward = src;
|
|
end->forward->forward = NULL;
|
|
}
|
|
|
|
void printErr(const Object *obj)
|
|
{
|
|
#ifdef STANDALONE
|
|
if(!obj || obj->type != TYPE_ERROR)
|
|
return;
|
|
|
|
printf("%s\n", errorText[(int)(obj->err)]);
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
// Puts a string version of the given object into a given string
|
|
char* stringObj(char *dest, const Object *obj)
|
|
{
|
|
if(!dest || !obj)
|
|
return NULL;
|
|
|
|
if(obj->type == TYPE_NUMBER) {
|
|
snprintf(dest, MAX_TOK_LEN, "%d", obj->number);
|
|
} else if(obj->type == TYPE_SYMBOL) {
|
|
snprintf(dest, MAX_TOK_LEN, "%s", obj->name);
|
|
} else if(obj->type == TYPE_BOOL) {
|
|
snprintf(dest, MAX_TOK_LEN, "%s", obj->number ? "T" : "F");
|
|
} else if(obj->type == TYPE_ERROR) {
|
|
snprintf(dest, MAX_TOK_LEN, "E%d", obj->err);
|
|
} else {
|
|
snprintf(dest, MAX_TOK_LEN, "%d", obj->number);
|
|
}
|
|
|
|
return dest;
|
|
}
|
|
|
|
int depth = 0;
|
|
|
|
// Prints the given object
|
|
void printObj(const Object *obj)
|
|
{
|
|
for(int i = 0; i < depth; i++)
|
|
printf(" ");
|
|
depth++;
|
|
|
|
if(obj->type == TYPE_NUMBER) {
|
|
printf("TYPE_NUMBER");
|
|
} else if(obj->type == TYPE_BOOL) {
|
|
printf("TYPE_BOOL");
|
|
} else if(obj->type == TYPE_LIST) {
|
|
printf("TYPE_LIST\n");
|
|
printList(obj);
|
|
depth--;
|
|
return;
|
|
} else if(obj->type == TYPE_FUNC) {
|
|
printf("TYPE_FUNC");
|
|
} else if(obj->type == TYPE_SYMBOL) {
|
|
printf("TYPE_SYMBOL");
|
|
} else if(obj->type == TYPE_LAMBDA) {
|
|
printf("TYPE_LAMBDA Params:\n");
|
|
depth++;
|
|
printObj(&obj->lambda->params);
|
|
for(int i = 1; i < depth; i++)
|
|
printf(" ");
|
|
printf("Lambda Body: \n");
|
|
printObj(&obj->lambda->body);
|
|
} else if(obj->type == TYPE_ERROR) {
|
|
printf("TYPE_ERROR: ");
|
|
} else {
|
|
printf("TYPE_OTHER (as int)");
|
|
}
|
|
depth--;
|
|
char temp[20] = "";
|
|
stringObj(temp, obj);
|
|
printf(": %s\n", temp);
|
|
printErr(obj);
|
|
}
|
|
|
|
void printList(const Object *list)
|
|
{
|
|
const Object *tail = list->list;
|
|
if(tail == NULL) {
|
|
for(int i = 0; i < depth; i++)
|
|
printf(" ");
|
|
printf("EMPTY LIST\n");
|
|
return;
|
|
}
|
|
while(tail != NULL) {
|
|
depth++;
|
|
printObj(tail);
|
|
depth--;
|
|
tail = tail->forward;
|
|
}
|
|
}
|
|
|
|
void cleanObject(Object *target)
|
|
{
|
|
if(target == NULL)
|
|
return;
|
|
|
|
const Type t = target->type;
|
|
if(t == TYPE_LAMBDA) {
|
|
free(target->lambda);
|
|
} else if(t == TYPE_LIST) {
|
|
deleteList(target);
|
|
}
|
|
}
|
|
|
|
// Frees all objects in a list
|
|
void deleteList(const Object *dest)
|
|
{
|
|
if(dest->type != TYPE_LIST) {
|
|
printf("Tried to delete something other than a list\n");
|
|
return;
|
|
}
|
|
|
|
Object *tail = dest->list;
|
|
while(tail != NULL) {
|
|
Object *prevTail = tail;
|
|
tail = tail->forward;
|
|
cleanObject(prevTail);
|
|
free(prevTail);
|
|
}
|
|
}
|
|
|
|
void copyList(Object *dest, const Object *src)
|
|
{
|
|
if(!dest || !src || dest->type != TYPE_LIST || src->type != TYPE_LIST)
|
|
return;
|
|
|
|
deleteList(dest);
|
|
const Object *march = src->list;
|
|
while(march != NULL) {
|
|
addToList(dest, *march);
|
|
march = march->forward;
|
|
}
|
|
}
|
|
|
|
inline Object newObject(Type type)
|
|
{
|
|
Object no;
|
|
no.forward = NULL;
|
|
no.type = type;
|
|
return no;
|
|
}
|
|
|
|
inline Object listObject()
|
|
{
|
|
Object list = newObject(TYPE_LIST);
|
|
list.list = NULL;
|
|
return list;
|
|
}
|
|
|
|
inline Object numberObject(int num)
|
|
{
|
|
Object o = newObject(TYPE_NUMBER);
|
|
o.number = num;
|
|
return o;
|
|
}
|
|
|
|
inline Object symbolObject()
|
|
{
|
|
Object o = newObject(TYPE_SYMBOL);
|
|
return o;
|
|
}
|
|
|
|
inline Object lambdaObject()
|
|
{
|
|
Object o = newObject(TYPE_LAMBDA);
|
|
o.lambda = malloc(sizeof(struct Lambda));
|
|
return o;
|
|
}
|
|
|
|
inline Object constructLambda(const Object *params, const Object *body)
|
|
{
|
|
if(!params || !body)
|
|
return errorObject(NULL_LAMBDA_LIST);
|
|
|
|
if(params->type != TYPE_LIST || body->type != TYPE_LIST)
|
|
return errorObject(LAMBDA_ARGS_NOT_LIST);
|
|
|
|
Object o = lambdaObject();
|
|
o.lambda->params = listObject();
|
|
o.lambda->body = listObject();
|
|
copyList(&o.lambda->params, params);
|
|
copyList(&o.lambda->body, body);
|
|
return o;
|
|
}
|
|
|
|
inline Object errorObject(enum errorCode err)
|
|
{
|
|
Object o = newObject(TYPE_ERROR);
|
|
o.err = err;
|
|
return o;
|
|
}
|