/**
 * Testing for collect strategies.
 */
module collect-test
imports libstratego-lib

strategies 

 main = 
  test-suite(!"collect-test",
    collect-split-tests
  ; collect-om-tests
  ; collect-all-tests
  ; crush-tests
  ; collect-legacy-tests
  ; occurrences-tests
  )

signature
  constructors
    F : A * A -> A
    G : A * A -> A
    H : A * A -> A
    I : A -> A
    A : A
    B : A
    C : A

  constructors
    Assign : Exp * Exp -> Exp
    Plus   : Exp * Exp -> Exp
    Var    : String -> Exp

strategies

  occurrences-tests = id
    ; apply-test(!"om occurences test 1"
      , om-occurrences(?Var(_))
      , !Plus(Var(Var(Var("x"))), Var("z"))
      , !2
      )
    ; apply-test(!"om occurences test 2"
      , om-occurrences(?Var(_))
      , !Var("z")
      , !1
      )
    ; apply-test(!"occurences test 1"
      , occurrences(?Var(_))
      , !Plus(Var(Var(Var("x"))), Var("z"))
      , !4
      )
    ; apply-test(!"occurences test 2"
      , occurrences(?Var(_))
      , !Var("z")
      , !1
      )



strategies

  collect-split-tests = 
    apply-test(!"collect split tests 1"
    , collect-split(\ H(x,y) -> I(x) \, \ H(x,y) -> [H(x,y)] \ )
    , !F(G(A,H(A,B)),H(B,C))
    , !(F(G(A,I(A)), I(B)), [H(A,B),H(B,C)])
    )
  ; apply-test(!"collect split tests 2"
    , collect-split(\ H(x,y) -> I(x) \, \ H(x,y) -> [H(x,y)] \ )
    , !F(G(A,H(A{"Test1"},B)){"Test2"},H(B,C))
    , !(F(G(A,I(A{"Test1"})){"Test2"}, I(B)), [H(A{"Test1"},B),H(B,C)])
    )
  ; apply-test(!"collect split tests 3"
    , collect-split(\ H(x,y) -> I(x) \, \ H(x,y) -> [H(x,y)] \ )
    , !F(G("a",H(A,3.0)),H(1,C))
    , !(F(G("a",I(A)), I(1)), [H(A,3.0),H(1,C)])
    )

  collect-om-tests =
    apply-test(!"collect-om test"
    , collect-om(G(id,id))
    , !F(G(A,G(A,B)),G(B,C))
    , ![G(A,G(A,B)),G(B,C)]
    )

  collect-all-tests =
    apply-test(!"collect-all test"
    , collect-all(G(id,id))
    , !F(G(A,G(A,B)),G(B,C))
    , ![G(A,G(A,B)),G(A,B),G(B,C)]
    )
  ; apply-test(!"collect-all skip test 1"
    , collect-all(?Var(_), conc, \ Assign(_, e) -> e \)
    , !Assign(Var("x"), Plus(Var("y"), Var("z")))
    , ![Var("y"), Var("z")]
    )

  ; apply-test(!"collect-all skip test 2"
    , collect-all(?Var(_), union, \ Assign(_, e) -> e \)
    , !Assign(Var("x"), Plus(Var("z"), Var("z")))
    , ![Var("z")]
    )

  ; apply-test(!"collect-all skip test 3"
    , collect-all(?Var(_), union, \ Assign(_, e) -> e \)
    , !Assign(Var("x"), Var("y"))
    , ![Var("y")]
    )


  crush-tests = 
    apply-test(!"crush test 1"
    , crush(id, ![<Fst> | <Snd>])
    , !F(G(A,G(A,B)),G(B,C))
    , ![G(A,G(A,B)),G(B,C)]
    )
  ; apply-test(!"crush test 2"
    , rec x(crush(id, ![<Fst> | <Snd>], x))
    , !F(G(A,G(A,B)),G(B,C))
    , ![[[],[[],[]]],[[],[]]]
    )

  collect-legacy-tests =
    apply-test(!"collect test with skip argument"
    , collect(G(id,id), not-under-f)
    , !H(G(A,G(A,B)),F(G(B,C),G(A,B)))
    , ![G(A,G(A,B)),G(A,B)]
    )

  not-under-f(coll, ignore) =
    F(ignore, coll)
