debugging dsls with xtext s new tracing api
play

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. Christian Schneider, Miro Spönemann 
 TypeFox.io DEBUGGING DSLS WITH XTEXT’S NEW TRACING API 1

  2. Debugging of Generated Code

  3. What’s needed? • Mapping of code regions in source 
 to code regions in target • Data structures implemented in org.eclipse.xtext

  4. What’s already there? • Xtext maps AST elements to 
 code regions in source

  5. What’s missing? • Mapping of AST elements to code regions in target 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"); }

  6. Requirements • API for tracing code regions in code generators • Should integrate nicely with Xtend’s template expressions • Trace code regions per eObject • Attributes: 
 Distinguish code regions corresponding to attributes • Containment: 
 Distinguish code regions corresponding to children

  7. XTEND http://xtend-lang.org def foo(Object parameter) ''' @Accessors Code code «parameter» code @FinalFieldsConstructor class Foo implements Bar { code with leading white space @Delegate «IF guard» val Bar bar guard is satisfied code } «ELSE» guard is missed code «ENDIF» «FOR element : list» element «element.name» code: def String name(Object o) { more element specific code ... «ENDFOR» } '''

  8. Example https://github.com/TypeFox/tracing_codegen

  9. Model: types+=ClassDeclaration*; class Person { ClassDeclaration: name: string 'class' name=ID '{' bag: Bag members+=Member* getCash(): number { '}'; bag.wallet.cash } Member: } Property | Operation; Property: name=ID ':' type=TypeRef; Operation: name=ID '(' parameters+=Parameter* ')' ':' type=TypeRef '{' expression=Expression? '}';

  10. class MyDslGenerator extends AbstractGenerator { override void doGenerate(Resource resource, 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 ''') } }

  11. class MyDslGenerator extends AbstractGenerator { override void doGenerate(Resource resource, 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 ''') } }

  12. 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» }; '''

  13. @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» }; '''

  14. @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» }; '''

  15. ClassDeclaration: ClassDeclaration MyDslFactory 'class' name=ID '{' name: String createClassDeclaration() members+=Member* members: Member[] … '}'; Xtext + EMF @TracedAccessors(MyDslFactory) class MyDslTraceExtensions {} Xtend Annotation Processor public IGeneratorNode _name(ClassDeclaration target) { … } @Inject extension MyDslTraceExtensions

  16. The Generator Tree double ; __local_2 cash = -> __local_1 double __local_2 = __local_1->cash;

  17. The Generator Tree AST Location double ; Location __local_2 cash = Location -> __local_1

  18. 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)

  19. Demo

  20. What else? • What if debugging the DSL is not possible? • Feeding back changes in target to the source is strongly recommended

  21. What else?

  22. To Go Further https://github.com/TypeFox/tracing_codegen

  23. Evaluate the Sessions Sign in and vote at eclipsecon.org -1 0 +1

Recommend


More recommend