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