|
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.
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]) ]