/* * #%~ * The VDM Pretty Printer * %% * Copyright (C) 2008 - 2014 Overture * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #~% */ package org.overture.prettyprinter; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Vector; import org.overture.ast.analysis.AnalysisException; import org.overture.ast.analysis.QuestionAnswerAdaptor; import org.overture.ast.definitions.AClassClassDefinition; import org.overture.ast.definitions.AExplicitFunctionDefinition; import org.overture.ast.definitions.AExplicitOperationDefinition; import org.overture.ast.definitions.AInstanceVariableDefinition; import org.overture.ast.definitions.ATypeDefinition; import org.overture.ast.definitions.AValueDefinition; import org.overture.ast.definitions.PDefinition; import org.overture.ast.expressions.AUndefinedExp; import org.overture.ast.expressions.PExp; import org.overture.ast.node.INode; import org.overture.ast.patterns.PPattern; import org.overture.ast.statements.PStm; import org.overture.ast.typechecker.NameScope; import org.overture.ast.types.AFieldField; import org.overture.ast.types.AFunctionType; import org.overture.ast.types.AOperationType; import org.overture.ast.types.ARecordInvariantType; import org.overture.ast.types.PType; import org.overture.ast.util.Utils; public class PrettyPrinterVisitorDefinitions extends QuestionAnswerAdaptor<PrettyPrinterEnv, String> { final static TypePrettyPrinterVisitor typePrinter = new TypePrettyPrinterVisitor(); @Override public String caseAClassClassDefinition(AClassClassDefinition node, PrettyPrinterEnv question) throws AnalysisException { StringBuffer sb = new StringBuffer(); question.setClassName(node.getName().getName()); sb.append("class " + node.getName()); sb.append("\n"); // print types printDefsToStringBuffer(sb, node, question, ATypeDefinition.class); printDefsToStringBuffer(sb, node, question, AValueDefinition.class); printDefsToStringBuffer(sb, node, question, AInstanceVariableDefinition.class); printDefsToStringBuffer(sb, node, question, AExplicitOperationDefinition.class); printDefsToStringBuffer(sb, node, question, AExplicitFunctionDefinition.class); sb.append("end " + node.getName()); return sb.toString(); } private void printDefsToStringBuffer(StringBuffer sb, AClassClassDefinition node, PrettyPrinterEnv question, Class<? extends PDefinition> pDefClass) throws AnalysisException { List<PDefinition> defs = getDefinitions(node.getDefinitions(), pDefClass); if (defs.isEmpty()) { return; } if (ATypeDefinition.class.equals(pDefClass)) { sb.append("types\n"); question.increaseIdent(); for (PDefinition def : defs) { sb.append(def.apply(this, question)); sb.append("\n"); } question.decreaseIdent(); } else if (AValueDefinition.class.equals(pDefClass)) { sb.append("values\n"); question.increaseIdent(); for (PDefinition def : defs) { sb.append(def.apply(this, question)); sb.append("\n"); } question.decreaseIdent(); } else if (AInstanceVariableDefinition.class.equals(pDefClass)) { sb.append("instance variables\n"); question.increaseIdent(); for (PDefinition def : defs) { sb.append(def.apply(this, question)); sb.append("\n"); } question.decreaseIdent(); } else if (AExplicitOperationDefinition.class.equals(pDefClass)) { sb.append("operations\n"); question.increaseIdent(); for (PDefinition def : defs) { sb.append(def.apply(this, question)); sb.append("\n"); } question.decreaseIdent(); } else if (AExplicitFunctionDefinition.class.equals(pDefClass)) { sb.append("functions\n"); question.increaseIdent(); for (PDefinition def : defs) { sb.append(def.apply(this, question)); sb.append("\n"); } question.decreaseIdent(); } else { } sb.append("\n"); } private List<PDefinition> getDefinitions( LinkedList<PDefinition> definitions, Class<? extends PDefinition> pDefClass) { List<PDefinition> result = new Vector<PDefinition>(); for (PDefinition pDefinition : definitions) { if (pDefClass.isInstance(pDefinition)) { result.add(pDefinition); } } return result; } @Override public String caseAInstanceVariableDefinition( AInstanceVariableDefinition node, PrettyPrinterEnv question) throws AnalysisException { StringBuilder sb = new StringBuilder(question.getIdent()); sb.append(node.getName() + ":" + node.getType().apply(typePrinter, question) + (node.getExpression() != null ? " := " + node.getExpression() : "")); return sb.toString() + ";"; } @Override public String caseAValueDefinition(AValueDefinition node, PrettyPrinterEnv question) throws AnalysisException { StringBuilder sb = new StringBuilder(question.getIdent()); sb.append(node.getPattern() + (node.getType() == null ? "" : ":" + node.getType().apply(typePrinter, question)) + (node.getExpression() != null ? " = " + node.getExpression() : ""));// node.toString()); return sb.toString() + ";"; } @Override public String caseATypeDefinition(ATypeDefinition node, PrettyPrinterEnv question) throws AnalysisException { StringBuilder sb = new StringBuilder(question.getIdent()); sb.append(node.getAccess().getAccess() + " "); sb.append(node.getName()); if (node.getType() instanceof ARecordInvariantType) { ARecordInvariantType record = (ARecordInvariantType) node.getType(); sb.append(" :: "); for (Iterator<AFieldField> itr = record.getFields().iterator(); itr.hasNext();) { if (itr.hasNext()) { sb.append("\n" + question.getIdent()); } sb.append(itr.next().apply(this, question)); } } else { sb.append(" = " + node.getType().apply(typePrinter, question)); } // + (node.getType() instanceof ARecordInvariantType ? " :: " // : " = ") + node.getType().apply(typePrinter, question)); return sb.toString() + ";"; } @Override public String caseAFieldField(AFieldField node, PrettyPrinterEnv question) throws AnalysisException { question.increaseIdent(); StringBuilder sb = new StringBuilder(question.getIdent()); sb.append(node.getTag() + " : " + node.getType().apply(typePrinter, question)); question.decreaseIdent(); return sb.toString(); } @Override public String defaultPType(PType node, PrettyPrinterEnv question) throws AnalysisException { return node.toString(); } @Override public String caseARecordInvariantType(ARecordInvariantType node, PrettyPrinterEnv question) throws AnalysisException { StringBuilder sb = new StringBuilder(); question.increaseIdent(); sb.append("\n"); for (AFieldField f : node.getFields()) { sb.append(question.getIdent() + f.getTag() + " : " + f.getType().apply(typePrinter, question) + "\n"); } question.decreaseIdent(); if (node.getFields().size() > 0) { sb.delete(sb.length() - 1, sb.length()); } return sb.toString(); } @Override public String caseAExplicitOperationDefinition( AExplicitOperationDefinition d, PrettyPrinterEnv question) throws AnalysisException { StringBuilder sb = new StringBuilder(question.getIdent()); String type = ": "; AOperationType optype = (AOperationType) d.getType(); if (optype.getParameters().isEmpty()) { type += "() "; } else { for (Iterator<PType> iterator = optype.getParameters().iterator(); iterator.hasNext();) { type += iterator.next().apply(typePrinter, question); if (iterator.hasNext()) { type += " * "; } } } type += " ==> " + optype.getResult().apply(typePrinter, question); String tmp = d.getAccess() + " " + d.getName() + " " + type + "\n" + question.getIdent() + d.getName() + "(" + Utils.listToString(d.getParameterPatterns()) + ")" + (d.getBody() == null ? "" : " ==\n" + question.increaseIdent() + d.getBody() + question.decreaseIdent().trim()) + (d.getPrecondition() == null ? "" : "\n" + question.getIdent() + "pre " + d.getPrecondition()) + (d.getPostcondition() == null ? "" : "\n" + question.getIdent() + "post " + d.getPostcondition()); sb.append(tmp + ";\n"); return sb.toString(); } @Override public String caseAExplicitFunctionDefinition( AExplicitFunctionDefinition d, PrettyPrinterEnv question) throws AnalysisException { AFunctionType functype = (AFunctionType) d.getType(); StringBuilder params = new StringBuilder(); for (List<PPattern> plist : d.getParamPatternList()) { params.append("(" + Utils.listToString(plist) + ")"); } String accessStr = d.getAccess().toString(); if (d.getNameScope() == NameScope.LOCAL) { accessStr = ""; } String type = ": "; if (functype.getParameters().isEmpty()) { type += "() "; } else { for (Iterator<PType> iterator = functype.getParameters().iterator(); iterator.hasNext();) { type += iterator.next().apply(typePrinter, question); if (iterator.hasNext()) { type += " * "; } } } type += " " + (functype.getPartial() ? "-" : "+") + "> " + functype.getResult().apply(typePrinter, question); String tmp = question.getIdent() + accessStr + d.getName().getName() + type + "\n" + question.getIdent() + d.getName().getName() + params + " ==\n" + question.increaseIdent() + d.getBody().apply(this, question) + question.decreaseIdent().trim() + (d.getPrecondition() == null ? "" : "\n" + question.getIdent() + "pre " + d.getPrecondition()) + (d.getPostcondition() == null ? "" : "\n" + question.getIdent() + "post " + d.getPostcondition()); return tmp + ";\n"; } @Override public String defaultPStm(PStm node, PrettyPrinterEnv question) throws AnalysisException { return node.toString(); } @Override public String defaultPExp(PExp node, PrettyPrinterEnv question) throws AnalysisException { return node.toString(); } @Override public String caseAUndefinedExp(AUndefinedExp node, PrettyPrinterEnv question) throws AnalysisException { return "undefined"; } @Override public String createNewReturnValue(INode arg0, PrettyPrinterEnv arg1) { // TODO Auto-generated method stub return null; } @Override public String createNewReturnValue(Object arg0, PrettyPrinterEnv arg1) { // TODO Auto-generated method stub return null; } }