Newer
Older
AlgebraicDataflowArchitectureModel / AlgebraicDataflowArchitectureModel / src / algorithms / MethodBodyGenerator.java
package algorithms;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import code.ast.MethodDeclaration;
import code.ast.TypeDeclaration;
import models.Edge;
import models.Node;
import models.algebra.Expression;
import models.algebra.InvalidMessage;
import models.algebra.ParameterizedIdentifierIsFutureWork;
import models.algebra.Symbol;
import models.algebra.Term;
import models.algebra.UnificationFailed;
import models.algebra.ValueUndefined;
import models.dataConstraintModel.ChannelMember;
import models.dataFlowModel.DataFlowModel;
import models.dataFlowModel.PushPullAttribute;
import models.dataFlowModel.PushPullValue;
import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork;
import models.dataFlowModel.ResourceDependency;
import models.dataFlowModel.ResourceDependencyGraph;
import models.dataFlowModel.ResourceNode;

public class MethodBodyGenerator {
	public static ArrayList<TypeDeclaration> doGenerate(ResourceDependencyGraph graph, DataFlowModel model, ArrayList<TypeDeclaration> types) {
		Symbol floor = model.getSymbol("floor");
		Symbol.Memento floorMem = null;
		if (floor != null) {
			floorMem = floor.createMemento();
			floor.setImplName("(int)Math.floor");
			floor.setImplOperatorType(Symbol.Type.PREFIX);
		}
		Symbol sum = model.getSymbol("sum");
		Symbol.Memento sumMem = null;
		if (sum != null) {
			sumMem = sum.createMemento();
			sum.setImplName("stream().mapToInt(x->x).sum");
			sum.setImplOperatorType(Symbol.Type.METHOD);
		}

		// Create a map from type names (lower case) to their types.
		Map<String, TypeDeclaration> typeMap = new HashMap<>();
		for (TypeDeclaration type: types) {
			typeMap.put(type.getTypeName().substring(0,1).toLowerCase() + type.getTypeName().substring(1), type);
		}
		
		// Generate the body of each update or getter method.
		try {
			for (Edge e: graph.getEdges()) {
				ResourceDependency d = (ResourceDependency) e;
				PushPullAttribute pushPull = (PushPullAttribute) d.getAttribute();
				ResourceNode src = (ResourceNode) d.getSource();
				ResourceNode dst = (ResourceNode) d.getDestination();
				String srcResourceName = src.getIdentifierTemplate().getResourceName();
				String dstResourceName = dst.getIdentifierTemplate().getResourceName();
				TypeDeclaration srcType = typeMap.get(srcResourceName);
				TypeDeclaration dstType = typeMap.get(dstResourceName);
				for (ChannelMember out: d.getChannelGenerator().getOutputChannelMembers()) {
					if (out.getIdentifierTemplate() == dst.getIdentifierTemplate()) {
						if (pushPull.getOptions().get(0) == PushPullValue.PUSH) {
							// push
							MethodDeclaration update = getUpdateMethod(dstType);
							Expression updateExp = d.getChannelGenerator().deriveUpdateExpressionOf(out, CodeGenerator.pushAccessor);
							String curState = updateExp.toImplementation();
							String updateStatement;
							if (updateExp instanceof Term && ((Term) updateExp).getSymbol().getImplOperatorType() == Symbol.Type.METHOD_WITH_SIDE_EFFECT) {
								updateStatement = curState + ";";								
							} else {
								updateStatement = dstResourceName + " = " + curState + ";";
							}
							if (update.getBody() == null || !update.getBody().getStatements().contains(updateStatement)) {
								update.addFirstStatement(updateStatement);
							}
							MethodDeclaration getter = getGetterMethod(dstType);
							if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) {
								getter.addStatement("return " + dstResourceName + ";");
							}
							// src side
							MethodDeclaration srcUpdate = getUpdateMethod(srcType);
							if (srcUpdate != null) srcUpdate.addStatement(dstResourceName + ".update(" + srcResourceName + ");");
						} else {
							// pull or push/pull
							MethodDeclaration getter = getGetterMethod(dstType);
							if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) {
								String curState = d.getChannelGenerator().deriveUpdateExpressionOf(out, CodeGenerator.pullAccessor).toImplementation();
								getter.addStatement("return " + curState + ";");
							}
						} 
					}
				}
			}
			for (Node n: graph.getNodes()) {
				ResourceNode resource = (ResourceNode) n;
				TypeDeclaration type = typeMap.get(resource.getIdentifierTemplate().getResourceName());
				MethodDeclaration getter = getGetterMethod(type);
				if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) {
					getter.addStatement("return " + resource.getIdentifierTemplate().getResourceName() + ";");
				}
			}
		} catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork
				| InvalidMessage | UnificationFailed | ValueUndefined e1) {
			e1.printStackTrace();
		}
		
		if (floor != null) floor.setMemento(floorMem);
		if (sum != null) sum.setMemento(sumMem);
		return types;
	}

	private static MethodDeclaration getUpdateMethod(TypeDeclaration dstType) {
		for (MethodDeclaration m: dstType.getMethods()) {
			if (m.getName().startsWith("update")) return m;
			if (m.getName().startsWith("set")) return m;
		}
		return null;
	}

	private static MethodDeclaration getGetterMethod(TypeDeclaration dstType) {
		for (MethodDeclaration m: dstType.getMethods()) {
			if (m.getName().startsWith("get")) return m;
		}
		return null;
	}

}