001/*
002 * Copyright (c) 2012-2017 Institut National des Sciences Appliquées de Lyon (INSA-Lyon)
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 */
009
010package org.eclipse.golo.compiler.ir;
011
012public class IrTreeDumper implements GoloIrVisitor {
013
014  private int spacing = 0;
015
016  private void space() {
017    System.out.print("# ");
018    for (int i = 0; i < spacing; i++) {
019      System.out.print(" ");
020    }
021  }
022
023  private void incr() {
024    spacing = spacing + 2;
025  }
026
027  private void decr() {
028    spacing = spacing - 2;
029  }
030
031  @Override
032  public void visitModule(GoloModule module) {
033    space();
034    System.out.println(module.getPackageAndClass());
035    module.walk(this);
036  }
037
038  @Override
039  public void visitModuleImport(ModuleImport moduleImport) {
040    incr();
041    space();
042    System.out.println(" - " + moduleImport);
043    moduleImport.walk(this);
044    decr();
045  }
046
047  @Override
048  public void visitNamedAugmentation(NamedAugmentation namedAugmentation) {
049    incr();
050    space();
051    System.out.println("Named Augmentation " + namedAugmentation.getName());
052    namedAugmentation.walk(this);
053    decr();
054  }
055
056  @Override
057  public void visitAugmentation(Augmentation augmentation) {
058    incr();
059    space();
060    System.out.println("Augmentation on " + augmentation.getTarget());
061    if (augmentation.hasNames()) {
062      incr();
063      for (String name : augmentation.getNames()) {
064        space();
065        System.out.println("Named Augmentation " + name);
066      }
067      decr();
068    }
069    augmentation.walk(this);
070    decr();
071  }
072
073  @Override
074  public void visitStruct(Struct struct) {
075    incr();
076    space();
077    System.out.println("Struct " + struct.getPackageAndClass().className());
078    space();
079    System.out.println(" - target class = " + struct.getPackageAndClass());
080    incr();
081    space();
082    System.out.println("Members: ");
083    struct.walk(this);
084    decr();
085    decr();
086  }
087
088  @Override
089  public void visitUnion(Union union) {
090    incr();
091    space();
092    System.out.println("Union " + union.getPackageAndClass().className());
093    space();
094    System.out.println(" - target class = " + union.getPackageAndClass());
095    union.walk(this);
096    decr();
097  }
098
099  @Override
100  public void visitUnionValue(UnionValue value) {
101    incr();
102    space();
103    System.out.println("Value " + value.getPackageAndClass().className());
104    space();
105    System.out.println(" - target class = " + value.getPackageAndClass());
106    if (value.hasMembers()) {
107      space();
108      System.out.println(" - members = " + value.getMembers());
109    }
110    decr();
111  }
112
113  @Override
114  public void visitFunction(GoloFunction function) {
115    incr();
116    space();
117    System.out.print("Function " + function.getName() + " = ");
118    visitFunctionDefinition(function);
119    decr();
120  }
121
122  private void visitFunctionDefinition(GoloFunction function) {
123    System.out.print("|");
124    boolean first = true;
125    for (String param : function.getParameterNames()) {
126      if (first) {
127        first = false;
128      } else {
129        System.out.print(", ");
130      }
131      System.out.print(param);
132    }
133    System.out.print("|");
134    if (function.isVarargs()) {
135      System.out.print(" (varargs)");
136    }
137    if (function.isSynthetic()) {
138      System.out.print(" (synthetic, " + function.getSyntheticParameterCount() + " synthetic parameters)");
139      if (function.getSyntheticSelfName() != null) {
140        System.out.print(" (selfname: " + function.getSyntheticSelfName() + ")");
141      }
142    }
143    System.out.println();
144    function.walk(this);
145  }
146
147  @Override
148  public void visitDecorator(Decorator decorator) {
149    incr();
150    space();
151    System.out.println("@Decorator");
152    decorator.getExpressionStatement().accept(this);
153    decr();
154  }
155
156  @Override
157  public void visitBlock(Block block) {
158    if (block.isEmpty()) { return; }
159    incr();
160    space();
161    System.out.println("Block");
162    block.walk(this);
163    decr();
164  }
165
166  @Override
167  public void visitLocalReference(LocalReference ref) {
168    incr();
169    space();
170    System.out.println(" - " + ref);
171    decr();
172  }
173
174  @Override
175  public void visitConstantStatement(ConstantStatement constantStatement) {
176    incr();
177    space();
178    System.out.println("Constant = " + constantStatement.getValue());
179    decr();
180  }
181
182  @Override
183  public void visitReturnStatement(ReturnStatement returnStatement) {
184    incr();
185    space();
186    System.out.println("Return");
187    returnStatement.walk(this);
188    decr();
189  }
190
191  @Override
192  public void visitFunctionInvocation(FunctionInvocation functionInvocation) {
193    incr();
194    space();
195    System.out.println("Function call: " + functionInvocation.getName()
196        + ", on reference? -> " + functionInvocation.isOnReference()
197        + ", on module state? -> " + functionInvocation.isOnModuleState()
198        + ", anonymous? -> " + functionInvocation.isAnonymous()
199        + ", named arguments? -> " + functionInvocation.usesNamedArguments());
200
201    functionInvocation.walk(this);
202    decr();
203  }
204
205  @Override
206  public void visitAssignmentStatement(AssignmentStatement assignmentStatement) {
207    incr();
208    space();
209    System.out.print("Assignment: " + assignmentStatement.getLocalReference());
210    System.out.println(assignmentStatement.isDeclaring() ? " (declaring)" : "");
211    assignmentStatement.walk(this);
212    decr();
213  }
214
215  @Override
216  public void visitDestructuringAssignment(DestructuringAssignment assignment) {
217    incr();
218    space();
219    System.out.format(
220        "Destructuring assignement: {declaring=%s, varargs=%s}%n",
221        assignment.isDeclaring(),
222        assignment.isVarargs());
223    incr();
224    for (LocalReference ref : assignment.getReferences()) {
225      space();
226      System.out.println("- " + ref);
227    }
228    decr();
229    assignment.getExpression().accept(this);
230    decr();
231  }
232
233  @Override
234  public void visitReferenceLookup(ReferenceLookup referenceLookup) {
235    incr();
236    space();
237    System.out.println("Reference lookup: " + referenceLookup.getName());
238    decr();
239  }
240
241  @Override
242  public void visitConditionalBranching(ConditionalBranching conditionalBranching) {
243    incr();
244    space();
245    System.out.println("Conditional");
246    conditionalBranching.getCondition().accept(this);
247    conditionalBranching.getTrueBlock().accept(this);
248    if (conditionalBranching.hasFalseBlock()) {
249      conditionalBranching.getFalseBlock().accept(this);
250    } else if (conditionalBranching.hasElseConditionalBranching()) {
251      conditionalBranching.getElseConditionalBranching().accept(this);
252    }
253    decr();
254  }
255
256  @Override
257  public void visitCaseStatement(CaseStatement caseStatement) {
258    incr();
259    space();
260    System.out.println("Case");
261    incr();
262    for (WhenClause<Block> c : caseStatement.getClauses()) {
263      space();
264      System.out.println("When");
265      incr();
266      c.condition().accept(this);
267      c.action().accept(this);
268      decr();
269    }
270    space();
271    System.out.println("Otherwise");
272    caseStatement.getOtherwise().accept(this);
273    decr();
274  }
275
276  @Override
277  public void visitMatchExpression(MatchExpression matchExpression) {
278    incr();
279    space();
280    System.out.println("Match");
281    incr();
282    for (WhenClause<?> c : matchExpression.getClauses()) {
283      c.accept(this);
284    }
285    space();
286    System.out.println("Otherwise");
287    matchExpression.getOtherwise().accept(this);
288    decr();
289  }
290
291  @Override
292  public void visitWhenClause(WhenClause<?> whenClause) {
293    space();
294    System.out.println("When");
295    incr();
296    whenClause.walk(this);
297    decr();
298  }
299
300  @Override
301  public void visitBinaryOperation(BinaryOperation binaryOperation) {
302    incr();
303    space();
304    System.out.println("Binary operator: " + binaryOperation.getType());
305    binaryOperation.walk(this);
306    decr();
307  }
308
309  @Override
310  public void visitUnaryOperation(UnaryOperation unaryOperation) {
311    incr();
312    space();
313    System.out.println("Unary operator: " + unaryOperation.getType());
314    unaryOperation.getExpressionStatement().accept(this);
315    decr();
316  }
317
318  @Override
319  public void visitLoopStatement(LoopStatement loopStatement) {
320    incr();
321    space();
322    System.out.println("Loop");
323    if (loopStatement.hasInitStatement()) {
324      loopStatement.getInitStatement().accept(this);
325    }
326    loopStatement.getConditionStatement().accept(this);
327    loopStatement.getBlock().accept(this);
328    if (loopStatement.hasPostStatement()) {
329      loopStatement.getPostStatement().accept(this);
330    }
331    decr();
332  }
333
334  @Override
335  public void visitForEachLoopStatement(ForEachLoopStatement foreachStatement) {
336    incr();
337    space();
338    System.out.println("Foreach");
339    incr();
340    for (LocalReference ref : foreachStatement.getReferences()) {
341      ref.accept(this);
342    }
343    foreachStatement.getIterable().accept(this);
344    if (foreachStatement.hasWhenClause()) {
345      space();
346      System.out.println("When:");
347      foreachStatement.getWhenClause().accept(this);
348    }
349    foreachStatement.getBlock().accept(this);
350    decr();
351    decr();
352  }
353
354  @Override
355  public void visitMethodInvocation(MethodInvocation methodInvocation) {
356    incr();
357    space();
358    System.out.format("Method invocation: %s, null safe? -> %s%n",
359        methodInvocation.getName(),
360        methodInvocation.isNullSafeGuarded());
361    methodInvocation.walk(this);
362    decr();
363  }
364
365  @Override
366  public void visitThrowStatement(ThrowStatement throwStatement) {
367    incr();
368    space();
369    System.out.println("Throw");
370    throwStatement.getExpressionStatement().accept(this);
371    decr();
372  }
373
374  @Override
375  public void visitTryCatchFinally(TryCatchFinally tryCatchFinally) {
376    incr();
377    space();
378    System.out.println("Try");
379    tryCatchFinally.getTryBlock().accept(this);
380    if (tryCatchFinally.hasCatchBlock()) {
381      space();
382      System.out.println("Catch: " + tryCatchFinally.getExceptionId());
383      tryCatchFinally.getCatchBlock().accept(this);
384    }
385    if (tryCatchFinally.hasFinallyBlock()) {
386      space();
387      System.out.println("Finally");
388      tryCatchFinally.getFinallyBlock().accept(this);
389    }
390    decr();
391  }
392
393  @Override
394  public void visitClosureReference(ClosureReference closureReference) {
395    GoloFunction target = closureReference.getTarget();
396    incr();
397    space();
398    if (target.isAnonymous()) {
399      System.out.print("Closure: ");
400      incr();
401      visitFunctionDefinition(target);
402      decr();
403    } else {
404      System.out.printf(
405          "Closure reference: %s, regular arguments at index %d%n",
406          target.getName(),
407          target.getSyntheticParameterCount());
408      incr();
409      for (String refName : closureReference.getCapturedReferenceNames()) {
410        space();
411        System.out.println("- capture: " + refName);
412      }
413      decr();
414    }
415    decr();
416  }
417
418  @Override
419  public void visitLoopBreakFlowStatement(LoopBreakFlowStatement loopBreakFlowStatement) {
420    incr();
421    space();
422    System.out.println("Loop break flow: " + loopBreakFlowStatement.getType().name());
423    decr();
424  }
425
426  @Override
427  public void visitCollectionLiteral(CollectionLiteral collectionLiteral) {
428    incr();
429    space();
430    System.out.println("Collection literal of type: " + collectionLiteral.getType());
431    for (ExpressionStatement statement : collectionLiteral.getExpressions()) {
432      statement.accept(this);
433    }
434    decr();
435  }
436
437  @Override
438  public void visitCollectionComprehension(CollectionComprehension collectionComprehension) {
439    incr();
440    space();
441    System.out.println("Collection comprehension of type: " + collectionComprehension.getType());
442    incr();
443    space();
444    System.out.println("Expression: ");
445    collectionComprehension.getExpression().accept(this);
446    space();
447    System.out.println("Comprehension: ");
448    for (Block b : collectionComprehension.getLoopBlocks()) {
449      b.accept(this);
450    }
451    decr();
452    decr();
453  }
454
455  @Override
456  public void visitNamedArgument(NamedArgument namedArgument) {
457    incr();
458    space();
459    System.out.println("Named argument: " + namedArgument.getName());
460    namedArgument.getExpression().accept(this);
461    decr();
462  }
463
464  @Override
465  public void visitMember(Member member) {
466    space();
467    System.out.print(" - ");
468    System.out.print(member.getName());
469    System.out.println();
470  }
471}