Broke lib-type code into array. New numparse errs

This commit is contained in:
= 2020-05-16 19:31:14 +01:00
parent c59789120c
commit 80967b9275
4 changed files with 82 additions and 34 deletions

View File

@ -142,6 +142,40 @@ void deleteEnv(struct Environment *e)
e->objects = NULL; 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 defaultEnv()
{ {
struct Environment e; struct Environment e;
@ -161,14 +195,10 @@ struct Environment defaultEnv()
addFunc("len", &len, &e); addFunc("len", &len, &e);
addFunc("cat", &catObjects, &e); addFunc("cat", &catObjects, &e);
parseEval("(def max (fn (a b) (if (> a b) a b)))", &e); int i = 0;
parseEval("(def min (fn (a b) (if (< a b) a b)))", &e); while(codes[i]) {
parseEval("(def ad (fn (a) (if (> a 10) a (ad (* 10 a) ))))", &e); parseEval(codes[i++], &e);
parseEval("(def spent (fn (a) \ }
(cat \"Tip: $\" \"\" \"\" (/ a 5) \".\" \
(/ (* 100 (% a 5)) 5) \
) \
))", &e);
return e; return e;
} }

View File

@ -32,7 +32,9 @@ enum errorCode {
DID_NOT_FIND_SYMBOL, DID_NOT_FIND_SYMBOL,
BAD_TYPE, BAD_TYPE,
UNEXPECTED_FORM, UNEXPECTED_FORM,
LISTS_NOT_SAME_SIZE LISTS_NOT_SAME_SIZE,
SYMBOLS_CANT_START_WITH_DIGITS,
UNSUPPORTED_NUMBER_TYPE
}; };
//#ifdef STANDALONE //#ifdef STANDALONE
@ -50,7 +52,9 @@ static const char *errorText[] = {
"DID_NOT_FIND_SYMBOL", "DID_NOT_FIND_SYMBOL",
"BAD_TYPE", "BAD_TYPE",
"UNEXPECTED_FORM", "UNEXPECTED_FORM",
"LISTS_NOT_SAME_SIZE" "LISTS_NOT_SAME_SIZE",
"SYMBOLS_CANT_START_WITH_DIGITS",
"UNSUPPORTED_NUMBER_TYPE"
}; };
//#endif //#endif

View File

@ -9,9 +9,9 @@
#define printf(...) APP_LOG(APP_LOG_LEVEL_DEBUG, __VA_ARGS__) #define printf(...) APP_LOG(APP_LOG_LEVEL_DEBUG, __VA_ARGS__)
#endif #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 char *name = newSymbol->name;
const Object newValue = eval(newSymbol->forward, env); const Object newValue = eval(newSymbol->forward, env);
@ -21,26 +21,26 @@ Object evalDefArgs(const Object *arg_forms, struct Environment *env)
return *newSymbol; 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? return eval(argForms, env).number?
eval(arg_forms->forward, env) : eval(argForms->forward, env) :
eval(arg_forms->forward->forward, env); eval(argForms->forward->forward, env);
} }
Object evalLambdaArgs(const Object *arg_forms) Object evalLambdaArgs(const Object *argForms)
{ {
// params // body // 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); return errorObject(NULL_MAP_ARGS);
const Object lambda = eval(arg_forms, env); const Object lambda = eval(argForms, env);
const Object *inputList = arg_forms->forward; const Object *inputList = argForms->forward;
if(lambda.type != TYPE_LAMBDA || inputList->type != TYPE_LIST) if(lambda.type != TYPE_LAMBDA || inputList->type != TYPE_LIST)
return errorObject(BAD_TYPE); return errorObject(BAD_TYPE);
@ -114,12 +114,11 @@ Object eval(const Object *obj, struct Environment *env)
Object *first_form = obj->list; Object *first_form = obj->list;
{ // Try to eval built-ins { // Try to eval built-ins
const Object built_in = const Object builtIn =
evalBuiltIns(first_form, first_form->forward, env); evalBuiltIns(first_form, first_form->forward, env);
// deleteList(obj); // Decreases indirectly lost memory, but fails on Pebble if(builtIn.type != TYPE_ERROR) {
if(built_in.type != TYPE_ERROR) { return builtIn;
return built_in;
} }
} }
@ -138,7 +137,6 @@ Object eval(const Object *obj, struct Environment *env)
cleanObject(&rest[i]); cleanObject(&rest[i]);
} }
// deleteList(obj); // Decreases indirectly lost memory, but fails on Pebble
return func_eval; return func_eval;
} else if (first_eval.type == TYPE_LAMBDA) { } else if (first_eval.type == TYPE_LAMBDA) {
@ -242,7 +240,7 @@ Object basicOp(const Object *obj1, const Object *obj2, const char op,
} }
return newList; return newList;
} else { // 2 lists } else { // 2 lists with the op applied to matching indices of both lists
if(listLength(obj1) == listLength(obj2)) { if(listLength(obj1) == listLength(obj2)) {
Object newList = listObject(); Object newList = listObject();
FOR_POINTERS_IN_LISTS(obj1, obj2) { 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; int num = 0;
for(int i = 0; i < s->length; i++) { for(int i = 0; i < s->length; i++) {
if(!isDigit(s->text[i])) {
return errorObject(SYMBOLS_CANT_START_WITH_DIGITS);
}
num *= 10; num *= 10;
num += s->text[i] - '0'; num += s->text[i] - '0';
} }
return numberObject(num); 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); 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); return boolObject(0);
} else if (s->text[0] == '"') { } else if (s->text[0] == '"') {

View File

@ -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" check "ImplicitCat" "(+ \"There are \" (* 5 4) \" bonks\")" "There are 20 bonks"
# Not recommended # Not recommended
check "CatAssocLeft" "(+ 10 20 \" rascals\")" "30 rascals" check "CatAssocLeft" "(+ 10 20 \" rascals\")" "30 rascals"
echo"" echo ""
check "EvalElems" "((* 10 10) 7)" "( 100 7 )" check "EvalElems" "((* 10 10) 7)" "( 100 7 )"
check "Duplicate" "(def dupe (fn (a) (a a a))) (dupe (*10 10))" "( 100 100 100 )" 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 if [ "$FAILS" -ne "0" ]; then
echo "$FAILS Tests Failed" echo "$FAILS Tests Failed"