package coreVisitors; 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 java.util.function.Function; import sugarVisitors.ToFormattedText; import tools.Assertions; import ast.Ast.*; import ast.ErrorMessage.*; import ast.ExpCore; import ast.ExpCore.*; import ast.ExpCore.Block.Dec; import ast.ExpCore.Loop; import ast.Redex; import ast.Redex.FUpdateExtended; import auxiliaryGrammar.Ctx; public class Move implements Visitor<Ctx<List<Block.Dec>>>{ final String x; private Move(String x){this.x=x;} public Ctx<List<Block.Dec>> visit(ExpCore.EPath s) {throw Assertions.codeNotReachable();} public Ctx<List<Block.Dec>> visit(X s) {throw Assertions.codeNotReachable();} public Ctx<List<Block.Dec>> visit(_void s) {throw Assertions.codeNotReachable();} public Ctx<List<Block.Dec>> visit(WalkBy s) { return new Ctx<List<Block.Dec>>(s, Collections.emptyList()); } public Ctx<List<Block.Dec>> visit(ClassB s) {throw Assertions.codeNotReachable();} public Ctx<List<Block.Dec>> visit(Signal s) { return lift(s.getInner().accept(this), ctx->s.withInner(ctx)); } public Ctx<List<Block.Dec>> visit(Using s) { for(ExpCore ei:s.getEs()){ if(!IsCtx.of(ei)){continue;} return lift(ei.accept(this),ctx->{ List<ExpCore> es=new ArrayList<ExpCore>(s.getEs()); es.set(es.indexOf(ei), ctx); return s.withEs(es); }); } return null; } public Ctx<List<Block.Dec>> visit(MCall s) { if(IsCtx.of(s.getInner())){ return lift(s.getInner().accept(this), ctx->s.withInner(ctx));} for(ExpCore ei:s.getEs()){ if(!IsCtx.of(ei)){continue;} return lift(ei.accept(this),ctx->{ List<ExpCore> es=new ArrayList<>(s.getEs()); es.set(es.indexOf(ei), ctx); return s.withEs(es); }); } return null; } private void split( List<Block.Dec> dvs,List<Block.Dec> dvs1,List<Block.Dec> dvs2,HashSet<String> xs){ for(Block.Dec dec:dvs){ if(xs.contains(dec.getX())){dvs1.add(dec);} else{dvs2.add(dec);} } iterate:while(true){ for(Block.Dec decX:dvs2){ for(Block.Dec decE:dvs1){ Set<String> fv = FreeVariables.of(decE.getInner()); if(!fv.contains(decX.getX())){continue;} dvs1.add(decX); dvs2.remove(decX); continue iterate; }}break;}; } public Ctx<List<Block.Dec>> visit(Block s) { List<Block.Dec> dvs=new ArrayList<Block.Dec>(); List<Block.Dec> ds=new ArrayList<Block.Dec>(); List<Block.Dec> dvs1=new ArrayList<Block.Dec>(); List<Block.Dec> dvs2=new ArrayList<Block.Dec>(); for(Block.Dec d:s.getDecs()){ if(ds.isEmpty() && !IsCtx.of(d.getInner())){ dvs.add(d); } else{ assert ds.isEmpty() || !IsCtx.of(d.getInner()); ds.add(d); } } Ctx<List<Block.Dec>> nestedCtx=null; if(ds.isEmpty()){ nestedCtx= s.getInner().accept(this); }else{ nestedCtx=ds.get(0).getInner().accept(this); } HashSet<String> richXs=new HashSet<String>(); richXs.add(x); for(Block.Dec dv:nestedCtx.hole){ richXs.addAll(FreeVariables.of(dv.getInner())); } split(dvs,dvs1,dvs2,richXs); Block s2=null; if(ds.isEmpty()){ s2=s.withInner(nestedCtx.ctx); }else{ ds.set(0,ds.get(0).withInner(nestedCtx.ctx)); dvs2.addAll(ds); s2=s; } s2=s2.withDecs(dvs2); dvs1.addAll(nestedCtx.hole); return new Ctx<List<Block.Dec>>(s2,dvs1); } private Ctx<List<Block.Dec>> lift(Ctx<List<Block.Dec>> res,Function<ExpCore,ExpCore> f){ res.ctx=f.apply(res.ctx); return res; } //solved on call side if atom!=x public static Block of(Block ctx,String a){ int ctxPosition=-1; //ExpCore ex=ctx.getDecs().get(ctx.domDecs().indexOf(x)).getE(); List<Block.Dec> newDecs=new ArrayList<>(); Ctx<List<Block.Dec>> res=null; int i=-1; for(Block.Dec dec:ctx.getDecs()){ i+=1; if(!IsCtx.of(dec.getInner())){ newDecs.add(dec); continue;} ctxPosition=i; res=dec.getInner().accept(new Move(a)); newDecs.add(dec.withInner(res.ctx)); } if(res!=null){ //ex fieldU1, newDecs.addAll(ctxPosition-1,res.hole); return ctx.withDecs(newDecs); } assert IsCtx.of(ctx.getInner()); assert ctx.getOns().isEmpty(); res=ctx.getInner().accept(new Move(a)); newDecs.addAll(res.hole); return ctx.withDecs(newDecs).withInner(res.ctx); } public Ctx<List<Dec>> visit(Loop s) {throw Assertions.codeNotReachable();} }