package newTypeSystem; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import ast.ExpCore; import ast.Ast.Doc; import ast.Ast.Mdf; import ast.Ast.MethodType; import ast.Ast.NormType; import ast.Ast.Path; import ast.Ast.SignalKind; import ast.Ast.Type; import ast.ExpCore.Block; import ast.ExpCore.Block.Dec; import ast.ExpCore.Block.On; import ast.ExpCore.ClassB.MethodWithType; import ast.ExpCore.ClassB.Phase; import programReduction.Program; abstract class AG<This extends AG<This>>{ AG(Map<String,NormType>g){this.g=g;} //TODO: should not be public abstract public This withG(Map<String,NormType>g);//{return new This();} abstract This self();//{return this;} final Map<String,NormType>g;//=Collections.emptyMap();//could be two arrays for efficiency public This addG(String x, NormType t){ assert !g.containsKey(x); Map<String,NormType>newG=new HashMap<String,NormType>(g); newG.put(x,t); return this.withG(newG); } public This removeG(String x){ Map<String,NormType>newG=new HashMap<String,NormType>(g); newG.remove(x); return this.withG(newG); } public This addGds(Program p,List<ExpCore.Block.Dec> ds){ Map<String,NormType>newG=new HashMap<String,NormType>(g); for(ExpCore.Block.Dec d : ds){ assert !g.containsKey(d.getX()); newG.put(d.getX(),programReduction.Norm.resolve(p,d.getT())); } return this.withG(newG); } public This addGG(AG<?> in){ Map<String,NormType>newG=new HashMap<String,NormType>(g); assert newG.keySet().stream().noneMatch(k->in.g.containsKey(k)); newG.putAll(in.g); return this.withG(newG); } public This removeGXs(Set<String> set) { Map<String,NormType>newG=new HashMap<String,NormType>(g); for(String x : set){ newG.remove(x); } return this.withG(newG); } public This removeGDs(List<Block.Dec> ds) { Map<String,NormType>newG=new HashMap<String,NormType>(g); for(Dec di : ds){ newG.remove(di.getX()); } return this.withG(newG); } public NormType g(String x){ NormType res=this.g.get(x); assert res!=null: x; return res; } public NormType _g(String x){ return this.g.get(x); } public Set<String> gDom(){return g.keySet();} //onlyMutOrImm(G)={x:G(x) | G(x) only mut or imm} public This toRead(){//toRead(G)(x)=toRead(G(x)) //thus undefined where toRead undefined Map<String,NormType>newG=new HashMap<String,NormType>(g); for(String xi:gDom()){ NormType ti=g(xi); assert ti!=null; ti=TypeManipulation._toRead(ti); if(ti==null){continue;} newG.put(xi,ti); } return this.withG(newG); } public This toLent(){//toLent(G)(x)=toLent(G(x)) //thus undefined where toLent undefined Map<String,NormType>newG=new HashMap<String,NormType>(g); for(String xi:gDom()){ NormType ti=g(xi); assert ti!=null; ti=TypeManipulation._toLent(ti); if(ti==null){continue;} newG.put(xi,ti); } return this.withG(newG); } public This gKs(List<ExpCore.Block.On>ks){ //G[ks] // G[]=G // G[k ks]=toRead(G) with k.throw=error and not catchRethrow(k) // otherwise G[k ks] = G[ks] for( On k:ks){ if(k.getKind()!=SignalKind.Error){continue;} if(TypeManipulation.catchRethrow(k)){continue;} return this.toRead(); } return this.self(); } } class G extends AG<G>{ private G(Map<String,NormType>g){super(g);} @Override public G withG(Map<String,NormType>g) {return new G(g);} @Override G self() {return this;} static final G instance=new G(Collections.emptyMap()); public String toString(){return g.toString();} } public class TIn extends AG<TIn>{ @Override public TIn withG(Map<String,NormType>g) {return new TIn(this.phase,this.p,this.e,this.expected,g);} @Override TIn self() {return this;} final Phase phase; final Program p; final ExpCore e; final NormType expected; public static TIn top(Phase phase,Program p,ExpCore e){ return new TIn(phase,p,e,Path.Library().toImmNT(),Collections.emptyMap()); } private TIn(Phase phase,Program p,ExpCore e,NormType expected,Map<String,NormType>g ){ super(g); this.phase=phase;this.p=p; this.e=e;this.expected=expected; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + e.hashCode(); result = prime * result + expected.hashCode(); result = prime * result + g.hashCode(); result = prime * result + p.hashCode(); result = prime * result + phase.hashCode(); return result; } @Override public boolean equals(Object obj) { if (this == obj){ return true;} assert obj!=null; assert getClass() == obj.getClass(); TIn other = (TIn) obj; if (phase != other.phase){ return false;} if (!e.equals(other.e)){ return false; } if (!expected.equals(other.expected)){ return false;} if (!g.equals(other.g)){return false;} if (p != other.p){return false;}//simplifing comparing ps return true; } public TIn withE(ExpCore newE,NormType newExpected){ return new TIn(this.phase,this.p,newE,newExpected,this.g); } public TIn withP(Program newP){ return new TIn(this.phase,newP,this.e,Path.Library().toImmNT(),this.g); } boolean isCoherent(){ return true; } @Override public String toString(){ String resE=sugarVisitors.ToFormattedText.of(this.e); resE=resE.replace("\n", " "); if(resE.length()>50){resE=resE.substring(0,40)+"[..]"+resE.substring(resE.length()-5,resE.length());} return this.phase+";p;"+this.g+"|-"+resE+":"+this.expected; } public TIn freshGFromMt(MethodWithType mwt){ MethodType mt=mwt.getMt(); assert mwt.get_inner().isPresent(); Map<String,NormType>newG=new HashMap<String,NormType>(g); newG.put("this",new NormType(mt.getMdf(),Path.outer(0),Doc.empty())); {int i=-1;for(String x:mwt.getMs().getNames()){i+=1; NormType ntx=mt.getTs().get(i).getNT(); newG.put(x,ntx); }} return new TIn(Phase.Typed,this.p,mwt.getInner(),TypeManipulation.fwdP(mt.getReturnType().getNT()),newG); } }