aspect ExprExt { syn boolean Expr.isStatementExpression() = false; eq AssignExpr.isStatementExpression() = true; eq PreIncExpr.isStatementExpression() = true; eq PreDecExpr.isStatementExpression() = true; eq PostfixExpr.isStatementExpression() = true; eq MethodAccess.isStatementExpression() = true; eq ClassInstanceExpr.isStatementExpression() = true; eq AbstractDot.isStatementExpression() = getRight().isStatementExpression(); // an expression is inextractible if it cannot be replaced by a variable access syn boolean Expr.inextractible() = notAnObject() || inInextractiblePosition(); // expressions that do not by themselves stand for objects syn boolean Expr.notAnObject() = type().isVoid(); eq AbstractDot.notAnObject() = super.notAnObject() || !isArrayAccess() && !isClassAccess() && getRight().notAnObject(); eq AbstractWildcard.notAnObject() = true; eq ArrayAccess.notAnObject() = true; eq ClassAccess.notAnObject() = true; eq PackageAccess.notAnObject() = true; eq ParTypeAccess.notAnObject() = true; eq SuperAccess.notAnObject() = true; eq TypeAccess.notAnObject() = true; eq CastExpr.notAnObject() = super.notAnObject() || getExpr().notAnObject(); eq ParExpr.notAnObject() = super.notAnObject() || getExpr().notAnObject(); // expressions in positions where they cannot be extracted into an assignment inh boolean Expr.inInextractiblePosition(); eq Program.getChild().inInextractiblePosition() = false; eq ConstructorDecl.getConstructorInvocation().inInextractiblePosition() = true; eq AssignExpr.getChild().inInextractiblePosition() = false; eq PreIncExpr.getChild().inInextractiblePosition() = false; eq PreDecExpr.getChild().inInextractiblePosition() = false; eq PostfixExpr.getChild().inInextractiblePosition() = false; eq AbstractDot.getRight().inInextractiblePosition() = true; eq MethodAccess.getArg().inInextractiblePosition() = false; eq ConstructorAccess.getArg().inInextractiblePosition() = false; eq ArrayAccess.getExpr().inInextractiblePosition() = false; eq ArrayTypeWithSizeAccess.getExpr().inInextractiblePosition() = false; eq ClassInstanceExpr.getArg().inInextractiblePosition() = false; eq ArrayCreationExpr.getArrayInit().inInextractiblePosition() = true; eq VariableDeclaration.getInit().inInextractiblePosition() = false; // an expression is flow invariant if it can be moved arbitrarily within the program (assuming that name bindings are preserved) syn boolean Expr.isFlowInvariant() = isConstant(); eq ArrayCreationExpr.isFlowInvariant() = getTypeAccess().isFlowInvariant() && (!hasArrayInit() || getArrayInit().isFlowInvariant()); eq ArrayInit.isFlowInvariant() { for(Expr e : getInits()) if(!e.isFlowInvariant()) return false; return true; } eq TypeAccess.isFlowInvariant() = true; eq ArrayTypeWithSizeAccess.isFlowInvariant() = getExpr().isConstant(); eq ClassInstanceExpr.isFlowInvariant() = decl().signature().equals("(java.lang.String p0)") || super.isFlowInvariant(); eq MethodAccess.isFlowInvariant() = decl().isPure() || super.isFlowInvariant(); syn Expr Access.enclosingInstanceQualifier(TypeDecl td) = hostType().enclosingInstanceQualifier(td, true); eq ClassInstanceExpr.enclosingInstanceQualifier(TypeDecl td) { if(isQualified()) return qualifier().type().instanceOf(td) ? parentDot().getLeft() : null; return super.enclosingInstanceQualifier(td); } eq SuperConstructorAccess.enclosingInstanceQualifier(TypeDecl td) { if(isQualified()) return qualifier().type().instanceOf(td) ? parentDot().getLeft() : null; return super.enclosingInstanceQualifier(td); } public Expr TypeDecl.enclosingInstanceQualifier(TypeDecl td, boolean innermost) { if(this.instanceOf(td)) { if(innermost) return new ThisAccess(true); else return createLockedAccess().qualifiesAccess(new ThisAccess(true)); } else { return enclosingType() == null ? null : enclosingType().enclosingInstanceQualifier(td, false); } } syn Expr Expr.convertSuperToThis() = this; eq AbstractDot.convertSuperToThis() = new AbstractDot(getLeft().convertSuperToThis(), (Access)getRight().convertSuperToThis()); eq SuperAccess.convertSuperToThis() = new ThisAccess(true); syn Expr Expr.convertThisToSuper() = null; eq AbstractDot.convertThisToSuper() = new AbstractDot((Expr)getLeft().fullCopyAndDetach(), (Access)getRight().convertThisToSuper()); eq Dot.convertThisToSuper() = new Dot((Expr)getLeft().fullCopyAndDetach(), (Access)getRight().convertThisToSuper()); eq ThisAccess.convertThisToSuper() = new SuperAccess(true); public boolean Expr.isArgument() { return getParent() instanceof List && getParent().getParent() instanceof Call; } syn boolean Expr.isParameterType() = false; eq Access.isParameterType() = isTypeAccess() && getParent() instanceof ParameterDeclaration; }