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
Christian Schneider, Miro Spönemann TypeFox.io DEBUGGING DSLS WITH XTEXT’S NEW TRACING API 1
Debugging of Generated Code
What’s needed? • Mapping of code regions in source to code regions in target • Data structures implemented in org.eclipse.xtext
What’s already there? • Xtext maps AST elements to code regions in source
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"); }
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
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» } '''
Example https://github.com/TypeFox/tracing_codegen
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? '}';
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 ''') } }
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 ''') } }
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: 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
The Generator Tree double ; __local_2 cash = -> __local_1 double __local_2 = __local_1->cash;
The Generator Tree AST Location double ; Location __local_2 cash = Location -> __local_1
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)
Demo
What else? • What if debugging the DSL is not possible? • Feeding back changes in target to the source is strongly recommended
What else?
To Go Further https://github.com/TypeFox/tracing_codegen
Evaluate the Sessions Sign in and vote at eclipsecon.org -1 0 +1
Recommend
More recommend
Explore More Topics
Stay informed with curated content and fresh updates.