diff --git a/src/env.c b/src/env.c index c331b15..d15f4ee 100644 --- a/src/env.c +++ b/src/env.c @@ -131,7 +131,7 @@ struct Environment envForLambda(const Object* params, const Object* arguments, i // Evaluate the `argument` list const Object* param = params->list; const Object* argument = arguments; - for (int i = 0; i < paramCount && param; i++) { + for (; param; param = param->forward) { const char* paramName = param->string; if (paramName[0] == '.' && paramName[1] == '.' && paramName[2] == '.' && paramName[3] != '\0') { paramName = ¶mName[3]; @@ -144,6 +144,9 @@ struct Environment envForLambda(const Object* params, const Object* arguments, i cleanObject(&varargs); break; } + if (!argument) { + break; + } Object newEnvObj = eval(argument, outer); @@ -151,8 +154,7 @@ struct Environment envForLambda(const Object* params, const Object* arguments, i cleanObject(&newEnvObj); - argument = argument ? argument->forward : NULL; - param = param->forward; + argument = argument->forward; } env.outer = outer; @@ -254,7 +256,8 @@ struct Environment defaultEnv() pf(help), pf(buildHashTable), pf(addToHashTable), - pf(getFromHashTable) + pf(getFromHashTable), + pf(randomO) #endif }; diff --git a/src/examples/lib.pbl b/src/examples/lib.pbl index bdee7c2..8454cf0 100644 --- a/src/examples/lib.pbl +++ b/src/examples/lib.pbl @@ -174,6 +174,14 @@ (eval (rf file-name)) ))) +(def any-in (fn (list f) + (> (len (fil f list)) 0) +)) + +(def none-in (fn (list f) + (not (any-in list f)) +)) + (def startsWith (fn (text pattern) ( (matches text (cat pattern "*")) ))) @@ -184,4 +192,4 @@ (def endsWith (fn (text pattern) ( (matches text (cat "*" pattern)) -))) \ No newline at end of file +))) diff --git a/src/examples/tic-tac-toe.pbl b/src/examples/tic-tac-toe.pbl index af24434..db54b46 100755 --- a/src/examples/tic-tac-toe.pbl +++ b/src/examples/tic-tac-toe.pbl @@ -6,48 +6,65 @@ " " " " " " )) +(def is-empty (fn (tile) (= " " tile))) + (def print-board (fn (board) ( (sys "clear") (def '(a b c d e f g h i) board) - (prnl (cat " " a " | " b " | " c)) - (prnl "-----------") - (prnl (cat " " d " | " e " | " f)) - (prnl "-----------") - (prnl (cat " " g " | " h " | " i)) + (prnl) + (prnl (cat " " a " | " b " | " c)) + (prnl " -----------") + (prnl (cat " " d " | " e " | " f)) + (prnl " -----------") + (prnl (cat " " g " | " h " | " i)) ))) -(def do-move (fn (board player) ( - (def input (inp)) +(def do-move (fn (board player warn) ( + (prnl) + (if warn (prnl "You can't go there!") ()) + (prnl "Your turn, " player "!") + (prnl "Where do you want to play?") + (def input (inp "1-9: ")) (def spot (eval input)) (def i 0) - (map (fn (piece) ( - (set i (+ 1 i)) - (if (= i spot) player piece) - )) board) + (if (& (is-empty (at (- spot 1) board)) (> spot 0) (< spot 10)) + (map (fn (piece) ( + (set i (+ 1 i)) + (if (= i spot) player piece) + )) board) + ( + (print-board board) + (do-move board player T) + ) + ) ))) -(def winning-row (fn (row) ( +(def is-winning-row (fn (row) ( (def '(a b c) row) - (& (not (= " " a)) (= a b c)) + (& (not (is-empty a)) (= a b c)) ))) +(def is-full-board (fn (board) + (none-in board is-empty) +)) + (def get-winner (fn (board) ( - (sys "clear") (def '(a b c d e f g h i) board) - (if (winning-row (a b c)) a - (if (winning-row (d e f)) d - (if (winning-row (g h i)) g - (if (winning-row (a d g)) a - (if (winning-row (b e h)) b - (if (winning-row (c f i)) c - (if (winning-row (a e i)) a - (if (winning-row (c e g)) c + (if (is-winning-row (a b c)) a + (if (is-winning-row (d e f)) d + (if (is-winning-row (g h i)) g + (if (is-winning-row (a d g)) a + (if (is-winning-row (b e h)) b + (if (is-winning-row (c f i)) c + (if (is-winning-row (a e i)) a + (if (is-winning-row (c e g)) c + (if (is-full-board board) "Nobody" " " - )))))))) + ))))))))) ))) (def next-player (fn (current) ( @@ -55,15 +72,15 @@ ))) (def game (fn (board player) ( - (if (= " " (get-winner board)) ( - (print-board board) - (def b (do-move board player)) + (print-board board) + (def winner (get-winner board)) + (if (is-empty winner) ( + (def b (do-move board player F)) (game b (next-player player)) ) ( - (print-board board) - (prnl "") - (prnl "Game over! " (next-player player) " wins!") + (prnl) + (prnl "Game over! " winner " wins!") )) ))) -(game empty-board "X") +(game empty-board (if (= 0 (rand 2)) "X" "O")) diff --git a/src/pebblisp.h b/src/pebblisp.h index db703a8..8169afc 100644 --- a/src/pebblisp.h +++ b/src/pebblisp.h @@ -49,6 +49,10 @@ Object typeCheck(const char* funcName, Object* params, int length, if (FAILED) { \ return ERROR; \ } +#define verifyTypes(FUNC, TYPE_CHECKS) int FAILED; Object ERROR = typeCheck(FUNC ## Symbol, params, length, TYPE_CHECKS, length, &FAILED); \ +if (FAILED) { \ + return ERROR; \ +} #else #define checkTypes(FUNC) ; #endif diff --git a/src/plfunc/pc.c b/src/plfunc/pc.c index 3953b68..3e3f70d 100644 --- a/src/plfunc/pc.c +++ b/src/plfunc/pc.c @@ -86,4 +86,20 @@ Object getEnvVar(Object* params, unused int length, unused struct Environment* e } return stringFromSlice("", 0); } + +#include +int initializedRand = 0; +Object randomO(Object* params, unused int length, unused struct Environment* env) +{ + if (!initializedRand) { + srand(time(0)); + initializedRand = 1; + } + int num = rand(); + if (length > 0 && params[0].type == TYPE_NUMBER) { + num = num % params[0].number; + } + return numberObject(num); +} + #endif // STANDALONE \ No newline at end of file diff --git a/src/plfunc/pc.h b/src/plfunc/pc.h index 9ea974f..fcbed79 100644 --- a/src/plfunc/pc.h +++ b/src/plfunc/pc.h @@ -60,6 +60,12 @@ tfn(getEnvVar, "env", "(env HOME) => /home/sagevaillancourt" ); +tfn(randomO, "rand", + ({ returns(isNumber) }), + "Returns a semi-random integer\n" + "(rand) => 2394568" +); + #endif //PEBBLISP_PC_H #endif // STANDALONE diff --git a/src/tests.sh b/src/tests.sh index c56f979..dc569e3 100755 --- a/src/tests.sh +++ b/src/tests.sh @@ -75,7 +75,9 @@ check() { fi + local expected="$3" if [ "$3" == "$regex" ]; then + expected="$4" if [[ "$output" =~ ^$4$ ]]; then pass "$1" $exit_code return @@ -86,7 +88,7 @@ check() { fi fail "$1" "$2" - FAIL_OUTPUT="${FAIL_OUTPUT}\n  expected '$3' but received '$output'\n" + FAIL_OUTPUT="${FAIL_OUTPUT}\n  expected '$expected' but received '$output'\n" } echo "::SHELL TESTS::"