package is.L42.connected.withSafeOperators; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import platformSpecific.javaTranslation.Resources; import privateMangling.RefreshUniqueNames; import sugarVisitors.CloneVisitor; import sugarVisitors.CollapsePositions; import tools.Map; import facade.Configuration; import is.L42.connected.withSafeOperators.ExtractInfo.ClassKind; import ast.Ast; import ast.Ast.Doc; import ast.Ast.MethodType; import ast.Ast.Path; import ast.Ast.Stage; import ast.ErrorMessage; import ast.ExpCore; import ast.ExpCore.ClassB; import ast.ExpCore.ClassB.Member; import ast.ExpCore.ClassB.MethodImplemented; import ast.ExpCore.ClassB.MethodWithType; import ast.ExpCore.ClassB.NestedClass; import ast.ExpCore.ClassB.Phase; import ast.Util.PathMwt; import auxiliaryGrammar.Functions; import ast.ExpCore.*; import programReduction.Program; import coreVisitors.From; public class _Sum { static ClassB sum(Program p, ClassB a, ClassB b) { //System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); //System.out.println("___________________________________________________"); //System.out.println(a); //System.out.println(b); //System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); a=ClassOperations.normalizePaths(a); b=ClassOperations.normalizePaths(b); b =(ClassB) RefreshUniqueNames.refresh(b); return normalizedTopSum(p, a, b); } public static ClassB normalizedTopSum(Program p, ClassB topA, ClassB topB) { ClassB result=normalizedSum(p,topA, topB,topA, topB, Collections.emptyList()); //Sum.interfaceClash(p,result); return result; } /* private static void interfaceClash(Program p, ClassB candidate) { try{ Configuration.typeSystem.computeStage(p,candidate); }catch(ErrorMessage.IncoherentMwts i){ List<Path>ps=new ArrayList<>(); List<Member>mems=new ArrayList<>(); Path ph=Path.outer(0,i.getExploredPath()); for(PathMwt e:i.getIncoherent()){ ps.add(From.fromP(e.getOriginal(),ph)); } assert !ps.isEmpty(); Member notInterf=null; Program p1=p.addAtTop(candidate); for(Path pi:ps){ ClassB cb=p1.extractCb(pi); System.out.println(pi); System.out.println(i); System.out.println(cb.getStage()); System.out.println(candidate.getStage()); Optional<Member> currentOpt=Program.getIfInDom(cb.getMs(),i.getGuilty()); Member current=currentOpt.get(); if(cb.isInterface()){ mems.add(current); } else notInterf=current; } if(notInterf==null){ throw Errors42.errorClassClash(i.getExploredPath(), ps); } Member mb=mems.get(0); throw Errors42.errorMethodClash(i.getExploredPath(), notInterf,mb, true,Collections.emptyList(),true,true,true); } } */ static ClassB normalizedSum(Program p, ClassB topA, ClassB topB,ClassB a, ClassB b, List<Ast.C> current) { List<Member> ms = doubleSimetricalMatch(p,topA,topB,a, b, current); List<ast.Ast.Type> superT = new ArrayList<>(a.getSupertypes()); superT.addAll(b.getSupertypes()); superT=Collections.unmodifiableList(superT); Doc doc1 = a.getDoc1().sum(b.getDoc1()); //Sum.checkClassClash(p, current, topA, topB, a, b); boolean isInterface =a.isInterface() || b.isInterface(); Phase accPhase = a.getPhase().acc(b.getPhase()); ExpCore.ClassB res= new ClassB(doc1, isInterface, superT, ms,CollapsePositions.accumulatePos(a.getP(), b.getP()), accPhase,accPhase==Phase.None?0:1); res=(ClassB) res.accept(new coreVisitors.CloneVisitor(){ public ExpCore visit(ClassB s){ if (s.getPhase()==Phase.None){return super.visit(s);} return super.visit(s.withPhase(accPhase)); } });//TODO: remove after new reduction introduced return res; } /* private static void checkMethodClashInterfaceAbstract(List<String> pathForError,List<PathMwt> aInh, List<PathMwt> bInh, List<Member> ms) { for(Member m:ms){ if (!(m instanceof MethodWithType)){continue;} MethodWithType mwt=(MethodWithType)m; for(PathMwt a: bInh){ if(a.getMwt().getMs().equals(mwt.getMs())){ throw Errors42.errorMethodClash(pathForError, mwt,a.getMwt(), false, Collections.emptyList(), false,false,true); } } for(PathMwt b: bInh){ if(b.getMwt().getMs().equals(mwt.getMs())){} } } } */ private static List<Member> doubleSimetricalMatch(Program p, ClassB topA, ClassB topB,ClassB a, ClassB b, List<Ast.C> current) { List<Member> ms=new ArrayList<>(); for (Member m : a.getMs()) {//add from a+b Optional<Member> oms = Functions.getIfInDom(b.getMs(), m); if (!oms.isPresent()) { ms.add(m); } else { doubleSimmetricalMatch(p, topA, topB, ms, current, m, oms.get()); } } for (Member m : b.getMs()) {//add the rest if (!Functions.getIfInDom(ms, m).isPresent()) { ms.add(m); } } return ms; } public static void doubleSimmetricalMatch(Program p, ClassB topA, ClassB topB, List<Member> ms, List<Ast.C> current, Member m, Member oms) { m.match( nc -> matchNC(p,topA,topB,nc, ms, (NestedClass) oms, current), mi -> matchMi(current, mi, ms, oms), mt -> matchMt(current, mt, ms, oms)); } private static Void matchNC(Program p, ClassB topA, ClassB topB,NestedClass nca, List<Member> ms, NestedClass ncb, List<Ast.C> current) { List<Ast.C> innerCurrent = new ArrayList<>(current); innerCurrent.add(nca.getName()); ClassB newInner = normalizedSum(p,topA,topB,(ClassB) nca.getInner(), (ClassB) ncb.getInner(), innerCurrent); Doc doc = nca.getDoc().sum(ncb.getDoc()); ms.add(nca.withInner(newInner).withDoc(doc)); return null; } private static Void matchMt(List<Ast.C> pathForError, MethodWithType mwta, List<Member> ms, Member mb) { if (mb instanceof MethodImplemented) { throw Errors42.errorMethodClash(pathForError, mwta, mb, false, Collections.emptyList(), false, false,false); } MethodWithType mwtb = (MethodWithType) mb; Errors42.checkMethodClash(pathForError, mwta, mwtb,false); ms.add(_Sum.sumMethod(mwta, mwtb)); return null; } private static Void matchMi(List<Ast.C> pathForError, MethodImplemented mia, List<Member> ms, Member mb) { throw Errors42.errorMethodClash(pathForError, mia, mb, false, Collections.emptyList(), false, false,false); } static MethodWithType sumMethod(MethodWithType ma, MethodWithType mb) { Set<Path> pa = new HashSet<>(Map.of(t->t.getNT().getPath(),ma.getMt().getExceptions())); Set<Path> pb = new HashSet<>(Map.of(t->t.getNT().getPath(),mb.getMt().getExceptions())); Set<Path> pc = new HashSet<>(pa); pc.retainAll(pb); Doc doc = ma.getDoc().sum(mb.getDoc()); MethodType mt = ma.getMt(); List<Ast.Type> opc =pc.stream().map(pi->(Ast.Type)pi.toImmNT()).collect(Collectors.toList()); Collections.sort(opc, (p1, p2) -> p1.toString().compareTo(p2.toString())); mt = mt.withExceptions(opc); MethodWithType mwt = ma.withMt(mt).withDoc(doc); //now mwt has min exceptions and summed docs assert !ma.get_inner().isPresent() || !mb.get_inner().isPresent(); if (mb.get_inner().isPresent()) { mwt = mwt.withInner(mb.getInner()); } return mwt; } public static void checkClassClash( Program p,List<Ast.C>current, ClassB topA,ClassB topB, ClassB currentA,ClassB currentB){ //*sum of two classes with private state //*sum class/interface invalid boolean privateA=ExtractInfo.hasPrivateState(currentA); boolean privateB=ExtractInfo.hasPrivateState(currentB); boolean twoPrivateState=privateA &&privateB; boolean isAllOk= !twoPrivateState && currentA.isInterface()==currentB.isInterface(); if (isAllOk){return;} ExtractInfo.ClassKind kindA=ExtractInfo.classKind(topA,current,currentA,null,privateA,null); ExtractInfo.ClassKind kindB=ExtractInfo.classKind(topB,current,currentB,null,privateB,null); boolean isClassInterfaceSumOk=currentA.isInterface()==currentB.isInterface(); if(!isClassInterfaceSumOk){ isClassInterfaceSumOk=kindA==ExtractInfo.ClassKind.FreeTemplate||kindB==ExtractInfo.ClassKind.FreeTemplate; } isAllOk= !twoPrivateState && isClassInterfaceSumOk; if (isAllOk){return;} throw Errors42.errorClassClash(current, Collections.emptyList()); } /* public static List<Path> conflictingImplementedInterfaces( Program p,List<String>current,ClassB cba,ClassB cbb){ List<Path> cc=new ArrayList<>(); for(PathMwt a: cba.getStage().getInherited()){ for(PathMwt b: cbb.getStage().getInherited()){ if(a.getMwt().getMs().equals(b.getMwt().getMs())){ if(a.getOriginal().equals(b.getOriginal())){continue;} cc.add(a.getOriginal()); cc.add(b.getOriginal()); } } } return cc; }*/ }