package programReduction; import java.nio.file.Path; import java.util.*; import java.util.stream.Collector; import java.util.stream.Collectors; import ast.Ast; import ast.ErrorMessage; import ast.ExpCore.ClassB; import coreVisitors.IsCompiled; public class Paths { //@SuppressWarnings("serial") //public static class EmptyPath extends RuntimeException{} final Paths next; final List<List<Ast.C>> current; private Paths(Paths next, List<List<Ast.C>> current){ this.next=next; this.current=current; } private static final Paths empty=new Paths(null,Collections.emptyList()); public static Paths empty(){return empty;} public boolean isEmpty(){return this==empty;} public List<List<Ast.C>> top(){ assert current!=null; return current; } public Paths pop(){ if (this==empty){return empty;} return this.next; } public Paths push(List<List<Ast.C>> css){ return new Paths(this,minimize(css)); } public Paths union(Paths other){ assert other!=null: ""; if (this==empty){return other;} if (other==empty){return this;} Paths rec=this.pop().union(other.pop()); List<List<Ast.C>> css = new ArrayList<>(this.top()); css.addAll(other.top()); return rec.push(css); } public Paths setMinus(Paths other){ assert other!=null: ""; if (this==empty){return this;} if (other==empty){return this;} Paths rec=this.pop().setMinus(other.pop()); List<List<Ast.C>> css = new ArrayList<>(); for(List<Ast.C> csi:this.top()){ if(other.top().contains(csi)){continue;} if(hasPrefixIn(other.top(),csi)){continue;} css.add(csi); } if(css.isEmpty() && rec.isEmpty()){return Paths.empty();} return rec.push(css); } public boolean checkAllDefined(Program p){ if(this.isEmpty()){return true;} for(List<Ast.C>cs:this.top()){ try{ ClassB li=p.top().getClassB(cs); if(!IsCompiled.of(li)){ throw new ErrorMessage.PathMetaOrNonExistant(true, cs, p.top(), p.top().getP(), null); } } catch(ErrorMessage.PathMetaOrNonExistant pne){ throw pne.withListOfNodeNames(cs); } catch(RuntimeException rte){ throw rte;//to breakpoint } } if(this.pop().isEmpty()){return true;} return this.pop().checkAllDefined(p.pop()); } public Paths prefix(List<Ast.C>cs){ if(this==empty){return empty;} if(cs.isEmpty()){return this;} if(this.pop()==empty){ List<List<Ast.C>> res=new ArrayList<>(); for(List<Ast.C>csi:this.top()){ List<Ast.C>cscsi=new ArrayList<>(cs); cscsi.addAll(csi); res.add(cscsi); } return new Paths(empty,res); } assert this.pop()!=empty; Paths path=this.pop(); List<Ast.C> csPopped=cs.subList(0, cs.size()-1); Paths paths0=path.prefix(csPopped); assert paths0!=empty; Paths paths1=new Paths(empty,this.top()).prefix(cs); assert paths1!=empty; return paths0.union(paths1); } public static Paths reorganize(List<Ast.Path> ps){ if(ps.isEmpty()){return empty;} return reorganize(0,ps); } private static Paths reorganize(int level,List<Ast.Path> ps){ if(ps.isEmpty()){return empty;} List<List<Ast.C>> csi=new ArrayList<>(); List<Ast.Path> nextPs=new ArrayList<>(); for(Ast.Path pi:ps){ if(pi.isPrimitive()){continue;} if(pi.outerNumber()==level){csi.add(pi.getCBar());continue;} nextPs.add(pi); } return reorganize(level+1,nextPs).push(csi); } public static List<List<Ast.C>> minimize(List<List<Ast.C>> css){ Set<List<Ast.C>> res=new LinkedHashSet<>(); for(List<Ast.C> csCandidate: css) { if(!hasPrefixIn(css,csCandidate)){res.add(csCandidate);} } return new ArrayList<>(res); } private static boolean hasPrefixIn(List<List<Ast.C>>cssShort,List<Ast.C>csLong){ for(List<Ast.C> csTest: cssShort){ if(isPrefix(csTest,csLong)){return true;} } return false; } private static boolean isPrefix(List<Ast.C>csShort,List<Ast.C>csLong){ if(csShort.size()>=csLong.size()){return false;} for(int i=0;i<csShort.size();i++){ if (!csShort.get(i).equals(csLong.get(i))){return false;} } //with cs1 in csShort.vals(), cs2 in csLong.vals(maxTo:csShort.size()) ( if cs1!=cs2 (return Bool.false())) return true; } public String toString(){ return toString(0); } public String toString(int n){ String result=""; if(this.isEmpty()){return "<Empty Paths>";} for(List<Ast.C> cs:this.top()){ result+=Ast.Path.outer(n, cs)+" "; } if(this.pop()!=empty){result+=this.pop().toString(n+1);} return result; } public boolean contains(ast.Ast.Path s) { if(s.isPrimitive()){return false;} Paths popped=this; for(int i=0;i<s.outerNumber();i++){ popped=popped.pop(); } return popped.current.contains(s.getCBar()); } }