use of org.codehaus.groovy.ast.expr.Expression in project groovy-core by groovy.
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.Expression in project groovy-core by groovy.
the class BinaryExpressionMultiTypeDispatcher method evaluateBinaryExpression.
@Override
protected void evaluateBinaryExpression(final String message, BinaryExpression binExp) {
int operation = removeAssignment(binExp.getOperation().getType());
ClassNode current = getController().getClassNode();
Expression leftExp = binExp.getLeftExpression();
ClassNode leftTypeOrig = getController().getTypeChooser().resolveType(leftExp, current);
ClassNode leftType = leftTypeOrig;
Expression rightExp = binExp.getRightExpression();
ClassNode rightType = getController().getTypeChooser().resolveType(rightExp, current);
AsmClassGenerator acg = getController().getAcg();
OperandStack os = getController().getOperandStack();
if (operation == LEFT_SQUARE_BRACKET) {
leftType = leftTypeOrig.getComponentType();
int operationType = getOperandType(leftType);
BinaryExpressionWriter bew = binExpWriter[operationType];
if (leftTypeOrig.isArray() && isIntCastableType(rightExp) && bew.arrayGet(operation, true)) {
leftExp.visit(acg);
os.doGroovyCast(leftTypeOrig);
rightExp.visit(acg);
os.doGroovyCast(int_TYPE);
bew.arrayGet(operation, false);
os.replace(bew.getArrayGetResultType(), 2);
} else {
super.evaluateBinaryExpression(message, binExp);
}
} else if (operation == DIVIDE) {
int operationType = getOperandType(getController().getTypeChooser().resolveType(binExp, current));
BinaryExpressionWriter bew = binExpWriter[operationType];
if (bew.writeDivision(true)) {
leftExp.visit(acg);
os.doGroovyCast(bew.getDevisionOpResultType());
rightExp.visit(acg);
os.doGroovyCast(bew.getDevisionOpResultType());
bew.writeDivision(false);
} else {
super.evaluateBinaryExpression(message, binExp);
}
} else {
int operationType = getOperandConversionType(leftType, rightType);
BinaryExpressionWriter bew = binExpWriter[operationType];
if (isShiftOperation(operation) && isIntCastableType(rightExp) && bew.write(operation, true)) {
leftExp.visit(acg);
os.doGroovyCast(bew.getNormalOpResultType());
rightExp.visit(acg);
os.doGroovyCast(int_TYPE);
bew.write(operation, false);
} else if (bew.write(operation, true)) {
leftExp.visit(acg);
os.doGroovyCast(bew.getNormalOpResultType());
rightExp.visit(acg);
os.doGroovyCast(bew.getNormalOpResultType());
bew.write(operation, false);
} else {
super.evaluateBinaryExpression(message, binExp);
}
}
}
use of org.codehaus.groovy.ast.expr.Expression in project groovy-core by groovy.
the class BinaryExpressionMultiTypeDispatcher method isAssignmentToArray.
private boolean isAssignmentToArray(BinaryExpression binExp) {
Expression leftExpression = binExp.getLeftExpression();
if (!(leftExpression instanceof BinaryExpression))
return false;
BinaryExpression leftBinExpr = (BinaryExpression) leftExpression;
if (leftBinExpr.getOperation().getType() != LEFT_SQUARE_BRACKET)
return false;
return true;
}
use of org.codehaus.groovy.ast.expr.Expression in project groovy-core by groovy.
the class BinaryExpressionMultiTypeDispatcher method evaluateCompareExpression.
@Override
protected void evaluateCompareExpression(final MethodCaller compareMethod, BinaryExpression binExp) {
ClassNode current = getController().getClassNode();
TypeChooser typeChooser = getController().getTypeChooser();
int operation = binExp.getOperation().getType();
Expression leftExp = binExp.getLeftExpression();
ClassNode leftType = typeChooser.resolveType(leftExp, current);
Expression rightExp = binExp.getRightExpression();
ClassNode rightType = typeChooser.resolveType(rightExp, current);
if (!doPrimitiveCompare(leftType, rightType, binExp)) {
super.evaluateCompareExpression(compareMethod, binExp);
}
}
use of org.codehaus.groovy.ast.expr.Expression in project groovy-core by groovy.
the class BinaryExpressionMultiTypeDispatcher method doAssignmentToArray.
private boolean doAssignmentToArray(BinaryExpression binExp) {
if (!isAssignmentToArray(binExp))
return false;
// we need to handle only assignment to arrays combined with an operation
// special here. e.g x[a] += b
int operation = removeAssignment(binExp.getOperation().getType());
ClassNode current = getController().getClassNode();
Expression leftExp = binExp.getLeftExpression();
ClassNode leftType = getController().getTypeChooser().resolveType(leftExp, current);
Expression rightExp = binExp.getRightExpression();
ClassNode rightType = getController().getTypeChooser().resolveType(rightExp, current);
int operationType = getOperandType(leftType);
BinaryExpressionWriter bew = binExpWriter[operationType];
boolean simulationSuccess = bew.arrayGet(LEFT_SQUARE_BRACKET, true);
simulationSuccess = simulationSuccess && bew.write(operation, true);
simulationSuccess = simulationSuccess && bew.arraySet(true);
if (!simulationSuccess)
return false;
AsmClassGenerator acg = getController().getAcg();
OperandStack operandStack = getController().getOperandStack();
CompileStack compileStack = getController().getCompileStack();
// for x[a] += b we have the structure:
// x = left(left(binExp))), b = right(binExp), a = right(left(binExp)))
// for array set we need these values on stack: array, index, right
// for array get we need these values on stack: array, index
// to eval the expression we need x[a] = x[a]+b
// -> arraySet(x,a, x[a]+b)
// -> arraySet(x,a, arrayGet(x,a,b))
// --> x,a, x,a, b as operands
// --> load x, load a, DUP2, call arrayGet, load b, call operation,call arraySet
// since we cannot DUP2 here easily we will save the subscript and DUP x
// --> sub=a, load x, DUP, load sub, call arrayGet, load b, call operation, load sub, call arraySet
BinaryExpression arrayWithSubscript = (BinaryExpression) leftExp;
Expression subscript = arrayWithSubscript.getRightExpression();
// load array index: sub=a [load x, DUP, load sub, call arrayGet, load b, call operation, load sub, call arraySet]
subscript.visit(acg);
operandStack.doGroovyCast(int_TYPE);
int subscriptValueId = compileStack.defineTemporaryVariable("$sub", ClassHelper.int_TYPE, true);
// load array: load x and DUP [load sub, call arrayGet, load b, call operation, load sub, call arraySet]
arrayWithSubscript.getLeftExpression().visit(acg);
operandStack.doGroovyCast(leftType.makeArray());
operandStack.dup();
// array get: load sub, call arrayGet [load b, call operation, load sub, call arraySet]
operandStack.load(ClassHelper.int_TYPE, subscriptValueId);
bew.arrayGet(LEFT_SQUARE_BRACKET, false);
operandStack.replace(leftType, 2);
// complete rhs: load b, call operation [load sub, call arraySet]
binExp.getRightExpression().visit(acg);
if (!(bew instanceof BinaryObjectExpressionHelper)) {
// in primopts we convert to the left type for supported binary operations
operandStack.doGroovyCast(leftType);
}
bew.write(operation, false);
// let us save that value for the return
operandStack.dup();
int resultValueId = compileStack.defineTemporaryVariable("$result", rightType, true);
// array set: load sub, call arraySet []
operandStack.load(ClassHelper.int_TYPE, subscriptValueId);
operandStack.swap();
bew.arraySet(false);
// 3 operands, the array, the index and the value!
operandStack.remove(3);
// load return value
operandStack.load(rightType, resultValueId);
// cleanup
compileStack.removeVar(resultValueId);
compileStack.removeVar(subscriptValueId);
return true;
}
Aggregations