]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/printing/ExpressionToStringVisitor.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / expressions / printing / ExpressionToStringVisitor.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/printing/ExpressionToStringVisitor.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/printing/ExpressionToStringVisitor.java
new file mode 100644 (file)
index 0000000..c5f8f36
--- /dev/null
@@ -0,0 +1,497 @@
+package org.simantics.scl.compiler.elaboration.expressions.printing;\r
+\r
+import java.util.Map.Entry;\r
+\r
+import org.simantics.scl.compiler.elaboration.expressions.Assignment;\r
+import org.simantics.scl.compiler.elaboration.expressions.Case;\r
+import org.simantics.scl.compiler.elaboration.expressions.EApply;\r
+import org.simantics.scl.compiler.elaboration.expressions.EApplyType;\r
+import org.simantics.scl.compiler.elaboration.expressions.EAsPattern;\r
+import org.simantics.scl.compiler.elaboration.expressions.EBind;\r
+import org.simantics.scl.compiler.elaboration.expressions.EConstant;\r
+import org.simantics.scl.compiler.elaboration.expressions.EEnforce;\r
+import org.simantics.scl.compiler.elaboration.expressions.EEquations;\r
+import org.simantics.scl.compiler.elaboration.expressions.EError;\r
+import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant;\r
+import org.simantics.scl.compiler.elaboration.expressions.EFieldAccess;\r
+import org.simantics.scl.compiler.elaboration.expressions.EGetConstraint;\r
+import org.simantics.scl.compiler.elaboration.expressions.EIf;\r
+import org.simantics.scl.compiler.elaboration.expressions.EIntegerLiteral;\r
+import org.simantics.scl.compiler.elaboration.expressions.ELambda;\r
+import org.simantics.scl.compiler.elaboration.expressions.ELambdaType;\r
+import org.simantics.scl.compiler.elaboration.expressions.ELet;\r
+import org.simantics.scl.compiler.elaboration.expressions.EListComprehension;\r
+import org.simantics.scl.compiler.elaboration.expressions.EListLiteral;\r
+import org.simantics.scl.compiler.elaboration.expressions.ELiteral;\r
+import org.simantics.scl.compiler.elaboration.expressions.EMatch;\r
+import org.simantics.scl.compiler.elaboration.expressions.EPlaceholder;\r
+import org.simantics.scl.compiler.elaboration.expressions.ECoveringBranchPoint;\r
+import org.simantics.scl.compiler.elaboration.expressions.ERealLiteral;\r
+import org.simantics.scl.compiler.elaboration.expressions.ERuleset;\r
+import org.simantics.scl.compiler.elaboration.expressions.ESelect;\r
+import org.simantics.scl.compiler.elaboration.expressions.ESimpleLambda;\r
+import org.simantics.scl.compiler.elaboration.expressions.ESimpleLet;\r
+import org.simantics.scl.compiler.elaboration.expressions.ETransformation;\r
+import org.simantics.scl.compiler.elaboration.expressions.ETypeAnnotation;\r
+import org.simantics.scl.compiler.elaboration.expressions.EVariable;\r
+import org.simantics.scl.compiler.elaboration.expressions.EWhen;\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+import org.simantics.scl.compiler.elaboration.expressions.ExpressionVisitor;\r
+import org.simantics.scl.compiler.elaboration.expressions.GuardedExpression;\r
+import org.simantics.scl.compiler.elaboration.expressions.GuardedExpressionGroup;\r
+import org.simantics.scl.compiler.elaboration.expressions.Variable;\r
+import org.simantics.scl.compiler.elaboration.java.EqRelation;\r
+import org.simantics.scl.compiler.elaboration.java.MemberRelation;\r
+import org.simantics.scl.compiler.elaboration.query.QAlternative;\r
+import org.simantics.scl.compiler.elaboration.query.QAtom;\r
+import org.simantics.scl.compiler.elaboration.query.QConjunction;\r
+import org.simantics.scl.compiler.elaboration.query.QDisjunction;\r
+import org.simantics.scl.compiler.elaboration.query.QExists;\r
+import org.simantics.scl.compiler.elaboration.query.QIf;\r
+import org.simantics.scl.compiler.elaboration.query.QMapping;\r
+import org.simantics.scl.compiler.elaboration.query.QNegation;\r
+import org.simantics.scl.compiler.elaboration.query.Query;\r
+import org.simantics.scl.compiler.elaboration.query.QueryVisitor;\r
+import org.simantics.scl.compiler.elaboration.rules.SectionName;\r
+import org.simantics.scl.compiler.elaboration.rules.TransformationRule;\r
+\r
+public class ExpressionToStringVisitor implements ExpressionVisitor, QueryVisitor {\r
+\r
+    StringBuilder b = new StringBuilder();\r
+    int indentation;\r
+    \r
+    public ExpressionToStringVisitor(StringBuilder b) {\r
+        this.b = b;\r
+    }\r
+\r
+    public void show(Variable variable) {\r
+        if(variable == null)\r
+            b.append("NULL_VARIABLE");\r
+        else\r
+            b.append(variable.getName());\r
+    }\r
+    \r
+    private void newLine() {\r
+        b.append('\n');\r
+        for(int i=0;i<indentation;++i)\r
+            b.append("  ");\r
+    }\r
+    \r
+    public void showPar(Expression expression) {\r
+        boolean needsPar = false;\r
+        while(true) {\r
+            if(expression instanceof EPlaceholder)\r
+                expression = ((EPlaceholder)expression).expression;\r
+            else if(expression instanceof ETypeAnnotation)\r
+                expression = ((ETypeAnnotation)expression).getValue();\r
+            else if(expression instanceof EApplyType)\r
+                expression = ((EApplyType)expression).getExpression();\r
+            else if(expression instanceof ELambdaType)\r
+                expression = ((ELambdaType)expression).value;\r
+            else if(expression instanceof ECoveringBranchPoint)\r
+                expression = ((ECoveringBranchPoint)expression).expression;\r
+            else\r
+                break;\r
+        }\r
+        if(expression instanceof EApply ||\r
+                expression instanceof EIf ||\r
+                expression instanceof ESimpleLambda ||\r
+                expression instanceof ESimpleLet)\r
+            needsPar = true;\r
+        if(needsPar)\r
+            b.append('(');\r
+        expression.accept(this);\r
+        if(needsPar)\r
+            b.append(')');\r
+    }\r
+    \r
+    @Override\r
+    public void visit(EApply expression) {\r
+        showPar(expression.getFunction());\r
+        for(Expression parameter : expression.getParameters()) {\r
+            b.append(' ');\r
+            showPar(parameter);\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public void visit(EApplyType expression) {\r
+        expression.getExpression().accept(this);\r
+    }\r
+\r
+    @Override\r
+    public void visit(EAsPattern expression) {\r
+        show(expression.getVariable());\r
+        b.append('@');\r
+        showPar(expression.getPattern());\r
+    }\r
+\r
+    @Override\r
+    public void visit(EBind expression) {\r
+        b.append("EBind");\r
+    }\r
+\r
+    @Override\r
+    public void visit(EConstant expression) {\r
+        String name = expression.getValue().getName().name;\r
+        if(Character.isJavaIdentifierStart(name.charAt(0)))\r
+            b.append(name);\r
+        else\r
+            b.append('(').append(name).append(')');\r
+    }\r
+\r
+    @Override\r
+    public void visit(EEnforce expression) {\r
+        b.append("enforce ");\r
+        expression.getQuery().accept(this);\r
+    }\r
+\r
+    @Override\r
+    public void visit(EError expression) {\r
+        b.append("EError");\r
+    }\r
+\r
+    @Override\r
+    public void visit(EExternalConstant expression) {\r
+        b.append(expression.getValue());\r
+    }\r
+\r
+    @Override\r
+    public void visit(EFieldAccess expression) {\r
+        b.append("EFieldAccess");\r
+    }\r
+\r
+    @Override\r
+    public void visit(EGetConstraint expression) {\r
+        b.append("EGetConstraint");\r
+    }\r
+\r
+    @Override\r
+    public void visit(EIf expression) {\r
+        b.append("if ");\r
+        expression.getCondition().accept(this);\r
+        ++indentation;\r
+        newLine();\r
+        b.append("then ");\r
+        expression.getThen().accept(this);\r
+        newLine();\r
+        b.append("else ");\r
+        expression.getElse().accept(this);\r
+        --indentation;\r
+    }\r
+    \r
+    @Override\r
+    public void visit(QIf query) {\r
+        b.append("if ");\r
+        query.condition.accept(this);\r
+        ++indentation;\r
+        newLine();\r
+        b.append("then ");\r
+        query.thenQuery.accept(this);\r
+        newLine();\r
+        b.append("else ");\r
+        query.elseQuery.accept(this);\r
+        --indentation;\r
+    }\r
+\r
+    @Override\r
+    public void visit(EIntegerLiteral expression) {\r
+        b.append(expression.getValue());\r
+    }\r
+\r
+    @Override\r
+    public void visit(ELambda expression) {\r
+        b.append('\\');\r
+        ++indentation;\r
+        for(Case case_ : expression.getCases()) {\r
+            newLine();\r
+            for(Expression pat : case_.patterns) {\r
+                showPar(pat);\r
+                b.append(' ');\r
+            }\r
+            b.append("-> ");\r
+            ++indentation;\r
+            case_.value.accept(this);\r
+            --indentation;\r
+        }\r
+        --indentation;\r
+    }\r
+\r
+    @Override\r
+    public void visit(ELambdaType expression) {\r
+        expression.value.accept(this);\r
+    }\r
+\r
+    @Override\r
+    public void visit(ELet expression) {\r
+        b.append("do");\r
+        ++indentation;\r
+        printAsDo(expression);\r
+        --indentation;\r
+    }\r
+\r
+    @Override\r
+    public void visit(EListComprehension expression) {\r
+        b.append("EListComprehension");\r
+    }\r
+\r
+    @Override\r
+    public void visit(EListLiteral expression) {\r
+        b.append('[');\r
+        boolean first = true;\r
+        for(Expression component : expression.getComponents()) {\r
+            if(first)\r
+                first = false;\r
+            else\r
+                b.append(',');\r
+            component.accept(this);\r
+        }\r
+        b.append(']');\r
+    }\r
+\r
+    @Override\r
+    public void visit(ELiteral expression) {\r
+        b.append(expression.getValue().toString());\r
+    }\r
+\r
+    @Override\r
+    public void visit(EMatch expression) {\r
+        b.append("match");\r
+        for(Expression s : expression.getScrutinee()) {\r
+            b.append(' ');\r
+            showPar(s);\r
+        }\r
+        b.append(" with");\r
+        ++indentation;\r
+        for(Case case_ : expression.getCases()) {\r
+            newLine();\r
+            for(Expression pat : case_.patterns) {\r
+                showPar(pat);\r
+                b.append(' ');\r
+            }\r
+            b.append("-> ");\r
+            ++indentation;\r
+            case_.value.accept(this);\r
+            --indentation;\r
+        }\r
+        --indentation;\r
+    }\r
+\r
+    @Override\r
+    public void visit(EPlaceholder expression) {\r
+        expression.expression.accept(this);\r
+    }\r
+\r
+    @Override\r
+    public void visit(ERealLiteral expression) {\r
+        b.append(expression.getValue());\r
+    }\r
+\r
+    @Override\r
+    public void visit(ERuleset expression) {\r
+        b.append("let\n");\r
+        ++indentation;\r
+        for(ERuleset.DatalogRule rule : expression.getRules()) {\r
+            newLine();\r
+            visit(rule);\r
+        }\r
+        --indentation;\r
+        b.append("\nin ");\r
+        expression.getIn().accept(this);\r
+    }\r
+\r
+    @Override\r
+    public void visit(ESelect expression) {\r
+        b.append("ESelect");\r
+    }\r
+\r
+    @Override\r
+    public void visit(ESimpleLambda expression) {\r
+        b.append('\\');\r
+        show(expression.getParameter());\r
+        while(expression.getValue() instanceof ESimpleLambda) {\r
+            expression = (ESimpleLambda)expression.getValue();\r
+            b.append(' ');\r
+            show(expression.getParameter());\r
+        }\r
+        b.append(" -> ");\r
+        expression.getValue().accept(this);\r
+    }\r
+\r
+    @Override\r
+    public void visit(ESimpleLet expression) {\r
+        b.append("do");\r
+        ++indentation;\r
+        printAsDo(expression);\r
+        --indentation;\r
+    }\r
+    \r
+    private void printAsDo(Expression expression) {\r
+        if(expression instanceof ESimpleLet) {\r
+            ESimpleLet let = (ESimpleLet)expression;\r
+            Variable variable = let.getVariable();\r
+            Expression value = let.getValue();\r
+            if("_".equals(variable.getName()))\r
+                printAsDo(value);\r
+            else {\r
+                newLine();\r
+                show(variable);\r
+                b.append(" = ");\r
+                value.accept(this);\r
+            }\r
+            printAsDo(let.getIn());\r
+        }\r
+        else if(expression instanceof ELet) {\r
+            ELet let = (ELet)expression;\r
+            for(Assignment assignment : let.assignments) {\r
+                newLine();\r
+                assignment.pattern.accept(this);\r
+                b.append(" = ");\r
+                assignment.value.accept(this);\r
+            }\r
+            printAsDo(let.in);\r
+        }\r
+        else {\r
+            newLine();\r
+            expression.accept(this);\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public void visit(ETransformation expression) {\r
+        b.append("<transformation>");\r
+    }\r
+\r
+    @Override\r
+    public void visit(ETypeAnnotation expression) {\r
+        expression.getValue().accept(this);\r
+    }\r
+\r
+    @Override\r
+    public void visit(EVariable expression) {\r
+        show(expression.getVariable());\r
+    }\r
+\r
+    @Override\r
+    public void visit(EWhen expression) {\r
+        b.append("when ");\r
+        expression.getQuery().accept(this);\r
+        b.append("\n");\r
+        expression.getAction().accept(this);\r
+    }\r
+\r
+    @Override\r
+    public void visit(GuardedExpressionGroup expression) {\r
+        boolean first = true;\r
+        for(GuardedExpression gexp : expression.expressions) {\r
+            if(first)\r
+                first = false;\r
+            else\r
+                newLine();\r
+            b.append("| ");\r
+            for(int i=0;i<gexp.guards.length;++i) {\r
+                if(i > 0)\r
+                    b.append(", ");\r
+                gexp.guards[i].accept(this);\r
+            }\r
+            b.append(" = ");\r
+            gexp.value.accept(this);\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public void visit(QAlternative query) {\r
+        b.append("QAlternative");\r
+    }\r
+\r
+    @Override\r
+    public void visit(QAtom query) {\r
+        if(query.relation == EqRelation.INSTANCE) {\r
+            query.parameters[0].accept(this);\r
+            b.append(" = ");\r
+            query.parameters[1].accept(this);\r
+        }\r
+        else if(query.relation == MemberRelation.INSTANCE) {\r
+            query.parameters[0].accept(this);\r
+            b.append(" <- ");\r
+            query.parameters[1].accept(this);\r
+        }\r
+        else {\r
+            b.append(query.relation);\r
+            for(Expression parameter : query.parameters) {\r
+                b.append(' ');\r
+                showPar(parameter);\r
+            }\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public void visit(QConjunction query) {\r
+        boolean first = true;\r
+        for(Query q : query.queries) {\r
+            if(first)\r
+                first = false;\r
+            else\r
+                newLine();\r
+            q.accept(this);\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public void visit(QDisjunction query) {\r
+        b.append("QDisjunction");\r
+    }\r
+\r
+    @Override\r
+    public void visit(QExists query) {\r
+        b.append("QExists");\r
+    }\r
+\r
+    @Override\r
+    public void visit(QNegation query) {\r
+        b.append("QNegation");\r
+    }\r
+\r
+    @Override\r
+    public void visit(QMapping query) {\r
+        b.append(query.mappingRelation.name.name);\r
+        for(Expression parameter : query.parameters) {\r
+            b.append(' ');\r
+            parameter.accept(this);\r
+        }\r
+    }\r
+\r
+    public void visit(ERuleset.DatalogRule rule) {\r
+        b.append(rule.headRelation.getName());\r
+        for(Expression parameter : rule.headParameters) {\r
+            b.append(' ');\r
+            showPar(parameter);\r
+        }\r
+        b.append(" :-\n");\r
+        ++indentation;\r
+        rule.body.accept(this);\r
+        --indentation;\r
+    }\r
+\r
+    public void visit(TransformationRule rule) {\r
+        b.append("rule ").append(rule.name.name).append(" where");\r
+        for(Entry<SectionName, Query[]> section : rule.sections.entrySet()) {\r
+            b.append("\n@").append(section.getKey().name());\r
+            for(Query query : section.getValue()) {\r
+                b.append('\n');\r
+                query.accept(this);\r
+            }\r
+        }\r
+    }\r
+\r
+\r
+    @Override\r
+    public void visit(ECoveringBranchPoint expression) {\r
+        expression.expression.accept(this);\r
+    }\r
+\r
+    @Override\r
+    public void visit(EEquations eEquations) {\r
+        b.append("eq");\r
+    }\r
+}\r