/*
 * Souffle - A Datalog Compiler
 * Copyright (c) 2021 The Souffle Developers. All rights reserved
 * Licensed under the Universal Permissive License v 1.0 as shown at:
 * - https://opensource.org/licenses/UPL
 * - <souffle root>/licenses/SOUFFLE-UPL.txt
 */

// Tests whether ADT access is working correctly

////////////
// Test 1 //
////////////

.type ADT1 = br1 {x : number, y :number}

.decl A(e:ADT1)
A($br1(1, 2)).

.decl test1()
test1() :-
   A($br1(1, 2)).

////////////
// Test 2 //
////////////

.type ADT2 = br2 {x : number}

.decl B(e:ADT2)
B($br2(1)).

.decl test2()
test2() :-
   B($br2(1)).

////////////
// Test 3 //
////////////

.type ADT3 = br3 {x : number, y :number}

.decl C(e:ADT3)
C($br3(1, 2)).

.decl D(e:number,b:number)
D(left,right) :-
   C($br3(left, right)).

.decl test3()
test3() :-
   D(1,2).

////////////
// Test 4 //
////////////

.type ADT4 = br4 {x : number}

.decl E(e:ADT4)
E($br4(1)).

.decl F(b:number)
F(left) :-
   E($br4(left)).

.decl test4()
test4() :-
   F(1).

////////////
// Test 5 //
////////////

.type ADT5 = br5 {} | br6 {}

.decl G(x:ADT5)
G($br5()).
G($br6()).

.decl test5()
test5() :-
   G($br5()),
   G($br6()).

////////////
// Test 6 //
////////////

.type ADT6 =
    A {s:symbol, a:symbol}
  | B {s:symbol, b:symbol}

.decl input2(a:symbol, b:symbol)
input2("a","b").

.decl input1(n:ADT6)
input1($B("c","b")).

.decl res(b:ADT6, a:ADT6)
res($B(s, b), $A(s, a)) :-
   input1($B(s, b)),
   input2(a,b).

.decl test6()
test6() :-
   res(_,_).

////////////
// Test 7 //
////////////

.type ADT7 = I{x:number, y:ADT7} | K{}

.decl X(x:ADT7)
X($I(1,$I(2,$K()))).
X(term) :-
  X($I(_,term)).

.decl Y(x:number)
Y(ord(a)) :-
  X(a).

.decl test7()
test7() :-
  count:{Y(_)} = 3.

////////////
// Test 8 //
////////////

.type VirtualNodeLattice =
  VirtualNodeValue     { v: VirtualNode }

.type VirtualNode =
  VBinaryNode { e1: symbol }

.decl add(n: VirtualNodeLattice, op1: symbol)

add($VirtualNodeValue($VBinaryNode("test0")),"test1").
add(vn, op1) :-
  add(vn, _),
  vn = $VirtualNodeValue(n),
  n = $VBinaryNode(op1).

.decl test8()
test8() :-
  count:{add(_,_)} = 2.

////////////
// Test 9 //
////////////

.type VirtualNode2 =
  VNV { variable: symbol }

.decl value_num(f: symbol, n: VirtualNode2)
.decl var_max(f: symbol)

value_num(func, $VNV("v")) :-
  var_max(func).

var_max("f").

var_max(func) :-
  var_max(_),
  value_num(func, $VNV(_)).

.decl test9()
test9() :-
  count:{var_max(_)} = 1.

.output test1, test2, test3, test4, test5, test6, test7, test8, test9
