Add TYPE_SLIST.

Not yet stable, but allows manipulation of lists without immediate
evaluation.
This commit is contained in:
Sage Vaillancourt 2021-12-15 14:30:16 -05:00 committed by Sage Vaillancourt
parent 5261880ebb
commit 55d39431b1
3 changed files with 47 additions and 17 deletions

View File

@ -23,7 +23,7 @@
*/
int listLength(const Object *listObj)
{
if(!listObj || listObj->type != TYPE_LIST)
if(!listObj || !isListy(*listObj))
return -1;
int len = 0;
@ -48,7 +48,7 @@ Object len(Object obj1, Object o_ignore, struct Environment *e_ignore)
*/
Object *itemAt(const Object *listObj, int n)
{
if(!listObj || listObj->type != TYPE_LIST)
if(!listObj || !isListy(*listObj))
return NULL;
FOR_POINTER_IN_LIST(listObj) {
@ -67,7 +67,7 @@ Object *itemAt(const Object *listObj, int n)
*/
Object *tail(const Object *listObj)
{
if(!listObj || listObj->type != TYPE_LIST)
if(!listObj || !isListy(*listObj))
return NULL;
Object *tail = NULL;
@ -96,6 +96,7 @@ inline int isEmpty(const Object *obj)
case TYPE_BOOL:
return obj->number == 0;
case TYPE_LIST:
case TYPE_SLIST:
return obj->list == NULL;
case TYPE_LAMBDA:
return obj->lambda == NULL;
@ -139,7 +140,7 @@ void allocObject(Object **spot, const Object src)
*/
void insertIntoList(Object *dest, int ind, const Object src)
{
if(!dest || dest->type != TYPE_LIST)
if(!dest || !isListy(*dest))
return;
// Merely append, when possible
@ -161,13 +162,14 @@ void insertIntoList(Object *dest, int ind, const Object src)
* Replace an Object in a list at a given index with a given Object
* Attempts to clean the replaced Object before adding the new one
* Immediately returns if `list` is NULL or not a list type
*
* @param list The list Object to replace an element of
* @param i The index of the element to replace
* @param src The Object to copy into the list
*/
void replaceListing(Object *list, int i, const Object src)
{
if(!list || list->type != TYPE_LIST)
if(!list || isListy(*list))
return;
Object *replace = itemAt(list, i);
Object *oldForward = replace->forward;
@ -184,7 +186,7 @@ void replaceListing(Object *list, int i, const Object src)
*/
void nf_addToList(Object *dest, const Object src)
{
if(!dest || dest->type != TYPE_LIST)
if(!dest || !isListy(*dest))
return;
if(isEmpty(dest)) {
@ -233,7 +235,7 @@ static const char *errorText[] = {
*/
void stringList(char *dest, const Object *obj)
{
if(!dest || obj->type != TYPE_LIST)
if(!dest || !isListy(*obj))
return;
dest[0] = '(';
@ -282,6 +284,7 @@ char* stringNObj(char *dest, const Object *obj, const size_t len) {
snprintf(dest, len, "`%s`", obj->string);
break;
case TYPE_LIST:
case TYPE_SLIST:
stringList(dest, obj);
break;
case TYPE_ERROR: {
@ -342,6 +345,9 @@ void printType(const Object *obj)
case TYPE_LIST:
printf("TYPE_LIST");
return;
case TYPE_SLIST:
printf("TYPE_SLIST");
return;
case TYPE_FUNC:
printf("TYPE_FUNC");
return;
@ -443,6 +449,7 @@ void cleanObject(Object *target)
target->string = NULL;
break;
case TYPE_LIST:
case TYPE_SLIST:
deleteList(target);
break;
case TYPE_LAMBDA:
@ -494,7 +501,7 @@ void deleteList(Object *dest)
if(!dest)
return;
if(dest->type != TYPE_LIST) {
if(!isListy(*dest)) {
printf("Tried to delete something other than a list\n");
return;
}
@ -515,7 +522,7 @@ void _copyList(Object *dest, const Object *src, int delete)
printd("NULL\n");
return;
}
if(dest->type != TYPE_LIST || src->type != TYPE_LIST) {
if(!isListy(*dest) || !isListy(*src)) {
printd("NOT A LIST\n");
return;
}
@ -524,7 +531,7 @@ void _copyList(Object *dest, const Object *src, int delete)
deleteList(dest);
FOR_POINTER_IN_LIST(src) {
if(POINTER->type == TYPE_LIST) {
if(isListy(*POINTER)) {
nf_addToList(dest, *POINTER);
tail(dest)->list = NULL;
_copyList(tail(dest), POINTER, 0);
@ -592,6 +599,11 @@ inline Object startList(const Object start)
return list;
}
inline int isListy(const Object test)
{
return test.type == TYPE_LIST || test.type == TYPE_SLIST;
}
inline int isStringy(const Object test)
{
return test.type == TYPE_STRING || test.type == TYPE_SYMBOL;
@ -603,6 +615,7 @@ inline int isValidType(const Object test)
case TYPE_NUMBER:
case TYPE_BOOL:
case TYPE_LIST:
case TYPE_SLIST:
case TYPE_FUNC:
case TYPE_SYMBOL:
case TYPE_LAMBDA:
@ -637,6 +650,7 @@ inline Object cloneList(const Object src)
{
Object list = listObject();
copyList(&list, &src);
list.type = src.type;
return list;
}
@ -649,6 +663,7 @@ inline Object cloneOther(const Object src) {
inline Object cloneObject(const Object src)
{
switch(src.type) {
case TYPE_SLIST:
case TYPE_LIST:
return cloneList(src);
case TYPE_LAMBDA:
@ -773,11 +788,10 @@ inline enum errorCode getErrorCode(const Object obj)
#ifndef SIMPLE_ERRORS
inline void errorAddContext(Object *o, const char* context)
{
printf("o: %p\n", o);
//printf("o: %p\n", o);
//printf("o->error: %s\n", o->error);
printf("o->error->context: %s\n", o->error->context);
o->error->context = calloc(sizeof(char), RESULT_LENGTH);
printf("context: %p\n", context);
//printf("context: %p\n", context);
strncpy(o->error->context, context, RESULT_LENGTH);
}

View File

@ -8,7 +8,7 @@
#define RESULT_LENGTH 128
#define FOR_POINTER_IN_LIST(_list) \
if(_list && _list->type == TYPE_LIST) \
if(_list && isListy(*_list)) \
for(Object *_element = _list->list; \
_element != NULL;\
_element = _element->forward)
@ -60,6 +60,7 @@ typedef enum Type {
TYPE_NUMBER,
TYPE_BOOL,
TYPE_LIST,
TYPE_SLIST,
TYPE_FUNC,
TYPE_SYMBOL,
TYPE_LAMBDA,
@ -132,6 +133,7 @@ void printAndClean(Object *target);
void allocObject(Object **spot, const Object src);
void appendList(Object *dest, const Object *src);
int isListy(const Object test);
int isStringy(const Object test);
int isValidType(const Object test);
int isError(const Object obj, const enum errorCode err);

View File

@ -309,6 +309,12 @@ Object eval(const Object *obj, struct Environment *env)
case TYPE_SYMBOL:
return fetchFromEnvironment(obj->string, env);
case TYPE_SLIST: {
Object o = cloneObject(*obj);
o.type = TYPE_LIST;
return o;
}
case TYPE_LIST:
return evalList(obj, env);
@ -630,7 +636,11 @@ Result parse(struct Slice *slices)
struct Slice *token = slices;
if(token && token->text) {
struct Slice *rest = &slices[1];
if(token->text[0] == '(') {
if(token->text[0] == '\'' && token->text[1] == '(') {
Result r = readSeq(&slices[2]);
r.obj.type = TYPE_SLIST;
return r;
} else if(token->text[0] == '(') {
// todo check for null rest
return readSeq(rest);
} else { // todo error on missing close paren
@ -781,8 +791,12 @@ Object parseEval(const char *input, struct Environment *env)
tok = &tok[i + 1];
i = -1;
}
obj = eval(&parsed, env);
cleanObject(&parsed);
if (parsed.type == TYPE_SLIST) {
obj = parsed;
} else {
obj = eval(&parsed, env);
cleanObject(&parsed);
}
}
i++;