;;; Some simple constant frames
((%() <= a))
((%() <= (*not* a)))
((%() <= (*OR* b a c)))
((%() <= (*or* a a)))
((%() <= (*MULT* b a c)))
((%() <= (*mult* a b a)))
((%() <= ((b 1) (a 2))))
((%() <= ((a 1) (b (*OR* c ((d 4)))))))


;;; Now some mixture of paths
((%() <= %()))
((%() <= ((a 1) (b (*OR* c ((d %())))))))


;;; The *TEST* keyword
((*test* a))
((*TEST* *Undefined*))
((*TEST* *Fail*))


;;; Statement lists
((%() <= a)
 (%() <= b)
 (%() <= c))

((%() <= a)
 (*TEST* *FAIL*)
 (%() <= c))

((%() <= ((a 1) (b 2)))
 (*PRINT* (*MULT* "Environment is: " %()))
)

; Here, the statement list is in a different file.
("secret_patrick_test.pat")


;;; Now for some nifty path extraction
((%() <= ((a 1) (b 2)))
 (%() <= ((empty %()) (no-paren %a) (paren %(b)))))

; Trick path: no adverb
((%() <= ((Subject I) (Predicate ((Verb like) (Object cheese)))))
 (%() <= ((Adverb %(Predicate Adverb)) (Object %(Predicate Object)))))

((%() <= ((Subject I) (Predicate (*NOT* ((Verb like) (Object cheese))))))
 (%() <= %(Predicate Object)))

; This will fail because of the *NOT* (and the *UNDEFINED* Adverb)
((%() <= ((Subject I) (Predicate (*NOT* ((Verb like) (Object cheese))))))
 (%() <= %(Predicate Adverb)))

((%() <= ((Subject I) (Predicate (*OR* ((Verb like) (Object cheese))
				      ((Verb like) (Object ham))))))
 (%() <= ((Object %(Predicate Object))
	 (Verb %(Predicate Verb))
	 (Adverb %(Predicate Adverb))
	 (Indices %(Predicate *INDEX*))
	 (Bad-Indices %(Predicate Adverb *index*))
	 (Reverse-Indices %(Predicate *REVERSE-index*)))))

((%() <= ((Subject I) (Predicate (*MULT* ((Verb like) (Object cheese))
				      ((Verb like) (Object ham))))))
 (%() <= ((Object %(Predicate Object))
	 (Verb %(Predicate Verb))
	 (Adverb %(Predicate Adverb))
	 (Indices %(Predicate *INDEX*))
	 (Bad-Indices %(Predicate Adverb *INDEX*))
	 (Reverse-Indices %(Predicate *REVERSE-INDEX*)))))


;;; Thoroughly test the overwrite statement (for path overwriting)

((%x <= -)
 (%x <= +))

((%x <= -)
 (%y <= +))

; Should fail
((%x <= -)
 (%y <= *FAIL*))

((%(a b c) <= +)
 (%(a b d e) <= +))

; shouldn't do anything
((%(a b c) <= *UNDEFINED*))

((%x <= (*MULT* 1 2 3 4))
 (%x = (*NOT* 3)))

((%x <= (*MULT* 1 2 3 4))
 (%x = (*NOT* 4)))

((%x <= (*MULT* 1 2 3 4))
 (%x = (*MULT* 2 4)))

((%x <= (*MULT* 1 2 3 4))
 (%x = (*OR* 2 4)))


((%() <= ((Subject I) (Predicate (*NOT* ((Verb like) (Object cheese))))))
 (%(Predicate) <= drink))


((%() <= ((Subject I) (Predicate (*OR* ((Verb eat) (Object cheese))
				      ((Verb eat) (Object ham))))))
 (%(Predicate Adverb) <= often))

; This overwrite should abolish the *OR*.
((%() <= ((Subject I) (Predicate (*OR* ((Verb eat) (Object cheese))
				      ((Verb eat) (Object ham))))))
 (%(Predicate Object) <= potatoes))


