m3 for moose
TRANSCRIPT
Oscar Nierstrasz
Software Composition Group
scg.unibe.ch
SC Seminar 2014-04-07
M3 for Moose
Roadmap
The agile modeling problem
4
Smalltalk
Navigation
Metrics
Querying
Grouping
Smalltalk
Java
C++
Python
…
Extensible meta model
Model repository
Moose is a powerful tool
once we have a model …
Roassal
Orion DSM ...BugMap
5
Grammar stealing
Recycling trees
Parsing by example
Evolutionary Grammar
Generation
Incrementally refine
island grammars
Automatic structure
recognition
6
(
(FAMIX.Namespace (id: 182)
(name 'snakes'))
(FAMIX.Class (id: 8)
(name 'DieTest')
...
m3(|project://...|)[
@fieldAccess={
...
},
...
Idea: steal models from Rascal
Especially
interesting for
languages other
than Java!
7
Works, but is very painful
Errors in generated
MSE are hard to
debug
M3 for Moose
9
Idea: directly parse and transform
M3 models from Pharo
m3(|project://...|)[
@fieldAccess={
...
},
...
10
m3(|project://p2-SnakesAndLadders|)[
@fieldAccess={
<|java+method://p2-SnakesAndLadders/snakes/Game/toString()|,|java+field://p2-SnakesAndLadders/snakes/Game/squares|>,
<|java+method://p2-SnakesAndLadders/snakes/Game/addSquares(int)|,|java+field://p2-SnakesAndLadders/snakes/Game/squares|>,
...
},
@extends={
<|java+class://p2-SnakesAndLadders/snakes/Snake|,|java+class://p2-SnakesAndLadders/snakes/Ladder|>,
<|java+class://p2-SnakesAndLadders/snakes/Ladder|,|java+class://p2-SnakesAndLadders/snakes/Square|>,
...
},
@methodInvocation={
<|java+method://p2-SnakesAndLadders/snakes/SimpleGameTest/move8jillWins(snakes.Game)|,|java+method://p2
<|java+variable://p2-SnakesAndLadders/snakes/Game/toString()/buffer|,|java+constructor://p2
...
},
@typeDependency={
<|java+method://p2-SnakesAndLadders/snakes/Square/nextSquare()|,|java+primitiveType://p2-SnakesAndLadders/int|>,
module m3::m3util
import lang::java::jdt::m3::Core;
import lang::java::m3::TypeHierarchy;
import IO;
import List;
/* dumpM3(|project://p2-SnakesAndLadders|); */
@doc { Write the M3 model for an Eclipse Java project to its source directory. }
public void dumpM3(loc project) {
M3 m = createM3FromEclipseProject(project);
loc file = m.id + "<m.id.authority>.m3.txt";
iprintToFile(file, m);
}
URIs (“locations”)
Step 1: dump M3 from Rascal and Eclipse
11
Step 2: parse M3
12
URIs are parsed separately
13
Step 3: build POSOs (Plain Old Smalltalk Objects)
PPM3ModelParser>>start
^ super start
==> [ :nodes |
M3Model new
project: nodes second;
annotations: nodes fourth;
uriCache: uriCache ]
14
Step 4: transform URIs to FAMIX entities
M3Model>>buildURIs
uriCache values do:
[ : each | |entity|
entity := each buildFAMIXEntity.
entity ifNotNil: [ mooseModel silentlyAdd: entity ] ]
M3URI>>famixClass
^ FAMIXClass new
name: self name;
yourself
M3URI>>famixInterface
^ self famixClass
isInterface: true;
yourself
M3URI>>famixMethod
^ FAMIXMethod new
name: self path;
yourself
M3URI>>famixConstructor
^ self famixMethod
isConstructor: true;
yourself
M3URI>>famixField
^ FAMIXAttribute new
name: self name;
yourself Etc. etc.
M3URI>>buildFAMIXEntity
famixEntity := self perform: (self class famixMethodFor: self scheme).
^ famixEntity
15
M3Model>>buildExtends
| extends |
extends := self at: 'extends'.
extends ifNotNil:
[extends do:
[ : inheritance || aSubclass aSuperclass |
aSubclass := inheritance first famixEntity.
aSuperclass := inheritance second famixEntity.
mooseModel silentlyAdd:
(FAMIXInheritance new
subclass: aSubclass;
superclass: aSuperclass) ] ]
Etc. etc.
Step 5: interpret annotations for FAMIX entities
16
M3Model>>buildContainment
...
(self at: 'containment') do:
[ : each | | whole part |
whole := each first famixEntity.
part := each second famixEntity.
part setContainer: whole.
...
]
... FAMIXAttribute>>setContainer: aFamixEntity
self assert: [ aFamixEntity isClass ].
aFamixEntity addAttribute: self
FAMIXLocalVariable>>setContainer: aFamixEntity
self assert: [ aFamixEntity isMethod ].
self parentBehaviouralEntity: aFamixEntity
FAMIXMethod>>setContainer: aFamixEntity
self assert: [ aFamixEntity isClass ].
aFamixEntity addMethod: self
Caveat! mappings from M3 to FAMIX can be tricky
17
Step 6: load into Moose!
M3Model import transformToMoose; install.
MoosePanel open.
Lessons Learned
19
It is easy to get lost when
your parser backtracks
Domain-specific browsers and debuggers are cool!
Two-level parsers
simplify development
and debugging
Model transformation
is not straightforward
m3(|project://...|)[
@fieldAccess={
...
},
...
?!
20
Links
http://smalltalkhub.com/#!/~onierstrasz/M3ForMoose
https://github.com/onierstrasz/M3ForMooseTestCase
https://github.com/onierstrasz/rascal-m3-to-mse