Jean-Baptiste Tristan & K. Rustan M. Leino |
class ClassName {}
predicate IsObject(c: ClassName) { c is object }
predicate IsRef(c: ClassName?) { c is object? }
class
declaration gives rise to two types:
ClassName
is the type of references to ClassName
objects
ClassName?
additionally contains the value null
object
is the type of all references
object?
additionally contains the value null
class ClassName<T> {}
class C<T(0)> {
var mutableField: T
}
private
, protected
, …)
(0)
0
says that variables of the type can be auto-initialized
predicate MemberAccess<T(0)>(c: C) { c.mutableField is T }
method Allocate<T(0)>() returns (c: C) {
c := new C;
}
method Update<T(0)>(c: C, value: T) {
c.mutableField := value;
}
mutableField
of the object referenced by c
class C {
const immutableField: int := 4
}
class C {
var mutableField: int
predicate This() { this is C }
}
this.
” (if there are no name conflicts)
this.mutableField
can be written simply as mutableField
class C {
var mutableField: int
const immutableField: int
constructor (i: int, j: int) {
immutableField := i;
mutableField := j;
}
}
method M() {
var c := new C(3, 4);
}
new
class C {
var mutableField: int
const immutableField: int
constructor Partial(i: int) {
immutableField := i;
}
constructor FromStringLength(s: string) {
mutableField := 0;
immutableField := |s|;
}
method M() {
var c := new C.FromStringLength("abc");
}
}
class C {
var mutableField: int
const immutableField: int
constructor(i: int, j: int) {
immutableField := i;
new;
mutableField := j;
}
}
new;
divides the two phases of the constructor
new;
is omitted, the first phase is the entire constructor body and the second phase is empty
new;
, the object is considered allocated
this
class C {
var mutableField: int
method Print() {
print mutableField, "\n";
}
function Get(): int {
mutableField
}
}
trait TraitName { }
trait T {
method Print() { print("Hello, World!"); }
}
class C extends T {
method RePrint() { Print(); }
}
trait
, class
, datatype
, opaque type) can inherit from (that is, extend, or implement) any number of trait
s
class
trait
more than once, but only if each time is with the same type-parameter instantiation
trait A {
method Print() { print("Hello, World!"); }
}
trait B extends A {}
method M1(o: A) { o.Print(); }
method M2(o: B) { M1(o); }
trait T {
function G(x: int): int
function F(x: int): int { G(x) }
}
class C extends T {
function G(x: int): int { x + 1 }
}
trait
can be left undefined
class
trait Complex {
function Real(): real
function Im(): real
}
class PolarComplex extends Complex {
var r: real
var i: real
function Real(): real { r }
function Im(): real { r }
}
trait Printer {
method Print()
}
class A extends Printer {
method Print() { print("A\n"); }
}
class B extends Printer {
method Print() { print("B\n"); }
}
method Print(p: Printer) {
p.Print();
}
method Main() {
var a := new A;
var b := new B;
Print(a);
Print(b);
}