use of org.codehaus.groovy.ast.ClassNode in project groovy-core by groovy.
the class AsmClassGenerator method visitCastExpression.
public void visitCastExpression(CastExpression castExpression) {
ClassNode type = castExpression.getType();
Expression subExpression = castExpression.getExpression();
subExpression.visit(this);
if (ClassHelper.OBJECT_TYPE.equals(type))
return;
if (castExpression.isCoerce()) {
controller.getOperandStack().doAsType(type);
} else {
if (isNullConstant(subExpression) && !ClassHelper.isPrimitiveType(type)) {
controller.getOperandStack().replace(type);
} else {
ClassNode subExprType = controller.getTypeChooser().resolveType(subExpression, controller.getClassNode());
if (castExpression.isStrict() || (!ClassHelper.isPrimitiveType(type) && WideningCategories.implementsInterfaceOrSubclassOf(subExprType, type))) {
BytecodeHelper.doCast(controller.getMethodVisitor(), type);
controller.getOperandStack().replace(type);
} else {
controller.getOperandStack().doGroovyCast(type);
}
}
}
}
use of org.codehaus.groovy.ast.ClassNode in project groovy-core by groovy.
the class AsmClassGenerator method visitArrayExpression.
public void visitArrayExpression(ArrayExpression expression) {
MethodVisitor mv = controller.getMethodVisitor();
ClassNode elementType = expression.getElementType();
String arrayTypeName = BytecodeHelper.getClassInternalName(elementType);
List sizeExpression = expression.getSizeExpression();
int size = 0;
int dimensions = 0;
if (sizeExpression != null) {
for (Iterator iter = sizeExpression.iterator(); iter.hasNext(); ) {
Expression element = (Expression) iter.next();
if (element == ConstantExpression.EMPTY_EXPRESSION)
break;
dimensions++;
// let's convert to an int
element.visit(this);
controller.getOperandStack().doGroovyCast(ClassHelper.int_TYPE);
}
controller.getOperandStack().remove(dimensions);
} else {
size = expression.getExpressions().size();
BytecodeHelper.pushConstant(mv, size);
}
int storeIns = AASTORE;
if (sizeExpression != null) {
arrayTypeName = BytecodeHelper.getTypeDescription(expression.getType());
mv.visitMultiANewArrayInsn(arrayTypeName, dimensions);
} else if (ClassHelper.isPrimitiveType(elementType)) {
int primType = 0;
if (elementType == ClassHelper.boolean_TYPE) {
primType = T_BOOLEAN;
storeIns = BASTORE;
} else if (elementType == ClassHelper.char_TYPE) {
primType = T_CHAR;
storeIns = CASTORE;
} else if (elementType == ClassHelper.float_TYPE) {
primType = T_FLOAT;
storeIns = FASTORE;
} else if (elementType == ClassHelper.double_TYPE) {
primType = T_DOUBLE;
storeIns = DASTORE;
} else if (elementType == ClassHelper.byte_TYPE) {
primType = T_BYTE;
storeIns = BASTORE;
} else if (elementType == ClassHelper.short_TYPE) {
primType = T_SHORT;
storeIns = SASTORE;
} else if (elementType == ClassHelper.int_TYPE) {
primType = T_INT;
storeIns = IASTORE;
} else if (elementType == ClassHelper.long_TYPE) {
primType = T_LONG;
storeIns = LASTORE;
}
mv.visitIntInsn(NEWARRAY, primType);
} else {
mv.visitTypeInsn(ANEWARRAY, arrayTypeName);
}
for (int i = 0; i < size; i++) {
mv.visitInsn(DUP);
BytecodeHelper.pushConstant(mv, i);
Expression elementExpression = expression.getExpression(i);
if (elementExpression == null) {
ConstantExpression.NULL.visit(this);
} else {
elementExpression.visit(this);
controller.getOperandStack().doGroovyCast(elementType);
}
mv.visitInsn(storeIns);
controller.getOperandStack().remove(1);
}
controller.getOperandStack().push(expression.getType());
}
use of org.codehaus.groovy.ast.ClassNode in project groovy-core by groovy.
the class AsmClassGenerator method visitStdMethod.
private void visitStdMethod(MethodNode node, boolean isConstructor, Parameter[] parameters, Statement code) {
MethodVisitor mv = controller.getMethodVisitor();
final ClassNode superClass = controller.getClassNode().getSuperClass();
if (isConstructor && (code == null || !((ConstructorNode) node).firstStatementIsSpecialConstructorCall())) {
boolean hasCallToSuper = false;
if (code != null && controller.getClassNode() instanceof InnerClassNode) {
// so we must ensure not to add it twice (see GROOVY-4471)
if (code instanceof BlockStatement) {
for (Statement statement : ((BlockStatement) code).getStatements()) {
if (statement instanceof ExpressionStatement) {
final Expression expression = ((ExpressionStatement) statement).getExpression();
if (expression instanceof ConstructorCallExpression) {
ConstructorCallExpression call = (ConstructorCallExpression) expression;
if (call.isSuperCall()) {
hasCallToSuper = true;
break;
}
}
}
}
}
}
if (!hasCallToSuper) {
// invokes the super class constructor
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, BytecodeHelper.getClassInternalName(superClass), "<init>", "()V", false);
}
}
controller.getCompileStack().init(node.getVariableScope(), parameters);
controller.getCallSiteWriter().makeSiteEntry();
// handle body
super.visitConstructorOrMethod(node, isConstructor);
controller.getCompileStack().clear();
if (node.isVoidMethod()) {
mv.visitInsn(RETURN);
} else {
// we make a dummy return for label ranges that reach here
ClassNode type = node.getReturnType().redirect();
if (ClassHelper.isPrimitiveType(type)) {
mv.visitLdcInsn(0);
controller.getOperandStack().push(ClassHelper.int_TYPE);
controller.getOperandStack().doGroovyCast(type);
BytecodeHelper.doReturn(mv, type);
controller.getOperandStack().remove(1);
} else {
mv.visitInsn(ACONST_NULL);
BytecodeHelper.doReturn(mv, type);
}
}
}
use of org.codehaus.groovy.ast.ClassNode in project groovy-core by groovy.
the class AsmClassGenerator method getStaticFieldName.
private static String getStaticFieldName(ClassNode type) {
ClassNode componentType = type;
String prefix = "";
for (; componentType.isArray(); componentType = componentType.getComponentType()) {
prefix += "$";
}
if (prefix.length() != 0)
prefix = "array" + prefix;
String name = prefix + "$class$" + makeFieldClassName(componentType);
return name;
}
use of org.codehaus.groovy.ast.ClassNode in project groovy-core by groovy.
the class BinaryExpressionHelper method evaluateElvisOperatorExpression.
private void evaluateElvisOperatorExpression(ElvisOperatorExpression expression) {
MethodVisitor mv = controller.getMethodVisitor();
CompileStack compileStack = controller.getCompileStack();
OperandStack operandStack = controller.getOperandStack();
TypeChooser typeChooser = controller.getTypeChooser();
Expression boolPart = expression.getBooleanExpression().getExpression();
Expression falsePart = expression.getFalseExpression();
ClassNode truePartType = typeChooser.resolveType(boolPart, controller.getClassNode());
ClassNode falsePartType = typeChooser.resolveType(falsePart, controller.getClassNode());
ClassNode common = WideningCategories.lowestUpperBound(truePartType, falsePartType);
// x?:y is equal to x?x:y, which evals to
// var t=x; boolean(t)?t:y
// first we load x, dup it, convert the dupped to boolean, then
// jump depending on the value. For true we are done, for false we
// have to load y, thus we first remove x and then load y.
// But since x and y may have different stack lengths, this cannot work
// Thus we have to have to do the following:
// Be X the type of x, Y the type of y and S the common supertype of
// X and Y, then we have to see x?:y as
// var t=x;boolean(t)?S(t):S(y)
// so we load x, dup it, store the value in a local variable (t), then
// do boolean conversion. In the true part load t and cast it to S,
// in the false part load y and cast y to S
// load x, dup it, store one in $t and cast the remaining one to boolean
int mark = operandStack.getStackLength();
boolPart.visit(controller.getAcg());
operandStack.dup();
if (ClassHelper.isPrimitiveType(truePartType) && !ClassHelper.isPrimitiveType(operandStack.getTopOperand())) {
truePartType = ClassHelper.getWrapper(truePartType);
}
int retValueId = compileStack.defineTemporaryVariable("$t", truePartType, true);
operandStack.castToBool(mark, true);
Label l0 = operandStack.jump(IFEQ);
// true part: load $t and cast to S
operandStack.load(truePartType, retValueId);
operandStack.doGroovyCast(common);
Label l1 = new Label();
mv.visitJumpInsn(GOTO, l1);
// false part: load false expression and cast to S
mv.visitLabel(l0);
falsePart.visit(controller.getAcg());
operandStack.doGroovyCast(common);
// finish and cleanup
mv.visitLabel(l1);
compileStack.removeVar(retValueId);
controller.getOperandStack().replace(common, 2);
}
Aggregations