/*
* Kodkod -- Copyright (c) 2005-2012, Emina Torlak
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package kodkod.examples.bmc;
import java.util.HashSet;
import java.util.Set;
/****** List demo ******/
/**
* Node spec.
*
* @specfield next: Node + null
* @specfield data: String + null
* @author Emina Torlak
*
*/
final class Node {
String data;
Node next;
Node(String data, Node next) {
this.data = data;
this.next = next;
}
}
/**
* List spec.
*
* @specfield head: Node + null
* @specfield nodes: set Node + null
* @invariant nodes = head.*next
* @invariant no iden & ^(next & nodes -> nodes)
* @author Emina Torlak
*
*/
public class List {
private Node head;
public List() {
head = null;
}
public void add(String item) {
head = new Node(item, head);
}
public boolean empty() {
return head == null;
}
/**
* @requires this.head != null && this.head.next != null
* @modifies next, head
* @ensures let ns = this.nodes - null | nodes' = nodes and next' & (ns -> ns) = ~ (next & (ns -> ns))
*/
public void reverse(){
Node nearNode = head;
Node midNode = nearNode.next;
Node farNode = midNode.next;
nearNode.next = farNode /* should be null */;
while(farNode != null){
midNode.next = nearNode;
nearNode = midNode;
midNode = farNode;
farNode = farNode.next;
}
midNode.next = nearNode;
head = midNode;
}
/**
* @requires this.head != null && this.head.next != null
* @modifies next, head
* @ensures let ns = nodes - null | nodes' = nodes and next' & (ns -> ns) = ~(next & (ns -> ns))
*/
public void reverseFinitized(){
assert this.head != null && // assume this.head != null && this.head.next != null
this.head.next != null;
Node nearNode = this.head; // nearNode0 := this.head
Node midNode = nearNode.next; // midNode0 := nearNode0.next
Node farNode = midNode.next; // farNode0 := midNode0.next
nearNode.next = farNode; // next0 := update(next, nearNode0 -> farNode0)
if (farNode != null) { // guard0 := farNode0 != null
midNode.next = nearNode; // next1 := update(next0, midNode0 -> nearNode0)
nearNode = midNode; // nearNode1 := midNode0
midNode = farNode; // midNode1 := farNode0
farNode = farNode.next; // farNode1 := farNode0.next1
}
// next2 := phi(guard0, next1, next0)
// nearNode2 := phi(guard0, nearNode1, nearNode0)
// midNode2 := phi(guard0, midNode1, midNode0)
// farNode2 := phi(guard0, farNode1, farNode0)
assert farNode == null; // assume farNode2 = null
midNode.next = nearNode; // next3 = update(next2, midNode2 -> nearNode2)
this.head = midNode; // head0 = update(head, this -> midNode2)
}
public String toString() {
final StringBuilder b = new StringBuilder();
final Set<Node> nodes = new HashSet<Node>();
b.append("[");
if (head != null) {
b.append(head.data);
Node current = head.next;
nodes.add(head);
while(current != null && nodes.add(current)) {
b.append(", ");
b.append(current.data);
current = current.next;
}
if (current != null)
b.append(", " + current.data + ", ...");
}
b.append("]");
return b.toString();
}
public static void test(String[] in) {
List l0 = new List();
for(String v : in)
l0.add(v);
System.out.println("\nl0: " + l0);
l0.reverse();
System.out.println("l0.reverse(): " + l0);
List l1 = new List();
for(String v : in)
l1.add(v);
System.out.println("l1: " + l1);
l1.reverseFinitized();
System.out.println("l1.reverseFinitized(): " + l1);
}
public static void main(String[] args) {
final String[] in2 = { "a", "b" }, in3 = { "a", "b", "c" };
test(in2);
test(in3);
}
}