/**
* Copyright 2004-2016 Riccardo Solmi. All rights reserved.
* This file is part of the Whole Platform.
*
* The Whole Platform is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Whole Platform 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whole.examples.lang.imp.visitors;
import org.whole.examples.lang.imp.model.Addition;
import org.whole.examples.lang.imp.model.And;
import org.whole.examples.lang.imp.model.Arguments;
import org.whole.examples.lang.imp.model.ArrayAccess;
import org.whole.examples.lang.imp.model.ArrayLiteral;
import org.whole.examples.lang.imp.model.ArrayType;
import org.whole.examples.lang.imp.model.AssignmentExpression;
import org.whole.examples.lang.imp.model.BooleanLiteral;
import org.whole.examples.lang.imp.model.Division;
import org.whole.examples.lang.imp.model.DoWhileStatement;
import org.whole.examples.lang.imp.model.EmptyStatement;
import org.whole.examples.lang.imp.model.Equals;
import org.whole.examples.lang.imp.model.Expression;
import org.whole.examples.lang.imp.model.ExpressionStatement;
import org.whole.examples.lang.imp.model.ForStatement;
import org.whole.examples.lang.imp.model.ForeachStatement;
import org.whole.examples.lang.imp.model.FunctionDeclaration;
import org.whole.examples.lang.imp.model.GreaterOrEquals;
import org.whole.examples.lang.imp.model.GreaterThan;
import org.whole.examples.lang.imp.model.IfElseStatement;
import org.whole.examples.lang.imp.model.IfStatement;
import org.whole.examples.lang.imp.model.IntLiteral;
import org.whole.examples.lang.imp.model.LessOrEquals;
import org.whole.examples.lang.imp.model.LessThan;
import org.whole.examples.lang.imp.model.Literal;
import org.whole.examples.lang.imp.model.LoadExpression;
import org.whole.examples.lang.imp.model.Multiplication;
import org.whole.examples.lang.imp.model.Name;
import org.whole.examples.lang.imp.model.NameExpression;
import org.whole.examples.lang.imp.model.Not;
import org.whole.examples.lang.imp.model.NotEquals;
import org.whole.examples.lang.imp.model.Or;
import org.whole.examples.lang.imp.model.Parameter;
import org.whole.examples.lang.imp.model.Parameters;
import org.whole.examples.lang.imp.model.PrimitiveType;
import org.whole.examples.lang.imp.model.PrintStatement;
import org.whole.examples.lang.imp.model.PrintlnStatement;
import org.whole.examples.lang.imp.model.RangeLiteral;
import org.whole.examples.lang.imp.model.Remainder;
import org.whole.examples.lang.imp.model.ReturnStatement;
import org.whole.examples.lang.imp.model.RunExpression;
import org.whole.examples.lang.imp.model.SaveStatement;
import org.whole.examples.lang.imp.model.SizeExpression;
import org.whole.examples.lang.imp.model.StringLiteral;
import org.whole.examples.lang.imp.model.Subtraction;
import org.whole.examples.lang.imp.model.VariableDeclaration;
import org.whole.examples.lang.imp.model.WhileStatement;
import org.whole.examples.lang.imp.reflect.ImpEntityDescriptorEnum;
import org.whole.lang.model.adapters.IEntityAdapter;
import org.whole.lang.operations.IPrettyPrintWriter;
import org.whole.lang.operations.PrettyPrinterOperation;
import org.whole.lang.util.EntityUtils;
/**
* @author Riccardo Solmi
*/
public class ImpPrettyPrinterVisitor extends ImpTraverseAllVisitor {
protected final IPrettyPrintWriter out;
public ImpPrettyPrinterVisitor(PrettyPrinterOperation operation) {
out = operation.getPrettyPrintWriter();
}
public boolean visitAdapter(IEntityAdapter entity) {
stagedVisit(entity.wGetAdaptee(false));
return false;
}
public void visit(FunctionDeclaration entity) {
out.printRaw("function ");
entity.getType().accept(this);
out.print(' ');
entity.getName().accept(this);
out.print('(');
entity.getParameters().accept(this);
out.printlnRaw(") {");
out.setRelativeIndentation((+1));
entity.getBody().accept(this);
out.setRelativeIndentation((-1));
out.printlnRaw("}");
}
public void visit(Parameters entity) {
for (int i = 0; i < entity.wSize(); i++) {
if (i>0)
out.printRaw(", ");
((Parameter) entity.wGet(i)).accept(this);
}
}
public void visit(Parameter entity) {
entity.getType().accept(this);
out.print(' ');
entity.getName().accept(this);
}
public void visit(VariableDeclaration entity) {
entity.getType().accept(this);
out.print(' ');
entity.getName().accept(this);
out.printRaw(" = ");
entity.getInitializer().accept(this);
if (!out.isInlined())
out.printlnRaw(";");
}
public void visit(Arguments entity) {
out.print('(');
for (int i = 0; i < entity.wSize(); i++) {
if (i>0)
out.printRaw(", ");
((Expression) entity.wGet(i)).accept(this);
}
out.print(')');
}
public void visit(EmptyStatement entity) {
out.printlnRaw(";");
}
public void visit(ReturnStatement entity) {
out.printRaw("return ");
entity.getExp().accept(this);
out.printlnRaw(";");
}
public void visit(IfStatement entity) {
out.printRaw("if (");
entity.getCondition().accept(this);
out.print(')');
if (entity.getTrueBody().wGetEntityDescriptor().equals(ImpEntityDescriptorEnum.BlockStatement))
out.printlnRaw(" {");
else
out.println();
out.setRelativeIndentation((+1));
entity.getTrueBody().accept(this);
out.setRelativeIndentation((-1));
if (entity.getTrueBody().wGetEntityDescriptor().equals(ImpEntityDescriptorEnum.BlockStatement)) {
out.printlnRaw("}");
}
}
public void visit(IfElseStatement entity) {
out.printRaw("if (");
entity.getCondition().accept(this);
out.print(')');
if (entity.getTrueBody().wGetEntityDescriptor().equals(ImpEntityDescriptorEnum.BlockStatement))
out.printlnRaw(" {");
else
out.println();
out.setRelativeIndentation((+1));
entity.getTrueBody().accept(this);
out.setRelativeIndentation((-1));
if (entity.getTrueBody().wGetEntityDescriptor().equals(ImpEntityDescriptorEnum.BlockStatement))
out.printRaw("} ");
out.printRaw("else");
if (entity.getFalseBody().wGetEntityDescriptor().equals(ImpEntityDescriptorEnum.BlockStatement))
out.printlnRaw(" {");
else
out.println();
out.setRelativeIndentation((+1));
entity.getFalseBody().accept(this);
out.setRelativeIndentation((-1));
if (entity.getFalseBody().wGetEntityDescriptor().equals(ImpEntityDescriptorEnum.BlockStatement)) {
out.printlnRaw("}");
}
}
public void visit(WhileStatement entity) {
out.printRaw("while (");
entity.getCondition().accept(this);
out.print(')');
if (entity.getTrueBody().wGetEntityDescriptor().equals(ImpEntityDescriptorEnum.BlockStatement))
out.printlnRaw(" {");
else
out.println();
out.setRelativeIndentation((+1));
entity.getTrueBody().accept(this);
out.setRelativeIndentation((-1));
if (entity.getTrueBody().wGetEntityDescriptor().equals(ImpEntityDescriptorEnum.BlockStatement)) {
out.printlnRaw("}");
}
}
public void visit(DoWhileStatement entity) {
out.printlnRaw("do {");
out.setRelativeIndentation((+1));
entity.getTrueBody().accept(this);
out.setRelativeIndentation((-1));
out.printRaw("} while (");
entity.getCondition().accept(this);
out.printlnRaw(");");
}
public void visit(ForStatement entity) {
out.printRaw("for (");
out.setInlined(true);
entity.getInitializer().accept(this);
out.setInlined(false);
out.printRaw("; ");
entity.getCondition().accept(this);
out.printRaw("; ");
out.setInlined(true);
entity.getUpdater().accept(this);
out.setInlined(false);
out.printRaw(")");
if (entity.getTrueBody().wGetEntityDescriptor().equals(ImpEntityDescriptorEnum.BlockStatement))
out.printlnRaw(" {");
else
out.println();
out.setRelativeIndentation((+1));
entity.getTrueBody().accept(this);
out.setRelativeIndentation((-1));
if (entity.getTrueBody().wGetEntityDescriptor().equals(ImpEntityDescriptorEnum.BlockStatement)) {
out.printlnRaw("}");
}
}
public void visit(ForeachStatement entity) {
out.printRaw("foreach (");
entity.getName().accept(this);
out.printRaw(" : ");
entity.getArrayExp().accept(this);
out.printRaw(")");
if (entity.getTrueBody().wGetEntityDescriptor().equals(ImpEntityDescriptorEnum.BlockStatement))
out.printlnRaw(" {");
else
out.println();
out.setRelativeIndentation((+1));
entity.getTrueBody().accept(this);
out.setRelativeIndentation((-1));
if (entity.getTrueBody().wGetEntityDescriptor().equals(ImpEntityDescriptorEnum.BlockStatement)) {
out.printlnRaw("}");
}
}
public void visit(ExpressionStatement entity) {
entity.getExp().accept(this);
out.printlnRaw(";");
}
public void visit(AssignmentExpression entity) {
entity.getName().accept(this);
out.printRaw(" = ");
entity.getExp().accept(this);
}
public void visit(PrintStatement entity) {
out.printRaw("print ");
entity.getExp().accept(this);
out.printlnRaw(";");
}
public void visit(PrintlnStatement entity) {
out.printRaw("println ");
entity.getExp().accept(this);
out.printlnRaw(";");
}
public void visit(SaveStatement entity) {
out.printRaw("save ");
entity.getExp().accept(this);
if (!EntityUtils.isResolver(entity.getFileName())) {
out.printRaw(" as ");
entity.getFileName().accept(this);
}
out.printlnRaw(";");
}
public void visit(LoadExpression entity) {
out.printRaw("load ");
entity.getFileName().accept(this);
if (!EntityUtils.isResolver(entity.getLanguage())) {
out.printRaw(" as ");
entity.getLanguage().accept(this);
}
}
public void visit(RunExpression entity) {
out.printRaw("run ");
entity.getExp().accept(this);
}
public void visit(BooleanLiteral entity) {
out.print(entity.wBooleanValue());
}
public void visit(IntLiteral entity) {
out.print(entity.wIntValue());
}
public void visit(StringLiteral entity) {
out.printRaw("\""+entity.wStringValue()+"\"");
}
public void visit(Name entity) {
out.printRaw(entity.getValue());
}
public void visit(NameExpression entity) {
out.printRaw(entity.getValue());
}
public void visit(PrimitiveType entity) {
out.print(entity.getValue());
}
public void visit(SizeExpression entity) {
out.print('#');
entity.getExp().accept(this);
}
public void visit(RangeLiteral entity) {
out.print('{');
entity.getLowerBound().accept(this);
out.printRaw("..");
entity.getUpperBound().accept(this);
out.print('}');
}
public void visit(ArrayLiteral entity) {
out.print('{');
for (int i = 0; i < entity.wSize(); i++) {
if (i>0)
out.printRaw(", ");
((Literal) entity.wGet(i)).accept(this);
}
out.print('}');
}
public void visit(ArrayType entity) {
entity.getContentType().accept(this);
out.print('[');
entity.getIndexType().accept(this);
out.print(']');
}
public void visit(ArrayAccess entity) {
entity.getArray().accept(this);
out.print('[');
entity.getIndex().accept(this);
out.print(']');
}
public void visit(Addition entity) {
entity.getExp1().accept(this);
out.printRaw(" + ");
entity.getExp2().accept(this);
}
public void visit(Subtraction entity) {
entity.getExp1().accept(this);
out.printRaw(" - ");
entity.getExp2().accept(this);
}
public void visit(Multiplication entity) {
entity.getExp1().accept(this);
out.printRaw(" * ");
entity.getExp2().accept(this);
}
public void visit(Division entity) {
entity.getExp1().accept(this);
out.printRaw(" / ");
entity.getExp2().accept(this);
}
public void visit(Remainder entity) {
entity.getExp1().accept(this);
out.printRaw(" % ");
entity.getExp2().accept(this);
}
public void visit(And entity) {
entity.getExp1().accept(this);
out.printRaw(" && ");
entity.getExp2().accept(this);
}
public void visit(Or entity) {
entity.getExp1().accept(this);
out.printRaw(" || ");
entity.getExp2().accept(this);
}
public void visit(Not entity) {
out.print('!');
entity.getExp().accept(this);
}
public void visit(Equals entity) {
entity.getExp1().accept(this);
out.printRaw(" == ");
entity.getExp2().accept(this);
}
public void visit(NotEquals entity) {
entity.getExp1().accept(this);
out.printRaw(" != ");
entity.getExp2().accept(this);
}
public void visit(LessThan entity) {
entity.getExp1().accept(this);
out.printRaw(" < ");
entity.getExp2().accept(this);
}
public void visit(LessOrEquals entity) {
entity.getExp1().accept(this);
out.printRaw(" <= ");
entity.getExp2().accept(this);
}
public void visit(GreaterThan entity) {
entity.getExp1().accept(this);
out.printRaw(" > ");
entity.getExp2().accept(this);
}
public void visit(GreaterOrEquals entity) {
entity.getExp1().accept(this);
out.printRaw(" >= ");
entity.getExp2().accept(this);
}
}