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 tools.Assertions; import tools.Map; import coreVisitors.CloneVisitor; import coreVisitors.CloneVisitorWithProgram; import coreVisitors.FromInClass; import facade.Configuration; import facade.L42; import ast.Ast; import ast.ExpCore; import ast.Ast.C; import ast.Ast.Doc; import ast.Ast.Path; import ast.Ast.Position; import ast.Ast.MethodSelector; import ast.Ast.Stage; import ast.Util.PathMx; import ast.Util.PathMxMx; import ast.ExpCore.*; 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.PathPath; import auxiliaryGrammar.Functions; import programReduction.Program; public class Rename { public static ClassB renameClass(Program p,ClassB cb,List<Ast.C> src,List<Ast.C> dest){ Errors42.checkExistsPathMethod(cb, src, Optional.empty()); if(src.equals(dest)){return cb;} if(src.isEmpty()){//push is asked return Push.pushMany(cb, dest); } if(dest.isEmpty() && src.size()==1){//pop is asked boolean rightSize=cb.getMs().size()==1; if(rightSize && ExtractInfo.isBox(cb,cb,Collections.emptyList())){ return Pop.pop(cb); }//otherwise, proceed with encoding } cb=ClassOperations.normalizePaths(cb); if(!ExtractInfo.isPrefix(src, dest)){ return ClassOperations.normalizePaths(directRename(p,cb,src,dest));} src=new ArrayList<>(src); dest=new ArrayList<>(dest); C result=C.of("Result"); src.add(0,result); dest.add(0,result); cb=Push.pushOne(cb,result); List<Ast.C> tmp = Collections.singletonList(C.of("Tmp")); cb=directRename(p,cb,src,tmp); if(!L42.trustPluginsAndFinalProgram) { newTypeSystem.TypeSystem.instance().topTypeLib(Phase.Typed, p.evilPush(cb)); } cb=directRename(p,cb,tmp,dest); cb=Pop.directPop(cb); return cb; } public static ClassB renameClassStrict(Program p,ClassB cb,List<Ast.C> src,List<Ast.C> dest){ /* errors: src is prefix of dest dest is prefix of src src does not exists dest+src is wrong */ Errors42.checkExistsPathMethod(cb, src, Optional.empty()); if(ExtractInfo.isPrefix(src,dest)){throw Errors42.errorPrefix(src,dest);} return ClassOperations.normalizePaths(directRename(p, cb, src, dest)); } private static ClassB directRename(Program p, ClassB cb, List<Ast.C> src, List<Ast.C> dest) { CollectedLocatorsMap clm=CollectedLocatorsMap.from(Path.outer(0,src), Path.outer(0,dest)); ClassB renamedCb=(ClassB)new RenameAlsoDefinition(cb,clm,p).visit(cb); ClassB clearCb=renamedCb.onNestedNavigateToPathAndDo(src,nc->Optional.empty()); ClassB newCb=redirectDefinition(src,dest,renamedCb); newCb=ClassOperations.normalizePaths(newCb); return _Sum.normalizedTopSum(p, clearCb, newCb); } public static ClassB renameMethod(Program p,ClassB cb,List<Ast.C> path,MethodSelector src,MethodSelector dest){ Member mem=Errors42.checkExistsPathMethod(cb, path, Optional.of(src)); assert mem instanceof MethodWithType; Errors42.checkCompatibleMs(path,(MethodWithType)mem,dest); CollectedLocatorsMap maps=CollectedLocatorsMap.from(Path.outer(0,path),(MethodWithType) mem,dest); RenameAlsoDefinition ren=new RenameAlsoDefinition(cb, maps,p); return (ClassB) ren.visit(cb); } static class UserForMethodResult{List<PathMx> asClient;List<MethodSelector>asThis;} public static UserForMethodResult userForMethod(Program p,ClassB cb,List<Ast.C> path,MethodSelector src,boolean checkMethExists ){ if(checkMethExists){ Member mem=Errors42.checkExistsPathMethod(cb, path, Optional.of(src)); assert mem instanceof MethodWithType; } Member mem=new ExpCore.ClassB.MethodImplemented(Doc.empty(),src,new ExpCore._void(),Position.noInfo); CollectedLocatorsMap maps=CollectedLocatorsMap.from(Path.outer(0,path), mem,src); HashSet<PathMx> result1=new HashSet<>(); HashSet<MethodSelector> result2=new HashSet<>(); MethodPathCloneVisitor ren=new RenameUsage(cb, maps,p){ public Ast.Type liftT(Ast.Type t){return t;} @Override protected MethodSelector liftMs(MethodSelector ms){return ms;} @Override protected MethodSelector liftMsInMetDec(MethodSelector ms){return ms;} public ExpCore visit(MCall s) { List<Ast.C> localPath = this.getLocator().getClassNamesPath(); if(!localPath.equals(path)){return super.visit(s);} if(s.getInner().equals(Path.outer(0)) || s.getInner().equals(new ExpCore.X(Position.noInfo,"this"))){ result2.add(s.getS()); return s.withInner(s.getInner().accept(this)).withEs(Map.of(e->e.accept(this), s.getEs())); } return super.visit(s); } @Override public MethodSelector visitMS(MethodSelector original, Path src) { MethodSelector toCollect=this.mSToReplaceOrNull(original, src); if(toCollect==null){return original;} Member m=this.getLocator().getLastMember(); assert !(m instanceof NestedClass): ""; MethodSelector msUser=m.match(nc->{throw Assertions.codeNotReachable();}, mi->mi.getS(), mt->mt.getMs()); Path pathUser=Path.outer(0,this.getLocator().getClassNamesPath()); result1.add(new PathMx(pathUser,msUser)); return original; } }; ren.visit(cb); return new UserForMethodResult(){{asClient=new ArrayList<>(result1);asThis=new ArrayList<>(result2);}}; } private static ClassB redirectDefinition(List<Ast.C>src,List<Ast.C>dest, ClassB lprime) { assert !src.isEmpty(); assert !dest.isEmpty(); NestedClass nsCb=lprime.getNested(src); Path toFrom=Path.outer(dest.size()-1,src.subList(0,src.size()-1)); ClassB cb=(ClassB) FromInClass.of((ClassB) nsCb.getInner(), toFrom); List<Member>ms=new ArrayList<>(); ms.add(Functions.encapsulateIn(dest, cb,nsCb.getDoc())); return ClassB.membersClass(ms,Position.noInfo,lprime.getPhase()); } //TODO: replace with same mechanism of private normalization when is completed static ClassB renameUsage(List<PathPath> mapPath, ClassB cb) { return (ClassB)cb.accept(new coreVisitors.CloneWithPath(){ @Override protected Path liftP(Path s) { if(s.isPrimitive()){return s;} assert s.isCore(); List<Ast.C> path = this.getLocator().getClassNamesPath(); if(s.outerNumber()>path.size()){return s;} List<Ast.C> unexploredPath=path.subList(0,path.size()-s.outerNumber());//in usedPath similar thing. if(unexploredPath.contains(null)){return s;}//we are in a class literal in a method and we look inside if(s.outerNumber()>path.size()){return s;} List<Ast.C>topView=ClassOperations.toTop(path,s); for(PathPath pp:mapPath){ List<Ast.C>src=pp.getPath1().getCBar(); if(topView.size()<src.size()){continue;} if(topView.equals(src)){ if(pp.getPath2().isPrimitive()){ return pp.getPath2(); } if(pp.getPath2().outerNumber()==0){ return ClassOperations.normalizePath(path,path.size(),pp.getPath2().getCBar()); } return pp.getPath2().setNewOuter(pp.getPath2().outerNumber()+path.size()); } List<Ast.C>trimmedTop=topView.subList(0, src.size()); if(trimmedTop.equals(src)){ List<Ast.C>elongatedDest=new ArrayList<>(pp.getPath2().getCBar()); elongatedDest.addAll(topView.subList(src.size(),topView.size())); if(pp.getPath2().outerNumber()==0){ return ClassOperations.normalizePath(path,path.size(),elongatedDest); } else{ return Path.outer(pp.getPath2().outerNumber()+path.size(),elongatedDest); }}} return s; } }); } }