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; 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 // Adds an object to the end of a list object
void addToList(Object *dest, const Object src) void addToList(Object *dest, const Object src)
{ {
if(!dest || dest->type != TYPE_LIST) if(!dest || dest->type != TYPE_LIST)
return; return;
if(dest->list == NULL) { if(isEmpty(dest)) {
dest->list = malloc(sizeof(struct Object)); allocObject(&dest->list, src);
*dest->list = src;
dest->list->forward = NULL;
return; return;
} }
Object *end = tail(dest); Object *end = tail(dest);
end->forward = malloc(sizeof(struct Object)); allocObject(&end->forward, src);
*end->forward = src;
end->forward->forward = NULL;
} }
void printErr(const Object *obj) 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) void copyList(Object *dest, const Object *src)
{ {
if(!dest || !src || dest->type != TYPE_LIST || src->type != TYPE_LIST) 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) inline Object newObject(Type type)
{ {
Object no; Object no;
@ -221,6 +291,7 @@ inline Object newObject(Type type)
return no; return no;
} }
// Returns an empty list object
inline Object listObject() inline Object listObject()
{ {
Object list = newObject(TYPE_LIST); Object list = newObject(TYPE_LIST);
@ -235,10 +306,16 @@ inline Object numberObject(int num)
return o; return o;
} }
inline Object boolObject(int b)
{
Object o = newObject(TYPE_BOOL);
o.number = b;
return o;
}
inline Object symbolObject() inline Object symbolObject()
{ {
Object o = newObject(TYPE_SYMBOL); return newObject(TYPE_SYMBOL);
return o;
} }
inline Object lambdaObject() inline Object lambdaObject()

View File

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

View File

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