package coreVisitors;
import java.util.ArrayList;
import java.util.List;
import ast.Ast.MethodSelector;
import ast.Ast.Path;
import ast.Ast.Type;
import ast.Ast;
import ast.ExpCore;
import ast.Redex;
import ast.ExpCore.Block.Dec;
import ast.ExpCore.*;
import ast.ExpCore.ClassB.*;
import ast.Redex.Garbage;
import ast.Ast.*;
import auxiliaryGrammar.Functions;
import programReduction.Program;
public class IsValue extends TestShapeVisitor{
Program p;
public IsValue(Program p){this.p=p;}
public static boolean of(Program p, ExpCore e){return e.accept(new IsValue(p));}
//atoms
public static boolean isAtom(ExpCore e){
return e instanceof Ast.Atom;
}
public static Redex.Garbage nestedGarbage(ExpCore e){
if(!(e instanceof Block)){return null;}
return nestedGarbage((Block)e);
}
public static Redex.Garbage nestedGarbage(Block b) {
//b is a right value!
Block b2=Functions.garbage(b,b.getDecs().size());
if(!b2.equals(b)){return new Redex.Garbage(b2);}
//else, try nested!
{int i=-1;for(Dec di:b.getDecs()){i+=1;
if (!(di.getInner() instanceof Block)){continue;}
Block bi=(Block) di.getInner();
Redex.Garbage ngi=nestedGarbage(bi);
if(ngi==null){continue;}
List<Block.Dec> ds=new ArrayList<Block.Dec>(b.getDecs());
ds.set(i,di.withInner(ngi.getThatLessGarbage()));
return new Redex.Garbage(b.withDecs(ds));
}}
if(!(b.getInner() instanceof Block)){return null;}
Block bIn=(Block)b.getInner();
Redex.Garbage ngIn=nestedGarbage(bIn);
if(ngIn==null){return null;}
return new Redex.Garbage(b.withInner(ngIn.getThatLessGarbage()));
}
public Boolean visit(ExpCore.EPath s) {return true;}
public Boolean visit(X s) {return true;}
public Boolean visit(_void s) {return true;}
public Boolean visit(ClassB s) {return true;}
public Boolean visit(Block s) {
if(!s.getOns().isEmpty()){return false;}
int dvsn=s.getDecs().size();
for( int i=0;i<dvsn;i++){
if(!validDv(s.getDecs().get(i))){return false;}
}
return s.getInner().accept(this);
}
public boolean validDv(Block.Dec dv) {
NormType nt=dv.getT().getNT();
if(nt.getMdf()==Mdf.Capsule){return false;}
if(!Functions.isComplete(nt)){return false;}
if(Functions.isInterface(p,nt.getPath())){return false;}
if(validRightValue(dv.getInner())){return true;}
if(nt.getMdf()==Mdf.Immutable && dv.getInner() instanceof Block){
return dv.getInner().accept(this);
}
return false;
}
public boolean validDecForPh(Dec dv) {
NormType nt=dv.getT().getNT();
if(validRightValue(dv.getInner())){return true;}
if(nt.getMdf()==Mdf.Immutable && dv.getInner() instanceof Block){
return dv.getInner().accept(this);
}
return false;
}
public boolean validRightValue(ExpCore ec) {
if(!(ec instanceof MCall))return false;
MCall s=(MCall)ec;
if(!(s.getInner() instanceof EPath)){return false;}
MethodSelector ms=s.getS();
MethodWithType mwt=(MethodWithType) p.extractClassB(((EPath)s.getInner()).getInner())._getMember(ms);
if(mwt.get_inner().isPresent()){return false;}
if(mwt.getMt().getMdf()!=ast.Ast.Mdf.Class){return false;}
for(ExpCore ei:s.getEs()){
if(!isAtom(ei)){return false;}
}
return true;
}
/*public static boolean isResult(Program p, ExpCore inner) {
if (!(inner instanceof Signal)){return false;}
return IsValue.of(p,((Signal)inner).getInner());
}*/
}