pebblisp/src/object.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;
}