use of php.runtime.ext.support.compile.CompileFunction in project jphp by jphp-compiler.
the class ExpressionStmtCompiler method writePushCall.
Memory writePushCall(CallExprToken function, boolean returnValue, boolean writeOpcode, PushCallStatistic statistic) {
Token name = function.getName();
if (name instanceof NameToken) {
String realName = ((NameToken) name).getName();
CompileFunction compileFunction = compiler.getScope().findCompileFunction(realName);
// try find system function, like max, sin, cos, etc.
if (compileFunction == null && name instanceof FulledNameToken && compiler.getEnvironment().fetchFunction(realName) == null && compiler.findFunction(realName) == null) {
String tryName = ((FulledNameToken) name).getLastName().getName();
compileFunction = compiler.getScope().findCompileFunction(tryName);
}
if (compileFunction != null) {
return writePushCompileFunction(function, compileFunction, returnValue, writeOpcode, statistic);
} else {
if (!writeOpcode)
return null;
method.entity.setImmutable(false);
int index = method.clazz.getAndIncCallFuncCount();
writePushEnv();
writePushTraceInfo(function);
writePushString(realName.toLowerCase());
writePushString(realName);
writePushParameters(function.getParameters());
writeGetStatic("$CALL_FUNC_CACHE", FunctionCallCache.class);
writePushConstInt(index);
writeSysStaticCall(InvokeHelper.class, "call", Memory.class, Environment.class, TraceInfo.class, String.class, String.class, Memory[].class, FunctionCallCache.class, Integer.TYPE);
if (!returnValue)
writePopAll(1);
}
} else if (name instanceof StaticAccessExprToken) {
method.entity.setImmutable(false);
if (((StaticAccessExprToken) name).isAsParent())
return writePushParentDynamicMethod(function, returnValue, writeOpcode, statistic);
else
return writePushStaticMethod(function, returnValue, writeOpcode, statistic);
} else if (name instanceof DynamicAccessExprToken) {
method.entity.setImmutable(false);
return writePushDynamicMethod(function, returnValue, writeOpcode, statistic);
} else {
if (!writeOpcode)
return null;
method.entity.setImmutable(false);
writeLineNumber(function);
writePush((ValueExprToken) function.getName(), true, false);
writePopBoxing();
writePushParameters(function.getParameters());
writePushEnv();
writePushTraceInfo(function);
writeSysStaticCall(InvokeHelper.class, "callAny", Memory.class, Memory.class, Memory[].class, Environment.class, TraceInfo.class);
if (!returnValue)
writePopAll(1);
}
return null;
}
use of php.runtime.ext.support.compile.CompileFunction in project jphp by jphp-compiler.
the class CompileScope method findCompileFunction.
public CompileFunction findCompileFunction(String name) {
name = name.toLowerCase();
CompileFunction function = compileFunctionMap.get(name);
if (function != null) {
return function;
}
synchronized (this) {
CompileFunctionSpec functionSpec = compileFunctionSpecMap.get(name);
if (functionSpec == null) {
return null;
}
compileFunctionMap.put(name, function = functionSpec.toFunction());
}
return function;
}
use of php.runtime.ext.support.compile.CompileFunction in project jphp by jphp-compiler.
the class ExpressionStmtCompiler method writePushCompileFunction.
Memory writePushCompileFunction(CallExprToken function, CompileFunction compileFunction, boolean returnValue, boolean writeOpcode, PushCallStatistic statistic) {
CompileFunction.Method method = compileFunction.find(function.getParameters().size());
if (method == null) {
if (!writeOpcode)
return Memory.NULL;
writeWarning(function, Messages.ERR_EXPECT_LEAST_PARAMS.fetch(compileFunction.name, compileFunction.getMinArgs(), function.getParameters().size()));
if (returnValue)
writePushNull();
return null;
} else if (!method.isVarArg() && method.argsCount < function.getParameters().size()) {
if (!writeOpcode)
return Memory.NULL;
writeWarning(function, Messages.ERR_EXPECT_EXACTLY_PARAMS.fetch(compileFunction.name, method.argsCount, function.getParameters().size()));
if (returnValue)
writePushNull();
return null;
}
if (statistic != null)
statistic.returnType = StackItem.Type.valueOf(method.resultType);
Class[] types = method.parameterTypes;
ListIterator<ExprStmtToken> iterator = function.getParameters().listIterator();
Object[] arguments = new Object[types.length];
int j = 0;
boolean immutable = method.isImmutable;
boolean init = false;
for (int i = 0; i < method.parameterTypes.length; i++) {
Class<?> argType = method.parameterTypes[i];
boolean isRef = method.references[i];
boolean isMutable = method.isPresentAnnotationOfParam(i, Runtime.MutableValue.class);
if (method.isPresentAnnotationOfParam(i, Runtime.GetLocals.class)) {
if (!writeOpcode)
return null;
immutable = false;
writePushLocal();
} else if (argType == Environment.class) {
if (immutable) {
arguments[i] = compiler.getEnvironment();
} else {
if (!writeOpcode)
return null;
writePushEnv();
}
} else if (argType == TraceInfo.class) {
if (immutable) {
arguments[i] = function.toTraceInfo(compiler.getContext());
} else {
if (!writeOpcode)
return null;
writePushTraceInfo(function);
}
} else {
if (argType == Memory[].class) {
Memory[] args = new Memory[function.getParameters().size() - j];
boolean arrCreated = false;
for (int t = 0; t < function.getParameters().size() - j; t++) {
ExprStmtToken next = iterator.next();
if (immutable)
args[t] = writeExpression(next, true, true, false);
if (args[t] == null) {
if (!writeOpcode)
return null;
if (!arrCreated) {
if (immutable) {
for (int n = 0; n < i; /*j*/
n++) {
if (arguments[n] instanceof TraceInfo) {
writePushTraceInfo(function);
} else if (arguments[n] instanceof Environment) {
writePushEnv();
} else {
writePushMemory((Memory) arguments[n]);
writePop(types[n], true, true);
arguments[t] = null;
}
}
}
// create new array
writePushSmallInt(args.length);
code.add(new TypeInsnNode(ANEWARRAY, Type.getInternalName(Memory.class)));
stackPop();
stackPush(Memory.Type.REFERENCE);
arrCreated = true;
}
writePushDup();
writePushSmallInt(t);
writeExpression(next, true, false, writeOpcode);
//if (!isRef) BUGFIX - array is memory[] and so we need to convert value to memory
writePopBoxing(!isRef);
code.add(new InsnNode(AASTORE));
stackPop();
stackPop();
stackPop();
immutable = false;
}
}
if (!immutable && !arrCreated) {
code.add(new InsnNode(ACONST_NULL));
stackPush(Memory.Type.REFERENCE);
}
arguments[i] = MemoryUtils.valueOf(args);
} else {
ExprStmtToken next = iterator.next();
if (!immutable && !init) {
init = true;
for (int k = 0; k < i; /*j*/
k++) {
if (arguments[k] != null) {
if (arguments[k] instanceof TraceInfo) {
writePushTraceInfo(function);
} else if (arguments[k] instanceof Environment) {
writePushEnv();
} else {
writePushMemory((Memory) arguments[k]);
writePop(types[k], true, isRef);
arguments[k] = null;
}
}
}
}
if (immutable)
arguments[i] = writeExpression(next, true, true, false);
if (arguments[i] == null) {
if (!writeOpcode)
return null;
if (!init) {
for (int n = 0; n < i; /*j*/
n++) {
if (arguments[n] instanceof TraceInfo) {
writePushTraceInfo(function);
} else if (arguments[n] instanceof Environment) {
writePushEnv();
} else {
writePushMemory((Memory) arguments[n]);
writePop(types[n], true, false);
}
arguments[n] = null;
}
init = true;
}
if (isRef)
writeExpression(next, true, false, writeOpcode);
else {
Memory tmp = writeExpression(next, true, true, true);
if (tmp != null)
writePushMemory(tmp);
}
writePop(argType, true, isMutable && !isRef);
if (!isMutable && !isRef && stackPeek().type.isReference()) {
writeSysDynamicCall(Memory.class, "toValue", Memory.class);
}
immutable = false;
}
j++;
}
}
}
if (immutable) {
if (!returnValue)
return null;
Object[] typedArguments = new Object[arguments.length];
for (int i = 0; i < arguments.length; i++) {
if (method.parameterTypes[i] != Memory.class && arguments[i] instanceof Memory)
typedArguments[i] = method.converters[i].run((Memory) arguments[i]);
else
//MemoryUtils.toValue((Memory)arguments[i], types[i]);
typedArguments[i] = arguments[i];
}
try {
Object value = method.method.invoke(null, typedArguments);
return MemoryUtils.valueOf(value);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e.getCause());
}
}
if (!writeOpcode)
return null;
this.method.entity.setImmutable(false);
writeLineNumber(function);
writePushStaticCall(method.method);
if (returnValue) {
if (method.resultType == void.class)
writePushNull();
setStackPeekAsImmutable();
}
return null;
}
Aggregations