PLAN OF THE TALK 1)TURBULENCE IN CLASSICAL AND QUANTUM FLUIDS-MOTIVATION (3-15)
Plan of the talk
description
Transcript of Plan of the talk
Flattening versus Direct semantics for Featherweight Jigsaw
Giovanni Lagorio, Marco Servetto and Elena Zucca
Plan of the talk Flattening and Direct semantics
By example: Inheritance Featherweight Jigsaw (FJig)
(nice and clean) surface syntax Generalized inheritance
I’ll gloss over its (ugly but equivalent) core syntax
Conclusions
Flattening Semantics
The intuition of Inheritance Please think how you’d explain inheritance
to a muggle1
(1 here, indicates someone who’s never heard of OO)
Odds are you’re thinking of flattening semantics
Flattening Semantics of inheritanceclass C1 { void m1() {…}}class C2 extends C1 { void m2() {…}} It’s as we
wrote C2 like this
class C2 { void m1() {…} void m2() {…}}
What does this mean?
ExtendedLanguage
The general idea Giving semantics of some feature by
translating it away Programs translated in (equivalent) programs
that don’t use the feature
Language
class C2 extends C1 { void m2() {…}}
class C2 { void m1() {…} void m2() {…}}
Extension flattened into the vanilla language
Let’s see pros and cons
Pros: it’s intuitive class C1 { void m1() {…}}
class C2 extends C1 { void m2() {…}}
class C3 extends C2 { void m3() {…}}
class C1 { void m1() {…}}class C2 { void m1() {…} void m2() {…}}
class C3 { void m1() {…} void m2() {…} void m3() {…}}
Pros: good old method lookupclass C1 { void m1() {…}}class C2 { void m1() {…} void m2() {…}}class C3 { void m1() {…} void m2() {…} void m3() {…}}
Lookup as easy as it can get
No changes in the definition (the program changes, not lookup)
For instance,lookup(C2, …)=
(inheritance has been flattened out)
class C1 { void m1() {…}}
class C2 extends C1 { void m2() {…}}
class C3 extends C2 { void m3() {…}}
Cons: compiling dependenciesclass C1 { void m1() {…}}class C2 { void m1() {…} void m2() {…}}class C3 { void m1() {…} void m2() {…} void m3() {…}}
the binarydepends on
Flattening Semantics, recap Intuitive: good tool for
teaching/understanding Been used to give the semantics of
mixins, traits, …but
Poor implementation choice Lot of compiling dependencies (unlike Java,
like C++) Code bloating
Direct Semantics
The implementation of Inheritance Please think how you’d implement
inheritance
Odds are you’re thinking of direct semantics
ExtendedLanguage
class C2 extends C1 { void m2() {…}}
The idea Classes can be defined in new ways Since programs are not translated,
good old method lookup can’t work anymore
Language
class C1 { void m1() {…}}
We can computelookup(C, m)=…
For instance, lookup(C1, m1)=…
lookup(C2, m1)=???
Extended method lookup
Needs to know what extends means
For instance, lookup(C3, m2) starts from C3
Don’t find m2, so proceeds with C2
And finds m2
class C1 { void m1() {…}}
class C2 extends C1 { void m2() {…}}
class C3 extends C2 { void m3() {…}}
A comparison
Flattening DirectIntuitive YES Less than the
otherGood old method lookup
YES NO
Is efficient? NO YES
Featherweight Jigsaw (FJig)
Flexible class definitions class C ClassExpression ClassExpression ::=
BasicClass | merge ClassExpression1,
ClassExpression2| rename N to N’ in ClassExpression | hide N in ClassExpression | …others…
BasicClass ::= { …constr/fields/methods… }
Basic class declaration One constructor; takes any kind of
parameters Internal representation hidden from clients
A series of members: fields and methods Members can be:
abstract virtual frozen local
no definition“someone” is expected
to provide it
there is a definition,but it can be later
replaced
there is a definition, that current clients will
see forever (even if replaced)
there is a definition, that no other object will
ever see
FJig Nice per se More than that, can encode:
standard inheritance mixins traits … it’s a general framework for sw composition
Wouldn’t be wonderful to have an intuitive (flattening) semantics and a (rather complex but) efficient (direct) one?
Actually, no it wouldn’t … unless they’re equivalent! And they
are!
An example class A {
abstract void m(); frozen int answer() { return 41; } local int loc() { return 1; }}
class B { frozen int answer() { return 42; } virtual void m() { loc(); } local int loc() { return answer(); } }
class C merge(rename answer to wrongAnswer in A),B
…what’s new C().answer()?
I’m “cheating” using an extra-sugared syntax primitive types and void
Flattening steps (1 of 5) class C merge
(rename answer to wrongAnswer in A),B
class C merge(rename answer to wrongAnswer in{ abstract void m(); frozen int answer() { return 41; } local int loc() { return 1; }}), B
Flattening steps (2 of 5) class C merge
(rename answer to wrongAnswer in{ abstract void m(); frozen int answer() { return 41; } local int loc() { return 1; }}), B
class C merge{ abstract void m(); frozen int wrongAnswer() { return 41; } local int loc() { return 1; }} , B
Flattening steps (3 of 5) class C merge
{ abstract void m(); frozen int wrongAnswer() { return 41; } local int loc() { return 1; }} , B
class C merge{ abstract void m(); frozen int wrongAnswer()
{ return 41; } local int loc() { return 1; }} , { frozen int answer() { return
42; } virtual void m() { loc(); } local int loc() { return
answer(); } }
Flattening steps (4 of 5) class C merge
{ abstract void m(); frozen int wrongAnswer()
{ return 41; } local int loc() { return 1; }} , { frozen int answer() { return
42; } virtual void m() { loc’(); } local int loc’() { return
answer(); } }
Flattening steps (5 of 5) class C { // equivalent flattened
definition frozen int wrongAnswer() { return
41; } local int loc() { return 1; } frozen int answer() { return 42; } virtual void m() { loc’(); } local int loc’() { return answer(); }
} now we can easily see what new
C().answer() is and, quite obviously , it’s 42
Direct Semanticsclass A {
abstract void m(); frozen int answer() {return 41; } local int loc() { return 1; }}
class C merge(rename answer to wrongAnswer in A),B
again, what does new C().answer() means? what is lookup(C, answer)?
class B { frozen int answer() {
return 42; } virtual void m() { loc(); } local int loc() { return answer(); } }
Direct Semanticsclass A {
abstract void m(); frozen int answer() { return 41; } local int loc() { return 1; }}
class C merge(rename answer to wrongAnswer in A), B
class B { frozen int answer() { return 42;} virtual void m() { loc(); } local int loc() { return answer(); } }
lookup(C, answer) = lookup(merge …, answer) =
= lookup((rename…), answer)
and non-deterministically = lookup(B, answer)
Lookup on a rename expression
lookup(rename FromN to ToN in ClassExpression, N)= failure if N=FromN lookup(ClassExpression, FromN) if N=ToN lookup(ClassExpression, N) otherwise
In the example: lookup((rename answer to wrongAnswer in A), answer)
fails, solookup(C, answer) = … 2 choices … = lookup(B, answer)
Lookup on a namelookup(B, answer) = lookup(ClassExpression,
answer)
where ClassExpression is the class expression of B,
which is a base (flatten) class. So, we can conclude.
Believe it or not, I’ve just scratched the surface: direct semantics is no picnic
Conclusions and further work
Flatten semantics: easy, intuitive but “performs” poorly
Direct semantics can be (rather) complex but it’s a good choice for implementation
FJig: general language for software composition encompasses inheritance, mixin, traits….
Given both semantics and proved equivalent Implemented interpreter as master-thesis:
http://www.disi.unige.it/person/LagorioG/FJig/ Exploring the equivalence for feature requiring
static types (e.g. overloading and static binding) Investigating smart implementation techniques
Thank you