{ void m1() {…} }

bart.disi.unige.it
  • No tags were found...

{ void m1() {…} }

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


Please think how you’d explain inheritance to a muggle 1( 1 here, indicates someone who’s never heard of OO) Odds are you’re thinking of flattening semantics


class C1 {void m1() {}}class C2 extends C1 {void m2() {}}It’s as we wroteC2 like thisWhat does this mean?class C2 {void m1() {}void m2() {}}


Giving semantics of some feature by translating it away Programs translated in (equivalent) programs thatdon’t use the featureExtendedLanguageLanguage Extension flattened intothe vanilla languageclass C2 {void m1() {}void m2() {}} Let’s see pros and consclass C2 extends C1 {void m2() {}}


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() {}}


Lookup as easy as itcan get No changes in thedefinition (the programchanges, not lookup) For instance,lookup(C2, )=(inheritance has beenflattened out)class C1 {void m1() {}}class C2 {void m1() {}void m2() {}}class C3 {void m1() {}void m2() {}void m3() {}}


class C1 {void m1() {}}class C2 extends C1 {void m2() {}}class C3 extends C2 {void m3() {}}the binarydepends onclass C1 {void m1() {}}class C2 {void m1() {}void m2() {}}class C3 {void m1() {}void m2() {}void m3() {}}


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


Please think how you’d implement inheritance Odds are you’re thinking of direct semantics


Classes can be defined in new ways Since programs are not translated,good old method lookup can’t work anymoreExtendedLanguageLanguageclass C1 {void m1() {}}We can computelookup(C, m)=class C2 extends C1 {void m2() {}}lookup(C2, m1)=???For instance, lookup(C1, m1)=


Needs to know whatextends means For instance,lookup(C3, m2) startsfrom C3 Don’t find m2, soproceeds with C2 And finds m2class C1 {void m1() {}}class C2 extends C1 {void m2() {}}class C3 extends C2 {void m3() {}}


FlatteningDirectIntuitive YES Less than theotherGood oldmethod lookupYESNOIs efficient? NO YES


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!


I’m “cheating” using class A { an extra-sugared syntax primitive types and voidabstract 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()?


class C merge{abstract void m();frozen int wrongAnswer() { return 41; }local int loc() { return 1; }} , B{frozen int answer() { return 42; }virtual void m() { loc(); }local int loc() { return answer(); }}


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(); }}


class C { // equivalent flattened definitionfrozen 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


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 again, what does new C().answer() means? what is lookup(C, answer)?


class A {abstract void m();frozen int answer() { return 41; }local int loc() { return 1; }}class C merge(rename answer to wrongAnswer in A), Bclass 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(rename FromN to ToN in ClassExpression, N)= failure if N=FromN lookup(ClassExpression, FromN) if N=ToN lookup(ClassExpression, N) otherwiseIn the example:lookup((rename answer to wrongAnswer in A), answer)fails, solookup(C, answer) = 2 choices = lookup(B, answer)


lookup(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: directsemantics is no picnic


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 statictypes (e.g. overloading and static binding) Investigating smart implementation techniques

More magazines by this user
Similar magazines