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