package coreVisitors;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import tools.Assertions;
import ast.Ast.Path;
import ast.ErrorMessage;
import ast.ExpCore;
import ast.ExpCore.Block;
import ast.ExpCore.ClassB;
import ast.ExpCore.Loop;
import ast.ExpCore.MCall;
import ast.ExpCore.Signal;
import ast.ExpCore.Using;
import ast.ExpCore.WalkBy;
import ast.ExpCore.X;
import ast.ExpCore._void;
import ast.Redex;
import auxiliaryGrammar.Ctx;
public class ExtractCtxCompiled implements Visitor<Ctx<ClassB>>{
//private ExtractCtxCompiled(Program p){this.p=p;}
public Ctx<ClassB> visit(ExpCore.EPath s) {throw Assertions.codeNotReachable();}
public Ctx<ClassB> visit(X s) {throw Assertions.codeNotReachable();}
public Ctx<ClassB> visit(_void s) {throw Assertions.codeNotReachable();}
public Ctx<ClassB> visit(WalkBy s) {throw Assertions.codeNotReachable();}
public Ctx<ClassB> visit(ClassB s) {
assert !IsCompiled.of(s);
return new Ctx<ClassB>(new WalkBy(),s);
}
public Ctx<ClassB> visit(Signal s) {
return lift(s.getInner().accept(this),s::withInner);
}
public Ctx<ClassB> visit(Loop s) {
return lift(s.getInner().accept(this),s::withInner);
}
public Ctx<ClassB> visit(Using s) {
for(ExpCore ei:s.getEs()){
if(IsCompiled.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);
});
}
assert !IsCompiled.of(s.getInner());
return lift(s.getInner().accept(this),s::withInner);
}
public Ctx<ClassB> visit(MCall s) {
if(!IsCompiled.of(s.getInner())){
return lift(s.getInner().accept(this),s::withInner);}
for(ExpCore ei:s.getEs()){
if(IsCompiled.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);
});
}
throw Assertions.codeNotReachable();
}
public Ctx<ClassB> visit(Block s) {
for(Block.Dec dec:s.getDecs()){
if(IsCompiled.of(dec.getInner())){continue;}
//otherwise, i is the first non dv
return lift(dec.getInner().accept(this),ctx->{
List<Block.Dec> es=new ArrayList<Block.Dec>(s.getDecs());
int ii=es.indexOf(dec);
es.set(ii,es.get(ii).withInner(ctx));
return s.withDecs(es);
});
}
return lift(s.getInner().accept(this),s::withInner); }
private Ctx<ClassB> lift(Ctx<ClassB> res,Function<ExpCore,ExpCore> f){
if(res!=null){res.ctx=f.apply(res.ctx);}
return res;
}
public static Ctx<ClassB> of(ExpCore e){
Ctx<ClassB> result=e.accept(new ExtractCtxCompiled());
assert result!=null;
return result;
}
}