package generators;
import models.algebra.*;
import models.dataConstraintModel.DataConstraintModel;
import models.dataConstraintModel.JsonAccessor;
import models.dataConstraintModel.JsonTerm;
/**
* This class is a Java implementation of {@link IExpressionVisitor}
* which holds and manages the actual method of implementation code generation
*
* @author s-yamagiwa
*/
public class JavaImplementationVisitor implements IExpressionVisitor {
private static int jsonCount = 0;
@Override
public String visit(Term term, String[] sideEffects) {
int[] implParamOrder = term.getSymbol().getImplParamOrder();
if (term.getSymbol().isImplLambda()) {
String[] components = term.getSymbol().getImplName().split("->");
String component0 = components[0].replace("(", "").replace(")", "");
String[] params = component0.split(",");
String exp = components[1];
String receiver = "";
if (implParamOrder == null) {
receiver = term.getChildren().get(0).accept(this, sideEffects);
exp = exp.replace(params[0], receiver);
for (int i = 1; i < params.length; i++) {
exp = exp.replace(params[i], term.getChildren().get(i).accept(this, sideEffects));
}
} else {
receiver = term.getChildren().get(implParamOrder[0]).accept(this, sideEffects);
exp = exp.replace(params[0], receiver);
for (int i = 1; i < params.length; i++) {
exp = exp.replace(params[i], term.getChildren().get(implParamOrder[i]).accept(this, sideEffects));
}
}
if (term.getSymbol().isImplWithSideEffect()) {
sideEffects[0] = sideEffects[0] + exp + ";\n";
exp = receiver;
}
return exp;
}
if (term.getSymbol().isImplGenerative()) {
Type[] childrenTypes = new Type[term.getChildren().size()];
String[] childrenImpl = new String[term.getChildren().size()];
String[] childrenSideEffects = new String[term.getChildren().size()];
if (implParamOrder == null) {
for (int i = 0; i < term.getChildren().size(); i++) {
Expression child = term.getChildren().get(i);
if (child instanceof Variable) {
childrenTypes[i] = ((Variable) child).getType();
} else if (child instanceof Term) {
childrenTypes[i] = ((Term) child).getType();
}
String[] childSideEffect = new String[]{""};
childrenImpl[i] = child.accept(this, childSideEffect);
childrenSideEffects[i] = childSideEffect[0];
}
String exp = term.getSymbol().generate(term.getType(), childrenTypes, childrenImpl, childrenSideEffects, sideEffects);
if (term.getSymbol().isImplWithSideEffect()) {
sideEffects[0] = sideEffects[0] + exp;
exp = childrenImpl[0]; // the value of this term
}
return exp;
} else {
for (int i = 0; i < term.getChildren().size(); i++) {
Expression child = term.getChildren().get(implParamOrder[i]);
if (child instanceof Variable) {
childrenTypes[i] = ((Variable) child).getType();
} else if (child instanceof Term) {
childrenTypes[i] = ((Term) child).getType();
}
String[] childSideEffect = new String[]{""};
childrenImpl[i] = child.accept(this, childSideEffect);
childrenSideEffects[i] = childSideEffect[0];
}
String exp = term.getSymbol().generate(term.getType(), childrenTypes, childrenImpl, childrenSideEffects, sideEffects);
if (term.getSymbol().isImplWithSideEffect()) {
sideEffects[0] = sideEffects[0] + exp;
exp = childrenImpl[0]; // the value of this term
}
return exp;
}
}
if (term.getArity() == 2 && term.getSymbol().isImplInfix()) {
if (implParamOrder == null) {
return "(" + term.getChildren().get(0).accept(this, sideEffects) + term.getSymbol().toImplementation() + term.getChildren().get(1).accept(this, sideEffects) + ")";
} else {
return "(" + term.getChildren().get(implParamOrder[0]).accept(this, sideEffects) + term.getSymbol().toImplementation() + term.getChildren().get(implParamOrder[1]).accept(this, sideEffects) + ")";
}
}
if ((term.getArity() >= 1 || term.getArity() == -1) && term.getSymbol().isImplMethod()) {
if (implParamOrder == null) {
String exp = null;
String receiver = "";
if (term.getChildren().size() > 0 && term.getChildren().get(0) != null) {
receiver = term.getChildren().get(0).accept(this, sideEffects);
exp = receiver + "." + term.getSymbol().toImplementation() + "(";
} else {
exp = term.getSymbol().toImplementation() + "(";
}
String delimiter = "";
for (int i = 1; i < term.getChildren().size(); i++) {
Expression e = term.getChildren().get(i);
exp += (delimiter + e.accept(this, sideEffects));
delimiter = ",";
}
exp += ")";
if (term.getSymbol().isImplWithSideEffect()) {
sideEffects[0] = sideEffects[0] + exp + ";\n";
exp = receiver;
}
return exp;
} else {
String receiver = term.getChildren().get(implParamOrder[0]).accept(this, sideEffects);
String exp = receiver + "." + term.getSymbol().toImplementation() + "(";
String delimiter = "";
for (int i = 1; i < term.getChildren().size(); i++) {
Expression e = term.getChildren().get(implParamOrder[i]);
exp += (delimiter + e.accept(this, sideEffects));
delimiter = ",";
}
exp += ")";
if (term.getSymbol().isImplWithSideEffect()) {
sideEffects[0] = sideEffects[0] + exp + ";\n";
exp = receiver;
}
return exp;
}
} else {
if (implParamOrder == null) {
String exp = term.getSymbol().toImplementation() + "(";
String delimiter = "";
for (Expression e : term.getChildren()) {
exp += (delimiter + e.accept(this, sideEffects));
delimiter = ",";
}
return exp + ")";
} else {
String exp = term.getSymbol().toImplementation() + "(";
String delimiter = "";
for (int i = 0; i < term.getChildren().size(); i++) {
Expression e = term.getChildren().get(implParamOrder[i]);
exp += (delimiter + e.accept(this, sideEffects));
delimiter = ",";
}
return exp + ")";
}
}
}
@Override
public String visit(Field field, String[] sideEffects) {
return "this." + visit((Constant) field, sideEffects);
}
@Override
public String visit(Constant constant, String[] sideEffects) {
if (constant.getSymbol().isImplGenerative()) {
String exp = constant.getSymbol().generate(constant.getType(), new Type[]{}, new String[]{}, new String[]{}, sideEffects);
return exp;
}
return constant.getSymbol().getImplName();
}
@Override
public String visit(Variable variable, String[] sideEffects) {
return variable.getName();
}
@Override
public String visit(JsonTerm jsonTerm, String[] sideEffects) {
String temp = "temp_json" + jsonCount;
jsonCount++;
String impl = "";
impl += "Map<String, Object> " + temp + " = new HashMap<>();\n";
for (String key : jsonTerm.keySet()) {
impl += temp + ".put(\"" + key + "\", " + jsonTerm.get(key).accept(this, sideEffects) + ");\n";
}
sideEffects[0] += impl;
return temp;
}
@Override
public String visit(JsonAccessor jsonAccessor, String[] sideEffects) {
if (jsonAccessor.getSymbol().equals(DataConstraintModel.dotParam)) {
return jsonAccessor.getChildren().get(0).accept(this, sideEffects) + "." + jsonAccessor.getSymbol().toImplementation() + "(" + jsonAccessor.getChildren().get(1).accept(this, sideEffects) + ")";
}
return visit((Term) jsonAccessor, sideEffects);
}
}