OPUS : The Next Generation

OPUS Logo

Contents:


Last revision: May 23, 1996


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


Motivation

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:

Technical Details

Syntax

Object	->
		Object.Ident(Object)
	|	[ Generator | Generator ]
	|	Ident
Generator	->
		Generator ; Generator
	|	Ident(Ident) = Ident#Object
	|	> Object <
	|	Ident
	|	empty

Denotational Semantics

Syntactic Domains

ObjExpr =	set of all syntactic object expressions
GenExpr =	set of all syntactic generator expressions
Ident =	set of all syntactic identifiers

Semantic Domains

Env[a] =	Ident -> Maybe[a]
Maybe[a] =	a + Unit
Object =	Env[Method]
Method =	Object -> Object
Generator =	Generator -> Object

Auxiliary Functions

{}	:	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

Semantics of an Object Expression

[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

Semantics of a Generator Expression

[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.{}

Examples

Booleans

[	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

Bank Account

[ 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)

Cartesian and polar points

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

Numerals

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

Papers

Technical Reports

Artifacts

The main artifacts of the OPUS calculus are:

Authors

The following persons were involved in developing the OPUS tNG calculus: