package newTypeSystem; import ast.Ast.MethodType; import ast.Ast.NormType; import ast.Ast.Type; import ast.Ast.Path; import ast.ExpCore.ClassB.Member; import ast.ExpCore.ClassB.MethodWithType; import auxiliaryGrammar.Functions; import auxiliaryGrammar.WellFormednessCore; import coreVisitors.From; import programReduction.Program; import tools.Map; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; import ast.Ast.Mdf; import ast.Ast.MethodSelector; import static newTypeSystem.TypeManipulation.*; public class AlternativeMethodTypes { static MethodType mBase(Program p, Path P, MethodSelector ms){ //p(P)(ms).mh[from P]=refine? mdf0 method T m(T1 x1,..Tn xn) exception Ps //T'=fwd% T if fwd_or_fwd%_in(Ts) //otherwise T'=T //(mBase)------------------------------------------------------------------- //mdf0 P T1..Tn-> T';Ps in methTypes(p,P,ms) MethodWithType mwt = (MethodWithType) p.extractClassB(P)._getMember(ms); MethodWithType mwt = (MethodWithType) p.extractClassB(P)._getMember(ms); assert mwt!=null; MethodType mt=From.from(mwt.getMt(),P); return mBase(mt); } static MethodType mBase(MethodType mt){ NormType retT=mt.getReturnType().getNT(); if (fwd_or_fwdP_in(mt.getTs())){ retT=fwdP(mt.getReturnType().getNT()); } return mt.withReturnType(retT); } static MethodType mNoFwd(MethodType mt){ // Ts->T;Ps in methTypes(p,P,ms) //(mNoFwd)------------------------------------------------------------------- // noFwd Ts-> noFwd T;Ps in methTypes(p,P,ms) List<Type> ts = Map.of(t->noFwd(t.getNT()),mt.getTs()); Type retT=noFwd(mt.getReturnType().getNT()); return mt.withReturnType(retT).withTs(ts); } static MethodType _mC(MethodType mt){ //Ts->mut P0;Ps in methTypes(p,P,ms) //(mC)------------------------------------------------------------------- //mutToCapsule(Ts)->capsule P0;Ps in methTypes(p,P,ms) NormType retT=mt.getReturnType().getNT(); if(retT.getMdf()!=Mdf.Mutable){return null;} retT=retT.withMdf(Mdf.Capsule); List<Type> ts = Map.of(t->mutToCapsule(t.getNT()),mt.getTs()); return mt.withReturnType(retT).withTs(ts).withMdf(mutToCapsule(mt.getMdf())); } static MethodType _mI(MethodType mt){ //Ts->read P0;Ps in methTypes(p,P,ms) //by well formedness if return type is read, not fwd_or_fwd%_in Ts //(mI)------------------------------------------------------------------- //toImmOrCapsule(Ts)->imm P0;Ps in methTypes(p,P,ms) ////the behaviour of immorcapsule on fwd is not relevant since the method //// returns a read and will be not well formed if it had fwd parameters NormType retT=mt.getReturnType().getNT(); if(retT.getMdf()!=Mdf.Readable && retT.getMdf()!=Mdf.Lent){return null;} retT=retT.withMdf(Mdf.Immutable); List<Type> ts = Map.of(t->toImmOrCapsule(t.getNT()),mt.getTs()); return mt.withReturnType(retT).withTs(ts).withMdf(toImmOrCapsule(mt.getMdf())); } static MethodType _mVp(MethodType mt, int parNum){ if(parNum>0){return _mVpNoRec(mt,parNum-1);} assert parNum==0; if(mt.getMdf()!=Mdf.Mutable){return null;} NormType retT=mt.getReturnType().getNT(); retT=_toLent(retT); if(retT==null){return null;} List<Type> ts = Map.of(t->mutToCapsule(t.getNT()),mt.getTs()); MethodType res= mt.withReturnType(retT).withTs(ts).withMdf(Mdf.Lent); if(WellFormednessCore.methodTypeWellFormed(res)){return res;} return null; } static MethodType _mVpNoRec(MethodType mt, int parNum){ //Ts0 mut P Ts2->T;Ps in methTypes(p,P,ms) //Ts'=mutToCapsule(Ts0) lent P mutToCapsule(Ts2) //this implies not fwd_or_fwd%_in Ts0,Ts2 //(mVp)------------------------------------------------------------------- //Ts'->toLent(T);Ps in methTypes(p,P,ms) NormType pN=mt.getTs().get(parNum).getNT(); if (pN.getMdf()!=Mdf.Mutable){return null;} NormType retT=mt.getReturnType().getNT(); retT=_toLent(retT); if(retT==null){return null;} List<Type> ts = Map.of(t->mutToCapsule(t.getNT()),mt.getTs()); ts.set(parNum, pN.withMdf(Mdf.Lent)); MethodType res= mt.withReturnType(retT).withTs(ts).withMdf(mutToCapsule(mt.getMdf())); if(WellFormednessCore.methodTypeWellFormed(res)){return res;} return null; } static MethodType _mImmFwd(MethodType mt){ //Ts->fwd%Mut P0;Ps in methTypes(p,P,ms) //fwd_or_fwd%_in(Ts) //(mImmFwd)------------------------------------------------------------------- //mutToCapsuleAndFwdMutToFwdImm(Ts)->fwd%Imm P0;Ps in methTypes(p,P,ms) if(!TypeManipulation.fwd_or_fwdP_in(mt.getTs())){return null;} NormType retT=mt.getReturnType().getNT(); if(retT.getMdf()!=Mdf.MutablePFwd){return null;} retT=retT.withMdf(Mdf.ImmutablePFwd); List<Type> ts = Map.of(t->mutToCapsuleAndFwdMutToFwdImm(t.getNT()),mt.getTs()); MethodType res= mt.withReturnType(retT).withTs(ts).withMdf(mutToCapsuleAndFwdMutToFwdImm(mt.getMdf())); if(WellFormednessCore.methodTypeWellFormed(res)){return res;} return null; } static MethodType _mRead(MethodType mt){ //Ts->fwd%Mut P0;Ps in methTypes(p,P,ms) //fwd_or_fwd%_in(Ts) //(mRead)------------------------------------------------------------------- //mutToCapsuleAndFwdToRead(Ts)->read P0;Ps in methTypes(p,P,ms) if(!TypeManipulation.fwd_or_fwdP_in(mt.getTs())){return null;} NormType retT=mt.getReturnType().getNT(); if(retT.getMdf()!=Mdf.MutablePFwd){return null;} retT=retT.withMdf(Mdf.Readable); List<Type> ts = Map.of(t->mutToCapsuleAndFwdToRead(t.getNT()),mt.getTs()); MethodType res=mt.withReturnType(retT).withTs(ts).withMdf(mutToCapsuleAndFwdToRead(mt.getMdf())); if(WellFormednessCore.methodTypeWellFormed(res)){return res;} return null; } static void add(List<MethodType>l,MethodType t){ if(t==null){return;} l.add(t); } static MethodType _mtDeclared(Program p, Path P, MethodSelector ms){ MethodWithType mwt = (MethodWithType) p.extractClassB(P)._getMember(ms); if(mwt==null){return null;} MethodType mt=From.from(mwt.getMt(),P); return mt; } static List<MethodType> types(MethodType mt){ List<MethodType>res=new ArrayList<>(); MethodType base=mBase(mt); add(res,base); MethodType mNoFwd=mNoFwd(base); add(res,mNoFwd); MethodType mImmFwd=_mImmFwd(base); add(res,mImmFwd); MethodType mRead=_mRead(base); add(res, mRead); add(res,_mC(base)); add(res,_mC(mNoFwd)); add(res,_mI(base)); if(mRead!=null){add(res,_mI(mRead));} if(mImmFwd!=null){add(res,mNoFwd(mImmFwd));} if(mt.getMdf()==Mdf.Mutable){add(res,_mVp(base,0));} //later, 0 for mvp is the receiver so is ok to start from 1 {int i=0;for(Type ti:base.getTs()){i+=1; if(ti.getNT().getMdf()!=Mdf.Mutable){continue;} add(res,_mVp(base,i)); //1 mType for each mut parameter }} if(mt.getMdf()==Mdf.Mutable){add(res,_mVp(mNoFwd,0));} {int i=0;for(Type ti:mNoFwd.getTs()){i+=1; if(ti.getNT().getMdf()!=Mdf.Mutable){continue;} add(res,_mVp(mNoFwd,i)); //1 mType for each mut parameter }} return res; } public static MethodType _firstMatchReturn(Program p,NormType nt,List<MethodType> mts){ for(MethodType mt:mts){ if(null==TypeSystem.subtype(p, mt.getReturnType().getNT(), nt)){return mt;} } return null; } public static MethodType _bestMatchMtype(Program p,MethodType superMt,List<MethodType> mts){ List<MethodType> res=new ArrayList<>(); for(MethodType mt:mts){ if(TypeSystem._methMdfTSubtype(mt, superMt)){ if(!res.stream().anyMatch(mti->TypeSystem._methMdfTSubtype(mti, mt))){ res=res.stream().filter(mti->!TypeSystem._methMdfTSubtype(mt, mti)).collect(Collectors.toList()); res.add(mt);//if there is no method that is even better, add } } } //assert res.size()==1: res.size(); sometime is false, for example capsule->capsule and mut->mut if(res.isEmpty()){return null;} if(res.size()==1){ return res.get(0); } List<MethodType> _res=res;//for final limitations Optional<MethodType> res1 = res.stream().filter( mt1->_res.stream().allMatch( mt2->Functions.isSubtype( mt1.getReturnType().getNT().getMdf(),mt2.getReturnType().getNT().getMdf() ))).findAny(); if(res1.isPresent()){return res1.get();} assert false: ""; return res.get(0); } }