metamodeling of custom pharo images
TRANSCRIPT
Esug 2017
Meta-modelingOf custom
Pharo images
Pavel Krivanek, INRIA Nord Europe
The last conference day,Friday before lunch,
The last presentation
And they want me to listen to a talkThat starts with
META- ????
What???
DEMO
Language meta-models
● provide statical description of the language elements
● used for source code models and operations above them
Blah blah…
When is the plane departure?
meta-models plague
● Pharo runtime meta-model● Monticello metamodel ● Refactoring Browser● Ficus● Hermes● FAMIX● Ring● ...
Damn,No instructions for
cases when the terrorists attack with
a new meta-model
Ring
● meta-model to replace MC and RB ● Veronica Uquillas Gomez● since Pharo 1.4 (2012)● provide common API at structural and Runtime
level● foundational model in Pharo
One ring to rule them all
Ring - problems
● not up-to-date– slots– layouts– limited traits support (compositions...)
It was nice with youBut it is time to update
the ring
Ring - problems
● standalone models● mixing of the model and real-time system
m := RGMethodDefinition className: #Objectselector: #yourselfisMetaSide: false.
m methodClass >>> Object
real class
I found a resolution of the Fermi paradox. Sooner or
later every civilization in the universe reaches a point when it mixes a model with
a Real-time system
Ring - problems
● is nil real value or undefined value?
aClass := RGClassDefinition named: #ProtoObject.aClass superclass >>> nil.
aClass2 := RGClassDefinition named: #SomeClass.aClass2 superclass >>> nil I swear that a minute
ago the superclass was there!
Ring - problems
● low tests coverage
protocol
self isActive IfTrue: [ ^ ...].
self isHistoricalIfTrue: [ ^... ].
^ protocolSelf isHysterical iftrue:
Improved Ring
● requirements– easy standalone models– transparent linkage on run-time system – cover new Pharo language features– handle unresolved values– usable for bootstrap– browseable– announcements
Do not forget to display an inscription when heated in
a fire
Improved Ring
● scenarios– browse current run-time environment– browse (& modify) external packages– browse remote image– run code quality check on an external packages– browse external (unloaded) package like a loaded one– bootstrap small IoT ready images– study history of the code
Browse the previous commit of an external package like it would be loaded into an external image running on a bulb in
my garden house
Ring 2 - fundamentals
1) every Ring model has own complete environment
method := RG2MethodDefinition named: #someMethod.method methodClass methods size >>> 1method methodClass metaclass methods size >>> 0.method package definedClasses size >>> 1.
layout := RG2EphemeronLayoutDefinition new.layout parent isClass >>> 1.layout environment hasTraits >>> false.
The next environmentalist!
Aaaaaaaaa!!!
Ring 2 - fundamentals
2) every model property is unresolved before we know its real value
method := RG2MethodDefinition named: #someMethod.method name isRing2Resolved >>> true.method methodClass isRing2Resolved >>> false.method package isRing2Resolved >>> false.method package: (method environment ensurePackageNamed: #somePackage).method package isRing2Resolved >>> true.
You only realize the real value of something when you lost it
Ring 2 - fundamentals
3) every unresolved value has a default valuemethod := RG2MethodDefinition named: #someMethod.method environment browse.
“Processor become: nil would be better default code! ”
Ring 2 - fundamentals
4) every Ring environment has a backend
aClass := RG2ClassDefinition named: #Point.aClass environment backend class >>> RG2EnvironmentBackend.
aClass superclass name >>> #unresolved.
aClass environment backend: (RG2ReadOnlyImageBackend for: aClass environment).
aClass superclass name >>> #Object.
RG2TennisBackhand
Ring 2 - fundamentals
env := RG2Environment new.env backend: (RG2ReadOnlyImageBackend for: env).env browse.
now show the same in
Nautilus
Hahaha!!
Ring 2 - fundamentals
RG2BehaviorDefinition>>#superclass^ self backend forBehavior superclassFor: self
RG2EnvironmentBackend>>#superclassFor:^ aRG2Behavior pvtSuperclass
RG2BehaviorDefinition>>#pvtSuperclass^ superclass value
Collections:
localMethodsDo:addLocalMethod:removeLocalMethod:cleanLocalMethods:
Behind Every Great Idea Is a stupid implementation
Ring 2 - fundamentals
4) backends can use other models
joinEnv := RG2Environment new.joinEnv backend: (RG2ReadOnlyJoinBackend for: joinEnv).joinEnv backend environment1: aRGEnvironment1.joinEnv backend environment2: aRGEnvironment2.
Ring 2 - fundamentals
5) be as general as possible– do not expect classes like Object, ProtoObject,
Metaclass– do not expect that all metaclasses have the same
metaclass (Metaclass)– do not expect that all Traits have the same metaclass
(Trait)– do not expect that all class traits have the same
metaclass (ClassTrait)– ProtoObject class superclass
Once I will be a general too!
Quiz
Object superclass >>> ProtoObject.
Object class superclass >>> ProtoObject class.
ProtoObject superclass >>> nil.
ProtoObject class class >>> Metaclass.
ProtoObject class superclass >>> ?
Metaclass class superclass >>> ?
Easy! Look, I know the answer
Default environments - classes
RG2ClassDefinition named: #SomeClass.
If you think it is easy to make such graphs in dia, try it yourself
Default environments - traits
RG2TraitDefinition named: #SomeTrait.
I needed some complex graphto look smart
Environments cleaning
● unify Metaclass (Metaclass, PCMetaclass) ● unify Trait● unify TraitClass● check class – superclass – superclass metaclass –
metaclass circles● remove unused unreferenced behaviors● remove unused unreferenced packages● fix ProtoObject class superclass
Recycle trash And Prefer bicycles over cars
Query interface
● prevent huge class for environment● RG2Environment provides only basic interface
needed for the backend● #ask● cachingenvironment := RG2Environment new.environment ask allClasses.
Behind Every stupid Idea Is an even more stupid
implementation
Announcements
● enable tools binding● multiple browsers on the same environment● can be suspended
environment := RG2Environment new.environment announcer.
environment := RG2Environment new.environment announcer suspendAllWhile: [
environment clean.].
Have you tried multiple environments on the same browser?
Behavior kind switching
● example:– during a package loading create an extension
method of a behavior, expect it is a class– later realize that it is a trait
env := RG2Environment new.class := env ensureClassNamed: #SomeBehavior.class class >>> RG2ClassDefinition.method := class ensureLocalMethodNamed: #someMethod.trait := env ensureTraitNamed: #SomeBehavior.(trait localMethods collect: #name) >>> #(someMethod).trait class >>> RG2TraitDefinition.(class == trait) >>> true
Blah blah, maybe I should go for lunch now to be the first one there
Bootstrap
● by Guille Polito● create image from a source code model● small task-oriented images
repository := MCFileTreeRepository newdirectory: './src' asFileReference;yourself.
environment := repository asRing2Environment.environment fixProtoObjectClassSuperclass.environment addGlobalsNamed: #(#Smalltalk #SourceFiles #Transcript #Undeclared #Display #TextConstants #Sensor #Processor #SystemOrganization).environment clean.environment bootstrap.
Congratulations,You have
a nice small image
Calypso
● by Denis Kudriashov● new system browser
environment := RG2Environment new.environment browse.
environment := RG2Environment new.#Kernel asPackage mcWorkingCopy snapshot
importInto: environment asPackageNamed: #Kernel.environment clean.environment browse.
Calypso kept Odysseus prisoner for seven years and they had sex together Although he was married
Hermes
● by Pablo Tesone● binary packages exporter/loader● needs full environment (instVars indexes)toExport := #('SUnit-Core').environment fixProtoObjectClassSuperclass.environment addGlobalsNamed: #(#Smalltalk #UTF8TextConverter #MacRomanTextConverter #FileStream ChangeSet Character).environment clean.
toExport do: [ :packageName |oldPackage := environment ask packageNamed: packageName.hePackage := HERing2ToHermesBuilder new visitPackage: (oldPackage).writer := HEBinaryReaderWriter new
stream: (File openForWriteFileNamed: packageName, '.hermes');yourself.
hePackage writeInto: writer.writer flush; close. ].
Never choose names from the Greek mythology, Hermes was a patron of thiefs
Further work
● Pharo integration● more backends● more importers/exporters● modify tools to support it (Dependency Analyzer,
QA)● ...
And of course - rule them all
Thank you