Cat with `+`; Related tests. Reordered pebblisp.c
This commit is contained in:
parent
4c228f8fb1
commit
58705b4aa9
171
src/pebblisp.c
171
src/pebblisp.c
|
@ -9,86 +9,6 @@
|
||||||
#define printf(...) APP_LOG(APP_LOG_LEVEL_DEBUG, __VA_ARGS__)
|
#define printf(...) APP_LOG(APP_LOG_LEVEL_DEBUG, __VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void copySlice(char * dest, struct Slice *src)
|
|
||||||
{
|
|
||||||
if(!dest || !src)
|
|
||||||
return;
|
|
||||||
strncpy(dest, src->text, src->length);
|
|
||||||
dest[(int)src->length] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
void debugSlice(struct Slice *s)
|
|
||||||
{
|
|
||||||
if(!s) {
|
|
||||||
printf("NULL SLICE\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
printf("Debug Slice\n text:'");
|
|
||||||
for(int i = 0; i < s->length; i++) {
|
|
||||||
printf("%c", s->text[i]);
|
|
||||||
if(s->text[i] == '\0')
|
|
||||||
printf("NULLCHAR\n");
|
|
||||||
}
|
|
||||||
printf("'\n");
|
|
||||||
printf(" length: %d\n", s->length);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result parse(struct Slice *slices)
|
|
||||||
{
|
|
||||||
struct Slice *token = slices;
|
|
||||||
if(token && token->text) {
|
|
||||||
struct Slice *rest = &slices[1];
|
|
||||||
if(token->text[0] == '(') {
|
|
||||||
// todo check for null rest
|
|
||||||
return readSeq(rest);
|
|
||||||
} else { // todo error on missing close paren
|
|
||||||
return result(parseAtom(token), rest);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return result(errorObject(NULL_PARSE), NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Result readSeq(struct Slice *tokens)
|
|
||||||
{
|
|
||||||
Object res = listObject();
|
|
||||||
for(;;) {
|
|
||||||
struct Slice *next = tokens;
|
|
||||||
struct Slice *rest = next->text? &next[1] : NULL;
|
|
||||||
if(next->text[0] == ')') {
|
|
||||||
return result(res, rest);
|
|
||||||
}
|
|
||||||
Result r = parse(tokens);
|
|
||||||
nf_addToList(&res, r.obj);
|
|
||||||
tokens = r.slices;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Object parseAtom(struct Slice *s)
|
|
||||||
{
|
|
||||||
if(isDigit(s->text[0])) {
|
|
||||||
int num = 0;
|
|
||||||
for(int i = 0; i < s->length; i++) {
|
|
||||||
num *= 10;
|
|
||||||
num += s->text[i] - '0';
|
|
||||||
}
|
|
||||||
return numberObject(num);
|
|
||||||
|
|
||||||
} else if (s->text[0] == 'T' && s->length == 1) {
|
|
||||||
return boolObject(1);
|
|
||||||
|
|
||||||
} else if (s->text[0] == 'F' && s->length == 1) {
|
|
||||||
return boolObject(0);
|
|
||||||
|
|
||||||
} else if (s->text[0] == '"') {
|
|
||||||
return objFromSlice(s->text, s->length);
|
|
||||||
} else {
|
|
||||||
Object o = symbolObject();
|
|
||||||
copySlice(o.name, s);
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Object evalDefArgs(const Object *arg_forms, struct Environment *env)
|
Object evalDefArgs(const Object *arg_forms, struct Environment *env)
|
||||||
{
|
{
|
||||||
const Object *newSymbol = arg_forms;
|
const Object *newSymbol = arg_forms;
|
||||||
|
@ -261,13 +181,16 @@ Object catObjects(const Object obj1, const Object obj2, struct Environment *env)
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
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 '+':
|
||||||
|
if(obj1->type == TYPE_STRING || obj2->type == TYPE_STRING)
|
||||||
|
return catObjects(*obj1, *obj2, env);
|
||||||
return numberObject(n1 + n2);
|
return numberObject(n1 + n2);
|
||||||
case '-':
|
case '-':
|
||||||
return numberObject(n1 - n2);
|
return numberObject(n1 - n2);
|
||||||
|
@ -294,7 +217,7 @@ Object basicOp(const Object *obj1, const Object *obj2, const char op,
|
||||||
{
|
{
|
||||||
int lists = (obj1->type == TYPE_LIST) + (obj2->type == TYPE_LIST);
|
int lists = (obj1->type == TYPE_LIST) + (obj2->type == TYPE_LIST);
|
||||||
if(lists == 0) {
|
if(lists == 0) {
|
||||||
return _basicOp(obj1, obj2, op);
|
return _basicOp(obj1, obj2, op, env);
|
||||||
|
|
||||||
} else if(lists == 1) { // Single operand is applied to each element in list
|
} else if(lists == 1) { // Single operand is applied to each element in list
|
||||||
const Object *listObj = (obj1->type == TYPE_LIST)? obj1 : obj2;
|
const Object *listObj = (obj1->type == TYPE_LIST)? obj1 : obj2;
|
||||||
|
@ -303,7 +226,7 @@ Object basicOp(const Object *obj1, const Object *obj2, const char op,
|
||||||
Object newList = listObject();
|
Object newList = listObject();
|
||||||
FOR_POINTER_IN_LIST(listObj) {
|
FOR_POINTER_IN_LIST(listObj) {
|
||||||
Object adding = eval(POINTER, env);
|
Object adding = eval(POINTER, env);
|
||||||
nf_addToList(&newList, _basicOp(&adding, singleObj, op));
|
nf_addToList(&newList, _basicOp(&adding, singleObj, op, env));
|
||||||
}
|
}
|
||||||
return newList;
|
return newList;
|
||||||
|
|
||||||
|
@ -313,7 +236,7 @@ Object basicOp(const Object *obj1, const Object *obj2, const char op,
|
||||||
FOR_POINTERS_IN_LISTS(obj1, obj2) {
|
FOR_POINTERS_IN_LISTS(obj1, obj2) {
|
||||||
const Object ev1 = eval(P1, env);
|
const Object ev1 = eval(P1, env);
|
||||||
const Object ev2 = eval(P2, env);
|
const Object ev2 = eval(P2, env);
|
||||||
nf_addToList(&newList, _basicOp(&ev1, &ev2, op));
|
nf_addToList(&newList, _basicOp(&ev1, &ev2, op, env));
|
||||||
}
|
}
|
||||||
return newList;
|
return newList;
|
||||||
} else {
|
} else {
|
||||||
|
@ -337,6 +260,86 @@ BASIC_OP(lth, '<');
|
||||||
|
|
||||||
#undef BASIC_OP
|
#undef BASIC_OP
|
||||||
|
|
||||||
|
void copySlice(char * dest, struct Slice *src)
|
||||||
|
{
|
||||||
|
if(!dest || !src)
|
||||||
|
return;
|
||||||
|
strncpy(dest, src->text, src->length);
|
||||||
|
dest[(int)src->length] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void debugSlice(struct Slice *s)
|
||||||
|
{
|
||||||
|
if(!s) {
|
||||||
|
printf("NULL SLICE\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf("Debug Slice\n text:'");
|
||||||
|
for(int i = 0; i < s->length; i++) {
|
||||||
|
printf("%c", s->text[i]);
|
||||||
|
if(s->text[i] == '\0')
|
||||||
|
printf("NULLCHAR\n");
|
||||||
|
}
|
||||||
|
printf("'\n");
|
||||||
|
printf(" length: %d\n", s->length);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result parse(struct Slice *slices)
|
||||||
|
{
|
||||||
|
struct Slice *token = slices;
|
||||||
|
if(token && token->text) {
|
||||||
|
struct Slice *rest = &slices[1];
|
||||||
|
if(token->text[0] == '(') {
|
||||||
|
// todo check for null rest
|
||||||
|
return readSeq(rest);
|
||||||
|
} else { // todo error on missing close paren
|
||||||
|
return result(parseAtom(token), rest);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return result(errorObject(NULL_PARSE), NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result readSeq(struct Slice *tokens)
|
||||||
|
{
|
||||||
|
Object res = listObject();
|
||||||
|
for(;;) {
|
||||||
|
struct Slice *next = tokens;
|
||||||
|
struct Slice *rest = next->text? &next[1] : NULL;
|
||||||
|
if(next->text[0] == ')') {
|
||||||
|
return result(res, rest);
|
||||||
|
}
|
||||||
|
Result r = parse(tokens);
|
||||||
|
nf_addToList(&res, r.obj);
|
||||||
|
tokens = r.slices;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Object parseAtom(struct Slice *s)
|
||||||
|
{
|
||||||
|
if(isDigit(s->text[0])) {
|
||||||
|
int num = 0;
|
||||||
|
for(int i = 0; i < s->length; i++) {
|
||||||
|
num *= 10;
|
||||||
|
num += s->text[i] - '0';
|
||||||
|
}
|
||||||
|
return numberObject(num);
|
||||||
|
|
||||||
|
} else if (s->text[0] == 'T' && s->length == 1) {
|
||||||
|
return boolObject(1);
|
||||||
|
|
||||||
|
} else if (s->text[0] == 'F' && s->length == 1) {
|
||||||
|
return boolObject(0);
|
||||||
|
|
||||||
|
} else if (s->text[0] == '"') {
|
||||||
|
return objFromSlice(s->text, s->length);
|
||||||
|
} else {
|
||||||
|
Object o = symbolObject();
|
||||||
|
copySlice(o.name, s);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Object parseEval(const char *input, struct Environment *env)
|
Object parseEval(const char *input, struct Environment *env)
|
||||||
{
|
{
|
||||||
struct Slice *tokens = nf_tokenize(input);
|
struct Slice *tokens = nf_tokenize(input);
|
||||||
|
|
|
@ -76,6 +76,10 @@ check "FbnciSeq" "(def fib (fn (a) \
|
||||||
))) \
|
))) \
|
||||||
(fib 20)" "6765"
|
(fib 20)" "6765"
|
||||||
echo ""
|
echo ""
|
||||||
|
check "ExplicitCat" "(cat \"Big\" \" Kitty\")" "Big Kitty"
|
||||||
|
check "CatNums" "(cat \"There are \" (+ 2 3) \" kitties\")" "There are 5 kitties"
|
||||||
|
check "ImplicitCat" "(+ \"There are \" (* 5 4) \" bonks\")" "There are 20 bonks"
|
||||||
|
check "CatAssocLeft" "(+ 10 20 \" rascals\")" "30 rascals"
|
||||||
|
|
||||||
if [ "$FAILS" -ne "0" ]; then
|
if [ "$FAILS" -ne "0" ]; then
|
||||||
echo "[1;31m$FAILS Tests Failed[0m"
|
echo "[1;31m$FAILS Tests Failed[0m"
|
||||||
|
|
Loading…
Reference in New Issue