use of php.runtime.Memory in project jphp by jphp-compiler.
the class ExpressionStmtCompiler method writePushParameters.
public void writePushParameters(Collection<ExprStmtToken> parameters, boolean useConstants, Memory... additional) {
if (parameters.isEmpty()) {
code.add(new InsnNode(ACONST_NULL));
stackPush(Memory.Type.REFERENCE);
return;
}
if (useConstants && additional == null || additional.length == 0) {
List<Memory> constantParameters = new ArrayList<Memory>();
for (ExprStmtToken param : parameters) {
Memory paramMemory = writeExpression(param, true, true, false);
if (paramMemory == null || paramMemory.isArray()) {
// skip arrays.
break;
}
constantParameters.add(paramMemory);
}
if (constantParameters.size() == parameters.size()) {
writePushConstantMemoryArray(constantParameters);
return;
}
}
writePushSmallInt(parameters.size() + (additional == null ? 0 : additional.length));
code.add(new TypeInsnNode(ANEWARRAY, Type.getInternalName(Memory.class)));
stackPop();
stackPush(Memory.Type.REFERENCE);
int i = 0;
for (ExprStmtToken param : parameters) {
writePushDup();
writePushSmallInt(i);
writeExpression(param, true, false);
writePopBoxing();
code.add(new InsnNode(AASTORE));
stackPop();
stackPop();
stackPop();
i++;
}
if (additional != null) {
for (Memory m : additional) {
writePushDup();
writePushSmallInt(i);
writePushMemory(m);
writePopBoxing();
code.add(new InsnNode(AASTORE));
stackPop();
stackPop();
stackPop();
i++;
}
}
}
use of php.runtime.Memory in project jphp by jphp-compiler.
the class ExpressionStmtCompiler method tryWritePushMacro.
Memory tryWritePushMacro(MacroToken macro, boolean writeOpcode) {
if (macro instanceof LineMacroToken) {
return LongMemory.valueOf(macro.getMeta().getStartLine() + 1);
} else if (macro instanceof FileMacroToken) {
return new StringMemory(compiler.getSourceFile());
} else if (macro instanceof DirMacroToken) {
String sourceFile = compiler.getSourceFile();
String parent = new File(sourceFile).getParent();
// Fix issue #198.
if (sourceFile.startsWith(parent + "//") && parent.endsWith(":")) {
parent += "//";
}
return new StringMemory(parent);
} else if (macro instanceof FunctionMacroToken) {
if (method.clazz.getFunctionName().isEmpty())
return method.clazz.isSystem() ? Memory.CONST_EMPTY_STRING : method.getRealName() == null ? Memory.CONST_EMPTY_STRING : new StringMemory(method.getRealName());
else {
return method.clazz.getFunctionName() == null ? Memory.CONST_EMPTY_STRING : new StringMemory(method.clazz.getFunctionName());
}
} else if (macro instanceof MethodMacroToken) {
if (method.clazz.isSystem())
return method.clazz.getFunctionName() != null ? new StringMemory(method.clazz.getFunctionName()) : Memory.NULL;
else
return new StringMemory(method.clazz.entity.getName() + (method.getRealName() == null ? "" : "::" + method.getRealName()));
} else if (macro instanceof ClassMacroToken) {
if (method.clazz.entity.isTrait()) {
if (writeOpcode) {
writePushEnv();
writeSysDynamicCall(Environment.class, "__getMacroClass", Memory.class);
}
return null;
} else {
if (method.clazz.getClassContext() != null) {
return new StringMemory(method.clazz.getClassContext().getFulledName());
} else {
return new StringMemory(method.clazz.isSystem() ? "" : method.clazz.entity.getName());
}
}
} else if (macro instanceof NamespaceMacroToken) {
return new StringMemory(compiler.getNamespace() == null || compiler.getNamespace().getName() == null ? "" : compiler.getNamespace().getName().getName());
} else if (macro instanceof TraitMacroToken) {
if (method.clazz.entity.isTrait())
return new StringMemory(method.clazz.entity.getName());
else
return Memory.CONST_EMPTY_STRING;
} else
throw new IllegalArgumentException("Unsupported macro value: " + macro.getWord());
}
use of php.runtime.Memory in project jphp by jphp-compiler.
the class ExpressionStmtCompiler method writeExpression.
@SuppressWarnings("unchecked")
public Memory writeExpression(ExprStmtToken expression, boolean returnValue, boolean returnMemory, boolean writeOpcode) {
int initStackSize = method.getStackCount();
exprStackInit.push(initStackSize);
if (!expression.isStmtList()) {
if (expression.getAsmExpr() == null) {
throw new CriticalException("Invalid expression token without asm expr, on line " + expression.getMeta().getStartLine() + ", expr = " + expression.getWord());
}
// new ASMExpression(compiler.getEnvironment(), compiler.getContext(), expression).getResult();
expression = expression.getAsmExpr();
}
List<Token> tokens = expression.getTokens();
int operatorCount = 0;
for (Token token : tokens) {
if (token instanceof OperatorExprToken)
operatorCount++;
}
boolean invalid = false;
for (Token token : tokens) {
if (token == null)
continue;
writeTickTrigger(token);
if (writeOpcode) {
if (token instanceof StmtToken) {
if (!(token instanceof ReturnStmtToken))
method.entity.setImmutable(false);
}
BaseStatementCompiler cmp = getCompiler(token.getClass());
if (cmp != null && !(cmp instanceof BaseExprCompiler)) {
cmp.write(token);
continue;
}
}
if (token instanceof ValueExprToken) {
// mixed, calls, numbers, strings, vars, etc.
if (token instanceof CallExprToken && ((CallExprToken) token).getName() instanceof OperatorExprToken) {
if (writeOpcode) {
writePush((ValueExprToken) token, true, true);
method.entity.setImmutable(false);
} else
break;
} else
stackPush((ValueExprToken) token);
} else if (token instanceof OperatorExprToken) {
// + - * / % && || or ! and == > < etc.
operatorCount--;
if (operatorCount >= 0) {
Memory result;
if (operatorCount == 0) {
result = writeOperator((OperatorExprToken) token, returnValue, writeOpcode);
} else
result = writeOperator((OperatorExprToken) token, true, writeOpcode);
if (!writeOpcode && result == null) {
invalid = true;
break;
}
if (result == null)
method.entity.setImmutable(false);
}
} else
break;
}
Memory result = null;
if (!invalid && returnMemory && returnValue && !stackEmpty(false) && stackPeek().isConstant()) {
result = stackPop().memory;
invalid = true;
}
if (!invalid) {
if (returnValue && !stackEmpty(false) && stackPeek().isKnown()) {
if (returnMemory)
result = tryWritePush(stackPop(), writeOpcode, returnValue, true);
else
writePush(stackPop());
} else if (method.getStackCount() > 0) {
if (stackPeekToken() instanceof CallableExprToken) {
if (returnMemory)
result = tryWritePush(stackPopToken(), returnValue, writeOpcode, true);
else
writePush(stackPopToken(), returnValue, true);
} else if (stackPeek().isConstant()) {
stackPop();
}
}
}
if (!returnValue && writeOpcode) {
writePopAll(method.getStackCount() - initStackSize);
} else if (!writeOpcode) {
int count = method.getStackCount() - initStackSize;
for (int i = 0; i < count; i++) {
stackPop();
}
}
exprStackInit.pop();
return result;
}
use of php.runtime.Memory in project jphp by jphp-compiler.
the class ExpressionStmtCompiler method writeLogicOperator.
Memory writeLogicOperator(LogicOperatorExprToken operator, boolean returnValue, boolean writeOpcode) {
if (stackEmpty(true))
unexpectedToken(operator);
if (!writeOpcode) {
StackItem top = stackPeek();
Memory one = tryWritePush(top, false, false, true);
if (one == null)
return null;
Memory two = writeExpression(operator.getRightValue(), true, true, false);
if (two == null)
return null;
stackPop();
Memory r = operator.calc(getCompiler().getEnvironment(), operator.toTraceInfo(getCompiler().getContext()), one, two);
stackPush(r);
return r;
}
writeLineNumber(operator);
StackItem o = stackPop();
writePush(o);
writePopBoolean();
LabelNode end = new LabelNode();
LabelNode next = new LabelNode();
if (operator instanceof BooleanOrExprToken || operator instanceof BooleanOr2ExprToken) {
code.add(new JumpInsnNode(IFEQ, next));
stackPop();
if (returnValue) {
writePushBooleanAsMemory(true);
stackPop();
}
} else if (operator instanceof BooleanAndExprToken || operator instanceof BooleanAnd2ExprToken) {
code.add(new JumpInsnNode(IFNE, next));
stackPop();
if (returnValue) {
writePushBooleanAsMemory(false);
stackPop();
}
}
code.add(new JumpInsnNode(GOTO, end));
code.add(next);
writeExpression(operator.getRightValue(), returnValue, false);
if (returnValue) {
if (operator.getLast() instanceof ValueIfElseToken)
writePopBoxing();
else
writePopBooleanAsObject();
}
code.add(end);
return null;
}
use of php.runtime.Memory 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;
}
Aggregations