package org.simantics.scl.compiler.elaboration.expressions.printing; import java.util.Map.Entry; import org.simantics.scl.compiler.elaboration.chr.CHRLiteral; import org.simantics.scl.compiler.elaboration.chr.CHRQuery; import org.simantics.scl.compiler.elaboration.chr.CHRRule; import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint; import org.simantics.scl.compiler.elaboration.expressions.Assignment; import org.simantics.scl.compiler.elaboration.expressions.Case; import org.simantics.scl.compiler.elaboration.expressions.EApply; import org.simantics.scl.compiler.elaboration.expressions.EApplyType; import org.simantics.scl.compiler.elaboration.expressions.EAsPattern; import org.simantics.scl.compiler.elaboration.expressions.EBind; import org.simantics.scl.compiler.elaboration.expressions.ECHRRuleset; import org.simantics.scl.compiler.elaboration.expressions.EConstant; import org.simantics.scl.compiler.elaboration.expressions.ECoveringBranchPoint; import org.simantics.scl.compiler.elaboration.expressions.EEnforce; import org.simantics.scl.compiler.elaboration.expressions.EEquations; import org.simantics.scl.compiler.elaboration.expressions.EError; import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant; import org.simantics.scl.compiler.elaboration.expressions.EFieldAccess; import org.simantics.scl.compiler.elaboration.expressions.EGetConstraint; import org.simantics.scl.compiler.elaboration.expressions.EIf; import org.simantics.scl.compiler.elaboration.expressions.EIntegerLiteral; import org.simantics.scl.compiler.elaboration.expressions.ELambda; import org.simantics.scl.compiler.elaboration.expressions.ELambdaType; import org.simantics.scl.compiler.elaboration.expressions.ELet; import org.simantics.scl.compiler.elaboration.expressions.EListComprehension; import org.simantics.scl.compiler.elaboration.expressions.EListLiteral; import org.simantics.scl.compiler.elaboration.expressions.ELiteral; import org.simantics.scl.compiler.elaboration.expressions.EMatch; import org.simantics.scl.compiler.elaboration.expressions.EPlaceholder; import org.simantics.scl.compiler.elaboration.expressions.ERealLiteral; import org.simantics.scl.compiler.elaboration.expressions.ERuleset; import org.simantics.scl.compiler.elaboration.expressions.ESelect; import org.simantics.scl.compiler.elaboration.expressions.ESimpleLambda; import org.simantics.scl.compiler.elaboration.expressions.ESimpleLet; import org.simantics.scl.compiler.elaboration.expressions.ETransformation; import org.simantics.scl.compiler.elaboration.expressions.ETypeAnnotation; import org.simantics.scl.compiler.elaboration.expressions.EVariable; import org.simantics.scl.compiler.elaboration.expressions.EViewPattern; import org.simantics.scl.compiler.elaboration.expressions.EWhen; import org.simantics.scl.compiler.elaboration.expressions.Expression; import org.simantics.scl.compiler.elaboration.expressions.ExpressionVisitor; import org.simantics.scl.compiler.elaboration.expressions.GuardedExpression; import org.simantics.scl.compiler.elaboration.expressions.GuardedExpressionGroup; import org.simantics.scl.compiler.elaboration.expressions.Variable; import org.simantics.scl.compiler.elaboration.java.EqRelation; import org.simantics.scl.compiler.elaboration.java.MemberRelation; import org.simantics.scl.compiler.elaboration.query.QAlternative; import org.simantics.scl.compiler.elaboration.query.QAtom; import org.simantics.scl.compiler.elaboration.query.QConjunction; import org.simantics.scl.compiler.elaboration.query.QDisjunction; import org.simantics.scl.compiler.elaboration.query.QExists; import org.simantics.scl.compiler.elaboration.query.QIf; import org.simantics.scl.compiler.elaboration.query.QMapping; import org.simantics.scl.compiler.elaboration.query.QNegation; import org.simantics.scl.compiler.elaboration.query.Query; import org.simantics.scl.compiler.elaboration.query.QueryVisitor; import org.simantics.scl.compiler.elaboration.rules.SectionName; import org.simantics.scl.compiler.elaboration.rules.TransformationRule; public class ExpressionToStringVisitor implements ExpressionVisitor, QueryVisitor { StringBuilder b = new StringBuilder(); int indentation; public ExpressionToStringVisitor(StringBuilder b) { this.b = b; } public void show(Variable variable) { if(variable == null) b.append("NULL_VARIABLE"); else b.append(variable.getName()); } private void newLine() { b.append('\n'); for(int i=0;i "); ++indentation; case_.value.accept(this); --indentation; } --indentation; } @Override public void visit(EViewPattern expression) { b.append('('); expression.expression.accept(this); b.append(" -> "); expression.pattern.accept(this); b.append(')'); } @Override public void visit(ELambdaType expression) { expression.value.accept(this); } @Override public void visit(ELet expression) { b.append("do"); ++indentation; printAsDo(expression); --indentation; } @Override public void visit(EListComprehension expression) { b.append("EListComprehension"); } @Override public void visit(EListLiteral expression) { b.append('['); boolean first = true; for(Expression component : expression.getComponents()) { if(first) first = false; else b.append(','); component.accept(this); } b.append(']'); } @Override public void visit(ELiteral expression) { b.append(expression.getValue().toString()); } @Override public void visit(EMatch expression) { b.append("match"); for(Expression s : expression.getScrutinee()) { b.append(' '); showPar(s); } b.append(" with"); ++indentation; for(Case case_ : expression.getCases()) { newLine(); for(Expression pat : case_.patterns) { showPar(pat); b.append(' '); } b.append("-> "); ++indentation; case_.value.accept(this); --indentation; } --indentation; } @Override public void visit(EPlaceholder expression) { expression.expression.accept(this); } @Override public void visit(ERealLiteral expression) { b.append(expression.getValue()); } @Override public void visit(ERuleset expression) { b.append("let\n"); ++indentation; for(ERuleset.DatalogRule rule : expression.getRules()) { newLine(); visit(rule); } --indentation; b.append("\nin "); expression.getIn().accept(this); } @Override public void visit(ESelect expression) { b.append("ESelect"); } @Override public void visit(ESimpleLambda expression) { b.append('\\'); show(expression.getParameter()); while(expression.getValue() instanceof ESimpleLambda) { expression = (ESimpleLambda)expression.getValue(); b.append(' '); show(expression.getParameter()); } b.append(" -> "); expression.getValue().accept(this); } @Override public void visit(ESimpleLet expression) { b.append("do"); ++indentation; printAsDo(expression); --indentation; } private void printAsDo(Expression expression) { if(expression instanceof ESimpleLet) { ESimpleLet let = (ESimpleLet)expression; Variable variable = let.getVariable(); Expression value = let.getValue(); if(variable == null || "_".equals(variable.getName())) printAsDo(value); else { newLine(); show(variable); b.append(" = "); value.accept(this); } printAsDo(let.getIn()); } else if(expression instanceof ELet) { ELet let = (ELet)expression; for(Assignment assignment : let.assignments) { newLine(); assignment.pattern.accept(this); b.append(" = "); assignment.value.accept(this); } printAsDo(let.in); } else { newLine(); expression.accept(this); } } @Override public void visit(ETransformation expression) { b.append(""); } @Override public void visit(ETypeAnnotation expression) { expression.getValue().accept(this); } @Override public void visit(EVariable expression) { show(expression.getVariable()); } @Override public void visit(EWhen expression) { b.append("when "); expression.getQuery().accept(this); b.append("\n"); expression.getAction().accept(this); } @Override public void visit(GuardedExpressionGroup expression) { boolean first = true; for(GuardedExpression gexp : expression.expressions) { if(first) first = false; else newLine(); b.append("| "); for(int i=0;i 0) b.append(", "); gexp.guards[i].accept(this); } b.append(" = "); gexp.value.accept(this); } } @Override public void visit(QAlternative query) { b.append("QAlternative"); } @Override public void visit(QAtom query) { if(query.relation == EqRelation.INSTANCE) { query.parameters[0].accept(this); b.append(" = "); query.parameters[1].accept(this); } else if(query.relation == MemberRelation.INSTANCE) { query.parameters[0].accept(this); b.append(" <- "); query.parameters[1].accept(this); } else { b.append(query.relation); for(Expression parameter : query.parameters) { b.append(' '); showPar(parameter); } } } @Override public void visit(QConjunction query) { boolean first = true; for(Query q : query.queries) { if(first) first = false; else newLine(); q.accept(this); } } @Override public void visit(QDisjunction query) { b.append("QDisjunction"); } @Override public void visit(QExists query) { b.append("QExists"); } @Override public void visit(QNegation query) { b.append("QNegation"); } @Override public void visit(QMapping query) { b.append(query.mappingRelation.name.name); for(Expression parameter : query.parameters) { b.append(' '); parameter.accept(this); } } public void visit(ERuleset.DatalogRule rule) { b.append(rule.headRelation.getName()); for(Expression parameter : rule.headParameters) { b.append(' '); showPar(parameter); } b.append(" :-\n"); ++indentation; rule.body.accept(this); --indentation; } public void visit(TransformationRule rule) { b.append("rule ").append(rule.name.name).append(" where"); for(Entry section : rule.sections.entrySet()) { b.append("\n@").append(section.getKey().name()); for(Query query : section.getValue()) { b.append('\n'); query.accept(this); } } } @Override public void visit(ECoveringBranchPoint expression) { expression.expression.accept(this); } @Override public void visit(EEquations eEquations) { b.append("eq"); } @Override public void visit(ECHRRuleset echrRuleset) { b.append("CHRRuleset"); } public void visit(CHRRule rule) { visit(rule.head); b.append(" => "); visit(rule.body); } public void visit(CHRQuery query) { boolean first = true; for(CHRLiteral literal : query.literals) { if(first) first = false; else b.append(", "); visit(literal); } } public void visit(CHRLiteral literal) { if(literal.passive && literal.relation instanceof CHRConstraint) b.append("@passive "); if(literal.killAfterMatch) b.append('-'); b.append(literal.relation); for(Expression parameter : literal.parameters) { b.append(' '); showPar(parameter); } } }