DEBUGGING DSLS WITH XTEXT’S NEW TRACING API
1
DEBUGGING DSLS WITH XTEXTS NEW TRACING API 1 Debugging of - - PowerPoint PPT Presentation
Christian Schneider, Miro Spnemann TypeFox.io DEBUGGING DSLS WITH XTEXTS NEW TRACING API 1 Debugging of Generated Code Whats needed? Mapping of code regions in source to code regions in target Data structures
1
to code regions in target
code regions in source
public class Debugging { public static void main(final String[] args) throws Throwable { IntegerRange _upTo = new IntegerRange(2, 100); final List<Integer> candidates = IterableExtensions.<Integer>toList(_upTo); List<Integer> _immutableCopy = ImmutableList.<Integer>copyOf(candidates); final Function1<Integer, Boolean> _function = new Function1<Integer, Boolean>() { @Override public Boolean apply(final Integer i) { return Boolean.valueOf(candidates.contains(i)); } }; Iterable<Integer> _filter = IterableExtensions.<Integer>filter(_immutableCopy final Function2<List<Integer>, Integer, List<Integer>> _function_1 = new Function2<List<Integer>, Integer, List<Integer>>() { @Override public List<Integer> apply(final List<Integer> res, final Integer i) { final Function1<Integer, Boolean> _function = new Function1<Integer, Boolean>() { @Override public Boolean apply(final Integer j) { return Boolean.valueOf((((j).intValue() % (i).intValue()) == 0)); } }; Iterable<Integer> _filter = IterableExtensions.<Integer>filter(candidates final List<Integer> sieved = IterableExtensions.<Integer>toList(_filter Iterables.removeAll(res, sieved); return res; } }; List<Integer> _fold = IterableExtensions.<Integer, List<Integer>>fold(_filter String _join = IterableExtensions.join(_fold, ", "); InputOutput.<String>println(_join); InputOutput.<String>println("done"); }
expressions
Distinguish code regions corresponding to attributes
Distinguish code regions corresponding to children
def foo(Object parameter) ''' Code code «parameter» code code with leading white space «IF guard» guard is satisfied code «ELSE» guard is missed code «ENDIF» «FOR element : list» element «element.name» code: more element specific code «ENDFOR» ''' @Accessors @FinalFieldsConstructor class Foo implements Bar { @Delegate val Bar bar } def String name(Object o) { ... }
http://xtend-lang.org
https://github.com/TypeFox/tracing_codegen
Model: types+=ClassDeclaration*; ClassDeclaration: 'class' name=ID '{' members+=Member* '}'; Member: Property | Operation; Property: name=ID ':' type=TypeRef; Operation: name=ID '(' parameters+=Parameter* ')' ':' type=TypeRef '{' expression=Expression? '}'; class Person { name: string bag: Bag getCash(): number { bag.wallet.cash } }
class MyDslGenerator extends AbstractGenerator {
IFileSystemAccess2 fsa, IGeneratorContext context) { val model = resource.contents.head as Model val baseName = resource.baseName fsa.generateFile(baseName + '.h', ''' /******************************** * Header file for «resource.URI.lastSegment» */ #ifndef «baseName.toUpperCase»_H #define «baseName.toUpperCase»_H «FOR c : model.types» «generateHeader(c)» «ENDFOR» #endif ''') } }
class MyDslGenerator extends AbstractGenerator {
IFileSystemAccess2 fsa, IGeneratorContext context) { val model = resource.contents.head as Model val baseName = resource.baseName fsa.generateTracedFile(baseName + '.h', model, ''' /******************************** * Header file for «resource.URI.lastSegment» */ #ifndef «baseName.toUpperCase»_H #define «baseName.toUpperCase»_H «FOR c : model.types» «generateHeader(c)» «ENDFOR» #endif ''') } }
protected def generateHeader(ClassDeclaration decl) ''' /* * Declaration of «decl.name» class */ struct «decl.name» { «FOR prop : decl.members.filter(Property)» /* Property «decl.name».«prop.name» */ «generateDeclaration(prop)» «ENDFOR» }; '''
@Traced protected def generateHeader(ClassDeclaration decl) ''' /* * Declaration of «decl.name» class */ struct «decl.name» { «FOR prop : decl.members.filter(Property)» /* Property «decl.name».«prop.name» */ «generateDeclaration(prop)» «ENDFOR» }; '''
@Traced protected def generateHeader(ClassDeclaration decl) ''' /* * Declaration of «decl.name» class */ struct «decl._name» { «FOR prop : decl.members.filter(Property)» /* Property «decl.name».«prop.name» */ «generateDeclaration(prop)» «ENDFOR» }; '''
ClassDeclaration: 'class' name=ID '{' members+=Member* '}'; @TracedAccessors(MyDslFactory) class MyDslTraceExtensions {}
ClassDeclaration name: String members: Member[] MyDslFactory createClassDeclaration() …
Xtext + EMF public IGeneratorNode _name(ClassDeclaration target) {…} Xtend Annotation Processor @Inject extension MyDslTraceExtensions
double __local_2 = __local_1
cash ;
double __local_2 = __local_1->cash;
double __local_2 = __local_1
cash ;
AST
Location Location Location
Building a Generator Tree
val node = trace(expression) node.append(generateType(expression.feature.type)) node.append(' ') node.append(resultVar) node.append(' = ') node.append(receiverVar ?: 'this') node.append('->') node.append(expression.feature.name)
strongly recommended
https://github.com/TypeFox/tracing_codegen
To Go Further