Add Object helpers (less redundancy). Add new errs

This commit is contained in:
= 2020-05-06 07:12:58 +01:00
parent f2c09c0818
commit 80ca6e1960
3 changed files with 120 additions and 62 deletions

View File

@ -52,23 +52,87 @@ Object *tail(const Object *listObj)
return t;
}
/**
* Checks if a given object is empty
* BOOL, NUMBER, and ERROR types return true only when 0
* LIST, LAMBDA, and FUNC types return true only when NULL
* SYMBOL returns true only when it begins with a nullchar
* Returns false if obj is NULL
*/
inline int isEmpty(const Object *obj)
{
if(obj == NULL)
return 0;
switch(obj->type) {
case TYPE_NUMBER:
case TYPE_BOOL:
return obj->number == 0;
case TYPE_LIST:
return obj->list == NULL;
case TYPE_LAMBDA:
return obj->lambda == NULL;
case TYPE_SYMBOL:
return obj->name[0] == '\0';
case TYPE_FUNC:
return obj->func == NULL;
case TYPE_ERROR:
return obj->err == 0;
default:
return 0;
}
}
void allocObject(Object **spot, const Object src)
{
*spot = malloc(sizeof(struct Object));
**spot = src;
(*spot)->forward = NULL;
}
// Insert `src` into list `dest` before index `ind`
// Adds to the end if the index is too high.
void insertIntoList(Object *dest, int ind, const Object src)
{
// Only work with non-null list types
if(!dest || dest->type != TYPE_LIST || ind < 0)
return;
if(isEmpty(dest)) {
allocObject(&dest->list, src);
return;
}
// TODO Check for off-by-one errors
// ensure pointers connect old and new
Object *march = dest->list;
for(int i = 1; i < ind; i++) {
if(march->forward == NULL) {
allocObject(&march->forward, src);
return;
}
march = march->forward;
}
// Save and re-apply current march->forward
Object *oldForward = march->forward;
allocObject(&march->forward, src);
march->forward->forward = oldForward;
}
// 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;
if(isEmpty(dest)) {
allocObject(&dest->list, src);
return;
}
Object *end = tail(dest);
end->forward = malloc(sizeof(struct Object));
*end->forward = src;
end->forward->forward = NULL;
allocObject(&end->forward, src);
}
void printErr(const Object *obj)
@ -200,6 +264,11 @@ void deleteList(const Object *dest)
}
}
/**
* Copies all items from `src` to `dest`
* Does nothing if either is NULL, or neither are lists
* First deletes all items from `dest`
*/
void copyList(Object *dest, const Object *src)
{
if(!dest || !src || dest->type != TYPE_LIST || src->type != TYPE_LIST)
@ -213,6 +282,7 @@ void copyList(Object *dest, const Object *src)
}
}
// Returns a basic object with NULL forward and the given `type`
inline Object newObject(Type type)
{
Object no;
@ -221,6 +291,7 @@ inline Object newObject(Type type)
return no;
}
// Returns an empty list object
inline Object listObject()
{
Object list = newObject(TYPE_LIST);
@ -235,10 +306,16 @@ inline Object numberObject(int num)
return o;
}
inline Object boolObject(int b)
{
Object o = newObject(TYPE_BOOL);
o.number = b;
return o;
}
inline Object symbolObject()
{
Object o = newObject(TYPE_SYMBOL);
return o;
return newObject(TYPE_SYMBOL);
}
inline Object lambdaObject()

View File

