Improve lambda param handling.

Add (rand)
Clean up testing output.
tic-tac-toe.pbl QOL changes
This commit is contained in:
Sage Vaillancourt 2022-10-25 14:36:10 -04:00
parent 9b6b80f204
commit 6176e9eb4b
7 changed files with 92 additions and 36 deletions

View File

@ -131,7 +131,7 @@ struct Environment envForLambda(const Object* params, const Object* arguments, i
// Evaluate the `argument` list // Evaluate the `argument` list
const Object* param = params->list; const Object* param = params->list;
const Object* argument = arguments; const Object* argument = arguments;
for (int i = 0; i < paramCount && param; i++) { for (; param; param = param->forward) {
const char* paramName = param->string; const char* paramName = param->string;
if (paramName[0] == '.' && paramName[1] == '.' && paramName[2] == '.' && paramName[3] != '\0') { if (paramName[0] == '.' && paramName[1] == '.' && paramName[2] == '.' && paramName[3] != '\0') {
paramName = &paramName[3]; paramName = &paramName[3];
@ -144,6 +144,9 @@ struct Environment envForLambda(const Object* params, const Object* arguments, i
cleanObject(&varargs); cleanObject(&varargs);
break; break;
} }
if (!argument) {
break;
}
Object newEnvObj = eval(argument, outer); Object newEnvObj = eval(argument, outer);
@ -151,8 +154,7 @@ struct Environment envForLambda(const Object* params, const Object* arguments, i
cleanObject(&newEnvObj); cleanObject(&newEnvObj);
argument = argument ? argument->forward : NULL; argument = argument->forward;
param = param->forward;
} }
env.outer = outer; env.outer = outer;
@ -254,7 +256,8 @@ struct Environment defaultEnv()
pf(help), pf(help),
pf(buildHashTable), pf(buildHashTable),
pf(addToHashTable), pf(addToHashTable),
pf(getFromHashTable) pf(getFromHashTable),
pf(randomO)
#endif #endif
}; };

View File

@ -174,6 +174,14 @@
(eval (rf file-name)) (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) ( (def startsWith (fn (text pattern) (
(matches text (cat pattern "*")) (matches text (cat pattern "*"))
))) )))

View File

@ -6,11 +6,14 @@
" " " " " " " " " " " "
)) ))
(def is-empty (fn (tile) (= " " tile)))
(def print-board (fn (board) ( (def print-board (fn (board) (
(sys "clear") (sys "clear")
(def '(a b c (def '(a b c
d e f d e f
g h i) board) g h i) board)
(prnl)
(prnl (cat " " a " | " b " | " c)) (prnl (cat " " a " | " b " | " c))
(prnl " -----------") (prnl " -----------")
(prnl (cat " " d " | " e " | " f)) (prnl (cat " " d " | " e " | " f))
@ -18,36 +21,50 @@
(prnl (cat " " g " | " h " | " i)) (prnl (cat " " g " | " h " | " i))
))) )))
(def do-move (fn (board player) ( (def do-move (fn (board player warn) (
(def input (inp)) (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 spot (eval input))
(def i 0) (def i 0)
(if (& (is-empty (at (- spot 1) board)) (> spot 0) (< spot 10))
(map (fn (piece) ( (map (fn (piece) (
(set i (+ 1 i)) (set i (+ 1 i))
(if (= i spot) player piece) (if (= i spot) player piece)
)) board) )) 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) (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) ( (def get-winner (fn (board) (
(sys "clear")
(def '(a b c (def '(a b c
d e f d e f
g h i) board) g h i) board)
(if (winning-row (a b c)) a (if (is-winning-row (a b c)) a
(if (winning-row (d e f)) d (if (is-winning-row (d e f)) d
(if (winning-row (g h i)) g (if (is-winning-row (g h i)) g
(if (winning-row (a d g)) a (if (is-winning-row (a d g)) a
(if (winning-row (b e h)) b (if (is-winning-row (b e h)) b
(if (winning-row (c f i)) c (if (is-winning-row (c f i)) c
(if (winning-row (a e i)) a (if (is-winning-row (a e i)) a
(if (winning-row (c e g)) c (if (is-winning-row (c e g)) c
(if (is-full-board board) "Nobody"
" " " "
)))))))) )))))))))
))) )))
(def next-player (fn (current) ( (def next-player (fn (current) (
@ -55,15 +72,15 @@
))) )))
(def game (fn (board player) ( (def game (fn (board player) (
(if (= " " (get-winner board)) (
(print-board board) (print-board board)
(def b (do-move board player)) (def winner (get-winner board))
(if (is-empty winner) (
(def b (do-move board player F))
(game b (next-player player)) (game b (next-player player))
) ( ) (
(print-board board) (prnl)
(prnl "") (prnl "Game over! " winner " wins!")
(prnl "Game over! " (next-player player) " wins!")
)) ))
))) )))
(game empty-board "X") (game empty-board (if (= 0 (rand 2)) "X" "O"))

View File

@ -49,6 +49,10 @@ Object typeCheck(const char* funcName, Object* params, int length,
if (FAILED) { \ if (FAILED) { \
return ERROR; \ 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 #else
#define checkTypes(FUNC) ; #define checkTypes(FUNC) ;
#endif #endif

View File

@ -86,4 +86,20 @@ Object getEnvVar(Object* params, unused int length, unused struct Environment* e
} }
return stringFromSlice("", 0); return stringFromSlice("", 0);
} }
#include <time.h>
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 #endif // STANDALONE

View File

@ -60,6 +60,12 @@ tfn(getEnvVar, "env",
"(env HOME) => /home/sagevaillancourt" "(env HOME) => /home/sagevaillancourt"
); );
tfn(randomO, "rand",
({ returns(isNumber) }),
"Returns a semi-random integer\n"
"(rand) => 2394568"
);
#endif //PEBBLISP_PC_H #endif //PEBBLISP_PC_H
#endif // STANDALONE #endif // STANDALONE

View File

@ -75,7 +75,9 @@ check() {
fi fi
local expected="$3"
if [ "$3" == "$regex" ]; then if [ "$3" == "$regex" ]; then
expected="$4"
if [[ "$output" =~ ^$4$ ]]; then if [[ "$output" =~ ^$4$ ]]; then
pass "$1" $exit_code pass "$1" $exit_code
return return
@ -86,7 +88,7 @@ check() {
fi fi
fail "$1" "$2" 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::" echo "::SHELL TESTS::"