;
; Test suite for Treacle
; Chris Pressey, March 2008
;
; Copyright (c)2008 Cat's Eye Technologies. All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions
; are met:
;
; 1. Redistributions of source code must retain the above copyright
; notices, this list of conditions and the following disclaimer.
; 2. Redistributions in binary form must reproduce the above copyright
; notices, this list of conditions, and the following disclaimer in
; the documentation and/or other materials provided with the
; distribution.
; 3. Neither the names of the copyright holders nor the names of their
; contributors may be used to endorse or promote products derived
; from this software without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
; ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES INCLUDING, BUT NOT
; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
; FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
; COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
; BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
; CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
; ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
; POSSIBILITY OF SUCH DAMAGE.
(load "utils.scm")
(load "pattern.scm");------------------------------------------------------
(test pattern-1
(mk-named 'jim (mk-wildcard))
'#(named jim #(wildcard))
)
(test pattern-2
(is-ground? (mk-named 'jim (mk-wildcard)))
#f
)
(test pattern-3
(is-ground? '(cat dog (rabbit) (oyster pigeon)))
#t
)
(test pattern-4
(is-replacement? (mk-named 'jim (mk-wildcard)))
#f
)
(test pattern-5
(is-replacement? (mk-named 'jim 0))
#t
)
(load "index.scm");--------------------------------------------------------
(test index-fetch-1
(term-index-fetch '(1 2 3) '())
'(1 2 3)
)
(test index-fetch-2
(term-index-fetch '(1 2 3) '(0))
1
)
(test index-fetch-3
(term-index-fetch '(1 2 (1 (1 2 99) (1 2 3))) '(2 1 2))
99
)
(test index-store-1
(term-index-store '(1 2 3) '(0) 99)
'(99 2 3)
)
(load "unifier.scm");--------------------------------------------------------
(test bind-name-1
(bind-name
'(a b c (d e f))
'(3)
'ralph
'()
)
'((ralph 3))
)
(test bind-name-2
(bind-name
'(a b c (d e f))
'(3)
'ralph
'((ralph 0))
)
#f
)
(test bind-name-3
(bind-name
'(a b c a)
'(3)
'ralph
'((ralph 0))
)
'((ralph 3) (ralph 0))
)
(test expand-vars-1
(expand-vars
'(a b c (d e f))
'(i j #(named ralph k))
'((ralph 3))
0
)
'(i j (d e f))
)
(test expand-vars-2
(expand-vars
'(a b c (d e f))
'(#(named ralph 0) #(named ed 0))
'((ralph 3 1))
0
)
'(e #(named ed 0))
)
(test expand-vars-3
(expand-vars
'(a b c (d e f))
'(#(newref))
'((ralph 3 1))
33
)
'(unique-ref-33)
)
(load "match.scm");-----------------------------------------------------------
(test match-1
(toplevel-match
'(a (b c))
'(a (b c))
)
'()
)
(test match-2
(toplevel-match
'(a (b c))
'(b c)
)
#f
)
(test match-3
(toplevel-match
'(a (b c))
'(a #(named ralph #(wildcard)))
)
'((ralph 1))
)
(test match-4
(toplevel-match
'(x right (y 1 2))
'#(named t (x #(named i #(wildcard)) #(named j #(wildcard))))
)
'((t) (j 2) (i 1))
)
(test match-hole-1
(toplevel-match
'(a (b b b (c c c (d e)) b b b))
'(a #(hole innermost e))
)
'()
)
(test match-hole-2
(toplevel-match
'(a (b b b (c c c (d e)) b b b))
'(a #(hole innermost f))
)
#f
)
(test match-hole-3
(toplevel-match
'(a (b b (flag k) (c c c (d (flag a))) b b b))
'(a #(hole innermost (flag #(named jim #(wildcard)))))
)
'((jim 1 2 1))
)
(test match-hole-4
(toplevel-match
'(a (b b (flag k) (c c c (d (flag a))) b b b))
'(a #(hole innermost #(named jim (flag #(wildcard)))))
)
'((jim 1 2))
)
(test match-hole-5
(toplevel-match
'(a (b b (flag k) (c c c (d (flag a))) b b b))
'(a #(named jim #(hole innermost (flag #(wildcard)))))
)
'((jim 1))
)
(test match-hole-6
(toplevel-match
'(pair a (b b (flag k) (c c c (d (flag a))) b b b))
'(pair #(named jim #(wildcard)) #(hole innermost (flag #(named bones #(named jim #(wildcard))))))
)
'((bones 2 3 3 1 1) (jim 2 3 3 1 1) (jim 1))
)
(test match-order-1
(toplevel-match
'(thing (flag (world (a b c) (a b (flag k)))) thang)
'#(hole innermost #(named jim (flag #(wildcard))))
)
'((jim 1 1 2 2))
)
(test match-order-2
(toplevel-match
'(thing (flag (world (a b c) (a b (flag k)))) thang)
'#(hole outermost #(named jim (flag #(wildcard))))
)
'((jim 1))
)
(test match-order-3
(toplevel-match
'(ast (+ _ (* (lit 2) (lit 3))))
'(ast #(hole innermost #(named src (lit #(wildcard)))))
)
'((src 1 2 1))
)
(load "reduce.scm");----------------------------------------------------------
(test apply-rule-1
(apply-rule
'(a b c)
'#(named jim (a b c))
'((jim . k) (bones 1 2 3))
0
)
'k
)
(test apply-rule-2
(apply-rule
'(x this (x descends (x to (x the (x right (y 1 2))))))
'#(hole innermost #(named t (x #(named i #(wildcard)) #(named j #(wildcard)))))
'((t . (xx #(named j 0) #(named i 0))))
0
)
'(x this (x descends (x to (x the (xx (y 1 2) right)))))
)
(test reduce-1
(toplevel-reduce
'(a b c)
'(
( #(named jim (a b c)) . ((jim . k) (bones 1 2 3)) )
)
)
'k
)
(test reduce-2
(toplevel-reduce
'(x this (x descends (x to (x the (x right (y 1 2))))))
'(
( ; rule 1
#(hole innermost #(named t (x #(named i #(wildcard)) #(named j #(wildcard))))) .
((t . (xx #(named j 0) #(named i 0))))
)
)
)
'(xx (xx (xx (xx (xx (y 1 2) right) the) to) descends) this)
)
(test reduce-3
(toplevel-reduce
'(x this (x descends (x to (x the (x right (y 1 2))))))
'(
( ; rule 1
#(hole innermost #(named t (x #(named i #(wildcard)) #(named j #(wildcard))))) .
((t . (xx #(named j 0) #(named i 0))))
)
( ; rule 2
#(hole innermost #(named p right)) .
((p . left))
)
)
)
'(xx (xx (xx (xx (xx (y 1 2) left) the) to) descends) this)
)
(load "syntax.scm");-----------------------------------------------------------
(test syntax-term-1
(term-atom (a b c))
'(a b c)
)
(test syntax-term-2
(term-list a b c)
'(a b c)
)
(test syntax-term-3
(term-atom (a * c))
'(a #(wildcard) c)
)
(test syntax-term-4
(term-atom *)
'#(wildcard)
)
(test syntax-term-5
(term-atom (a (? bob *) (c d @) f g))
'(a #(named bob #(wildcard)) (c d #(newref)) f g)
)
(test syntax-replacements-1
(replacements a : (a b @) b : (? eb *))
'(
(a . (a b #(newref)))
(b . #(named eb #(wildcard)))
)
)
(test syntax-rules-1
(rules
(:i (? t (x (? i *) (? j *)))) -> ( t : (xx (? j 0) (? i 0)) )
(:i (? p right)) -> ( p : left )
)
'(
(
#(hole innermost #(named t (x #(named i #(wildcard)) #(named j #(wildcard))))) .
((t . (xx #(named j 0) #(named i 0))))
)
(
#(hole innermost #(named p right)) .
((p . left))
)
)
)
;-------------------------------------------------------------------
; Forest-rewriting, a la Arboretuum.
;-------------------------------------------------------------------
(test rewrite-forest-1
(toplevel-reduce
'(forest (ast (+ (lit 3) (* (lit 2) (lit 3))))
(out halt))
'(
( ; rule 1
(forest (ast #(hole innermost #(named src (lit #(named val #(wildcard))))))
(out #(hole innermost #(named dest halt)))) .
((src . _) (dest . (push #(named val) halt)))
)
( ; rule 2
(forest (ast #(hole innermost #(named src (+ _ _))))
(out #(hole innermost #(named dest halt)))) .
((src . _) (dest . (add halt)))
)
( ; rule 3
(forest (ast #(hole innermost #(named src (* _ _))))
(out #(hole innermost #(named dest halt)))) .
((src . _) (dest . (mul halt)))
)
)
)
'(forest (ast _) (out (push 3 (push 2 (push 3 (mul (add halt)))))))
)
(test rewrite-forest-2
(toplevel-reduce
'(forest (stab (a 4 eot))
(ast (+ 1 2 3 a 5 6 a 7 8 9)))
'(
( ; rule 1
(forest (stab #(hole innermost (#(named n #(wildcard)) #(named v #(wildcard)) #(named tab #(wildcard)))))
(ast #(hole innermost #(named dest #(named n #(wildcard)))))) .
((dest . #(named v)))
)
)
)
'(forest (stab (a 4 eot)) (ast (+ 1 2 3 4 5 6 4 7 8 9)))
)
(test rewrite-forest-3
(toplevel-reduce
'(forest (ast (let a (lit 4) (+ (lit 3) (* (var a) (lit 3)))) )
(stab eot)
(out halt))
'(
( ; rule 1
(forest (ast #(hole innermost #(named src
(let #(named n #(wildcard)) #(named v #(wildcard)) #(named expr #(wildcard))) )))
(stab #(hole innermost #(named dest eot)))
(out #(wildcard))) .
((src . #(named expr 0)) (dest . (#(named n 0) #(named v 0) eot)))
)
( ; rule 2
(forest (ast #(hole innermost #(named src (var #(named n #(wildcard))))))
(stab #(hole innermost (#(named n #(wildcard)) #(named v #(wildcard)) #(wildcard))))
(out #(wildcard))) .
((src . #(named v 0)))
)
( ; rule 3
(forest (ast #(hole innermost #(named src (lit #(named val #(wildcard))))))
(stab #(wildcard))
(out #(hole innermost #(named dest halt)))) .
((src . _) (dest . (push #(named val) halt)))
)
( ; rule 4
(forest (ast #(hole innermost #(named src (+ _ _))))
(stab #(wildcard))
(out #(hole innermost #(named dest halt)))) .
((src . _) (dest . (add halt)))
)
( ; rule 5
(forest (ast #(hole innermost #(named src (* _ _))))
(stab #(wildcard))
(out #(hole innermost #(named dest halt)))) .
((src . _) (dest . (mul halt)))
)
)
)
'(forest (ast _)
(stab (a (lit 4) eot))
(out (push 3 (push 4 (push 3 (mul (add halt)))))))
)
;
; This test is close to (although not exactly) what we'd like to see, for
; translating "if" statements to machine code. It uses newref to generate
; labels for the jumps. It rewrites the AST several times to ensure that
; the jumps and labels are generated in the right order.
;
(test rewrite-forest-4
(toplevel-reduce
'(forest (ast (if (> (lit 6) (lit 4)) (print (lit 1)) (print (lit 2))) )
(out halt))
'(
( ; rule -- get label for if
(forest (ast #(hole innermost #(named src (if _ #(named then #(wildcard)) #(named else #(wildcard)) ))))
(out #(wildcard))) .
((src . (iflab #(named then 0) #(named else 0) #(newref))))
)
( ; rule -- reduce if to then
(forest (ast #(hole innermost #(named src
(iflab #(named then #(wildcard)) #(named else #(wildcard)) #(named elselab #(wildcard)))
)))
(out #(hole innermost #(named dest halt)))) .
((src . (then #(named then 0) #(named else 0) #(named elselab 0)))
(dest . (jmp-if-false #(named elselab 0) halt)))
)
( ; rule -- reduce then to else
(forest (ast #(hole innermost #(named src (then _ #(named else #(wildcard)) #(named elselab #(wildcard))))))
(out #(hole innermost #(named dest halt)))) .
((src . #(named else 0)) (dest . (label #(named elselab 0) halt)))
)
( ; rule -- translate operator
(forest (ast #(hole innermost #(named src (> _ _))))
(out #(hole innermost #(named dest halt)))) .
((src . _) (dest . (gt halt)))
)
( ; rule -- translate command
(forest (ast #(hole innermost #(named src (print _))))
(out #(hole innermost #(named dest halt)))) .
((src . _) (dest . (print halt)))
)
( ; rule -- translate literal
(forest (ast #(hole innermost #(named src (lit #(named val #(wildcard))))))
(out #(hole innermost #(named dest halt)))) .
((src . _) (dest . (push #(named val) halt)))
)
)
)
'(forest (ast _)
(out (push 6 (push 4 (gt (jmp-if-false unique-ref-16
(push 1 (print (label unique-ref-16 (push 2 (print halt)))))))))))
)
;
; This test is pretty much exactly what we'd like to see for translation of
; "if" statements to machine code. It relies on the fact that all newrefs
; in a replacement generate the same new reference. It also uses an auxilliary
; tree, the bpt (branch point table) instead of rewriting the main AST to
; clarify somewhat the dependencies.
;
(test rewrite-forest-5
(toplevel-reduce
'(forest (ast (if (> (lit 6) (lit 4)) (print (lit 1)) (print (lit 2))) )
(bpt eot)
(out halt))
'(
( ; rule -- get label for if
(forest (ast #(hole innermost #(named src (if _ #(named then #(wildcard)) #(named else #(wildcard)) ))))
(bpt #(hole innermost #(named branch eot)))
(out #(hole innermost #(named dest halt)))) .
((branch . (then #(newref))) (dest . (jmp-if-false #(newref) halt)))
)
( ; rule -- get label for if
(forest (ast #(hole innermost #(named src (if _ _ #(named else #(wildcard)) ))))
(bpt #(hole innermost #(named branch (then #(named ref #(wildcard))) eot))) ; XXX???
(out #(hole innermost #(named dest halt)))) .
((branch . (else #(newref))) (dest . (goto #(newref) (label #(named ref 0) halt))))
)
( ; rule -- get label for if
(forest (ast #(hole innermost #(named src (if _ _ _) )))
(bpt #(hole innermost #(named branch (else #(named ref #(wildcard))) eot)))
(out #(hole innermost #(named dest halt)))) .
((src . _) (branch . eot) (dest . (label #(named ref 0) halt)))
)
( ; rule -- translate operator
(forest (ast #(hole innermost #(named src (> _ _))))
(bpt #(wildcard))
(out #(hole innermost #(named dest halt)))) .
((src . _) (dest . (gt halt)))
)
( ; rule -- translate command
(forest (ast #(hole innermost #(named src (print _))))
(bpt #(wildcard))
(out #(hole innermost #(named dest halt)))) .
((src . _) (dest . (print halt)))
)
( ; rule -- translate literal
(forest (ast #(hole innermost #(named src (lit #(named val #(wildcard))))))
(bpt #(wildcard))
(out #(hole innermost #(named dest halt)))) .
((src . _) (dest . (push #(named val 0) halt)))
)
))
'(forest (ast _)
(bpt eot)
(out (push 6 (push 4 (gt (jmp-if-false unique-ref-16
(push 1 (print (goto unique-ref-29
(label unique-ref-16 (push 2 (print
(label unique-ref-29 halt)))))))))))))
)
; Treacle syntax for previous test.
(test rewrite-forest-6
(toplevel-reduce
'(forest (ast (if (> (lit 6) (lit 4)) (print (lit 1)) (print (lit 2))) )
(bpt eot)
(out halt))
(rules
(forest (ast (:i (? src (if _ (? then *) (? else *)))))
(bpt (:i (? branch eot)))
(out (:i (? dest halt))))
-> ( branch : (then @) dest : (jmp-if-false @ halt) )
(forest (ast (:i (? src (if _ _ (? else *)))))
(bpt (:i (? branch (then (? ref *)))))
(out (:i (? dest halt))))
-> ( branch : (else @) dest : (goto @ (label (? ref *) halt)) )
(forest (ast (:i (? src (if _ _ _))))
(bpt (:i (? branch (else (? ref *)))))
(out (:i (? dest halt))))
-> ( src : _ branch : eot dest : (label (? ref *) halt) )
(forest (ast (:i (? src (> _ _ ))))
(bpt *)
(out (:i (? dest halt))))
-> ( src : _ dest : (gt halt) )
(forest (ast (:i (? src (print _))))
(bpt *)
(out (:i (? dest halt))))
-> ( src : _ dest : (print halt) )
(forest (ast (:i (? src (lit (? val *)))))
(bpt *)
(out (:i (? dest halt))))
-> ( src : _ dest : (push (? val *) halt) )
))
'(forest (ast _)
(bpt eot)
(out (push 6 (push 4 (gt (jmp-if-false unique-ref-16
(push 1 (print (goto unique-ref-29
(label unique-ref-16 (push 2 (print
(label unique-ref-29 halt)))))))))))))
)