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) {
codes.get(0).addField(new FieldDeclaration(rn.getIdentifierTemplate().getResourceStateType(),
rn.getIdentifierTemplate().getResourceName()));
codes.add(new TypeDeclaration(rn.getIdentifierTemplate().getResourceName()));
}
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;
}
};
}