((%() <= ((Subject I) (Predicate (*MULT* ((Verb like) (Object cheese))
				      ((Verb like) (Object ham))))))
 (%(Predicate Object) <= potatoes))

((%() <= ((Subject I) (Predicate (*MULT* ((Verb eat) (Object cheese))
				      ((Verb eat) (Object ham))))))
 (%(Predicate Adverb) <= often))

((%() <= ((Subject I) (Predicate (*MULT* ((Verb eat) (Object cheese))
				      ((Verb eat) (Object ham))))))
 (%(Predicate Object) <= (*MULT* oats rice barley corn)))


;;; Thoroughly test the assignment statement (for path unify)
;;; (Does not include path-path assignment)

((%x = (*OR* ((a 1)) ((b 2)))))

((%x <= (*OR* 0 1))
 (%x = (*OR* 1 2)))

; should pass
((%x <= -)
 (%x = -))

; should fail
((%x <= -)
 (%x = +))

; should pass
((%x <= -)
 (%y = +))

((%x <= a)
 (%x = (*NOT* b)))

((%x <= (*NOT* a))
 (%x = b))

; This result is somewhat counterintuitive. Be wary of unifying two *NOT*s
; (It is the correct result according to the design rules)
((%x <= (*NOT* a))
 (%x = (*NOT* b)))

((%() <= ((Subject I) (Predicate (*OR* ((Verb eat) (Object cheese))
				      ((Verb eat) (Object ham))))))
 (%(Predicate Adverb) = often))

; This unification prunes out drinking
((%() <= ((Subject I) (Predicate (*OR* ((Verb eat) (Object cheese))
				      ((Verb drink) (Object coffee))))))
 (%(Predicate Object) = cheese))

; Fails
((%() <= ((Subject I) (Predicate (*OR* ((Verb eat) (Object cheese))
				      ((Verb drink) (Object coffee))))))
 (%(Predicate Verb) = be_merry))

; Should collapse *OR* w/o pruning values
((%() <= ((Subject I) (Predicate (*OR* ((Verb eat) (Object (*OR* ham cheese)))
			      ((Verb eat) (Object (*OR* green_eggs ham)))))))
 (%(Predicate Object) = ham))

; Prounes out ham, but passes with 'quickly'.
((%() <= ((Subject I) (Predicate (*OR* ((Verb eat) (Object ham))
			      ((Verb eat) (Adverb quickly))))))
 (%(Predicate Object) = cheese))

((%() <= ((Subject I) (Predicate (*MULT* ((Verb eat) (Object cheese))
				      ((Verb eat) (Object ham))))))
 (%(Predicate Adverb) <= often))

; fails
((%() <= ((Subject I) (Predicate (*MULT* ((Verb like) (Object cheese))
				      ((Verb like) (Object ham))))))
 (%(Predicate Object) = potatoes))

; Creates two identical items
((%() <= ((Subject I) (Predicate (*MULT* ((Verb eat) (Object (*OR* ham cheese)))
			      ((Verb eat) (Object (*OR* green_eggs ham)))))))
 (%(Predicate Object) = ham))

; A MULT-style unification
((%() <= ((Subject I) (Predicate (*MULT* ((Verb eat) (Object (*OR* ham cheese)))
			      ((Verb like) (Object (*OR* green_eggs ham)))))))
 (%(Predicate Object) = (*MULT* cheese green_eggs)))

; Order matters; this one fails
((%() <= ((Subject I) (Predicate (*MULT* ((Verb eat) (Object (*OR* ham cheese)))
			      ((Verb like) (Object (*OR* green_eggs ham)))))))
 (%(Predicate Object) = (*MULT* green_eggs cheese)))


;;; Test *INDEX* and *REVERSE-INDEX*

; Does nothing
((%(x *REVERSE-INDEX*) = 1))