@ -13,7 +13,8 @@ enum errorCode {
NULL_PARSE,
NULL_LAMBDA_LIST,
LAMBDA_ARGS_NOT_LIST,
DID_NOT_FIND_SYMBOL
DID_NOT_FIND_SYMBOL,
UNEXPECTED_FORM
};
#ifdef STANDALONE
@ -25,7 +26,8 @@ enum errorCode {
"NULL_PARSE",
"NULL_LAMBDA_LIST",
"LAMBDA_ARGS_NOT_LIST",
"DID_NOT_FIND_SYMBOL"
"DID_NOT_FIND_SYMBOL",
"UNEXPECTED_FORM"
};
#endif
@ -50,12 +52,12 @@ struct Object {
Object *list;
char name[MAX_TOK_LEN];
Object (*func)(Object, Object);
struct Lambda *lambda; // Maybe better as not a pointer
struct Lambda *lambda; // Maybe better as not a pointer?
enum errorCode err;
};
};
// Maybe better as pointers
// Maybe better as pointers?
struct Lambda {
Object params;
Object body;
@ -66,6 +68,7 @@ void printList(const Object *list);
void printObj(const Object *obj);
void debugObj(const Object *obj);
int isEmpty(const Object *obj);
Object *tail(const Object *listObj);
void addToList(Object *dest, Object src);
void deleteList(const Object *dest);
@ -74,12 +77,15 @@ Object *itemAt(const Object *listObj, int n);
void copyList(Object *dest, const Object *src);
void cleanObject(Object *target);
void allocObject(Object **spot, const Object src);
Object newObject(Type type);
Object listObject();
Object numberObject(int num);
Object lambdaObject();
Object constructLambda(const Object *params, const Object *body);
Object symbolObject();
Object boolObject(int b);
Object numberObject(int num);
Object errorObject(enum errorCode err);
Object constructLambda(const Object *params, const Object *body);
#endif

View File

@ -80,27 +80,26 @@ Result readSeq(struct Slice *tokens)
Object parseAtom(struct Slice *s)
{
Object o;
o.forward = NULL;
if(isDigit(s->text[0])) {
o.type = TYPE_NUMBER;
o.number = 0;
int num = 0;
for(int i = 0; i < s->length; i++) {
o.number *= 10;
o.number += s->text[i] - '0';
num *= 10;
num += s->text[i] - '0';
}
return numberObject(num);
} else if (s->text[0] == 'T' && s->text[1] == '\0') {
o.type = TYPE_BOOL;
o.number = 1;
return boolObject(1);
} else if (s->text[0] == 'F' && s->text[1] == '\0') {
o.type = TYPE_BOOL;
o.number = 0;
return boolObject(0);
} else {
o.type = TYPE_SYMBOL;
Object o = symbolObject();
copySlice(o.name, s);
}
return o;
}
}
Object evalDefArgs(const Object *arg_forms, struct Environment *env)
{
@ -242,12 +241,8 @@ Object eval(const Object *obj, struct Environment *env)
}
}
case TYPE_LAMBDA:
{
Object o;
o.type = TYPE_ERROR;
printf("UNEXPECTED FORM\n");
return o;
}
return errorObject(UNEXPECTED_FORM);
default:
;
}
@ -292,50 +287,33 @@ void printEnv(struct Environment *env)
Object basicOp(Object *obj1, Object *obj2, const char op)
{
Object o;
o.forward = NULL;
o.type = TYPE_NUMBER;
const int n1 = obj1->number;
const int n2 = obj2->number;
switch(op){
case '+':
o.number = n1 + n2;
return o;
return numberObject(n1 + n2);
case '-':
o.number = n1 - n2;
return o;
return numberObject(n1 - n2);
case '*':
o.number = n1 * n2;
return o;
return numberObject(n1 * n2);
case '/':
o.number = n1 / n2;
return o;
}
return numberObject(n1 / n2);
o.type = TYPE_BOOL;
switch(op) {
case '=':
o.number = n1 == n2;
return o;
return boolObject(n1 == n2);
case '>':
o.number = n1 > n2;
return o;
return boolObject(n1 > n2);
case '<':
o.number = n1 < n2;
return o;
return boolObject(n1 < n2);
}
o = *obj1;
return o;
return *obj1;
}
#define bopf(_name, _char) \
Object _name(Object obj1, Object obj2) \
{ \
return basicOp(&obj1, &obj2, _char); \
}
{ return basicOp(&obj1, &obj2, _char); }
bopf(add, '+');
bopf(sub, '-');
@ -405,9 +383,6 @@ Object parseEval(const char *input, struct Environment *env)
}
#endif
Object parsed = parse(tokens).obj;
// printf("PARSEEVAL() PRINTLIST():\n");
// debugObject(&parsed);
// printf("end PARSEEVAL() PRINTLIST():\n\n");
free(tokens);
return eval(&parsed, env);
}