package newTypeSystem; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Function; import java.util.stream.Stream; import ast.Ast; import ast.Ast.NormType; import ast.Ast.Path; import ast.Ast.SignalKind; import ast.Ast.Type; import ast.ExpCore; import ast.Ast.C; import ast.Ast.Doc; import ast.Ast.Mdf; import ast.Ast.MethodType; import ast.ExpCore.Block; import ast.ExpCore.Block.On; import ast.ExpCore.ClassB; import ast.ExpCore.ClassB.MethodWithType; import ast.ExpCore.ClassB.Phase; 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 auxiliaryGrammar.Functions; import coreVisitors.PropagatorVisitor; import coreVisitors.Visitor; import programReduction.Program; import tools.Assertions; public interface TypeSystem{ static TypeSystem instance(){return new Impl();} default ExpCore topTypeExpVoid(Program p,ExpCore e){ TIn in=TIn.top(Phase.Norm,p, e); TOut out=type(in.withE(e,Path.Void().toImmNT())); if(out.isOk()){return out.toOk().annotated;} TErr err=out.toError(); throw new FormattedError(err); } default ExpCore topTypeExp(Program p,ExpCore e){ TIn in=TIn.top(Phase.Norm,p, e); TOut out=type(in); if(out.isOk()){return out.toOk().annotated;} TErr err=out.toError(); throw new FormattedError(err); } default ClassB topTypeLib(Phase phase,Program p){ TIn in=TIn.top(phase,p, p.top()); TOut out=typeLib(in);//this already check if the phase is already good enough! if(out.isOk()){return (ClassB) out.toOk().annotated;} TErr err=out.toError(); throw new FormattedError(err); //errors from norm still leak out, are they good looking? } TOut type(TIn in); TOut typeLib(TIn in); public static ErrorKind subtype(Program p,Path pSub,Path pSuper){ if (!p.subtypeEq(pSub, pSuper)){return ErrorKind.NotSubtypeClass;} return null; } public static void checkExists(Program p, Path pi){ if (pi.isCore()){p.extractClassB(pi);} } public static ErrorKind subtype(Program p, NormType tSub, NormType tSuper) { checkExists(p,tSub.getPath()); checkExists(p,tSuper.getPath()); if (!p.subtypeEq(tSub.getPath(),tSuper.getPath())){return ErrorKind.NotSubtypeClass;} if(!Functions.isSubtype(tSub.getMdf(),tSuper.getMdf())){return ErrorKind.NotSubtypeMdf;} return null; } //only check mdf subtyping public static boolean _methMdfTSubtype(MethodType mSub,MethodType mSuper){ if (!Functions.isSubtype(mSuper.getMdf(),mSub.getMdf())){return false;} if (!Functions.isSubtype(mSub.getReturnType().getNT().getMdf(),mSuper.getReturnType().getNT().getMdf())){return false;} {int i=-1;for(Type tSub:mSub.getTs()){i+=1;Type tSuper=mSuper.getTs().get(i); if (!Functions.isSubtype(tSuper.getNT().getMdf(),tSub.getNT().getMdf())){ return false; } }} return true; } public static boolean methTSubtype(Program p,MethodType mSub,MethodType mSuper){ if (!Functions.isSubtype(mSuper.getMdf(),mSub.getMdf())){return false;} if (null!=subtype(p,mSub.getReturnType().getNT(),mSuper.getReturnType().getNT())){ return false; } if(mSub.getTs().size()!=mSuper.getTs().size()){return false;} {int i=-1;for(Type tSub:mSub.getTs()){i+=1;Type tSuper=mSuper.getTs().get(i); if (null!=subtype(p,tSuper.getNT(),tSub.getNT())){ return false; } }} for(Type ti:mSub.getExceptions()){ if(!exceptionSubtype(p,ti.getNT(), mSuper)){return false;} } return true; } public static boolean exceptionSubtype(Program p,NormType ti, MethodType mSuper) { for(Type tj:mSuper.getExceptions()){ if(p.subtypeEq(ti.getPath(),tj.getNT().getPath())){ return true; } } return false; } } class Impl implements TypeSystem,TsOperations,TsBlock,TsMCall,TsLibrary{ HashMap<TIn,TOut>map=new HashMap<>();//memoized map @Override public TOut type(TIn in){ TOut res=_memoizedTSRes(in); if (res!=null){return res;} try{ res=in.e.accept(new Visitor<TOut>(){ public TOut visit(ExpCore.EPath s) {return tsPath(in,s);} public TOut visit(X s) {return tsX(in,s);} public TOut visit(_void s) {return tsVoid(in,s);} public TOut visit(Using s) {return tsUsing(in,s);} public TOut visit(Signal s) {return tsSignal(in,s);} public TOut visit(MCall s) {return tsMCall(in,s);} public TOut visit(Block s) {return tsBlock(in,s);} public TOut visit(ClassB s) {return tsClassB(in,s);} public TOut visit(Loop s) {return tsLoop(in,s);} public TOut visit(WalkBy s) {throw Assertions.codeNotReachable();} }); } finally{if(res!=null){memoizeTSRes(in,res);}} assert res!=null: ""; return res; } private void memoizeTSRes(TIn in, TOut out) { //memoizeTSRes need to not memoize null res assert out!=null: ""; assert !map.containsKey(in); map.put(in, out); } private TOut _memoizedTSRes(TIn in) { TOut out=map.get(in); return out; } }