use of org.codehaus.groovy.ast.expr.VariableExpression in project groovy by apache.
the class Verifier method addGroovyObjectInterfaceAndMethods.
protected void addGroovyObjectInterfaceAndMethods(ClassNode node, final String classInternalName) {
if (!node.isDerivedFromGroovyObject())
node.addInterface(ClassHelper.make(GroovyObject.class));
FieldNode metaClassField = getMetaClassField(node);
if (!node.hasMethod("getMetaClass", Parameter.EMPTY_ARRAY)) {
metaClassField = setMetaClassFieldIfNotExists(node, metaClassField);
addMethod(node, !isAbstract(node.getModifiers()), "getMetaClass", ACC_PUBLIC, ClassHelper.METACLASS_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, new BytecodeSequence(new BytecodeInstruction() {
public void visit(MethodVisitor mv) {
Label nullLabel = new Label();
/**
* the code is:
* if (this.metaClass==null) {
* this.metaClass = this.$getStaticMetaClass
* return this.metaClass
* } else {
* return this.metaClass
* }
* with the optimization that the result of the
* first this.metaClass is duped on the operand
* stack and reused for the return in the else part
*/
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
mv.visitInsn(DUP);
mv.visitJumpInsn(IFNULL, nullLabel);
mv.visitInsn(ARETURN);
mv.visitLabel(nullLabel);
mv.visitInsn(POP);
mv.visitVarInsn(ALOAD, 0);
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "$getStaticMetaClass", "()Lgroovy/lang/MetaClass;", false);
mv.visitFieldInsn(PUTFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
mv.visitInsn(ARETURN);
}
}));
}
Parameter[] parameters = new Parameter[] { new Parameter(ClassHelper.METACLASS_TYPE, "mc") };
if (!node.hasMethod("setMetaClass", parameters)) {
metaClassField = setMetaClassFieldIfNotExists(node, metaClassField);
Statement setMetaClassCode;
if (isFinal(metaClassField.getModifiers())) {
ConstantExpression text = new ConstantExpression("cannot set read-only meta class");
ConstructorCallExpression cce = new ConstructorCallExpression(ClassHelper.make(IllegalArgumentException.class), text);
setMetaClassCode = new ExpressionStatement(cce);
} else {
List list = new ArrayList();
list.add(new BytecodeInstruction() {
public void visit(MethodVisitor mv) {
/**
* the code is (meta class is stored in 1):
* this.metaClass = <1>
*/
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitFieldInsn(PUTFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
mv.visitInsn(RETURN);
}
});
setMetaClassCode = new BytecodeSequence(list);
}
addMethod(node, !isAbstract(node.getModifiers()), "setMetaClass", ACC_PUBLIC, ClassHelper.VOID_TYPE, SET_METACLASS_PARAMS, ClassNode.EMPTY_ARRAY, setMetaClassCode);
}
if (!node.hasMethod("invokeMethod", INVOKE_METHOD_PARAMS)) {
VariableExpression vMethods = new VariableExpression("method");
VariableExpression vArguments = new VariableExpression("arguments");
VariableScope blockScope = new VariableScope();
blockScope.putReferencedLocalVariable(vMethods);
blockScope.putReferencedLocalVariable(vArguments);
addMethod(node, !isAbstract(node.getModifiers()), "invokeMethod", ACC_PUBLIC, ClassHelper.OBJECT_TYPE, INVOKE_METHOD_PARAMS, ClassNode.EMPTY_ARRAY, new BytecodeSequence(new BytecodeInstruction() {
public void visit(MethodVisitor mv) {
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "getMetaClass", "()Lgroovy/lang/MetaClass;", false);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEINTERFACE, "groovy/lang/MetaClass", "invokeMethod", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;", true);
mv.visitInsn(ARETURN);
}
}));
}
if (!node.hasMethod("getProperty", GET_PROPERTY_PARAMS)) {
addMethod(node, !isAbstract(node.getModifiers()), "getProperty", ACC_PUBLIC, ClassHelper.OBJECT_TYPE, GET_PROPERTY_PARAMS, ClassNode.EMPTY_ARRAY, new BytecodeSequence(new BytecodeInstruction() {
public void visit(MethodVisitor mv) {
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "getMetaClass", "()Lgroovy/lang/MetaClass;", false);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEINTERFACE, "groovy/lang/MetaClass", "getProperty", "(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;", true);
mv.visitInsn(ARETURN);
}
}));
}
if (!node.hasMethod("setProperty", SET_PROPERTY_PARAMS)) {
addMethod(node, !isAbstract(node.getModifiers()), "setProperty", ACC_PUBLIC, ClassHelper.VOID_TYPE, SET_PROPERTY_PARAMS, ClassNode.EMPTY_ARRAY, new BytecodeSequence(new BytecodeInstruction() {
public void visit(MethodVisitor mv) {
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "getMetaClass", "()Lgroovy/lang/MetaClass;", false);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEINTERFACE, "groovy/lang/MetaClass", "setProperty", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V", true);
mv.visitInsn(RETURN);
}
}));
}
}
use of org.codehaus.groovy.ast.expr.VariableExpression in project groovy by apache.
the class Verifier method addDefaultParameters.
protected void addDefaultParameters(DefaultArgsAction action, MethodNode method) {
Parameter[] parameters = method.getParameters();
int counter = 0;
List paramValues = new ArrayList();
int size = parameters.length;
for (int i = size - 1; i >= 0; i--) {
Parameter parameter = parameters[i];
if (parameter != null && parameter.hasInitialExpression()) {
paramValues.add(i);
paramValues.add(new CastExpression(parameter.getType(), parameter.getInitialExpression()));
counter++;
}
}
for (int j = 1; j <= counter; j++) {
Parameter[] newParams = new Parameter[parameters.length - j];
ArgumentListExpression arguments = new ArgumentListExpression();
int index = 0;
int k = 1;
for (Parameter parameter : parameters) {
if (parameter == null) {
throw new GroovyBugError("Parameter should not be null for method " + methodNode.getName());
} else {
if (k > counter - j && parameter.hasInitialExpression()) {
arguments.addExpression(new CastExpression(parameter.getType(), parameter.getInitialExpression()));
k++;
} else if (parameter.hasInitialExpression()) {
newParams[index++] = parameter;
arguments.addExpression(new CastExpression(parameter.getType(), new VariableExpression(parameter.getName())));
k++;
} else {
newParams[index++] = parameter;
arguments.addExpression(new CastExpression(parameter.getType(), new VariableExpression(parameter.getName())));
}
}
}
action.call(arguments, newParams, method);
}
for (Parameter parameter : parameters) {
// remove default expression and store it as node metadata
parameter.putNodeMetaData(Verifier.INITIAL_EXPRESSION, parameter.getInitialExpression());
parameter.setInitialExpression(null);
}
}
use of org.codehaus.groovy.ast.expr.VariableExpression in project groovy by apache.
the class ClassCompletionVerifier method checkFinalFieldAccess.
private void checkFinalFieldAccess(Expression expression) {
if (!(expression instanceof VariableExpression) && !(expression instanceof PropertyExpression))
return;
Variable v = null;
if (expression instanceof VariableExpression) {
VariableExpression ve = (VariableExpression) expression;
v = ve.getAccessedVariable();
} else {
PropertyExpression propExp = ((PropertyExpression) expression);
Expression objectExpression = propExp.getObjectExpression();
if (objectExpression instanceof VariableExpression) {
VariableExpression varExp = (VariableExpression) objectExpression;
if (varExp.isThisExpression()) {
v = currentClass.getDeclaredField(propExp.getPropertyAsString());
}
}
}
if (v instanceof FieldNode) {
FieldNode fn = (FieldNode) v;
/*
* if it is static final but not accessed inside a static constructor, or,
* if it is an instance final but not accessed inside a instance constructor, it is an error
*/
boolean isFinal = fn.isFinal();
boolean isStatic = fn.isStatic();
boolean error = isFinal && ((isStatic && !inStaticConstructor) || (!isStatic && !inConstructor));
if (error)
addError("cannot modify" + (isStatic ? " static" : "") + " final field '" + fn.getName() + "' outside of " + (isStatic ? "static initialization block." : "constructor."), expression);
}
}
use of org.codehaus.groovy.ast.expr.VariableExpression in project groovy by apache.
the class BinaryExpressionHelper method evaluateEqual.
public void evaluateEqual(BinaryExpression expression, boolean defineVariable) {
AsmClassGenerator acg = controller.getAcg();
CompileStack compileStack = controller.getCompileStack();
OperandStack operandStack = controller.getOperandStack();
Expression rightExpression = expression.getRightExpression();
Expression leftExpression = expression.getLeftExpression();
ClassNode lhsType = controller.getTypeChooser().resolveType(leftExpression, controller.getClassNode());
if (defineVariable && rightExpression instanceof EmptyExpression && !(leftExpression instanceof TupleExpression)) {
VariableExpression ve = (VariableExpression) leftExpression;
BytecodeVariable var = compileStack.defineVariable(ve, controller.getTypeChooser().resolveType(ve, controller.getClassNode()), false);
operandStack.loadOrStoreVariable(var, false);
return;
}
// let's evaluate the RHS and store the result
ClassNode rhsType;
if (rightExpression instanceof ListExpression && lhsType.isArray()) {
ListExpression list = (ListExpression) rightExpression;
ArrayExpression array = new ArrayExpression(lhsType.getComponentType(), list.getExpressions());
array.setSourcePosition(list);
array.visit(acg);
} else if (rightExpression instanceof EmptyExpression) {
rhsType = leftExpression.getType();
loadInitValue(rhsType);
} else {
rightExpression.visit(acg);
}
rhsType = operandStack.getTopOperand();
boolean directAssignment = defineVariable && !(leftExpression instanceof TupleExpression);
int rhsValueId;
if (directAssignment) {
VariableExpression var = (VariableExpression) leftExpression;
if (var.isClosureSharedVariable() && ClassHelper.isPrimitiveType(rhsType)) {
// GROOVY-5570: if a closure shared variable is a primitive type, it must be boxed
rhsType = ClassHelper.getWrapper(rhsType);
operandStack.box();
}
// form as it is closure shared
if (var.isClosureSharedVariable() && ClassHelper.isPrimitiveType(var.getOriginType()) && isNull(rightExpression)) {
operandStack.doGroovyCast(var.getOriginType());
// these two are never reached in bytecode and only there
// to avoid verifyerrors and compiler infrastructure hazzle
operandStack.box();
operandStack.doGroovyCast(lhsType);
}
// normal type transformation
if (!ClassHelper.isPrimitiveType(lhsType) && isNull(rightExpression)) {
operandStack.replace(lhsType);
} else {
operandStack.doGroovyCast(lhsType);
}
rhsType = lhsType;
rhsValueId = compileStack.defineVariable(var, lhsType, true).getIndex();
} else {
rhsValueId = compileStack.defineTemporaryVariable("$rhs", rhsType, true);
}
//TODO: if rhs is VariableSlotLoader already, then skip crating a new one
BytecodeExpression rhsValueLoader = new VariableSlotLoader(rhsType, rhsValueId, operandStack);
// assignment for subscript
if (leftExpression instanceof BinaryExpression) {
BinaryExpression leftBinExpr = (BinaryExpression) leftExpression;
if (leftBinExpr.getOperation().getType() == Types.LEFT_SQUARE_BRACKET) {
assignToArray(expression, leftBinExpr.getLeftExpression(), leftBinExpr.getRightExpression(), rhsValueLoader);
}
compileStack.removeVar(rhsValueId);
return;
}
compileStack.pushLHS(true);
// multiple declaration
if (leftExpression instanceof TupleExpression) {
TupleExpression tuple = (TupleExpression) leftExpression;
int i = 0;
for (Expression e : tuple.getExpressions()) {
VariableExpression var = (VariableExpression) e;
MethodCallExpression call = new MethodCallExpression(rhsValueLoader, "getAt", new ArgumentListExpression(new ConstantExpression(i)));
call.visit(acg);
i++;
if (defineVariable) {
operandStack.doGroovyCast(var);
compileStack.defineVariable(var, true);
operandStack.remove(1);
} else {
acg.visitVariableExpression(var);
}
}
} else // single declaration
if (defineVariable) {
rhsValueLoader.visit(acg);
operandStack.remove(1);
compileStack.popLHS();
return;
} else // normal assignment
{
int mark = operandStack.getStackLength();
// to leave a copy of the rightExpression value on the stack after the assignment.
rhsValueLoader.visit(acg);
TypeChooser typeChooser = controller.getTypeChooser();
ClassNode targetType = typeChooser.resolveType(leftExpression, controller.getClassNode());
operandStack.doGroovyCast(targetType);
leftExpression.visit(acg);
operandStack.remove(operandStack.getStackLength() - mark);
}
compileStack.popLHS();
// return value of assignment
rhsValueLoader.visit(acg);
compileStack.removeVar(rhsValueId);
}
use of org.codehaus.groovy.ast.expr.VariableExpression in project groovy by apache.
the class FinalVariableAnalyzer method visitBinaryExpression.
@Override
public void visitBinaryExpression(final BinaryExpression expression) {
boolean assignment = StaticTypeCheckingSupport.isAssignment(expression.getOperation().getType());
boolean isDeclaration = expression instanceof DeclarationExpression;
Expression leftExpression = expression.getLeftExpression();
Expression rightExpression = expression.getRightExpression();
if (isDeclaration && leftExpression instanceof VariableExpression) {
VariableExpression var = (VariableExpression) leftExpression;
if (Modifier.isFinal(var.getModifiers())) {
declaredFinalVariables.add(var);
}
}
leftExpression.visit(this);
inAssignment = assignment;
rightExpression.visit(this);
inAssignment = false;
if (assignment) {
if (leftExpression instanceof Variable) {
boolean uninitialized = isDeclaration && rightExpression == EmptyExpression.INSTANCE;
recordAssignment((Variable) leftExpression, isDeclaration, uninitialized, false, expression);
} else if (leftExpression instanceof TupleExpression) {
TupleExpression te = (TupleExpression) leftExpression;
for (Expression next : te.getExpressions()) {
if (next instanceof Variable) {
recordAssignment((Variable) next, isDeclaration, false, false, next);
}
}
}
}
}
Aggregations