package auxiliaryGrammar; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import ast.ExpCore; import ast.Ast.Mdf; import ast.Ast.Path; import ast.Ast.Type; import ast.ErrorMessage; import ast.ExpCore.Block; import ast.ExpCore.X; import ast.ExpCore.Block.Dec; import ast.ExpCore.Block.On; import coreVisitors.CollectPaths0; import newTypeSystem.TypeManipulation; import tools.Assertions; import ast.Ast.MethodType; import ast.Ast.Type; public class WellFormednessCore { public static boolean methodTypeWellFormed(MethodType mt){ boolean r1=false; boolean r2=false; //if exists fwdImm _ in Ts then (return type).mdf in {mut, fwdMut, imm, fwdImm} //if exists fwdMut _ in Ts then (return type).mdf in {mut, fwdMut} for(Type t:mt.getTs()){ Mdf m=t.getNT().getMdf(); if(m==Mdf.ImmutableFwd){r1=true;} if(m==Mdf.MutableFwd){r2=true;} } Mdf m=mt.getReturnType().getNT().getMdf(); if(r2){ if(m!=Mdf.Mutable && m!=Mdf.MutableFwd && m!=Mdf.MutablePFwd){return false;} } else if(r1){ if(m!=Mdf.Mutable && m!=Mdf.Immutable && !TypeManipulation.fwd_or_fwdP_in(m)){return false;} } //TODO: do we want this extra restriction? if(!r1&&!r2){//no fwd at all if(TypeManipulation.fwd_or_fwdP_in(m)){return false;} } return true; } //should replicate some of the other well formedness for sugared? even if already checked?? public static void capsuleOnlyOnce(ExpCore.ClassB.NestedClass nc){ countX(nc.getInner()); } public static void capsuleOnlyOnce(ExpCore.ClassB.MethodWithType mwt){ List<String> res = countX(mwt.getInner()); {int i=-1;for(Type ti:mwt.getMt().getTs()){i++; if(ti.getNT().getMdf()!=Mdf.Capsule){continue;} String capsX=mwt.getMs().getNames().get(i); if(Collections.frequency(res,capsX)<=1){continue;} throw new ErrorMessage.CapsuleUsedMoreThenOne(null,capsX,mwt.getP()); }} if(mwt.getMt().getMdf()==Mdf.Capsule){ if(Collections.frequency(res,"this")>1){ throw new ErrorMessage.CapsuleUsedMoreThenOne(null,"this",mwt.getP()); } } } public static List<String> countX(ExpCore e){ return CX.of(e); } private static class CX extends coreVisitors.PropagatorVisitor{ protected List<String> res=new ArrayList<>(); public static List<String> of(ExpCore e){ CX cp=new CX(); e.accept(cp); return cp.res; } public Void visit(X s) { res.add(s.getInner()); return super.visit(s); } public Void visit(ExpCore.Loop s) { super.visit(s);//do it twice return super.visit(s); } public Void visit(Block s) { List<String> ys=new ArrayList<>(); for(Dec d:s.getDecs()){ys.addAll(CX.of(d.getInner()));} List<List<String>> xsi=new ArrayList<>(); xsi.add(CX.of(s.getInner())); for(On o:s.getOns()){xsi.add(CX.of(o.getInner()));} for(Dec d:s.getDecs()){ if(d.getT().getNT().getMdf()!=Mdf.Capsule){continue;} String xi=d.getX(); //xi at most 1 in ys,xs0 int howMany_xs0=Collections.frequency(xsi.get(0),xi); int howMany_ys=Collections.frequency(ys,xi); if(howMany_xs0+howMany_ys<=1){continue;} throw new ErrorMessage.CapsuleUsedMoreThenOne(null,xi,s.getP()); } for(Dec d:s.getDecs()){ ys.removeIf(d.getX()::equals); xsi.get(0).removeIf(d.getX()::equals); } ys.addAll(xsi.stream().reduce((xs1,xs2)->max(xs1,xs2)).get()); this.res.addAll(ys); return null; } } public static List<String> max(List<String> l1,List<String>l2){ if(l1.isEmpty()){return l2;} if(l2.isEmpty()){return l1;} List<String>res=new ArrayList<>(l2); for(String s:l1){ res.remove(s);//removes the leftmost if any } res.addAll(l1); return res; } }