String form of potentially cyclic types
A potentially cyclic object might have more that one reference to the same object. When you need the string form of a potentially cyclic object, the correlator uses a special syntax to ensure that you can distinguish multiple references to the same object from references to separate objects that merely have the same content.
When the correlator converts a potentially cyclic object to a string, the correlator labels that object @0. If the correlator encounters a second object during execution of the same method, it labels that object as @1, and so on. Whenever the correlator encounters an object that it has already converted, it outputs that object's @index label rather than converting it again. For example:
event E { sequence<E> seq; }
E e := new E;
e.seq.append(e);
print e.toString(); // "E([@0])"
Following is a more complicated example:
event Test {
string str;
sequence<Test> seq;
string str2;
}
monitor m {
action onload() {
Test t:=new Test;
t.str:="hello";
t.str2:=t.str;
t.seq.append(t);
Test t2:=new Test;
t.seq.append(t2);
t.seq.append(t2);
t2.seq.append(t);
print t.toString();
}
}
This prints the following:
Test("hello",[@0,Test("",[@0],""),@2],"hello")
The objects @0, @1, @2, and @3 correspond to the following:
@0 | Test("hello",[@0,Test("",[@0],""),@2],"hello") | t in the above example |
@1 | [@0,Test("",[@0],""),@2] | t.seq in the above example |
@2 | Test("",[@0],"") | t2 in the above example |
@3 | [@0] | t2.seq in the above example |
The following example uses the clone() method and contains action references. The result uses the new string syntax for aliases to the same object.
event E {
action<> act;
sequence<string> x;
sequence<string> y;
}
monitor m {
action onload() {
E a:=new E;
a.x.append("alpha");
a.y:=a.x;
E b:=a.clone();
b.x[0]:="beta";
print b.y.toString();
print a.toString();
}
}
The output is as follows:
["beta"]
E(new action<>,["alpha"],@1)
Note that dictionary keys can never contain aliases so they do not receive @n labels for referenced objects in toString() and parse() methods.
Whether you need to do anything to handle this string syntax depends on why you want a string representation of your object:
If you are using the string for diagnostic messages, you just need to understand the syntax.
If you plan to feed the string into the
parse() method, the
parse() method will handle it correctly.
If you plan to feed the string into some other program, you should either avoid repeated references in an object or make sure the other program can handle the
@index syntax.