package deadlock.analyser.factory;
import java.util.HashMap;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import abs.frontend.ast.ASTNode;
import abs.frontend.ast.AwaitStmt;
import abs.frontend.ast.Stmt;
import abs.frontend.typechecker.DataTypeType;
import com.gzoumix.semisolver.substitution.Substitution;
import com.gzoumix.semisolver.term.Variable;
import com.gzoumix.semisolver.term.Term;
import com.gzoumix.semisolver.term.TermStructured;
import com.gzoumix.semisolver.term.TermVariable;
import com.gzoumix.semisolver.constraint.Constraint;
public class Factory extends com.gzoumix.semisolver.factory.Factory {
private boolean verbose;
private IRecord dummyDataType;
/* Constructor */
public Factory(boolean v) { verbose = v; dummyDataType = new RecordDataType(RecordDataType._prefix + "DUMMY", new LinkedList<Term>()); }
/* 1. RECORDS */
public RecordField newRecordField(String name, IRecord r) {
RecordField res = new RecordField(name, r);
return res;
}
public RecordPresent newRecordPresent(GroupName a, List<RecordField> fields){
RecordPresent res = new RecordPresent(a, fields);
return res;
}
public RecordFuture newRecordFuture(GroupName a, IRecord r) {
RecordFuture res = new RecordFuture(a, r);
return res;
}
public RecordDataType newRecordDataType(DataTypeType data, List<IRecord> r) {
RecordDataType res = new RecordDataType(data,r);
return res;
}
public GroupName newGroupName() {
GroupName res = new GroupName(new Variable());
return res;
}
public GroupName newGroupName(boolean isFresh) {
GroupName res = new GroupName(new Variable(), isFresh);
return res;
}
public RecordVariable newRecordVariable() {
RecordVariable res = new RecordVariable(new Variable());
return res;
}
/* 2. CONTRACTS */
public Contract newContractEmpty() { return new Contract(); }
public Contract newContractSequence(List<Contract> ce) {
List<Term> l = new LinkedList<Term>();
for(Contract contract: ce) { l.addAll(((TermStructured)contract).getSubTerms()); }
return new Contract(l);
}
public Contract newContractAwait(ASTNode n, GroupName a, GroupName b) {
List<Term> l = new ArrayList<Term>();
l.add(new ContractElementAwait(n, a, b));
return new Contract(l);
}
public Contract newContractGet(ASTNode n, GroupName a, GroupName b) {
List<Term> l = new LinkedList<Term>();
l.add(new ContractElementGet(n, a, b));
return new Contract(l);
}
public Contract newContractInvk(ASTNode n, String nameClass, String nameMethod, MethodInterface mi) {
List<Term> l = new LinkedList<Term>();
l.add(new ContractElementInvk(n, nameClass, nameMethod, mi));
return new Contract(l);
}
public Contract newContractSyncInvk(ASTNode n, String nameClass, String nameMethod, MethodInterface mi) {
List<Term> l = new LinkedList<Term>();
l.add(new ContractElementSyncInvk(n, nameClass, nameMethod, mi));
return new Contract(l);
}
public Contract newContractInvkA(ASTNode n, ContractElementInvk i, ContractElementAwait a) {
List<Term> l = new LinkedList<Term>();
l.add(new ContractElementInvkA(n, i, a));
return new Contract(l);
}
public Contract newContractInvkG(ASTNode n, ContractElementInvk i, ContractElementGet g) {
List<Term> l = new LinkedList<Term>();
l.add(new ContractElementInvkG(n, i, g));
return new Contract(l);
}
public Contract newContractUnion(ASTNode n, Contract c1, Contract c2) {
List<Term> l = new LinkedList<Term>();
l.add(new ContractElementUnion(n, c1, c2));
return new Contract(l);
}
public Contract newContractParallel(ASTNode n, List<Contract> l) {
List<Term> l1 = new LinkedList<Term>();
l1.add(new ContractElementParallel(n, l));
return new Contract(l1);
}
/* 4. Methods */
public MethodInterface newMethodInterface(IRecord r, List<IRecord> s, IRecord res){
return new MethodInterface(r, s, res);
}
public MethodContract newMethodContract(MethodInterface mi, Contract cp,Contract cf){
return new MethodContract(mi, cp, cf);
}
/* 5. Reimplementation of Generic News */
public TermVariable freshTermVariableFromTerm(Term t) {
if(t instanceof GroupName) { return newGroupName(); }
else if(t instanceof IRecord) { return newRecordVariable(); }
else{ System.out.println("WHAT THE HELL !!!???"); return super.freshTermVariableFromTerm(t); }
}
public Term newTerm(String c, List<Term> l) {
if(c.equals(Contract.name)) { return new Contract(l); }
else if(c.equals(ContractElementAwait.name)) { return new ContractElementAwait(l); }
else if(c.equals(ContractElementGet.name)) { return new ContractElementGet(l); }
else if(c.startsWith(ContractElementInvk.prefix)) { return new ContractElementInvk(c, l); }
else if(c.equals(ContractElementInvkA.name)) { return new ContractElementInvkA(l); }
else if(c.equals(ContractElementInvkG.name)) { return new ContractElementInvkG(l); }
else if(c.equals(ContractElementParallel.name)) { return new ContractElementParallel(l); }
else if(c.startsWith(ContractElementSyncInvk.prefix)) { return new ContractElementSyncInvk(c, l); }
else if(c.equals(ContractElementUnion.name)) { return new ContractElementUnion(l); }
else if(c.equals(FunctionInterface.name)) { return new FunctionInterface(l); }
else if(c.equals(MethodContract.name)) { return new MethodContract(l); }
else if(c.equals(MethodInterface.name)) { return new MethodInterface(l); }
else if(c.startsWith(RecordDataType._prefix)) { return new RecordDataType(c, l); }
else if(c.startsWith(RecordField.prefix)) { return new RecordField(c, l); }
else if(c.equals(RecordFuture.name)) { return new RecordFuture(l); }
else if(c.equals(RecordPresent.name)) { return new RecordPresent(l); }
else {return super.newTerm(c, l); } // should never occur
}
public Constraint newConstraint() {
Constraint res = super.newConstraint();
if(verbose) { res.setDebugFile(System.out); }
return res;
}
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/* Tool for substitution? *//*
public Term freshTerm(Term t){// TODO give a better semantics or name
Map<Variable,Term> mapFresh = new HashMap<Variable,Term>();
for(Variable var : t.fv()){
mapFresh.put(var, this.freshTermVariable());
}
Substitution s = new Substitution(this, mapFresh);
return s.apply(t);
}*/
/*
//
public Term accumulateContract(Term c, Term cGetorAwait){
//If c is null then return cGetorAwait
if(c == null) return cGetorAwait;
//If cGetorAwait is null return c
if(cGetorAwait == null) return c;
//Case cGetorAwait is a ContractGet
if((((TermStructured) cGetorAwait).getConstructor()).equals("ContractGet")){
//Case c is a ContractInvk
if((((TermStructured) c).getConstructor()).startsWith("Class")) return newContractGInvk(c,cGetorAwait);
//Case c is a ContractSeq
else if((((TermStructured) c).getConstructor()).equals("ContractSeq")){
//We analyze the last contract of the ContractSeq
Term lastTerm;
List<Term> subs = ((TermStructured) c).getSubTerms();
lastTerm = subs.get(subs.size() - 1);
//Case LastContract is not a ContractInvk
if(!(((TermStructured) lastTerm).getConstructor()).startsWith("Class")){
subs.add(cGetorAwait);
//ther's no concatenation and we add together c and cGetorAwait
return newContractSequence(subs);
}
//Case LastContract is a ContractInvk
else {
//We replace LastTerm and create a new ContractSeq
lastTerm = newContractGInvk(lastTerm,cGetorAwait);
subs.remove(subs.size() - 1);
subs.add(lastTerm);
return newContractSequence(subs);
}
}
//case c is not ContractInvk and not a ContracSeq
else{
//we add together c and cGetorAwait
List<Term> t = new LinkedList<Term>();
t.add(c);
t.add(cGetorAwait);
return newContractSequence(t);
}
//similar to the first case, this time we have ContractAwait and we replace newContractGInvk with newContractAInvk
} else if((((TermStructured) cGetorAwait).getConstructor()).equals("ContractAwait")){
if((((TermStructured) c).getConstructor()).startsWith("Class")) return newContractAInvk(c,cGetorAwait);
else if((((TermStructured) c).getConstructor()).equals("ContractSeq")){
Term lastTerm;
List<Term> subs = ((TermStructured) c).getSubTerms();
lastTerm = subs.get(subs.size() - 1);
if(!(((TermStructured) lastTerm).getConstructor()).startsWith("Class")){
subs.add(cGetorAwait);
return newContractSequence(subs);
}
else {
lastTerm = newContractAInvk(lastTerm,cGetorAwait);
subs.remove(subs.size() - 1);
subs.add(lastTerm);
return newContractSequence(subs);
}
} else{
List<Term> t = new LinkedList<Term>();
t.add(c);
t.add(cGetorAwait);
return newContractSequence(t);
}
//last case where cGetorAwait is neither a get or an await contract and we add it to c
} else return addContract(c,cGetorAwait);
}
*/
public Term cleanContractMethod(Term cm){
//this method has sense only if Term cm is a MethodContract
if(((TermStructured) cm).getConstructor().equals("MethodContract")){
//I recover the 2 main term inside the MethodContract, in particular, the contract c
Term mi = ((TermStructured) cm).getSubTerms().get(0);
Term c = ((TermStructured) cm).getSubTerms().get(1);
//if c is a contractSeq we need to control it
if(((TermStructured) c).getConstructor().equals("ContractSeq")){
//but only if the contractSeq contains 2 or more contract we need to analyze it
if(((TermStructured) c).getSubTerms().size() > 1){
List<Term> cCopy = new LinkedList<Term>();
Iterator<Term> i = ((TermStructured) c).getSubTerms().iterator();
while(i.hasNext()){
Term j=i.next();
if(((TermStructured) j).getConstructor().equals("ContractAInvk")){
Term cAwait = ((TermStructured) j).getSubTerms().get(1);
Term v1 = ((TermStructured) cAwait).getSubTerms().get(0);
Term v2 = ((TermStructured) cAwait).getSubTerms().get(1);
if(i.hasNext()){
Term j2=i.next();
if(((TermStructured) j2).getConstructor().equals("ContractGet")){
Term v12 = ((TermStructured) j2).getSubTerms().get(0);
Term v22 = ((TermStructured) j2).getSubTerms().get(1);
if(v1.toString().equals(v12.toString()) && v2.toString().equals(v22.toString())){
cCopy.add(j);
}else{
cCopy.add(j);
cCopy.add(j2);
}
}else{
cCopy.add(j);
cCopy.add(j2);
}
}else{
cCopy.add(j);
}
}else{
cCopy.add(j);
}
}
List<Term> newMc = new LinkedList<Term>();
newMc.add(mi);
newMc.add(newTerm("ContractSeq", cCopy));
return newTerm("MethodContract",newMc);
} else return cm;
} else return cm;
} else if(((TermStructured) cm).getConstructor().equals("ContractSeq")){
//but only if the contractSeq contains 2 or more contract we need to analyze it
if(((TermStructured) cm).getSubTerms().size() > 1){
List<Term> cCopy = new LinkedList<Term>();
Iterator<Term> i = ((TermStructured) cm).getSubTerms().iterator();
while(i.hasNext()){
Term j=i.next();
if(((TermStructured) j).getConstructor().equals("ContractAInvk")){
Term cAwait = ((TermStructured) j).getSubTerms().get(1);
Term v1 = ((TermStructured) cAwait).getSubTerms().get(0);
Term v2 = ((TermStructured) cAwait).getSubTerms().get(1);
if(i.hasNext()){
Term j2=i.next();
if(((TermStructured) j2).getConstructor().equals("ContractGet")){
Term v12 = ((TermStructured) j2).getSubTerms().get(0);
Term v22 = ((TermStructured) j2).getSubTerms().get(1);
if(v1.toString().equals(v12.toString()) && v2.toString().equals(v22.toString())){
cCopy.add(j);
}else{
cCopy.add(j);
cCopy.add(j2);
}
}else{
cCopy.add(j);
cCopy.add(j2);
}
}else{
cCopy.add(j);
}
}else{
cCopy.add(j);
}
}
return newTerm("ContractSeq", cCopy);
} else return cm;
}else return cm;
}
public ContractElementParallel newContractElementParallel(Contract c1, ContractElementParallel c2) {
c2.getSubTerms().add(c1);
return c2;
}
public Contract newContract(ContractElement e) {
return new Contract(e);
}
public ITypingEnvironmentVariableType dummyDataType() {
//return dummyDataType;
return this.newRecordVariable();
}
} // end class DeadlockFactory