package sugarVisitors; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import tools.Assertions; import tools.Map; import ast.Ast; import ast.ErrorMessage; import ast.Expression; import ast.Ast.C; import ast.Ast.Doc; import ast.Ast.FieldDec; import ast.Ast.Mdf; import ast.Ast.NormType; import ast.Ast.Op; import ast.Ast.Parameters; import ast.Ast.Path; import ast.Ast.Position; import ast.Ast.SignalKind; import ast.Ast.Stage; import ast.Ast.Type; import ast.Expression.Catch; import ast.Expression.Catch1; import ast.Expression.With.On; import ast.Expression.BlockContent; import ast.Ast.VarDec; import ast.Ast.VarDecCE; import ast.Ast.VarDecE; import ast.Ast.VarDecXE; import ast.ErrorMessage.NotWellFormedMsk; import ast.Expression.BinOp; import ast.Expression.ClassB; import ast.Expression.ClassReuse; import ast.Expression.ContextId; import ast.Expression.CurlyBlock; import ast.Expression.DocE; import ast.Expression.DotDotDot; import ast.Expression.FCall; import ast.Expression.If; import ast.Expression.Literal; import ast.Expression.Loop; import ast.Expression.MCall; import ast.Expression.RoundBlock; import ast.Expression.Signal; import ast.Expression.SquareCall; import ast.Expression.SquareWithCall; import ast.Expression.UnOp; import ast.Expression.UseSquare; import ast.Expression.Using; import ast.Expression.WalkBy; import ast.Expression.While; import ast.Expression.With; import ast.Expression.X; import ast.Expression._void; import ast.Expression.ClassB.MethodImplemented; import ast.Expression.ClassB.MethodWithType; import ast.Expression.ClassB.NestedClass; import auxiliaryGrammar.Functions; import facade.L42; public class DesugarVars extends CloneVisitor{ Set<String> usedVars=new HashSet<String>(); public static boolean assertVarsRemoved(Expression _e){ _e.accept(new CloneVisitor(){ //Ok liftVarDec since With uses liftVarDecXE @Override protected ast.Ast.VarDec liftVarDec(ast.Ast.VarDec d) { return d.match( vdxe->{ if(vdxe.isVar()){ throw new AssertionError("Variable local binding found:"+vdxe.toString()); } return this.liftVarDecXE(vdxe); }, this::liftVarDecE, this::liftVarDecCE); } }); return true; } public static Expression of(Set<String> usedVars,Expression e){ DesugarVars d=new DesugarVars(); d.usedVars=usedVars; Expression result= e.accept(d); return result; } private RoundBlock blockContentSepare(RoundBlock s) { if(s.getContents().size()<=1){return s;} List<Expression.BlockContent> ctxTop = new ArrayList<>(s.getContents().subList(0,1)); List<Expression.BlockContent> ctxPop = new ArrayList<>(s.getContents().subList(1, s.getContents().size())); RoundBlock next=blockContentSepare(s.withContents(ctxPop)); return s.withContents(ctxTop).withInner(next); } public Expression visit(CurlyBlock s) { Expression inner; if(s.getContents().size()==1 && s.getContents().get(0).get_catch().isEmpty() && s.getContents().get(0).getDecs().size()==1&& s.getContents().get(0).getDecs().get(0) instanceof VarDecE ){ inner=((VarDecE)s.getContents().get(0).getDecs().get(0)).getInner(); } else{ inner=new RoundBlock(s.getP(),s.getDoc(),Expression._void.instance,s.getContents());} inner=inner.accept(this); List<VarDec> vd = Collections.singletonList((VarDec)new VarDecE(inner)); BlockContent o=new BlockContent(vd,Collections.emptyList()); return new CurlyBlock(s.getP(),Doc.empty(),Collections.singletonList(o)); } public Expression visit(RoundBlock s) { s=blockContentSepare(s); s=blockVarClass(s); Expression result= super.visit(s); return result; } public RoundBlock blockVarClass(RoundBlock s) { RoundBlock res=_blockVarClass(s); if(res.equals(s)){return res;} return blockVarClass(res); } private int firstVar(List<VarDec> varDecs){ {int i=-1; for(VarDec _dec:varDecs){i+=1; if(!(_dec instanceof VarDecXE)){continue;} VarDecXE dec=(VarDecXE)_dec; //assert dec.getT().isPresent(); if(!dec.isVar()){continue;} return i; }} return -1; } private VarDecXE getDecForVar(Ast.C cName,VarDecXE varDec) { NormType nt=new NormType(Mdf.Mutable,Path.outer(0).pushC(cName),Doc.empty()); Position pos = Desugar.getPosition(varDec.getInner()); MCall right=new MCall(new Expression.EPath(pos,nt.getPath()),"#apply",Doc.empty(), Desugar.getPs("inner",new X(pos,varDec.getX())),pos); String nameZ=Functions.freshName(nt.getPath(), usedVars); //usedVars.add(nameZ); return new VarDecXE(false,Optional.of(nt),nameZ,right); } private RoundBlock _blockVarClass(RoundBlock s) { if(s.getContents().isEmpty()){return s;} List<VarDec> varDecs = new ArrayList<VarDec>(s.getContents().get(0).getDecs()); int pos=firstVar(varDecs); if(pos==-1){return s;} VarDecXE varDec=(VarDecXE)varDecs.get(pos); varDecs.set(pos,varDec.withVar(false)); VarDecCE ce=getClassBForVar(varDec); VarDecXE d=getDecForVar(ce.getInner().getName(),varDec); X x=new X(s.getP(),varDec.getX()); X z=new X(s.getP(),d.getX()); int d3First=findD2(x,pos,varDecs); RoundBlock fake = getFakeBlock(x,z,s, varDecs, d3First); List<VarDec> trueDecs=new ArrayList<VarDec>(); trueDecs.add(ce); if(d3First!=-1){trueDecs.addAll(varDecs.subList(0, d3First));} else{trueDecs.addAll(varDecs);} trueDecs.add(d); trueDecs.addAll(fake.getContents().get(0).getDecs()); List<Expression.BlockContent> trueContent=new ArrayList<>(); trueContent.add(new Expression.BlockContent(trueDecs,fake.getContents().get(0).get_catch())); return fake.withContents(trueContent); } private int findD2(X x,int pos, List<VarDec> decs) { for(VarDec _dec:decs.subList(pos+1,decs.size())){ pos+=1; Expression[] inner={null}; _dec.match(xe->inner[0]=xe.getInner(), e->inner[0]=e.getInner(), ce->null); if(inner[0]==null){continue;} boolean isAssigned=Exists.of(inner[0],e->{ if(!(e instanceof BinOp)){return false;} BinOp bo=(BinOp)e; if(bo.getOp().kind!=Ast.OpKind.EqOp){return false;} return bo.getLeft().equals(x); }); if (isAssigned){return pos;} } return -1; } private RoundBlock getFakeBlock(X x, X z,RoundBlock s, List<VarDec> varDecs, int d3First) { Position pos=Desugar.getPosition(s); List<Expression.BlockContent> fakeContent=new ArrayList<>(); List<VarDec> fakeDecs=new ArrayList<VarDec>(); if(d3First!=-1){//d3 not empty fakeDecs.addAll(varDecs.subList(d3First, varDecs.size())); } fakeContent.add(new Expression.BlockContent(fakeDecs,s.getContents().get(0).get_catch())); RoundBlock fake=s.withContents(fakeContent); fake=(RoundBlock) XEqOpInZEqOp.of(x, z, fake); fake=(RoundBlock) XInE.of(x,Desugar.getMCall(pos, z,"#inner", Desugar.getPs()),fake); return fake; } private VarDecCE getClassBForVar(VarDecXE varDec) { List<FieldDec> fs=new ArrayList<FieldDec>(); fs.add(new FieldDec(true,_computeTypeForClassBForVar(varDec),"inner",Doc.empty())); ClassB cb=new ClassB(Doc.empty(),new Ast.ConcreteHeader(Mdf.Mutable, "",fs,Position.noInfo),Collections.emptyList(),Collections.emptyList(),Collections.emptyList(),Position.noInfo); String nameC=Functions.freshName("Var"+varDec.getX(), L42.usedNames); //usedCnames.add(nameC); return new VarDecCE(new NestedClass(Doc.empty(),C.of(nameC).withUniqueNum(L42.freshPrivate()),cb,null)); } public Type _computeTypeForClassBForVar(VarDecXE varDec) { assert varDec.getT().isPresent(): " it is now required by the stricted syntax"; Type t=varDec.getT().get(); t=t.match( nt->nt.withPath(computeTypeForClassBForVar(nt.getPath())), h -> h.withPath(computeTypeForClassBForVar(h.getPath())) ); return t; } private Path computeTypeForClassBForVar(Path path) { if (path.isPrimitive()){return path;} if (!path.isCore()){return path;} return path.setNewOuter(path.outerNumber()+1); } }