Add TYPE_SLIST.
Not yet stable, but allows manipulation of lists without immediate evaluation.
This commit is contained in:
parent
5261880ebb
commit
55d39431b1
40
src/object.c
40
src/object.c
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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++;
|
||||
|
|
Loading…
Reference in New Issue