package platformSpecific.fakeInternet; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Set; import java.util.stream.IntStream; import platformSpecific.fakeInternet.ActionType.Type; import platformSpecific.javaTranslation.Resources; import tools.StringBuilders; import ast.Ast.MethodType; import ast.Ast; import ast.ErrorMessage; import ast.ExpCore; import ast.ExpCore.Using; import auxiliaryGrammar.Functions; import programReduction.Program; class ProtectedPluginType{ static Method getMethod(PluginType that,Program p,Using u){ String mName=Resources.nameOf(u.getS().nameToS(),u.getS().getNames()); return getMethod(that.getClass(),p,mName,u.getS().getNames().size(),u); } static Method getMethod(Class<?> that,Program p,String mName, int argNum,Using uForError){ Class<?>[] parameterTypes=new Class<?>[argNum]; Arrays.fill(parameterTypes, Object.class); try {return that.getMethod(mName, parameterTypes);} catch (NoSuchMethodException e) { List<String> options=new ArrayList<>(); for(Method m:that.getDeclaredMethods()){ options.add(m.getName()); } throw new ErrorMessage.PluginMethodUndefined(options,uForError,null,null); } catch (SecurityException e) { throw new Error(e);} } static Object executeMethod(Method m,Program p,Object rec, Object[] es){ try { Object r = m.invoke(rec,es); if(Resources.isValid(p, r, es)){return r;} else{throw Resources.notAct;} } catch (IllegalAccessException | IllegalArgumentException e) { throw new Error(e); } catch (InvocationTargetException e) { if(e.getCause() instanceof RuntimeException){ throw(RuntimeException)e.getCause(); } if(e.getCause() instanceof Error){ throw(Error)e.getCause(); } throw new Error(e.getCause()); } } static String executableWrapper(Using s, Set<String> labels){ // (plF,xsF)->plF. // MnameEncoded£xn1£xn2(xsF[0],..,xsF[n]), String plF="L"+Functions.freshName("pl",labels); String xsF="L"+Functions.freshName("xs",labels); StringBuilder res=new StringBuilder(); res.append("("+plF+","+xsF+")->"+plF+"."); res.append(Resources.nameOf(s.getS().nameToS(),s.getS().getNames())); res.append("("); StringBuilders.formatSequence(res, IntStream.range(0, s.getEs().size()).iterator(), ", ", i->res.append(xsF+"["+i+"]")); res.append(")"); return res.toString(); } } public interface PluginType { default List<ast.Ast.NormType> typeOf(Program p, Using u){ Method m=ProtectedPluginType.getMethod(this,p, u); ActionType ann = m.getAnnotation(ActionType.class); assert ann!=null; ArrayList<Ast.NormType> ts=new ArrayList<>(); for(ActionType.Type path:ann.value()){ ts.add(path.type.getNT()); } return ts; }; default Object execute(Program p, Using u){ //NOTE: this is not called with compilation but only with single steps"; Method m=ProtectedPluginType.getMethod(this,p, u); return ProtectedPluginType.executeMethod(m, p, this, u.getEs().toArray()); } default String executableJ(Program p,Using s,String e,List<String>es,Set<String> labels){ StringBuilder res=new StringBuilder(); String plgName=this.getClass().getName(); res.append("platformSpecific.javaTranslation.Resources.plgExecutor("); res.append("\""+s.getS().nameToS()+"\","); res.append("platformSpecific.javaTranslation.Resources.getP(), "); res.append("new "+plgName+"(), "); res.append(ProtectedPluginType.executableWrapper(s, labels)); //plgExecutor("PathName",p,new plgName(), // (plF,xsF)->plF. // MnameEncoded£xn1£xn2(xsF[0],..,xsF[n]), //()->e,e0,..,en); res.append(", ()->("); res.append(e); res.append(")"); for(String ei:es){ res.append(", "); res.append(ei); } res.append(")"); return res.toString(); } }