diff --git a/src/env.c b/src/env.c index 590f0af..7ccb3b8 100644 --- a/src/env.c +++ b/src/env.c @@ -142,6 +142,40 @@ void deleteEnv(struct Environment *e) e->objects = NULL; } +const char *codes[] = { + // Exponentiate a^b + "(def exp (fn (a b) " + "(if (= b 0)" + "1" + "(* a (exp a (- b 1)))" + ")" + "))", + + // Square a + "(def sq (fn (a) (exp a 2)))", + + // Cube a + "(def cube (fn (a) (exp a 3)))", + + // Return the larger of the two + "(def max (fn (a b) (if (> a b) a b)))", + + // Return the smaller of the two + "(def min (fn (a b) (if (< a b) a b)))", + + // Arbitrary recursion tester + "(def ad (fn (a) (if (> a 10) a (ad (* 10 a) ))))", + + // A demo tip calculator + "(def spent (fn (a) \ + (cat \"Tip: $\" \"\" \"\" (/ a 5) \".\" \ + (/ (* 100 (% a 5)) 5) \ + ) \ + ))", + + NULL +}; + struct Environment defaultEnv() { struct Environment e; @@ -161,14 +195,10 @@ struct Environment defaultEnv() addFunc("len", &len, &e); addFunc("cat", &catObjects, &e); - parseEval("(def max (fn (a b) (if (> a b) a b)))", &e); - parseEval("(def min (fn (a b) (if (< a b) a b)))", &e); - parseEval("(def ad (fn (a) (if (> a 10) a (ad (* 10 a) ))))", &e); - parseEval("(def spent (fn (a) \ - (cat \"Tip: $\" \"\" \"\" (/ a 5) \".\" \ - (/ (* 100 (% a 5)) 5) \ - ) \ - ))", &e); + int i = 0; + while(codes[i]) { + parseEval(codes[i++], &e); + } return e; } diff --git a/src/object.h b/src/object.h index 1b3a78d..86bd048 100644 --- a/src/object.h +++ b/src/object.h @@ -32,7 +32,9 @@ enum errorCode { DID_NOT_FIND_SYMBOL, BAD_TYPE, UNEXPECTED_FORM, - LISTS_NOT_SAME_SIZE + LISTS_NOT_SAME_SIZE, + SYMBOLS_CANT_START_WITH_DIGITS, + UNSUPPORTED_NUMBER_TYPE }; //#ifdef STANDALONE @@ -50,7 +52,9 @@ static const char *errorText[] = { "DID_NOT_FIND_SYMBOL", "BAD_TYPE", "UNEXPECTED_FORM", - "LISTS_NOT_SAME_SIZE" + "LISTS_NOT_SAME_SIZE", + "SYMBOLS_CANT_START_WITH_DIGITS", + "UNSUPPORTED_NUMBER_TYPE" }; //#endif diff --git a/src/pebblisp.c b/src/pebblisp.c index 5e0391d..2f7d7b7 100644 --- a/src/pebblisp.c +++ b/src/pebblisp.c @@ -9,9 +9,9 @@ #define printf(...) APP_LOG(APP_LOG_LEVEL_DEBUG, __VA_ARGS__) #endif -Object evalDefArgs(const Object *arg_forms, struct Environment *env) +Object evalDefArgs(const Object *argForms, struct Environment *env) { - const Object *newSymbol = arg_forms; + const Object *newSymbol = argForms; const char *name = newSymbol->name; const Object newValue = eval(newSymbol->forward, env); @@ -21,26 +21,26 @@ Object evalDefArgs(const Object *arg_forms, struct Environment *env) return *newSymbol; } -Object evalIfArgs(const Object *arg_forms, struct Environment *env) +Object evalIfArgs(const Object *argForms, struct Environment *env) { - return eval(arg_forms, env).number? - eval(arg_forms->forward, env) : - eval(arg_forms->forward->forward, env); + return eval(argForms, env).number? + eval(argForms->forward, env) : + eval(argForms->forward->forward, env); } -Object evalLambdaArgs(const Object *arg_forms) +Object evalLambdaArgs(const Object *argForms) { // params // body - return constructLambda(arg_forms, arg_forms? arg_forms->forward : NULL); + return constructLambda(argForms, argForms? argForms->forward : NULL); } -Object evalMapArgs(const Object *arg_forms, struct Environment *env) +Object evalMapArgs(const Object *argForms, struct Environment *env) { - if(!arg_forms) + if(!argForms) return errorObject(NULL_MAP_ARGS); - const Object lambda = eval(arg_forms, env); - const Object *inputList = arg_forms->forward; + const Object lambda = eval(argForms, env); + const Object *inputList = argForms->forward; if(lambda.type != TYPE_LAMBDA || inputList->type != TYPE_LIST) return errorObject(BAD_TYPE); @@ -114,12 +114,11 @@ Object eval(const Object *obj, struct Environment *env) Object *first_form = obj->list; { // Try to eval built-ins - const Object built_in = + const Object builtIn = evalBuiltIns(first_form, first_form->forward, env); - // deleteList(obj); // Decreases indirectly lost memory, but fails on Pebble - if(built_in.type != TYPE_ERROR) { - return built_in; + if(builtIn.type != TYPE_ERROR) { + return builtIn; } } @@ -138,7 +137,6 @@ Object eval(const Object *obj, struct Environment *env) cleanObject(&rest[i]); } - // deleteList(obj); // Decreases indirectly lost memory, but fails on Pebble return func_eval; } else if (first_eval.type == TYPE_LAMBDA) { @@ -242,7 +240,7 @@ Object basicOp(const Object *obj1, const Object *obj2, const char op, } return newList; - } else { // 2 lists + } else { // 2 lists with the op applied to matching indices of both lists if(listLength(obj1) == listLength(obj2)) { Object newList = listObject(); FOR_POINTERS_IN_LISTS(obj1, obj2) { @@ -327,20 +325,32 @@ Result readSeq(struct Slice *tokens) } } -Object parseAtom(struct Slice *s) +Object parseDecimal(struct Slice *s) { - if(isDigit(s->text[0])) { int num = 0; for(int i = 0; i < s->length; i++) { + if(!isDigit(s->text[i])) { + return errorObject(SYMBOLS_CANT_START_WITH_DIGITS); + } num *= 10; num += s->text[i] - '0'; } return numberObject(num); +} - } else if (s->text[0] == 'T' && s->length == 1) { +Object parseAtom(struct Slice *s) +{ + if(isDigit(s->text[0])) { + if(s->text[0] != '0' || s->length == 1) + return parseDecimal(s); + else { + return errorObject(UNSUPPORTED_NUMBER_TYPE); + } + + } else if (s->length == 1 && (s->text[0] == 'T' || s->text[0] == 't')) { return boolObject(1); - } else if (s->text[0] == 'F' && s->length == 1) { + } else if (s->length == 1 && (s->text[0] == 'F' || s->text[0] == 'f')) { return boolObject(0); } else if (s->text[0] == '"') { diff --git a/src/tests.sh b/src/tests.sh index ac7d019..7871e87 100755 --- a/src/tests.sh +++ b/src/tests.sh @@ -82,10 +82,14 @@ check "CatNums" "(cat \"There are \" (+ 2 3) \" kitties\")" "There are 5 kitties check "ImplicitCat" "(+ \"There are \" (* 5 4) \" bonks\")" "There are 20 bonks" # Not recommended check "CatAssocLeft" "(+ 10 20 \" rascals\")" "30 rascals" -echo"" +echo "" check "EvalElems" "((* 10 10) 7)" "( 100 7 )" check "Duplicate" "(def dupe (fn (a) (a a a))) (dupe (*10 10))" "( 100 100 100 )" -echo"" +echo "" +check "Squaring" "(sq 9876)" "97535376" +check "Cubing" "(cube 81)" "531441" +check "Exponent" "(exp 9 9)" "387420489" +echo "" if [ "$FAILS" -ne "0" ]; then echo "$FAILS Tests Failed"