original.name="Property_Valid_21" ====== >>> main.whiley // This benchmark was created specifically to test recursive // properties. type Node is {int data, List next} type List is null|Node // A given (sub)list is "reachable" from its enclosing list property reachable(List head, List child) -> (bool r): // Either we met the child, or need to keep searching return (head == child) || (head is Node && reachable(head.next,child)) // Lemma is needed to go "against" the direction of unrolling. This // may seem kind of strange. function lemma(List head, List child) // If head ~~> child requires reachable(head,child) // Then, head ~~> child.next ensures (child is null) || reachable(head,child.next): // if head != child: assert head is Node lemma(head.next,child) // Determine length of a list function len(List l) -> (int r): // int x = 0 List ol = l // ghost // iterate until while l is Node where l is null || reachable(ol,l): lemma(ol,l) l = l.next x = x + 1 // return x public export method test(): // List of length 1 List l1 = {data: 0, next: null} // List of length 2 List l2 = {data: 0, next: l1} // List of length 3 List l3 = {data: 0, next: l2} // assume len(null) == 0 // assume len(l1) == 1 // assume len(l2) == 2 // assume len(l3) == 3 ---