package php.runtime.ext.support.compile; import php.runtime.Memory; import php.runtime.annotation.Reflection; import php.runtime.env.Environment; import php.runtime.env.TraceInfo; import php.runtime.invoke.Invoker; import php.runtime.memory.ObjectMemory; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Collection; import java.util.HashMap; import java.util.Map; abstract public class FunctionsContainer { protected static boolean expectingReference(Environment env, TraceInfo trace, Memory memory, String funcName) { if (!memory.isReference()) { env.error(trace, (funcName == null ? "" : funcName + "() - ") + "Only variables can be passed by reference"); return false; } return true; } /** * Use expectingReference(Environment env, TraceInfo trace, Memory memory, String funcName) */ @Deprecated protected static boolean expectingReference(Environment env, TraceInfo trace, Memory memory) { return expectingReference(env, trace, memory, null); } protected static boolean expecting(Environment env, TraceInfo trace, int index, Memory memory, Memory.Type type) { if (memory.getRealType() != type) { env.warning(trace, "expects parameter " + index + " to be " + type.toString() + ", " + memory.getRealType().toString() + " given"); return false; } return true; } protected static boolean expectingImplement(Environment env, TraceInfo trace, int index, Memory memory, Class<?> clazz) { if (!memory.isObject() || !memory.toValue(ObjectMemory.class).getClass().isAssignableFrom(clazz)) { String given = memory.getRealType().toString(); if (memory.isObject()) given = memory.toValue(ObjectMemory.class).getReflection().getName(); env.warning(trace, "expects parameter " + index + " must implement " + (clazz.isInterface() ? "interface " : "") + clazz.getSimpleName() + ", " + given + " given"); return false; } return true; } protected static Invoker expectingCallback(Environment env, TraceInfo trace, int index, Memory memory) { Invoker invoker = Invoker.valueOf(env, null, memory); if (invoker == null) { env.warning(trace, "expects parameter " + index + " to be valid callback"); return null; } if (invoker.canAccess(env) != 0) { env.warning(trace, "expects parameter " + index + " to be valid callback, cannot access"); return null; } return invoker; } protected Map<String, Method> getNativeFunctions() { return new HashMap<String, Method>(); } protected Method getNative(Class clazz, String name, Class<?>... argumentTypes) { try { return clazz.getDeclaredMethod(name, argumentTypes); } catch (NoSuchMethodException e) { throw new RuntimeException(e); } } public Collection<CompileFunctionSpec> getFunctionSpecs() { Map<String, CompileFunctionSpec> result = new HashMap<String, CompileFunctionSpec>(); for (Method method : getClass().getMethods()) { int mod = method.getModifiers(); if (Modifier.isStatic(mod)) { String name = method.getName(); Reflection.Name altName = method.getAnnotation(Reflection.Name.class); if (altName != null) name = altName.value(); CompileFunctionSpec function = result.get(name); if (function == null) result.put(name, function = new CompileFunctionSpec(name)); function.addMethod(method); } } for (Map.Entry<String, Method> item : getNativeFunctions().entrySet()) { Method method = item.getValue(); CompileFunctionSpec function = new CompileFunctionSpec(item.getKey(), true); result.put(item.getKey(), function); function.addMethod(method); } return result.values(); } public Collection<CompileFunction> getFunctions() { Map<String, CompileFunction> result = new HashMap<String, CompileFunction>(); for (Method method : getClass().getDeclaredMethods()) { int mod = method.getModifiers(); if (Modifier.isStatic(mod) && Modifier.isPublic(mod)) { String name = method.getName(); Reflection.Name altName = method.getAnnotation(Reflection.Name.class); if (altName != null) name = altName.value(); CompileFunction function = result.get(name); if (function == null) result.put(name, function = new CompileFunction(name)); function.addMethod(method); } } for (Map.Entry<String, Method> item : getNativeFunctions().entrySet()) { Method method = item.getValue(); CompileFunction function = result.get(item.getKey()); if (function == null) { result.put(item.getKey(), function = new CompileFunction( item.getKey() ) ); } function.addMethod(method, true); } return result.values(); } }