package coreVisitors;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import tools.Assertions;
import tools.Map;
import ast.ExpCore;
import ast.Ast.Doc;
import ast.Ast.HistoricType;
import ast.Ast.MethodSelector;
import ast.Ast.MethodSelectorX;
import ast.Ast.MethodType;
import ast.Ast.NormType;
import ast.Ast.Path;
import ast.Ast.Type;
import ast.ExpCore.Block;
import ast.ExpCore.Block.Dec;
import ast.ExpCore.Block.On;
import ast.ExpCore.ClassB.Member;
import ast.ExpCore.ClassB.MethodImplemented;
import ast.ExpCore.ClassB.MethodWithType;
import ast.ExpCore.ClassB.NestedClass;
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;
public class PropagatorVisitor implements Visitor<Void>{
protected void lift(ExpCore e){
e.accept(this);
}
protected void liftP(Path p){}
protected void liftT(Type t){
liftDoc(t.getDoc());
if(t instanceof NormType){liftP(((NormType)t).getPath());}
else {
HistoricType ht=(HistoricType) t;
liftSXs(ht.getSelectors());
liftP(ht.getPath());
}
}
protected void liftSXs(List<MethodSelectorX> selectors) {
for(MethodSelectorX msx: selectors){liftSX(msx);}
}
protected void liftSX(MethodSelectorX selector) {
liftMs(selector.getMs());
}
protected void liftMs(MethodSelector ms){}//Do nothing on purpose, can be overridden
protected void liftO(ExpCore.Block.On on){
liftT(on.getT());
lift(on.getInner());
}
protected void liftDec(Block.Dec f) {
liftT(f.getT());
lift(f.getInner());
}
protected void liftDoc(Doc doc) {
for(Object a:doc.getAnnotations()){
if(a instanceof ExpCore){lift((ExpCore)a);}}
}
protected void liftM(Member m) {
//I can not do the follow for void return type: m.match(this::visit,this::visit, this::visit);
if( m instanceof NestedClass){visit((NestedClass)m);}
else if( m instanceof MethodWithType){visit((MethodWithType)m);}
else visit((MethodImplemented)m);
}
public void visit(ClassB.NestedClass nc){
liftDoc(nc.getDoc());
lift(nc.getInner());
}
public void visit(ClassB.MethodImplemented mi){
liftDoc(mi.getDoc());
liftMsInMetDec(mi.getS());
lift(mi.getInner());
}
public void visit(ClassB.MethodWithType mt){
liftDoc(mt.getDoc());
liftMsInMetDec(mt.getMs());
liftMT(mt.getMt());
if(mt.get_inner().isPresent()){lift(mt.getInner());}
}
protected void liftMT(MethodType mt) {
for(Type t:mt.getTs()){liftT(t);}
liftT(mt.getReturnType());
for(Type p:mt.getExceptions()){liftT(p);}
}
public Void visit(Using s) {
liftP(s.getPath());
liftMs(s.getS());
liftDoc(s.getDoc());
for(ExpCore e:s.getEs()){lift(e);}
lift(s.getInner());
return null;
}
public Void visit(Signal s) {
lift(s.getInner());
return null;
}
public Void visit(MCall s) {
lift(s.getInner());
liftMs(s.getS());
liftDoc(s.getDoc());
for(ExpCore e:s.getEs()){lift(e);}
return null;
}
public Void visit(Block s) {
liftDoc(s.getDoc());
liftDecs(s.getDecs());
lift(s.getInner());
for(On o:s.getOns()){liftO(o);}
return null;
}
protected void liftDecs(List<Dec> s) {
for(Dec e:s){liftDec(e);}
}
public Void visit(ClassB s) {
liftSup(s.getSupertypes());
liftMembers(s.getMs());
liftDoc(s.getDoc1());
return null;
}
public void liftMembers(List<Member> s) {
for(Member m:s){liftM(m);}
}
protected void liftSup(List<Type> s) {
for(Type e:s){liftT(e);}
}
public Void visit(Loop s) {
lift(s.getInner());
return null;
}
protected void liftMsInMetDec(MethodSelector ms) {liftMs(ms);}//delegate on more common lift, to play with overriding better.
public Void visit(WalkBy s) {throw Assertions.codeNotReachable();}
public Void visit(ExpCore.EPath s) {liftP(s.getInner());return null;}
public Void visit(X s) {return null;}//Do nothing on purpose, can be overridden
public Void visit(_void s) {return null;}//Do nothing on purpose, can be overridden
}