; Fails
((%*INDEX* = 2))

((%() <= (*OR* a b))
 (%*INDEX* = 1))

; Fails
((%() <= (*OR* a b))
 (%*INDEX* = 2))

((%() <= (*MULT* a b c))
 (%*INDEX* = 3))

((%() <= (*MULT* a b c))
 (%*REVERSE-INDEX* = 3))

((%() <= (*MULT* a b c))
 (%*INDEX* = (*NOT* 3)))


;;; Function
((%() <= (*MULT* a #nop b #nop #nop c)))


;;; Constrain

; Constrain usually works like assign:
((%() <= ((a (*OR* 1 2)) (b (*OR* 2 3))))
 (%a = 2)
 (%b =c 2))

; but path must be defined. This passes
((%() <= ((a 1) (b 2)))
 (%c = 1))

; but this fails
((%() <= ((a 1) (b 2)))
 (%c =c 1))

; so should this
((%() <= (*OR* ((a 1) (b 2)) ((a 2))))
 (%b =c (*NOT* 1)))

; on *MULT*s, = - for some, =c - for every. This passes:
((%() <= (*MULT* 1 1 2))
 (%() = 1))

; but this fails
((%() <= (*MULT* 1 1 2))
 (%() =c 1))

; fails
((%x <= (*MULT* 1 2 3 4))
 (%x =c (*NOT* 3)))

; passes
((%x <= (*MULT* 1 2 3 4))
 (%x =c (*NOT* 5)))

; fails
((%x <= (*MULT* 1 2 3 4))
 (%x =c (*MULT* 2 4)))

; passes
((%x <= (*MULT* (*OR* 1 a) (*OR* 2 b) (*OR* 3 c) (*OR* 4 d)))
 (%x =c (*MULT* (*OR* 1 w) (*OR* 2 x) (*OR* 3 y) (*OR* 4 z))))

; Fails
((%x <= (*MULT* 1 2 3 4))
 (%x =c (*OR* 2 4)))

; passes
((%x <= (*MULT* 1 2 3 4))
 (%x =c (*OR* 1 2 3 4)))


; Slots unify differently, too. This fails:
((%() <= ((a 1) (b 2)))
 (%() = ((b 3) (c 4))))

; but this passes
((%() <= ((a 1) (b 2)))
 (%() =c ((b 3) (c 4))))

; but this passes
((%() <= ((x ((a 1) (b 2)))))
 (%() =c ((x ((b 3) (c 4))))))

; should fail
((%a <= 1)
 (%(b c) =c +))

; also should fail
((%a <= +)
 (%(a b) =c +))

; should fail
((%a <= +)
 (%(b c) =c (*NOT* +)))

; Fails.
; (Theoretically, one could conceive that the 'object ham' is pruned
; out, and 'object I' is added to the 'quickly' clause. However, the
; algorithm decides that 'I' doesn't unify with 'ham')
((%() <= ((Subject I) (Predicate (*OR* ((Verb eat) (Object ham))
			      ((Verb eat) (Adverb quickly))))))
 (%(Predicate Object) = %Subject))


;;; Transfer

((%() = ((a 1) (b 2)))
 (%c == %a))

((%() = ((a 1) (b 2)))
 (%a == %a))

; should fail
((%() = ((a 1) (b 2)))
 (%c == %d))

; a bit weird, due to the empty slot.
((%() = ((a 1) (b 2)))
 (%(c d) == %(c d)))

((%() = ((Predicate (*OR* ((Verb Eat) (Object cheese))
			  ((Verb Drink) (Object coffee))))))
 (%Subject == %(Predicate Object)))


;;; Path-path assignment

((%() <= ((a (*OR* 1 2)) (b (*OR* 2 3))))
 (%a = %b))

; Does nothing
((%() <= ((a (*OR* 1 2)) (b (*OR* 2 3))))
 (%a = %a))

; Correct, although x used to get changed around a bit.
((%x <= (*OR* ((a 1)) ((b 2))))
 (%y = %x))


;;; Push
((%() <= ((x (*MULT* 1 2))))
 (%x > 9))

((%() <= ((x (*MULT* 1 2))))
 (%x > (*MULT* 8 9)))

((%() <= ((x 1)))
 (%x > 9))

((%x > 9))

((%x = 1)
 (%y > #eval-slots %z))

((%() <= (*OR* ((x (*MULT* 1 2 3))) ((x 4))))
 (%x > 9))

; Adds 'cheese' to both predicates, creating object when necessary
((%() <= ((Subject I) (Predicate (*OR* ((Verb eat) (Object ham))
			      ((Verb eat) (Adverb quickly))))))
 (%(Predicate Object) > cheese))


;;; Pop

((%() <= ((x (*MULT* 1 2 3))))
 (%y < %x))

((%() <= ((x (*MULT* 1 2))))
 (%y < %x))

((%() <= ((x (*OR* 1 2))))
 (%y < %x))

; fails
((%() <= ((x 1)))
 (%y < %z))

; self-reference
((%() <= ((x (*MULT* 1 2 3))))
 (%x < %x))

; Pops out 'han', ignoring the adverbial predicate
((%() <= ((Subject I) (Predicate (*OR* ((Verb eat) (Object ham))
			      ((Verb eat) (Adverb quickly))))))
 (%result < %(Predicate Object)))

; Pops out 'han' and 'cheese'.
((%() <= ((Subject I) (Predicate (*OR* ((Verb eat) (Object ham))
			      ((Verb eat) (Object cheese))))))
 (%result < %(Predicate Object)))


;;; defined

((%() = ((Predicate (*OR* ((Verb Eat) (Object cheese))
			  ((Verb Drink) (Object coffee))))))
 (%(Predicate Object) = *DEFINED*))

((%() = ((Predicate (*OR* ((Verb Eat) (Object cheese))
			  ((Verb Drink) (Object coffee))))))
 (%(Predicate Adverb) = *Defined*))

; should prune out object clause
((%() = ((Predicate (*OR* ((Verb Eat) (Object cheese))
			  ((Verb Drink) (Adverb quickly))))))
 (%(Predicate Adverb) = *defined*))

((%x = *DEFINED*))

;;; undefined

((%() = ((Predicate (*OR* ((Verb Eat) (Object cheese))
			  ((Verb Drink) (Object coffee))))))
 (%(Predicate Object) = *UNDEFINED*))

((%() = ((Predicate (*OR* ((Verb Eat) (Object cheese))
			  ((Verb Drink) (Object coffee))))))
 (%(Predicate Adverb) = *undefined*))

; should prune out adverb clause
((%() = ((Predicate (*OR* ((Verb Eat) (Object cheese))
			  ((Verb Drink) (Adverb quickly))))))
 (%(Predicate Adverb) = *undefined*))


;;; remove

((%() = ((Predicate (*OR* ((Verb Eat) (Object cheese))
			  ((Verb Drink) (Object coffee))))))
 (%(Predicate Object) = *REMOVE*))

((%() = ((Predicate (*OR* ((Verb Eat) (Object cheese))
			  ((Verb Drink) (Object coffee))))))
 (%(Predicate Adverb) = *Remove*))


;;; Try

; Passes, sets c
((%() <= ((a 1) (b 2)))
 (*TRY* ((%c = 3))))

; Passes; does nothing
((%() <= ((a 1) (b 2)))
 (*Try* ((%a = 3))))

; Passes, sets c, doesn't set d
((%() <= ((a 1) (b 2)))
 (*TRY* ((%c = 3))
	((%d = 4))))

; Passes, sets d
((%() <= ((a 1) (b 2)))
 (*TRY* ((%a = 3))
	((%d = 4))))

; Fails
((%() <= ((a 1) (b 2)))
 (*TRY* ((%a = 3))
	((%b = 4))))


;;; Not

; Fails
((%() <= ((a 1) (b 2)))
 (*NOT* ((%c = 3))))

; Passes; does nothing
((%() <= ((a 1) (b 2)))
 (*Not* ((%a = 3))))

; Fails
((%() <= ((a 1) (b 2)))
 (*NOT* ((%b = 3))
	((%c = 4))))

; Passes; does nothing
((%() <= ((a 1) (b 2)))
 (*NOT* ((%a = 3))
	((%b = 4))))


;;; Or

; Passes, sets c
((%() <= ((a 1) (b 2)))
 (*OR* ((%c = 3))))

; Passes; does nothing
((%() <= ((a 1) (b 2)))
 (*Or* ((%a = 3))))

; Passes, sets c, and d, returns *OR*
((%() <= ((a 1) (b 2)))
 (*OR*  ((%c = 3))
	((%d = 4))))

; Passes, sets d
((%() <= ((a 1) (b 2)))
 (*OR*  ((%a = 3))
	((%d = 4))))

; Fails
((%() <= ((a 1) (b 2)))
 (*OR*  ((%a = 3))
	((%b = 4))))

; Succeeds, doesn't change environment
((%() <= ((a 1) (b 2)))
 (*OR*  ((%a = *UNDEFINED*))
	((%a = *DEFINED*))))


;;; Test the global callouts

((%() <= #collapse-mult (*MULT* a c e a f b g f a e d)))
((%() <= #collapse-mult (*MULT* b a)))
((%() <= #collapse-mult (*OR* b a)))

((%() <= ((Subject I) (Predicate (*MULT* ((Verb like) (Object cheese))
				      ((Verb like) (Object ham))))))
 (%(result env) = #eval-path ((env %())))
 (%(result Subject) = #eval-path ((env %()) (path Subject)))
 (%(result Object) = #eval-path ((env %()) (path (*MULT* Predicate Object))))
 (%(result Adverb) = #eval-path ((env %()) (path (*MULT* Predicate Adverb))))
 (%(result Index) = #eval-path ((env %()) (path (*MULT* Predicate *INDEX*))))
 (%(result Reverse-Index) = #eval-path ((env %()) (path (*MULT* Predicate *REVERSE-INDEX*)))))

((%() <= #eval-slots (*MULT* ((slot a) (value (*MULT* 1 2 3)))
			     ((slot b) (value +)))))
; Alternately:
((%() <= #eval-slots ((slot (*MULT* a b c)) (value (*MULT* 1 2 3)))))

((*TEST* #is-mult (*OR* a b)))
((*TEST* #is-mult (*MULT* a b)))

((*TEST* #is-or (*OR* a b)))
((*TEST* #is-or (*MULT* a b)))

((*TEST* #is-slots ((a 1) (b 2))))
((*TEST* #is-slots a))

((*TEST* #is-symbol ((a 1) (b 2))))
((*TEST* #is-symbol a))
; A bool, but still a symbol
((*TEST* #is-symbol +))
; *UNDEFINED* is not a symbol.
((*TEST* #is-symbol *UNDEFINED*))

((%() <= #join (*MULT* f o o b a r)))
((%() <= #join ((member (*MULT* f o o b a r)))))
((%() <= #join ((member (*MULT* f o o b a r)) (interceding "x "))))

((%() <= #split "foo bar baz"))
((%() <= #split "Tést"))
((%() <= #split ((string "foo bar baz"))))
((%() <= #split ((string "foo bar baz") (interceding " "))))
((%() <= #split ((string "foo bar baz") (interceding ba))))

((%() <= #plus (*MULT* 2 3 4)))
((%() <= #plus (*MULT* 2 3 "400")))

((%() <= #max (*OR* 2 3 4)))
((%() <= #min (*MULT* 2 3 4)))

