Some new list functions and better error handling

New list functions include (append) (at) (rest) and (reverse). Single quotes now supported for strings.
This commit is contained in:
= 2020-05-28 15:28:28 +01:00
parent d041e7c5bb
commit 81d5a545cf
6 changed files with 109 additions and 25 deletions

View File

@ -28,7 +28,7 @@ Object fetchFromEnvironment(const char *name, struct Environment *env)
debugObj(&env->objects[i]);
if(strcmp(name, env->strings[i]) == 0) {
printd("Returning!\n");
return env->objects[i];
return cloneObject(env->objects[i]);
}
}
@ -191,10 +191,16 @@ struct Environment defaultEnv()
addFunc("=", &equ, &e);
addFunc(">", &gth, &e);
addFunc("<", &lth, &e);
addFunc("len", &len, &e);
addFunc("cat", &catObjects, &e);
addFunc("fil", &filter, &e);
addFunc("len", &len, &e);
addFunc("ap", &append, &e);
addFunc("at", &at, &e);
addFunc("rest", &rest, &e);
addFunc("rev", &reverse, &e);
int i = 0;
while(codes[i]) {
parseEval(codes[i++], &e);

View File

@ -33,7 +33,13 @@ int listLength(const Object *listObj)
}
Object len(Object obj1, Object o_ignore, struct Environment *e_ignore)
{ return numberObject(listLength(&obj1)); }
{
Object o = numberObject(listLength(&obj1));
if(o.number < 0) {
return errorObject(NOT_A_LIST);
}
return o;
}
/**
* Returns a pointer to the Object at the given index in a given list
@ -207,7 +213,9 @@ static const char *errorText[] = {
"LISTS_NOT_SAME_SIZE",
"SYMBOLS_CANT_START_WITH_DIGITS",
"UNSUPPORTED_NUMBER_TYPE",
"NOT_A_SYMBOL"
"NOT_A_SYMBOL",
"ONLY_ONE_ARGUMENT",
"NOT_A_LIST"
};
/**
@ -285,7 +293,11 @@ char* stringObj(char *dest, const Object *obj)
stringList(dest, obj);
break;
case TYPE_ERROR:
#ifdef STANDALONE
snprintf(dest, RESULT_LENGTH, "%s", errorText[(int)(obj->err)]);
#else
snprintf(dest, RESULT_LENGTH, "E%d", obj->err);
#endif
break;
case TYPE_FUNC:
case TYPE_LAMBDA:
@ -352,7 +364,6 @@ void _printObj(const Object *obj, int newline)
printf("%s\n", temp);
else
printf("%s", temp);
printErr(obj);
}
/**
@ -361,7 +372,7 @@ void _printObj(const Object *obj, int newline)
* If the DEBUG flag is set, the Object's type will be printed first
* @param obj The Object to print
*/
void printObj(const Object *obj)
inline void printObj(const Object *obj)
{
_printObj(obj, 1);
}
@ -661,6 +672,11 @@ inline Object constructLambda(const Object *params, const Object *body)
return o;
}
inline int isError(const Object obj, const enum errorCode err)
{
return obj.type == TYPE_ERROR && obj.err == err;
}
inline Object errorObject(enum errorCode err)
{
Object o = newObject(TYPE_ERROR);

View File

@ -17,8 +17,6 @@
#define P1 POINTER
#define P2 _element2
#define SKIP_FIRST() if(_element == _list->list) {continue;}
enum errorCode {
MISMATCHED_PARENS,
BAD_LIST_OF_SYMBOL_STRINGS,
@ -36,7 +34,9 @@ enum errorCode {
LISTS_NOT_SAME_SIZE,
SYMBOLS_CANT_START_WITH_DIGITS,
UNSUPPORTED_NUMBER_TYPE,
NOT_A_SYMBOL
NOT_A_SYMBOL,
ONLY_ONE_ARGUMENT,
NOT_A_LIST
};
#define MALLOC_FLAG 64
@ -101,6 +101,7 @@ void appendList(Object *dest, const Object *src);
int isStringy(const Object test);
int isValidType(const Object test);
int isError(const Object obj, const enum errorCode err);
Object cloneList(const Object src);
Object cloneString(Object obj);

View File

@ -40,7 +40,7 @@ Object evalMapArgs(const Object *argForms, struct Environment *env)
if(!argForms)
return errorObject(NULL_MAP_ARGS);
const Object lambda = eval(argForms, env);
Object lambda = eval(argForms, env);
const Object *inputList = argForms->forward;
if(lambda.type != TYPE_LAMBDA || inputList->type != TYPE_LIST)
@ -61,6 +61,7 @@ Object evalMapArgs(const Object *argForms, struct Environment *env)
deleteEnv(&newEnv);
cleanObject(&tempList);
}
cleanObject(&lambda);
return list;
}
@ -130,18 +131,21 @@ Object eval(const Object *obj, struct Environment *env)
eval_forms(rest, obj, env);
Object func_eval = rest[0];
for(int i = 1; i < length; i++) {
Object toClean = func_eval;
func_eval = first_eval.func(func_eval, rest[i], env);
//if(i != length - 1)
cleanObject(&toClean);
cleanObject(&rest[i]);
if(length == 1) {
func_eval = first_eval.func(
func_eval, errorObject(ONLY_ONE_ARGUMENT), env);
if(isError(func_eval, ONLY_ONE_ARGUMENT)) // Consider it a partial function
return cloneObject(*obj);
} else {
for(int i = 1; i < length; i++) {
Object toClean = func_eval;
func_eval = first_eval.func(func_eval, rest[i], env);
//if(i != length - 1)
cleanObject(&toClean);
cleanObject(&rest[i]);
}
}
// Consider the object a partial function
if(length == 1)
return cloneObject(*obj);
return func_eval;
} else if (first_eval.type == TYPE_LAMBDA) {
@ -149,6 +153,7 @@ Object eval(const Object *obj, struct Environment *env)
envForLambda(&first_eval.lambda->params, first_form->forward, env);
Object ret = eval(&first_eval.lambda->body, &newEnv);
deleteEnv(&newEnv);
cleanObject(&first_eval);
return ret;
} else {
@ -233,6 +238,9 @@ Object _basicOp(const Object *obj1, const Object *obj2, const char op,
Object basicOp(const Object *obj1, const Object *obj2, const char op,
struct Environment *env)
{
if(isError(*obj2, ONLY_ONE_ARGUMENT))
return *obj2;
int lists = (obj1->type == TYPE_LIST) + (obj2->type == TYPE_LIST);
if(lists == 0) {
return _basicOp(obj1, obj2, op, env);
@ -285,14 +293,56 @@ Object filter(Object obj1, Object obj2, struct Environment *env)
FOR_POINTER_IN_LIST(filteringList) {
Object conditional = cloneObject(obj1);
nf_addToList(&conditional, *POINTER); // cloneObject()?
conditional = eval(&conditional, env);
if(conditional.number == 1) {
Object result = eval(&conditional, env);
cleanObject(&conditional);
if(result.number == 1) {
nf_addToList(&filteredList, *POINTER);
}
}
return filteredList;
}
Object append(Object list, Object newElement, struct Environment *env)
{
Object newList = cloneObject(list);
nf_addToList(&newList, newElement);
return newList;
}
Object at(Object index, Object list, struct Environment *env)
{
return cloneObject(*itemAt(&list, index.number));
}
Object rest(Object list, Object ignore, struct Environment *env)
{
Object ret = listObject();
Object *l = &list;
FOR_POINTER_IN_LIST(l) {
if(POINTER == l->list)
continue;
nf_addToList(&ret, *POINTER);
}
return ret;
}
Object reverse(Object _list, Object ignore, struct Environment *ignore2)
{
const Object *list = &_list;
Object rev = listObject();
Object *tail = NULL;
FOR_POINTER_IN_LIST(list) {
Object *oldTail = tail;
allocObject(&tail, cloneObject(*POINTER));
if(oldTail)
tail->forward = oldTail;
}
rev.list = tail;
return rev;
}
void copySlice(char * dest, struct Slice *src)
{
if(!dest || !src)
@ -343,6 +393,8 @@ Result readSeq(struct Slice *tokens)
return result(res, rest);
}
Result r = parse(tokens);
if(r.obj.type == TYPE_ERROR)
return r;
nf_addToList(&res, cloneObject(r.obj));
tokens = r.slices;
cleanObject(&r.obj);
@ -377,7 +429,7 @@ Object parseAtom(struct Slice *s)
} else if (s->length == 1 && (s->text[0] == 'F' || s->text[0] == 'f')) {
return boolObject(0);
} else if (s->text[0] == '"') {
} else if (s->text[0] == '"' || s->text[0] == '\'') {
return objFromSlice(s->text, s->length);
} else {
return symFromSlice(s->text, s->length);
@ -411,6 +463,8 @@ Object parseEval(const char *input, struct Environment *env)
struct Slice *tok = tokens;
if(tok[i].text[0] != '(') {
Object parsed = parse(tok).obj;
if(parsed.type == TYPE_ERROR)
return parsed;
obj = eval(&parsed, env);
cleanObject(&parsed);
} else {
@ -422,6 +476,8 @@ Object parseEval(const char *input, struct Environment *env)
if(parens == 0) {
cleanObject(&obj);
Object parsed = parse(tok).obj;
if(parsed.type == TYPE_ERROR)
return parsed;
tok = &tok[i + 1];
i = -1;
//printObj(&parsed);

View File

@ -50,5 +50,9 @@ BASIC_OP(gth); BASIC_OP(lth);
#undef BASIC_OP
Object catObjects(const Object obj1, const Object obj2, struct Environment *env);
Object filter(Object obj1, Object obj2, struct Environment *env);
Object append(Object list, Object newElement, struct Environment *env);
Object at(Object index, Object list, struct Environment *env);
Object rest(Object list, Object ignore, struct Environment *env);
Object reverse(Object _list, Object ignore, struct Environment *ignore2);
#endif

View File

@ -79,8 +79,9 @@ struct Slice *nf_tokenize(const char *input)
if(isSingle(input[i])) {
i++;
} else if(input[i] == '"') {
while(input[++i] != '"' && input[i] != '\0') {
} else if(input[i] == '"' || input[i] == '\'') {
const char quote = input[i];
while(input[++i] != quote && input[i] != '\0') {
l++;
}
i++;