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)
|
int listLength(const Object *listObj)
|
||||||
{
|
{
|
||||||
if(!listObj || listObj->type != TYPE_LIST)
|
if(!listObj || !isListy(*listObj))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
int len = 0;
|
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)
|
Object *itemAt(const Object *listObj, int n)
|
||||||
{
|
{
|
||||||
if(!listObj || listObj->type != TYPE_LIST)
|
if(!listObj || !isListy(*listObj))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
FOR_POINTER_IN_LIST(listObj) {
|
FOR_POINTER_IN_LIST(listObj) {
|
||||||
|
@ -67,7 +67,7 @@ Object *itemAt(const Object *listObj, int n)
|
||||||
*/
|
*/
|
||||||
Object *tail(const Object *listObj)
|
Object *tail(const Object *listObj)
|
||||||
{
|
{
|
||||||
if(!listObj || listObj->type != TYPE_LIST)
|
if(!listObj || !isListy(*listObj))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
Object *tail = NULL;
|
Object *tail = NULL;
|
||||||
|
@ -96,6 +96,7 @@ inline int isEmpty(const Object *obj)
|
||||||
case TYPE_BOOL:
|
case TYPE_BOOL:
|
||||||
return obj->number == 0;
|
return obj->number == 0;
|
||||||
case TYPE_LIST:
|
case TYPE_LIST:
|
||||||
|
case TYPE_SLIST:
|
||||||
return obj->list == NULL;
|
return obj->list == NULL;
|
||||||
case TYPE_LAMBDA:
|
case TYPE_LAMBDA:
|
||||||
return obj->lambda == NULL;
|
return obj->lambda == NULL;
|
||||||
|
@ -139,7 +140,7 @@ void allocObject(Object **spot, const Object src)
|
||||||
*/
|
*/
|
||||||
void insertIntoList(Object *dest, int ind, const Object src)
|
void insertIntoList(Object *dest, int ind, const Object src)
|
||||||
{
|
{
|
||||||
if(!dest || dest->type != TYPE_LIST)
|
if(!dest || !isListy(*dest))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Merely append, when possible
|
// 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
|
* 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
|
* Attempts to clean the replaced Object before adding the new one
|
||||||
* Immediately returns if `list` is NULL or not a list type
|
* Immediately returns if `list` is NULL or not a list type
|
||||||
|
*
|
||||||
* @param list The list Object to replace an element of
|
* @param list The list Object to replace an element of
|
||||||
* @param i The index of the element to replace
|
* @param i The index of the element to replace
|
||||||
* @param src The Object to copy into the list
|
* @param src The Object to copy into the list
|
||||||
*/
|
*/
|
||||||
void replaceListing(Object *list, int i, const Object src)
|
void replaceListing(Object *list, int i, const Object src)
|
||||||
{
|
{
|
||||||
if(!list || list->type != TYPE_LIST)
|
if(!list || isListy(*list))
|
||||||
return;
|
return;
|
||||||
Object *replace = itemAt(list, i);
|
Object *replace = itemAt(list, i);
|
||||||
Object *oldForward = replace->forward;
|
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)
|
void nf_addToList(Object *dest, const Object src)
|
||||||
{
|
{
|
||||||
if(!dest || dest->type != TYPE_LIST)
|
if(!dest || !isListy(*dest))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(isEmpty(dest)) {
|
if(isEmpty(dest)) {
|
||||||
|
@ -233,7 +235,7 @@ static const char *errorText[] = {
|
||||||
*/
|
*/
|
||||||
void stringList(char *dest, const Object *obj)
|
void stringList(char *dest, const Object *obj)
|
||||||
{
|
{
|
||||||
if(!dest || obj->type != TYPE_LIST)
|
if(!dest || !isListy(*obj))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dest[0] = '(';
|
dest[0] = '(';
|
||||||
|
@ -282,6 +284,7 @@ char* stringNObj(char *dest, const Object *obj, const size_t len) {
|
||||||
snprintf(dest, len, "`%s`", obj->string);
|
snprintf(dest, len, "`%s`", obj->string);
|
||||||
break;
|
break;
|
||||||
case TYPE_LIST:
|
case TYPE_LIST:
|
||||||
|
case TYPE_SLIST:
|
||||||
stringList(dest, obj);
|
stringList(dest, obj);
|
||||||
break;
|
break;
|
||||||
case TYPE_ERROR: {
|
case TYPE_ERROR: {
|
||||||
|
@ -342,6 +345,9 @@ void printType(const Object *obj)
|
||||||
case TYPE_LIST:
|
case TYPE_LIST:
|
||||||
printf("TYPE_LIST");
|
printf("TYPE_LIST");
|
||||||
return;
|
return;
|
||||||
|
case TYPE_SLIST:
|
||||||
|
printf("TYPE_SLIST");
|
||||||
|
return;
|
||||||
case TYPE_FUNC:
|
case TYPE_FUNC:
|
||||||
printf("TYPE_FUNC");
|
printf("TYPE_FUNC");
|
||||||
return;
|
return;
|
||||||
|
@ -443,6 +449,7 @@ void cleanObject(Object *target)
|
||||||
target->string = NULL;
|
target->string = NULL;
|
||||||
break;
|
break;
|
||||||
case TYPE_LIST:
|
case TYPE_LIST:
|
||||||
|
case TYPE_SLIST:
|
||||||
deleteList(target);
|
deleteList(target);
|
||||||
break;
|
break;
|
||||||
case TYPE_LAMBDA:
|
case TYPE_LAMBDA:
|
||||||
|
@ -494,7 +501,7 @@ void deleteList(Object *dest)
|
||||||
if(!dest)
|
if(!dest)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(dest->type != TYPE_LIST) {
|
if(!isListy(*dest)) {
|
||||||
printf("Tried to delete something other than a list\n");
|
printf("Tried to delete something other than a list\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -515,7 +522,7 @@ void _copyList(Object *dest, const Object *src, int delete)
|
||||||
printd("NULL\n");
|
printd("NULL\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(dest->type != TYPE_LIST || src->type != TYPE_LIST) {
|
if(!isListy(*dest) || !isListy(*src)) {
|
||||||
printd("NOT A LIST\n");
|
printd("NOT A LIST\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -524,7 +531,7 @@ void _copyList(Object *dest, const Object *src, int delete)
|
||||||
deleteList(dest);
|
deleteList(dest);
|
||||||
|
|
||||||
FOR_POINTER_IN_LIST(src) {
|
FOR_POINTER_IN_LIST(src) {
|
||||||
if(POINTER->type == TYPE_LIST) {
|
if(isListy(*POINTER)) {
|
||||||
nf_addToList(dest, *POINTER);
|
nf_addToList(dest, *POINTER);
|
||||||
tail(dest)->list = NULL;
|
tail(dest)->list = NULL;
|
||||||
_copyList(tail(dest), POINTER, 0);
|
_copyList(tail(dest), POINTER, 0);
|
||||||
|
@ -592,6 +599,11 @@ inline Object startList(const Object start)
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline int isListy(const Object test)
|
||||||
|
{
|
||||||
|
return test.type == TYPE_LIST || test.type == TYPE_SLIST;
|
||||||
|
}
|
||||||
|
|
||||||
inline int isStringy(const Object test)
|
inline int isStringy(const Object test)
|
||||||
{
|
{
|
||||||
return test.type == TYPE_STRING || test.type == TYPE_SYMBOL;
|
return test.type == TYPE_STRING || test.type == TYPE_SYMBOL;
|
||||||
|
@ -603,6 +615,7 @@ inline int isValidType(const Object test)
|
||||||
case TYPE_NUMBER:
|
case TYPE_NUMBER:
|
||||||
case TYPE_BOOL:
|
case TYPE_BOOL:
|
||||||
case TYPE_LIST:
|
case TYPE_LIST:
|
||||||
|
case TYPE_SLIST:
|
||||||
case TYPE_FUNC:
|
case TYPE_FUNC:
|
||||||
case TYPE_SYMBOL:
|
case TYPE_SYMBOL:
|
||||||
case TYPE_LAMBDA:
|
case TYPE_LAMBDA:
|
||||||
|
@ -637,6 +650,7 @@ inline Object cloneList(const Object src)
|
||||||
{
|
{
|
||||||
Object list = listObject();
|
Object list = listObject();
|
||||||
copyList(&list, &src);
|
copyList(&list, &src);
|
||||||
|
list.type = src.type;
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -649,6 +663,7 @@ inline Object cloneOther(const Object src) {
|
||||||
inline Object cloneObject(const Object src)
|
inline Object cloneObject(const Object src)
|
||||||
{
|
{
|
||||||
switch(src.type) {
|
switch(src.type) {
|
||||||
|
case TYPE_SLIST:
|
||||||
case TYPE_LIST:
|
case TYPE_LIST:
|
||||||
return cloneList(src);
|
return cloneList(src);
|
||||||
case TYPE_LAMBDA:
|
case TYPE_LAMBDA:
|
||||||
|
@ -773,11 +788,10 @@ inline enum errorCode getErrorCode(const Object obj)
|
||||||
#ifndef SIMPLE_ERRORS
|
#ifndef SIMPLE_ERRORS
|
||||||
inline void errorAddContext(Object *o, const char* context)
|
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: %s\n", o->error);
|
||||||
printf("o->error->context: %s\n", o->error->context);
|
|
||||||
o->error->context = calloc(sizeof(char), RESULT_LENGTH);
|
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);
|
strncpy(o->error->context, context, RESULT_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#define RESULT_LENGTH 128
|
#define RESULT_LENGTH 128
|
||||||
|
|
||||||
#define FOR_POINTER_IN_LIST(_list) \
|
#define FOR_POINTER_IN_LIST(_list) \
|
||||||
if(_list && _list->type == TYPE_LIST) \
|
if(_list && isListy(*_list)) \
|
||||||
for(Object *_element = _list->list; \
|
for(Object *_element = _list->list; \
|
||||||
_element != NULL;\
|
_element != NULL;\
|
||||||
_element = _element->forward)
|
_element = _element->forward)
|
||||||
|
@ -60,6 +60,7 @@ typedef enum Type {
|
||||||
TYPE_NUMBER,
|
TYPE_NUMBER,
|
||||||
TYPE_BOOL,
|
TYPE_BOOL,
|
||||||
TYPE_LIST,
|
TYPE_LIST,
|
||||||
|
TYPE_SLIST,
|
||||||
TYPE_FUNC,
|
TYPE_FUNC,
|
||||||
TYPE_SYMBOL,
|
TYPE_SYMBOL,
|
||||||
TYPE_LAMBDA,
|
TYPE_LAMBDA,
|
||||||
|
@ -132,6 +133,7 @@ void printAndClean(Object *target);
|
||||||
void allocObject(Object **spot, const Object src);
|
void allocObject(Object **spot, const Object src);
|
||||||
void appendList(Object *dest, const Object *src);
|
void appendList(Object *dest, const Object *src);
|
||||||
|
|
||||||
|
int isListy(const Object test);
|
||||||
int isStringy(const Object test);
|
int isStringy(const Object test);
|
||||||
int isValidType(const Object test);
|
int isValidType(const Object test);
|
||||||
int isError(const Object obj, const enum errorCode err);
|
int isError(const Object obj, const enum errorCode err);
|
||||||
|
|
|
@ -309,6 +309,12 @@ Object eval(const Object *obj, struct Environment *env)
|
||||||
case TYPE_SYMBOL:
|
case TYPE_SYMBOL:
|
||||||
return fetchFromEnvironment(obj->string, env);
|
return fetchFromEnvironment(obj->string, env);
|
||||||
|
|
||||||
|
case TYPE_SLIST: {
|
||||||
|
Object o = cloneObject(*obj);
|
||||||
|
o.type = TYPE_LIST;
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
case TYPE_LIST:
|
case TYPE_LIST:
|
||||||
return evalList(obj, env);
|
return evalList(obj, env);
|
||||||
|
|
||||||
|
@ -630,7 +636,11 @@ Result parse(struct Slice *slices)
|
||||||
struct Slice *token = slices;
|
struct Slice *token = slices;
|
||||||
if(token && token->text) {
|
if(token && token->text) {
|
||||||
struct Slice *rest = &slices[1];
|
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
|
// todo check for null rest
|
||||||
return readSeq(rest);
|
return readSeq(rest);
|
||||||
} else { // todo error on missing close paren
|
} else { // todo error on missing close paren
|
||||||
|
@ -781,8 +791,12 @@ Object parseEval(const char *input, struct Environment *env)
|
||||||
tok = &tok[i + 1];
|
tok = &tok[i + 1];
|
||||||
i = -1;
|
i = -1;
|
||||||
}
|
}
|
||||||
obj = eval(&parsed, env);
|
if (parsed.type == TYPE_SLIST) {
|
||||||
cleanObject(&parsed);
|
obj = parsed;
|
||||||
|
} else {
|
||||||
|
obj = eval(&parsed, env);
|
||||||
|
cleanObject(&parsed);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
|
|
Loading…
Reference in New Issue