package php.runtime.ext.core.reflection;
import php.runtime.Memory;
import php.runtime.common.HintType;
import php.runtime.env.Environment;
import php.runtime.invoke.InvokeHelper;
import php.runtime.invoke.ObjectInvokeHelper;
import php.runtime.lang.Closure;
import php.runtime.lang.IObject;
import php.runtime.memory.ArrayMemory;
import php.runtime.memory.LongMemory;
import php.runtime.memory.ObjectMemory;
import php.runtime.memory.StringMemory;
import php.runtime.reflection.ClassEntity;
import php.runtime.reflection.CompileFunctionEntity;
import php.runtime.reflection.FunctionEntity;
import php.runtime.reflection.ParameterEntity;
import php.runtime.reflection.helper.ClosureEntity;
import php.runtime.reflection.support.AbstractFunctionEntity;
import static php.runtime.annotation.Reflection.*;
@Name("ReflectionFunction")
@Signature(
@Arg(value = "name", type = HintType.STRING, readOnly = true)
)
public class ReflectionFunction extends ReflectionFunctionAbstract {
public final static int IS_DEPRECATED = 262144;
protected Closure closure;
protected ClosureEntity closureEntity;
protected FunctionEntity functionEntity;
protected ArrayMemory cachedParameters;
public ReflectionFunction(Environment env, ClassEntity clazz) {
super(env, clazz);
}
public void setFunctionEntity(FunctionEntity functionEntity) {
this.functionEntity = functionEntity;
getProperties().put("name", new StringMemory(functionEntity.getName()));
}
@Signature(@Arg(value = "name"))
public Memory __construct(Environment env, Memory... args){
Memory name = args[0].toValue();
if (name.isClosure()){
closure = (Closure)name.toValue(ObjectMemory.class).value;
closureEntity = (ClosureEntity)closure.getReflection();
} else {
functionEntity = env.fetchFunction(name.toString());
if (functionEntity == null)
exception(env, "Function %s does not exist", name.toString());
setFunctionEntity(functionEntity);
}
return Memory.NULL;
}
@Override
protected AbstractFunctionEntity getEntity() {
return functionEntity;
}
@Override
protected ClosureEntity getClosureEntity() {
return closureEntity;
}
@Override
protected IObject getInstance() {
return closure;
}
@Override
@Signature
public Memory getNumberOfParameters(Environment env, Memory... args) {
if (functionEntity instanceof CompileFunctionEntity)
return LongMemory.valueOf(((CompileFunctionEntity) functionEntity).getCompileFunction().getMaxArgs());
else
return super.getNumberOfParameters(env, args);
}
@Override
@Signature
public Memory getNumberOfRequiredParameters(Environment env, Memory... args) {
if (functionEntity instanceof CompileFunctionEntity)
return LongMemory.valueOf(((CompileFunctionEntity) functionEntity).getCompileFunction().getMinArgs());
else
return super.getNumberOfRequiredParameters(env, args);
}
@Signature
public Memory isDisabled(Environment env, Memory... args){
if (closure != null)
return Memory.FALSE;
return Memory.FALSE;
}
@Signature
public Memory getClosure(final Environment env, Memory... args) throws Throwable {
if (closure != null)
return new ObjectMemory(closure);
return new ObjectMemory(functionEntity.getClosure(env));
}
@Signature
public Memory invoke(Environment env, Memory... args) throws Throwable {
if (closure != null)
return ObjectInvokeHelper.invokeMethod(
closure, closureEntity.methodMagicInvoke, env, env.peekCall(0).trace, args, true
);
else {
return InvokeHelper.call(env, env.peekCall(0).trace, functionEntity, args);
}
}
@Signature(@Arg(value = "args", type = HintType.ARRAY))
public Memory invokeArgs(Environment env, Memory... args) throws Throwable {
ArrayMemory value = args[0].toValue(ArrayMemory.class);
Memory[] passed = value.values();
return invoke(env, passed);
}
@Override
@Signature
public Memory getParameters(Environment env, Memory... args) {
if (cachedParameters != null)
return cachedParameters;
if (functionEntity instanceof CompileFunctionEntity)
exception(env, "Cannot get parameters for internal function %s()", functionEntity.getName());
ParameterEntity[] parameters = closureEntity == null ? functionEntity.getParameters() : closureEntity.parameters;
ClassEntity entity = env.fetchClass("ReflectionParameter");
ArrayMemory result = new ArrayMemory();
int i = 0;
for(ParameterEntity param : parameters){
ReflectionParameter e = new ReflectionParameter(env, entity);
e.setEntity(param);
e.setFunctionEntity(functionEntity);
e.setPosition(i);
i++;
result.add(new ObjectMemory(e));
}
return cachedParameters = result;
}
@Signature({
@Arg(value = "reflector", type = HintType.OBJECT),
@Arg(value = "return", type = HintType.BOOLEAN, optional = @Optional(value = "", type = HintType.BOOLEAN))
})
public static Memory export(Environment env, Memory... args){
ReflectionFunction e = new ReflectionFunction(env, env.fetchClass("ReflectionFunction"));
if (args[1].toBoolean())
return e.__toString(env);
else
env.echo(e.__toString(env));
return Memory.NULL;
}
}