use of org.develnext.jphp.core.compiler.jvm.node.MethodNodeImpl in project jphp by jphp-compiler.
the class ClassStmtCompiler method writeCopiedMethod.
protected void writeCopiedMethod(ClassStmtToken.Alias alias, String methodName, ClassEntity trait) {
final MethodEntity methodEntity = fetchClassAndCheck(alias.getTrait()).findMethod(methodName.toLowerCase());
String name = alias.getName();
if (name == null)
name = methodName;
MethodEntity origin = entity.findMethod(name.toLowerCase());
if (origin != null) {
if (origin.getClazz() == entity) {
if (origin.getTrait() != null) {
compiler.getEnvironment().error(entity.getTrace(), Messages.ERR_TRAIT_METHOD_COLLISION.fetch(methodName, trait.getName(), origin.getTrait().getName(), entity.getName()));
}
return;
}
}
if (methodEntity == null) {
compiler.getEnvironment().error(entity.getTrace(), Messages.ERR_METHOD_NOT_FOUND.fetch(alias.getTrait(), methodName));
return;
}
MethodEntity dup = methodEntity.duplicateForInject();
dup.setClazz(entity);
dup.setTrait(trait);
if (alias.getName() != null)
dup.setName(alias.getName());
if (alias.getModifier() != null)
dup.setModifier(alias.getModifier());
MethodNodeImpl methodNode = MethodNodeImpl.duplicate(methodEntity.getAdditionalData("methodNode", MethodNode.class, new Function<MethodNode>() {
@Override
public MethodNode call() {
ClassNode classNode = methodEntity.getClazz().getAdditionalData("classNode", ClassNode.class, new Function<ClassNode>() {
@Override
public ClassNode call() {
ClassReader classReader;
if (methodEntity.getClazz().getData() != null)
classReader = new ClassReader(methodEntity.getClazz().getData());
else {
try {
classReader = new ClassReader(methodEntity.getClazz().getName());
} catch (IOException e) {
throw new CriticalException(e);
}
}
ClassNode classNode = new ClassNode();
classReader.accept(classNode, 0);
return classNode;
}
});
for (Object m : classNode.methods) {
MethodNode method = (MethodNode) m;
if (method.name.equals(methodEntity.getInternalName())) {
return method;
}
}
throw new CriticalException("Cannot find MethodNode for method - " + methodEntity.getName() + "(" + methodEntity.getSignatureString(true) + ")");
}
}));
if (origin != null) {
dup.setPrototype(origin);
}
dup.setInternalName(dup.getName() + "$" + entity.nextMethodIndex());
methodNode.name = dup.getInternalName();
ClassEntity.SignatureResult result = entity.addMethod(dup, null);
result.check(compiler.getEnvironment());
node.methods.add(methodNode);
}
use of org.develnext.jphp.core.compiler.jvm.node.MethodNodeImpl in project jphp by jphp-compiler.
the class ClassStmtCompiler method writeDefaultConstructors.
protected void writeDefaultConstructors() {
if (!isSystem && !isClosure() && entity.getParent() != null && entity.getParent().getNativeClass() != null && !BaseObject.class.isAssignableFrom(entity.getParent().getNativeClass())) {
for (Constructor el : entity.getParent().getNativeClass().getConstructors()) {
Class<?>[] parameterTypes = el.getParameterTypes();
if (parameterTypes.length == 2 && parameterTypes[0] == Environment.class && parameterTypes[1] == ClassEntity.class) {
continue;
}
MethodNode constructor = new MethodNodeImpl();
constructor.name = Constants.INIT_METHOD;
constructor.access = el.getModifiers();
constructor.exceptions = new ArrayList();
MethodStmtCompiler methodCompiler = new MethodStmtCompiler(this, constructor);
ExpressionStmtCompiler expressionCompiler = new ExpressionStmtCompiler(methodCompiler, null);
LabelNode l0 = writeLabel(constructor, statement.getMeta().getStartLine());
methodCompiler.addLocalVariable("~this", l0);
Type[] argumentTypes = new Type[parameterTypes.length];
int i = 0;
for (Class type : parameterTypes) {
argumentTypes[i++] = Type.getType(type);
methodCompiler.addLocalVariable("arg" + i, l0, type);
}
constructor.desc = Type.getMethodDescriptor(Type.getType(void.class), argumentTypes);
methodCompiler.writeHeader();
expressionCompiler.writeVarLoad("~this");
for (i = 0; i < argumentTypes.length; i++) {
expressionCompiler.writeVarLoad("arg" + (i + 1));
}
constructor.instructions.add(new MethodInsnNode(INVOKESPECIAL, node.superName, Constants.INIT_METHOD, constructor.desc, false));
methodCompiler.writeFooter();
constructor.instructions.add(new InsnNode(RETURN));
node.methods.add(constructor);
}
}
}
use of org.develnext.jphp.core.compiler.jvm.node.MethodNodeImpl in project jphp by jphp-compiler.
the class ClassStmtCompiler method writeInitStatic.
@SuppressWarnings("unchecked")
protected void writeInitStatic() {
MethodNode node = new MethodNodeImpl();
node.access = ACC_STATIC;
node.name = Constants.STATIC_INIT_METHOD;
node.desc = Type.getMethodDescriptor(Type.getType(void.class));
MethodStmtCompiler methodCompiler = new MethodStmtCompiler(this, node);
ExpressionStmtCompiler expressionCompiler = new ExpressionStmtCompiler(methodCompiler, null);
methodCompiler.writeHeader();
// trace list
expressionCompiler.writePushSmallInt(traceList.size());
node.instructions.add(new TypeInsnNode(ANEWARRAY, Type.getInternalName(TraceInfo.class)));
expressionCompiler.stackPush(Memory.Type.REFERENCE);
int i = 0;
for (TraceInfo traceInfo : traceList) {
expressionCompiler.writePushDup();
expressionCompiler.writePushSmallInt(i);
expressionCompiler.writePushCreateTraceInfo(traceInfo.getStartLine(), traceInfo.getStartPosition());
node.instructions.add(new InsnNode(AASTORE));
expressionCompiler.stackPop();
expressionCompiler.stackPop();
i++;
}
expressionCompiler.writePutStatic("$TRC", TraceInfo[].class);
// memory constants
expressionCompiler.writePushSmallInt(memoryConstants.size());
node.instructions.add(new TypeInsnNode(ANEWARRAY, Type.getInternalName(Memory.class)));
expressionCompiler.stackPush(Memory.Type.REFERENCE);
i = 0;
for (Memory memory : memoryConstants) {
expressionCompiler.writePushDup();
expressionCompiler.writePushSmallInt(i);
expressionCompiler.writePushMemory(memory);
expressionCompiler.writePopBoxing(true, false);
node.instructions.add(new InsnNode(AASTORE));
expressionCompiler.stackPop();
expressionCompiler.stackPop();
i++;
}
expressionCompiler.writePutStatic("$MEM", Memory[].class);
// memory array constants
expressionCompiler.writePushSmallInt(memoryArrayConstants.size());
node.instructions.add(new TypeInsnNode(ANEWARRAY, Type.getInternalName(Memory[].class)));
expressionCompiler.stackPush(Memory.Type.REFERENCE);
i = 0;
for (Collection<Memory> memories : memoryArrayConstants) {
expressionCompiler.writePushDup();
expressionCompiler.writePushSmallInt(i);
expressionCompiler.writePushParameters(memories);
node.instructions.add(new InsnNode(AASTORE));
expressionCompiler.stackPop();
expressionCompiler.stackPop();
i++;
}
expressionCompiler.writePutStatic("$AMEM", Memory[][].class);
// cached calls
expressionCompiler.writePushNewObject(FunctionCallCache.class);
expressionCompiler.writePutStatic("$CALL_FUNC_CACHE", FunctionCallCache.class);
expressionCompiler.writePushNewObject(MethodCallCache.class);
expressionCompiler.writePutStatic("$CALL_METH_CACHE", MethodCallCache.class);
expressionCompiler.writePushNewObject(ConstantCallCache.class);
expressionCompiler.writePutStatic("$CALL_CONST_CACHE", ConstantCallCache.class);
expressionCompiler.writePushNewObject(PropertyCallCache.class);
expressionCompiler.writePutStatic("$CALL_PROP_CACHE", PropertyCallCache.class);
node.instructions.add(new InsnNode(RETURN));
methodCompiler.writeFooter();
this.node.methods.add(node);
}
use of org.develnext.jphp.core.compiler.jvm.node.MethodNodeImpl in project jphp by jphp-compiler.
the class ClassStmtCompiler method writeInitEnvironment.
@SuppressWarnings("unchecked")
protected void writeInitEnvironment() {
if (!dynamicConstants.isEmpty() || !dynamicProperties.isEmpty()) {
initDynamicExists = true;
MethodNode node = new MethodNodeImpl();
node.access = ACC_STATIC + ACC_PUBLIC;
node.name = "__$initEnvironment";
node.desc = Type.getMethodDescriptor(Type.getType(void.class), Type.getType(Environment.class));
if (entity.isTrait()) {
node.desc = Type.getMethodDescriptor(Type.getType(void.class), Type.getType(Environment.class), Type.getType(String.class));
}
MethodStmtCompiler methodCompiler = new MethodStmtCompiler(this, node);
ExpressionStmtCompiler expressionCompiler = new ExpressionStmtCompiler(methodCompiler, null);
methodCompiler.writeHeader();
LabelNode l0 = expressionCompiler.makeLabel();
methodCompiler.addLocalVariable("~env", l0, Environment.class);
if (entity.isTrait())
methodCompiler.addLocalVariable("~class_name", l0, String.class);
LocalVariable l_class = methodCompiler.addLocalVariable("~class", l0, ClassEntity.class);
expressionCompiler.writePushEnv();
if (entity.isTrait()) {
expressionCompiler.writeVarLoad("~class_name");
expressionCompiler.writePushDupLowerCase();
} else {
expressionCompiler.writePushConstString(entity.getName());
expressionCompiler.writePushConstString(entity.getLowerName());
}
expressionCompiler.writePushConstBoolean(true);
expressionCompiler.writeSysDynamicCall(Environment.class, "fetchClass", ClassEntity.class, String.class, String.class, Boolean.TYPE);
expressionCompiler.writeVarStore(l_class, false, false);
// corrects defination of constants
final List<ConstStmtToken.Item> first = new ArrayList<ConstStmtToken.Item>();
final Set<String> usedNames = new HashSet<String>();
final List<ConstStmtToken.Item> other = new ArrayList<ConstStmtToken.Item>();
for (ConstStmtToken.Item el : dynamicConstants) {
Token tk = el.value.getSingle();
if (tk instanceof StaticAccessExprToken) {
StaticAccessExprToken access = (StaticAccessExprToken) tk;
boolean self = false;
if (access.getClazz() instanceof SelfExprToken)
self = true;
else if (access.getClazz() instanceof FulledNameToken && ((FulledNameToken) access.getClazz()).getName().equalsIgnoreCase(entity.getName())) {
self = true;
}
if (self) {
String name = ((NameToken) access.getField()).getName();
if (usedNames.contains(el.getFulledName()))
first.add(0, el);
else
first.add(el);
usedNames.add(name);
continue;
}
}
if (usedNames.contains(el.getFulledName()))
first.add(0, el);
else
other.add(el);
}
other.addAll(0, first);
for (ConstStmtToken.Item el : other) {
expressionCompiler.writeVarLoad(l_class);
expressionCompiler.writePushEnv();
expressionCompiler.writePushConstString(el.getFulledName());
expressionCompiler.writeExpression(el.value, true, false, true);
expressionCompiler.writePopBoxing(true);
expressionCompiler.writeSysDynamicCall(ClassEntity.class, "addDynamicConstant", void.class, Environment.class, String.class, Memory.class);
}
for (ClassVarStmtToken el : dynamicProperties) {
expressionCompiler.writeVarLoad(l_class);
expressionCompiler.writePushEnv();
expressionCompiler.writePushConstString(el.getVariable().getName());
expressionCompiler.writeExpression(el.getValue(), true, false, true);
expressionCompiler.writePopBoxing(true);
expressionCompiler.writeSysDynamicCall(ClassEntity.class, el.isStatic() ? "addDynamicStaticProperty" : "addDynamicProperty", void.class, Environment.class, String.class, Memory.class);
}
node.instructions.add(new InsnNode(RETURN));
methodCompiler.writeFooter();
this.node.methods.add(node);
}
}
use of org.develnext.jphp.core.compiler.jvm.node.MethodNodeImpl in project jphp by jphp-compiler.
the class ClassStmtCompiler method writeConstructor.
@SuppressWarnings("unchecked")
protected void writeConstructor() {
MethodNode constructor = new MethodNodeImpl();
constructor.name = Constants.INIT_METHOD;
constructor.access = ACC_PUBLIC;
constructor.exceptions = new ArrayList();
MethodStmtCompiler methodCompiler = new MethodStmtCompiler(this, constructor);
ExpressionStmtCompiler expressionCompiler = new ExpressionStmtCompiler(methodCompiler, null);
methodCompiler.writeHeader();
LabelNode l0 = writeLabel(constructor, statement.getMeta().getStartLine());
methodCompiler.addLocalVariable("~this", l0);
if (isClosure() || generatorEntity != null) {
constructor.desc = Type.getMethodDescriptor(Type.getType(void.class), Type.getType(Environment.class), Type.getType(ClassEntity.class), Type.getType(Memory.class), Type.getType(Memory[].class));
if (isClosure()) {
constructor.desc = Type.getMethodDescriptor(Type.getType(void.class), Type.getType(Environment.class), Type.getType(ClassEntity.class), Type.getType(Memory.class), Type.getType(String.class), Type.getType(Memory[].class));
}
methodCompiler.addLocalVariable("~env", l0, Environment.class);
methodCompiler.addLocalVariable("~class", l0, ClassEntity.class);
methodCompiler.addLocalVariable("~self", l0, Memory.class);
if (isClosure()) {
methodCompiler.addLocalVariable("~context", l0, String.class);
}
methodCompiler.addLocalVariable("~uses", l0, Memory[].class);
methodCompiler.writeHeader();
expressionCompiler.writeVarLoad("~this");
expressionCompiler.writeVarLoad("~env");
expressionCompiler.writeVarLoad("~class");
expressionCompiler.writeVarLoad("~self");
if (isClosure()) {
expressionCompiler.writeVarLoad("~context");
}
expressionCompiler.writeVarLoad("~uses");
constructor.instructions.add(new MethodInsnNode(INVOKESPECIAL, node.superName, Constants.INIT_METHOD, constructor.desc, false));
} else {
constructor.desc = Type.getMethodDescriptor(Type.getType(void.class), Type.getType(Environment.class), Type.getType(ClassEntity.class));
methodCompiler.addLocalVariable("~env", l0, Environment.class);
methodCompiler.addLocalVariable("~class", l0, String.class);
expressionCompiler.writeVarLoad("~this");
expressionCompiler.writeVarLoad("~env");
expressionCompiler.writeVarLoad("~class");
constructor.instructions.add(new MethodInsnNode(INVOKESPECIAL, node.superName, Constants.INIT_METHOD, constructor.desc, false));
// PROPERTIES
for (ClassVarStmtToken property : statement.getProperties()) {
ExpressionStmtCompiler expressionStmtCompiler = new ExpressionStmtCompiler(methodCompiler, null);
Memory value = Memory.NULL;
if (property.getValue() != null)
value = expressionStmtCompiler.writeExpression(property.getValue(), true, true, false);
PropertyEntity prop = new PropertyEntity(compiler.getContext());
prop.setName(property.getVariable().getName());
prop.setModifier(property.getModifier());
prop.setStatic(property.isStatic());
prop.setDefaultValue(value);
prop.setDefault(property.getValue() != null);
prop.setTrace(property.toTraceInfo(compiler.getContext()));
if (property.getDocComment() != null) {
prop.setDocComment(new DocumentComment(property.getDocComment().getComment()));
}
ClassEntity.PropertyResult result = entity.addProperty(prop);
result.check(compiler.getEnvironment());
if (value == null && property.getValue() != null) {
if (property.getValue().isSingle() && ValueExprToken.isConstable(property.getValue().getSingle(), true))
dynamicProperties.add(property);
else
compiler.getEnvironment().error(property.getVariable().toTraceInfo(compiler.getContext()), ErrorType.E_COMPILE_ERROR, Messages.ERR_EXPECTED_CONST_VALUE.fetch(entity.getName() + "::$" + property.getVariable().getName()));
}
}
}
methodCompiler.writeFooter();
constructor.instructions.add(new InsnNode(RETURN));
node.methods.add(constructor);
}
Aggregations