package algorithms;
import java.util.ArrayList;
import code.ast.*;
import models.*;
import models.algebra.*;
import models.dataConstraintModel.*;
import models.dataFlowModel.*;
import models.dataFlowModel.DataflowChannelGenerator.IResourceStateAccessor;
public class CodeGenerator {
static public ArrayList<TypeDeclaration> doGenerate(ResourceDependencyGraph graph, DataFlowModel model) {
ArrayList<TypeDeclaration> codes = new ArrayList<>();
ArrayList<ResourceNode> resources = StoreResourceCheck(graph);
codes.add(new TypeDeclaration("Main"));
for (ResourceNode rn : resources) {
String name = rn.getIdentifierTemplate().getResourceName().substring(0, 1).toUpperCase()
+ rn.getIdentifierTemplate().getResourceName().substring(1);
FieldDeclaration field = new FieldDeclaration(new Type(name, name),
rn.getIdentifierTemplate().getResourceName());
TypeDeclaration type = new TypeDeclaration(name);
codes.get(0).addField(field);
for (Edge e : rn.getOutEdges()) {
ResourceDependency re = (ResourceDependency) e;
String rename = ((ResourceNode) re.getDestination()).getIdentifierTemplate().getResourceName()
.substring(0, 1).toUpperCase()
+ ((ResourceNode) re.getDestination()).getIdentifierTemplate().getResourceName().substring(1);
if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) {
type.addField(new FieldDeclaration(new Type(rename, rename),
((ResourceNode) re.getDestination()).getIdentifierTemplate().getResourceName()));
type.addConstructor(new VariableDeclaration(new Type(rename, rename),((ResourceNode) re.getSource()).getIdentifierTemplate().getResourceName()));
}
}
for (Edge e : rn.getInEdges()) {
ResourceDependency re = (ResourceDependency) e;
String rename = ((ResourceNode) re.getSource()).getIdentifierTemplate().getResourceName()
.substring(0, 1).toUpperCase()
+ ((ResourceNode) re.getSource()).getIdentifierTemplate().getResourceName().substring(1);
if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) {
type.addField(new FieldDeclaration(new Type(rename, rename),
((ResourceNode) re.getSource()).getIdentifierTemplate().getResourceName()));
type.addConstructor(new VariableDeclaration(new Type(rename, rename),((ResourceNode) re.getSource()).getIdentifierTemplate().getResourceName()));
}
}
if (((StoreAttribute) rn.getAttribute()).isStored())
type.addField(new FieldDeclaration(DataConstraintModel.typeInt,
rn.getIdentifierTemplate().getResourceName()));
codes.add(type);
}
return codes;
}
static public ArrayList<String> getCodes(ArrayList<TypeDeclaration> codeTree) {
ArrayList<String> codes = new ArrayList<>();
for (TypeDeclaration type : codeTree) {
codes.add("public class " + type.getTypeName() + "{");
for (FieldDeclaration field : type.getFields()) {
if(type.getTypeName() != "Main") {
codes.add("\t" + field.getType().getImplementationTypeName() + " " + field.getName() + " = null;");
}else {
codes.add("\t" + field.getType().getImplementationTypeName() + " " + field.getName() + " = new " + field.getType().getTypeName() + "(" + ");");
}
}
codes.add("");
if (type.getTypeName() != "Main") {
String cons = "\t" + type.getTypeName() + "(";
for(VariableDeclaration constructor:type.getConstructor()) {
cons += constructor.getType().getTypeName() + " " + constructor.getName() + ",";
}
cons = cons.substring(0, cons.length() - 1);
cons += ");";
codes.add(cons);
for (FieldDeclaration field : type.getFields()) {
if(type.getTypeName().toLowerCase() != field.getName()) codes.add("\t\t" + "this." + field.getName() + " = " + field.getName());
}
codes.add("\t" + "}");
}
for (MethodDeclaration method : type.getMethods()) {
codes.add("\t" + "public " + method.getReturnType().getImplementationTypeName() + " " + method.getName()
+ "{");
for (VariableDeclaration value : method.getParameters()) {
codes.add("\t\t" + value.getType().getImplementationTypeName() + " " + value.getName());
}
codes.add("\t" + "}");
codes.add("");
}
codes.add("}");
}
return codes;
}
static private ArrayList<ResourceNode> StoreResourceCheck(ResourceDependencyGraph graph) {
ArrayList<ResourceNode> resources = new ArrayList<>();
for (Node n : graph.getNodes()) {
ResourceNode rn = (ResourceNode) n;
boolean flag = true;
for (Edge e : rn.getOutEdges()) {
ResourceDependency re = (ResourceDependency) e;
if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) {
flag = false;
}
}
for (Edge e : rn.getInEdges()) {
ResourceDependency re = (ResourceDependency) e;
if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) {
flag = false;
}
}
if (flag)
resources.add(rn);
}
trackNode(resources.get(0), resources);
return resources;
}
static private void trackNode(ResourceNode current, ArrayList<ResourceNode> resources) {
if (!resources.contains(current))
resources.add(current);
for (Edge e : current.getOutEdges()) {
ResourceDependency re = (ResourceDependency) e;
if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) {
trackNode((ResourceNode) re.getDestination(), resources);
}
}
for (Edge e : current.getInEdges()) {
ResourceDependency re = (ResourceDependency) e;
if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) {
trackNode((ResourceNode) re.getSource(), resources);
}
}
}
static public IResourceStateAccessor pushAccessor = new IResourceStateAccessor() {
@Override
public Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) {
if (target.equals(from)) {
return new Field(target.getResourceName(),
target.getResourceStateType() != null ? target.getResourceStateType()
: DataConstraintModel.typeInt);
}
return null;
}
@Override
public Expression getNextStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) {
return new Parameter(target.getResourceName(),
target.getResourceStateType() != null ? target.getResourceStateType()
: DataConstraintModel.typeInt);
}
};
static public IResourceStateAccessor pullAccessor = new IResourceStateAccessor() {
@Override
public Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) {
if (target.equals(from)) {
return new Field(target.getResourceName(),
target.getResourceStateType() != null ? target.getResourceStateType()
: DataConstraintModel.typeInt);
}
return null;
}
@Override
public Expression getNextStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) {
Term getter = new Term(new Symbol("get" + target.getResourceName(), 1, Symbol.Type.METHOD));
getter.addChild(new Field(target.getResourceName(), target.getResourceStateType()));
return getter;
}
};
}