]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/printing/ExpressionToStringVisitor.java
(refs #7375) Replaced collectEffects by CollectEffectsVisitor
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / expressions / printing / ExpressionToStringVisitor.java
1 package org.simantics.scl.compiler.elaboration.expressions.printing;
2
3 import java.util.Map.Entry;
4
5 import org.simantics.scl.compiler.elaboration.chr.CHRLiteral;
6 import org.simantics.scl.compiler.elaboration.chr.CHRQuery;
7 import org.simantics.scl.compiler.elaboration.chr.CHRRule;
8 import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;
9 import org.simantics.scl.compiler.elaboration.expressions.Assignment;
10 import org.simantics.scl.compiler.elaboration.expressions.Case;
11 import org.simantics.scl.compiler.elaboration.expressions.EAmbiguous;
12 import org.simantics.scl.compiler.elaboration.expressions.EApply;
13 import org.simantics.scl.compiler.elaboration.expressions.EApplyType;
14 import org.simantics.scl.compiler.elaboration.expressions.EAsPattern;
15 import org.simantics.scl.compiler.elaboration.expressions.EBinary;
16 import org.simantics.scl.compiler.elaboration.expressions.EBind;
17 import org.simantics.scl.compiler.elaboration.expressions.EBlock;
18 import org.simantics.scl.compiler.elaboration.expressions.ECHRRuleset;
19 import org.simantics.scl.compiler.elaboration.expressions.ECHRRulesetConstructor;
20 import org.simantics.scl.compiler.elaboration.expressions.ECHRSelect;
21 import org.simantics.scl.compiler.elaboration.expressions.EConstant;
22 import org.simantics.scl.compiler.elaboration.expressions.ECoveringBranchPoint;
23 import org.simantics.scl.compiler.elaboration.expressions.EEnforce;
24 import org.simantics.scl.compiler.elaboration.expressions.EEquations;
25 import org.simantics.scl.compiler.elaboration.expressions.EError;
26 import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant;
27 import org.simantics.scl.compiler.elaboration.expressions.EFieldAccess;
28 import org.simantics.scl.compiler.elaboration.expressions.EGetConstraint;
29 import org.simantics.scl.compiler.elaboration.expressions.EIf;
30 import org.simantics.scl.compiler.elaboration.expressions.EIntegerLiteral;
31 import org.simantics.scl.compiler.elaboration.expressions.ELambda;
32 import org.simantics.scl.compiler.elaboration.expressions.ELambdaType;
33 import org.simantics.scl.compiler.elaboration.expressions.ELet;
34 import org.simantics.scl.compiler.elaboration.expressions.EListComprehension;
35 import org.simantics.scl.compiler.elaboration.expressions.EListLiteral;
36 import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
37 import org.simantics.scl.compiler.elaboration.expressions.EMatch;
38 import org.simantics.scl.compiler.elaboration.expressions.EPlaceholder;
39 import org.simantics.scl.compiler.elaboration.expressions.EPreLet;
40 import org.simantics.scl.compiler.elaboration.expressions.ERange;
41 import org.simantics.scl.compiler.elaboration.expressions.ERealLiteral;
42 import org.simantics.scl.compiler.elaboration.expressions.ERecord;
43 import org.simantics.scl.compiler.elaboration.expressions.ERuleset;
44 import org.simantics.scl.compiler.elaboration.expressions.ESelect;
45 import org.simantics.scl.compiler.elaboration.expressions.ESimpleLambda;
46 import org.simantics.scl.compiler.elaboration.expressions.ESimpleLet;
47 import org.simantics.scl.compiler.elaboration.expressions.EStringLiteral;
48 import org.simantics.scl.compiler.elaboration.expressions.ETransformation;
49 import org.simantics.scl.compiler.elaboration.expressions.ETypeAnnotation;
50 import org.simantics.scl.compiler.elaboration.expressions.EVar;
51 import org.simantics.scl.compiler.elaboration.expressions.EVariable;
52 import org.simantics.scl.compiler.elaboration.expressions.EViewPattern;
53 import org.simantics.scl.compiler.elaboration.expressions.EWhen;
54 import org.simantics.scl.compiler.elaboration.expressions.Expression;
55 import org.simantics.scl.compiler.elaboration.expressions.ExpressionVisitor;
56 import org.simantics.scl.compiler.elaboration.expressions.GuardedExpression;
57 import org.simantics.scl.compiler.elaboration.expressions.GuardedExpressionGroup;
58 import org.simantics.scl.compiler.elaboration.expressions.Variable;
59 import org.simantics.scl.compiler.elaboration.java.EqRelation;
60 import org.simantics.scl.compiler.elaboration.java.MemberRelation;
61 import org.simantics.scl.compiler.elaboration.query.QAlternative;
62 import org.simantics.scl.compiler.elaboration.query.QAtom;
63 import org.simantics.scl.compiler.elaboration.query.QConjunction;
64 import org.simantics.scl.compiler.elaboration.query.QDisjunction;
65 import org.simantics.scl.compiler.elaboration.query.QExists;
66 import org.simantics.scl.compiler.elaboration.query.QIf;
67 import org.simantics.scl.compiler.elaboration.query.QMapping;
68 import org.simantics.scl.compiler.elaboration.query.QNegation;
69 import org.simantics.scl.compiler.elaboration.query.Query;
70 import org.simantics.scl.compiler.elaboration.query.QueryVisitor;
71 import org.simantics.scl.compiler.elaboration.rules.SectionName;
72 import org.simantics.scl.compiler.elaboration.rules.TransformationRule;
73
74 public class ExpressionToStringVisitor implements ExpressionVisitor, QueryVisitor {
75
76     StringBuilder b = new StringBuilder();
77     int indentation;
78     
79     public ExpressionToStringVisitor(StringBuilder b) {
80         this.b = b;
81     }
82
83     public void show(Variable variable) {
84         if(variable == null)
85             b.append("NULL_VARIABLE");
86         else
87             b.append(variable.getName());
88     }
89     
90     private void newLine() {
91         b.append('\n');
92         for(int i=0;i<indentation;++i)
93             b.append("  ");
94     }
95     
96     public void showPar(Expression expression) {
97         boolean needsPar = false;
98         while(true) {
99             if(expression instanceof EPlaceholder)
100                 expression = ((EPlaceholder)expression).expression;
101             else if(expression instanceof ETypeAnnotation)
102                 expression = ((ETypeAnnotation)expression).getValue();
103             else if(expression instanceof EApplyType)
104                 expression = ((EApplyType)expression).getExpression();
105             else if(expression instanceof ELambdaType)
106                 expression = ((ELambdaType)expression).value;
107             else if(expression instanceof ECoveringBranchPoint)
108                 expression = ((ECoveringBranchPoint)expression).expression;
109             else
110                 break;
111         }
112         if(expression instanceof EApply ||
113                 expression instanceof EIf ||
114                 expression instanceof ESimpleLambda ||
115                 expression instanceof ESimpleLet)
116             needsPar = true;
117         if(needsPar)
118             b.append('(');
119         expression.accept(this);
120         if(needsPar)
121             b.append(')');
122     }
123     
124     @Override
125     public void visit(EApply expression) {
126         showPar(expression.getFunction());
127         for(Expression parameter : expression.getParameters()) {
128             b.append(' ');
129             showPar(parameter);
130         }
131     }
132
133     @Override
134     public void visit(EApplyType expression) {
135         expression.getExpression().accept(this);
136     }
137
138     @Override
139     public void visit(EAsPattern expression) {
140         show(expression.getVariable());
141         b.append('@');
142         showPar(expression.getPattern());
143     }
144
145     @Override
146     public void visit(EBind expression) {
147         b.append("EBind");
148     }
149
150     @Override
151     public void visit(EConstant expression) {
152         String name = expression.getValue().getName().name;
153         if(Character.isJavaIdentifierStart(name.charAt(0)))
154             b.append(name);
155         else
156             b.append('(').append(name).append(')');
157     }
158
159     @Override
160     public void visit(EEnforce expression) {
161         b.append("enforce ");
162         expression.getQuery().accept(this);
163     }
164
165     @Override
166     public void visit(EError expression) {
167         b.append("EError");
168     }
169
170     @Override
171     public void visit(EExternalConstant expression) {
172         b.append(expression.getValue());
173     }
174
175     @Override
176     public void visit(EFieldAccess expression) {
177         b.append("EFieldAccess");
178     }
179
180     @Override
181     public void visit(EGetConstraint expression) {
182         b.append("EGetConstraint");
183     }
184
185     @Override
186     public void visit(EIf expression) {
187         b.append("if ");
188         expression.condition.accept(this);
189         ++indentation;
190         newLine();
191         b.append("then ");
192         expression.then_.accept(this);
193         if(expression.else_ != null) {
194             newLine();
195             b.append("else ");
196             expression.else_.accept(this);
197         }
198         --indentation;
199     }
200     
201     @Override
202     public void visit(QIf query) {
203         b.append("if ");
204         query.condition.accept(this);
205         ++indentation;
206         newLine();
207         b.append("then ");
208         query.thenQuery.accept(this);
209         newLine();
210         b.append("else ");
211         query.elseQuery.accept(this);
212         --indentation;
213     }
214
215     @Override
216     public void visit(EIntegerLiteral expression) {
217         b.append(expression.getValue());
218     }
219
220     @Override
221     public void visit(ELambda expression) {
222         b.append('\\');
223         ++indentation;
224         for(Case case_ : expression.getCases()) {
225             newLine();
226             for(Expression pat : case_.patterns) {
227                 showPar(pat);
228                 b.append(' ');
229             }
230             b.append("-> ");
231             ++indentation;
232             case_.value.accept(this);
233             --indentation;
234         }
235         --indentation;
236     }
237     
238     @Override
239     public void visit(EViewPattern expression) {
240         b.append('(');
241         expression.expression.accept(this);
242         b.append(" -> ");
243         expression.pattern.accept(this);
244         b.append(')');
245     }
246
247     @Override
248     public void visit(ELambdaType expression) {
249         expression.value.accept(this);
250     }
251
252     @Override
253     public void visit(ELet expression) {
254         b.append("do");
255         ++indentation;
256         printAsDo(expression);
257         --indentation;
258     }
259
260     @Override
261     public void visit(EListComprehension expression) {
262         b.append("EListComprehension");
263     }
264
265     @Override
266     public void visit(EListLiteral expression) {
267         b.append('[');
268         boolean first = true;
269         for(Expression component : expression.getComponents()) {
270             if(first)
271                 first = false;
272             else
273                 b.append(',');
274             component.accept(this);
275         }
276         b.append(']');
277     }
278
279     @Override
280     public void visit(ELiteral expression) {
281         b.append(expression.getValue().toString());
282     }
283
284     @Override
285     public void visit(EMatch expression) {
286         b.append("match");
287         for(Expression s : expression.getScrutinee()) {
288             b.append(' ');
289             showPar(s);
290         }
291         b.append(" with");
292         ++indentation;
293         for(Case case_ : expression.getCases()) {
294             newLine();
295             for(Expression pat : case_.patterns) {
296                 showPar(pat);
297                 b.append(' ');
298             }
299             b.append("-> ");
300             ++indentation;
301             case_.value.accept(this);
302             --indentation;
303         }
304         --indentation;
305     }
306
307     @Override
308     public void visit(EPlaceholder expression) {
309         expression.expression.accept(this);
310     }
311
312     @Override
313     public void visit(ERealLiteral expression) {
314         b.append(expression.getValue());
315     }
316
317     @Override
318     public void visit(ERuleset expression) {
319         b.append("let\n");
320         ++indentation;
321         for(ERuleset.DatalogRule rule : expression.getRules()) {
322             newLine();
323             visit(rule);
324         }
325         --indentation;
326         b.append("\nin ");
327         expression.getIn().accept(this);
328     }
329
330     @Override
331     public void visit(ESelect expression) {
332         b.append("ESelect");
333     }
334     
335     @Override
336     public void visit(ECHRSelect expression) {
337         b.append("ECHRSelect");
338     }
339     
340     @Override
341     public void visit(ESimpleLambda expression) {
342         b.append('\\');
343         show(expression.getParameter());
344         while(expression.getValue() instanceof ESimpleLambda) {
345             expression = (ESimpleLambda)expression.getValue();
346             b.append(' ');
347             show(expression.getParameter());
348         }
349         b.append(" -> ");
350         expression.getValue().accept(this);
351     }
352
353     @Override
354     public void visit(ESimpleLet expression) {
355         b.append("do");
356         ++indentation;
357         printAsDo(expression);
358         --indentation;
359     }
360     
361     private void printAsDo(Expression expression) {
362         if(expression instanceof ESimpleLet) {
363             ESimpleLet let = (ESimpleLet)expression;
364             Variable variable = let.getVariable();
365             Expression value = let.getValue();
366             if(variable == null || "_".equals(variable.getName()))
367                 printAsDo(value);
368             else {
369                 newLine();
370                 show(variable);
371                 b.append(" = ");
372                 value.accept(this);
373             }
374             printAsDo(let.getIn());
375         }
376         else if(expression instanceof ELet) {
377             ELet let = (ELet)expression;
378             for(Assignment assignment : let.assignments) {
379                 newLine();
380                 assignment.pattern.accept(this);
381                 b.append(" = ");
382                 assignment.value.accept(this);
383             }
384             printAsDo(let.in);
385         }
386         else {
387             newLine();
388             expression.accept(this);
389         }
390     }
391
392     @Override
393     public void visit(ETransformation expression) {
394         b.append("<transformation>");
395     }
396
397     @Override
398     public void visit(ETypeAnnotation expression) {
399         expression.getValue().accept(this);
400     }
401
402     @Override
403     public void visit(EVar expression) {
404         b.append(expression.name);
405     }
406
407     @Override
408     public void visit(EVariable expression) {
409         show(expression.getVariable());
410     }
411
412     @Override
413     public void visit(EWhen expression) {
414         b.append("when ");
415         expression.getQuery().accept(this);
416         b.append("\n");
417         expression.getAction().accept(this);
418     }
419
420     @Override
421     public void visit(GuardedExpressionGroup expression) {
422         boolean first = true;
423         for(GuardedExpression gexp : expression.expressions) {
424             if(first)
425                 first = false;
426             else
427                 newLine();
428             b.append("| ");
429             for(int i=0;i<gexp.guards.length;++i) {
430                 if(i > 0)
431                     b.append(", ");
432                 gexp.guards[i].accept(this);
433             }
434             b.append(" = ");
435             gexp.value.accept(this);
436         }
437     }
438
439     @Override
440     public void visit(QAlternative query) {
441         b.append("QAlternative");
442     }
443
444     @Override
445     public void visit(QAtom query) {
446         if(query.relation == EqRelation.INSTANCE) {
447             query.parameters[0].accept(this);
448             b.append(" = ");
449             query.parameters[1].accept(this);
450         }
451         else if(query.relation == MemberRelation.INSTANCE) {
452             query.parameters[0].accept(this);
453             b.append(" <- ");
454             query.parameters[1].accept(this);
455         }
456         else {
457             b.append(query.relation);
458             for(Expression parameter : query.parameters) {
459                 b.append(' ');
460                 showPar(parameter);
461             }
462         }
463     }
464
465     @Override
466     public void visit(QConjunction query) {
467         boolean first = true;
468         for(Query q : query.queries) {
469             if(first)
470                 first = false;
471             else
472                 newLine();
473             q.accept(this);
474         }
475     }
476
477     @Override
478     public void visit(QDisjunction query) {
479         b.append("QDisjunction");
480     }
481
482     @Override
483     public void visit(QExists query) {
484         b.append("QExists");
485     }
486
487     @Override
488     public void visit(QNegation query) {
489         b.append("QNegation");
490     }
491
492     @Override
493     public void visit(QMapping query) {
494         b.append(query.mappingRelation.name.name);
495         for(Expression parameter : query.parameters) {
496             b.append(' ');
497             parameter.accept(this);
498         }
499     }
500
501     public void visit(ERuleset.DatalogRule rule) {
502         b.append(rule.headRelation.getName());
503         for(Expression parameter : rule.headParameters) {
504             b.append(' ');
505             showPar(parameter);
506         }
507         b.append(" :-\n");
508         ++indentation;
509         rule.body.accept(this);
510         --indentation;
511     }
512
513     public void visit(TransformationRule rule) {
514         b.append("rule ").append(rule.name.name).append(" where");
515         for(Entry<SectionName, Query[]> section : rule.sections.entrySet()) {
516             b.append("\n@").append(section.getKey().name());
517             for(Query query : section.getValue()) {
518                 b.append('\n');
519                 query.accept(this);
520             }
521         }
522     }
523
524
525     @Override
526     public void visit(ECoveringBranchPoint expression) {
527         expression.expression.accept(this);
528     }
529
530     @Override
531     public void visit(EEquations expression) {
532         b.append("eq");
533     }
534
535     @Override
536     public void visit(ECHRRuleset expression) {
537         b.append("ECHRRuleset");
538     }
539     
540     @Override
541     public void visit(ECHRRulesetConstructor expression) {
542         b.append("ECHRRulesetConstructor");
543     }
544
545     public void visit(CHRRule rule) {
546         visit(rule.head);
547         b.append(" => ");
548         visit(rule.body);
549     }
550
551     public void visit(CHRQuery query) {
552         boolean first = true;
553         for(CHRLiteral literal : query.literals) {
554             if(first)
555                 first = false;
556             else
557                 b.append(", ");
558             visit(literal);
559         }
560     }
561
562     public void visit(CHRLiteral literal) {
563         if(literal.passive && literal.relation instanceof CHRConstraint)
564             b.append("@passive ");
565         if(literal.killAfterMatch)
566             b.append('-');
567         b.append(literal.relation);
568         for(Expression parameter : literal.parameters) {
569             b.append(' ');
570             showPar(parameter);
571         }
572     }
573
574     @Override
575     public void visit(EBinary expression) {
576         b.append("<EBinary>");
577     }
578
579     @Override
580     public void visit(EBlock expression) {
581         b.append("<EBlock>");
582     }
583
584     @Override
585     public void visit(EPreLet expression) {
586         b.append("<EPreLet>");
587     }
588
589     @Override
590     public void visit(ERange expression) {
591         b.append('[');
592         expression.from.accept(this);
593         b.append("..");
594         expression.to.accept(this);
595         b.append(']');
596     }
597
598     @Override
599     public void visit(ERecord expression) {
600         b.append("<ERecord>");
601     }
602
603     @Override
604     public void visit(EStringLiteral expression) {
605         b.append('"');
606         for(int i=0;i<expression.strings.length;++i) {
607             b.append(expression.strings[i]);
608             if(i < expression.expressions.length) {
609                 b.append("\\(");
610                 expression.expressions[i].accept(this);
611                 b.append(')');
612             }
613         }
614         b.append('"');
615     }
616
617     @Override
618     public void visit(EAmbiguous eAmbiguous) {
619         b.append("EAmbigious");
620     }
621 }