![]() |
Contents: |
|
|
... Encapsulation, ... the final frontier ... These are the attempts of the OPUS calculus
It's continuing mission to explore strange new concepts,
and new object-oriented languages
To boldly orthogonalise what no man has orthogonalised before.
Opus the Next Generation (OPUS tNG) is not an extension of the previous version of OPUS. It is a calculus that was completely redesigned from scratch.
The major source of inspiration in the design of OPUS tNG was the principle of encapsulated inheritance as explained in the paper [Steyaert&De Meuter95]. The paper shows that there is an inherent conflict between inheritance and encapsulation.
The starting premise in the design of OPUS tNG was that there should be a clear syntactic distinction between inheritable entities and first class objects. This yields a calculus with a clean integration of the object model and the inheritance mechanism while retaining syntactic and semantic simplicity.
While developing the calculus, we used the following design guidelines:
Object -> Object.Ident(Object) | [ Generator | Generator ] | Ident Generator -> Generator ; Generator | Ident(Ident) = Ident#Object | > Object < | Ident | empty
ObjExpr = set of all syntactic object expressions GenExpr = set of all syntactic generator expressions Ident = set of all syntactic identifiers
Env[a] = Ident -> Maybe[a] Maybe[a] = a + Unit Object = Env[Method] Method = Object -> Object Generator = Generator -> Object
{} : Env[a]
{} = \x.inMaybe[a]()
{...->...} : Ident -> a -> Env[a]
{key->val} = \x.(x=key -> inMaybe[a](val) , inMaybe[a]())
... +r ... : Env[a] -> Env[a] -> Env[a]
f +r g = \x.cases (g x) of
isUnit() -> f x ,
isa() -> g x
end
lookup : Env[a] -> Ident -> a
lookup = \r.\k.cases (r k) of
isa(v) -> v ,
isUnit() -> bottom
end
[ObjExpr]O : Env[Object] -> Env[Generator] -> Object [Or.I(Oa)]O = \e.\c.lookup ([Or]O e c) I ([Oa]O e c) [ [G1|G2] ]O = \e.\c.([G1]G e c) ([G2]G e c) [[G]]O = [[G|G]]O = \e.\c.([G]G e c) ([G]G e c) [I]O = \e.\c.lookup e I
[GenExpr]G : Env[Object] -> Env[Generator] -> Generator
[G1;G2]G = \e.\c.\s.([G1]G e c) s +r ([G2]G e c) s
[Im(Ia)=Is#O]G = \e.\c.\s.{Im->body}
where body = \a.[O]O (e +r {Ia->a}) (c +r {Is->s})
[>O<]G = \e.\c.\s.[O]O e c
[I]G = \e.\c.lookup c I
[empty]G = \e.\c.\s.{}
[ true = Env # [ if(action) = action.then; not = [Env].false; or(boolean) = Self # [Self]; and(boolean) = boolean ]; false = Env # [ if(action) = action.else; not = [Env].true; or(boolean) = boolean; and(boolean) = Self # [Self] ]; test = Env # [Env].false.not.or([Env].true) .if([ then=[Env].true; else=[Env].false ]) ].test
[ makeAccount(owner) = [
name = owner;
amount = 0;
withdraw(value) = Self #
[ Self; amount=[Self].amount.substract(value) ];
deposit(value) = Self # [Self; amount=[Self].amount.add(value)];
secureAccount(secret) = Self # [
Self;
checkValidity(pwd) = Self # secret.equals(pwd);
withdraw(arg) = Self # [Self].checkValidity(arg.password).if([
then = [Super|Self].withdraw(arg.value);
else = "Warning: your password is incorrect!"
]);
setPassword(arg) = Self # [Self].checkValidity(arg.old).if([
then = [Self].secureAccount(arg.new);
else = "Warning: your password is incorrect!"
])
]
];
account = Env # [Env].makeAccount("Jones")
.secureAccount("gf&452aQ")
.deposit(1000)
.setPassword([old="gf&452aQ";new="%6*tyusQ"]);
stealMoney(amount) = Env # [
>[Env].account<;
checkValidity(pwd) = True
].withdraw([value=amount;password="Don't care"])
].stealMoney(500)
[ makeCartesian(a) = [ getx = a.x; gety = a.y; distance = Self # [Self].sumOfSquares.sqrt; sumOfSquares = Self # [Self].getx.sqr.add([Self].gety.sqr) ]; makePolar(a) = [ getx = a.r.times(a.teta.cos); gety = a.r.times(a.teta.sin); distance = a.r; sumOfSquares = Self#[Self].distance.sqr ]; cartesianPoint = Env#[Env].makeCartesian([x=0;y=1]); polarPoint = Env#[Env].makePolar([r=1;teta=1,5708]); point = Env#[Env].polarPoint; manhattanPoint = Env # [ >[Env].point<; distance = Self # [Self].getx.abs.add([Self].gety.abs) ] ]
[ zero = [ ifZero(action) = action.then; succ = Pred # [ Pred; ifZero(action) = action.else; pred = [Pred] ]; ] withAdd(number) = Env # [ >number<; pred = [Env].withAdd(number.pred); succ = [Env].withAdd(number.succ); add(n) = Self # [Self].ifZero([ then = n; else = [Self].pred.add(n.succ) ]) ]; zeroWithAdd = Env # [Env].withAdd([Env].zero); one = Env # [Env].zeroWithAdd.succ; two = Env # [Env].one.succ; four = Env # [Env].two.add([Env].two); test = Env # [Env].four.pred.pred.pred.pred .ifZero([then=1;else=0]) ]
The main artifacts of the OPUS calculus are:
The following persons were involved in developing the OPUS tNG calculus: