package sugarVisitors; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import tools.Assertions; import ast.Ast.Doc; import ast.Ast.Mdf; import ast.Ast.MethodSelector; import ast.Ast.Op; import ast.Ast.Path; import ast.Ast.Type; import ast.Ast.NormType; import ast.Ast.HistoricType; import ast.Ast; import ast.Ast.VarDec; import ast.Expression; import ast.Expression.*; public class GuessType implements Visitor<Type> { HashMap<String,Type> varEnv; public GuessType(HashMap<String, Type> varEnv) { this.varEnv=varEnv; } public static Type of(Expression e,HashMap<String,Type> varEnv){ Type t=e.accept(new GuessType(varEnv)); return t; } public Type visit(Signal s) {return NormType.immVoid;} public Type visit(If s) {return NormType.immVoid;} public Type visit(While s) {return NormType.immVoid;} public Type visit(With s) {return NormType.immVoid;} public Type visit(UseSquare s) {return NormType.immVoid;} public Type visit(_void s) {return NormType.immVoid;} public Type visit(Loop s) {return NormType.immVoid;} public Type visit(DocE s) {return s.getInner().accept(this);} public Type visit(Using s) { //WE CAN NOT DO SOMETHING LIKE THAT, //SINCE PROGRAM NOT AVAILABLE DURING DESUGARING //List<NormType> ts = OnLineCode.pluginType(p, s); return s.getInner().accept(this); } public Type visit(X s) { assert (this.varEnv.containsKey(s.getInner())): s; assert this.varEnv.get(s.getInner())!=null; return this.varEnv.get(s.getInner()); } public Type visit(Expression.EPath s) { return new NormType(Mdf.Class,s.getInner(),Doc.empty()); } public Type visit(RoundBlock s) { HashMap<String, Type> tmpVarEnv = this.varEnv; this.varEnv=new HashMap<String, Type>(this.varEnv); for(BlockContent cnt:s.getContents()){ for(VarDec vd:cnt.getDecs()){ if(vd instanceof Ast.VarDecXE){ Ast.VarDecXE vdx=(Ast.VarDecXE) vd; if(vdx.getT().isPresent()){ varEnv.put(vdx.getX(),vdx.getT().get()); } else{ varEnv.put(vdx.getX(),vdx.getInner().accept(this)); } } } } Type result=s.getInner().accept(this); this.varEnv=tmpVarEnv; return result; } public static HistoricType concatHistoricType(Type t,MethodSelector ms ){ if(t instanceof NormType){ NormType nt = (NormType)t; List<Ast.MethodSelectorX> selectors=Collections.singletonList(new Ast.MethodSelectorX(ms,"")); return new HistoricType(nt.getPath(), selectors,Doc.empty()); } HistoricType ht=(HistoricType)t; List<Ast.MethodSelectorX> selectors = new ArrayList<>(ht.getSelectors()); selectors.add(new Ast.MethodSelectorX(ms,"")); return ht.withSelectors(selectors); } public Type visit(MCall s) { Type t=s.getReceiver().accept(this); assert t!=null:s; return concatHistoricType(t,getMS(s)); } MethodSelector getMS(MCall mc){ List<String> xs=new ArrayList<String>(); if(mc.getPs().getE().isPresent()){xs.add("that");} xs.addAll(mc.getPs().getXs()); return MethodSelector.of(mc.getName(),xs); } public Type visit(UnOp s) { return visit(Desugar.visit1Step(s));} public Type visit(FCall s) { return visit(Desugar.visit1Step(s));} public Type visit(SquareCall s) { return GuessType.concatHistoricType(s.getReceiver().accept(this),Desugar.squareGuessedSelector());} public Type visit(Literal s) { return GuessType.concatHistoricType(s.getReceiver().accept(this),Desugar.literalGuessedSelector());} public Type visit(BinOp s) { Op op=s.getOp(); if(op.kind==Ast.OpKind.EqOp){return NormType.immVoid;} if(op.negated){ BinOp s2=s.withOp(op.nonNegatedVersion()); return visit(new UnOp(s.getP(),Op.Bang,s2)); } if(!op.normalized){ BinOp op2=new BinOp(s.getP(),s.getRight(),op.normalizedVersion(),s.getLeft()); return visit(op2); } assert !op.negated && op.normalized :op; MCall mc=Desugar.getMCall(s.getP(),s.getLeft(),Desugar.desugarName(op.inner),Desugar.getPs(s.getRight())); return visit(mc); } public Type visit(SquareWithCall s) { { return GuessType.concatHistoricType(s.getReceiver().accept(this),Desugar.squareGuessedSelector());} } public Type visit(DotDotDot s) {throw Assertions.codeNotReachable();} public Type visit(WalkBy s) {throw Assertions.codeNotReachable();} public Type visit(CurlyBlock s) { throw new ast.ErrorMessage.NotWellFormedMsk(s,s,"Can not infer the type of a { ... return ... } block."); } public Type visit(ClassReuse s){return NormType.immLibrary;} public Type visit(ClassB s) {return NormType.immLibrary;} @Override public Type visit(ContextId s) { throw new ast.ErrorMessage.NotWellFormedMsk(s,s,"Can not infer the type of a hashId (can this error happens?)"); } }