package coreVisitors;
import ast.Ast.Mdf;
import ast.Ast.Path;
import ast.ErrorMessage;
import ast.ExpCore;
import ast.ExpCore.Loop;
import ast.ExpCore.Block;
import ast.ExpCore.ClassB;
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 Dec implements Visitor<ExpCore> {
String x;
boolean ensureImmutable;
private Dec(String x,boolean ensureImmutable){
this.x=x;this.ensureImmutable=ensureImmutable;
}
public static ExpCore of(ExpCore ctxVal,String x,boolean ensureImmutable){
Dec dec=new Dec(x,ensureImmutable);
return ctxVal.accept(dec);
}
//return null if not walkBy,
//return walkby on walkby but not dec for x,
//return dec for x otherwise
public ExpCore visit(Signal s) {
return s.getInner().accept(this);
}
public ExpCore visit(Loop s) {
return s.getInner().accept(this);
}
@Override
public ExpCore visit(Using s) {
ExpCore result=null;
for(ExpCore ei:s.getEs()){
result=acc(result,ei.accept(this));
}
return acc(result,s.getInner().accept(this));
}
@Override
public ExpCore visit(MCall s) {
ExpCore result=s.getInner().accept(this);
for(ExpCore ei:s.getEs()){
result=acc(result,ei.accept(this));
}
return result;
}
@Override
public ExpCore visit(Block s) {
ExpCore result=null;
for(Block.Dec ei:s.getDecs()){
result=acc(result,ei.getInner().accept(this));
}
result=acc(result,s.getInner().accept(this));
if(result==null){return null;}
if(!(result instanceof WalkBy)){return result;}
int pos=-1;
for(int i=0;i<s.getDecs().size();i++){
if(!s.getDecs().get(i).getX().equals(this.x)){continue;}
pos=i;break;
}
if(pos==-1){return result;}
if(ensureImmutable){
ast.Ast.NormType ti=s.getDecs().get(pos).getT().getNT();
if(ti.getMdf()!=Mdf.Immutable){throw new ErrorMessage.ExpectedImmutableVar(s,x);}
}
return s.getDecs().get(pos).getInner();
}
@Override public ExpCore visit(ExpCore.EPath s) {return null;}
public ExpCore visit(X s) {return null;}
public ExpCore visit(_void s) {return null;}
public ExpCore visit(WalkBy s) {return s;}
public ExpCore visit(ClassB s) {return null;}
private ExpCore acc(ExpCore c1,ExpCore c2){
if(c2==null){return c1;}
return c2;
}
}