this.visitedList.clear( );
	AggregateExpression compileAggregateExpr( Context context, Node parent,			Node callNode ) throws DataException	{		assert ( callNode.getType( ) == Token.CALL );		IAggregation aggregation = getAggregationFunction( callNode );		// not an aggregation function being called, then it's considered		// a complex expression		if ( aggregation == null )		{			return null;		}		passLevel = 0;		AggregateExpression aggregateExpression = new AggregateExpression( aggregation );		AggregateObject aggregateObj = new AggregateObject( aggregateExpression );		this.hasAggregate = true;		extractArguments( context, aggregateExpression, callNode );		Iterator iter = aggregateExpression.getArguments( ).iterator( );		while ( iter.hasNext( ) )		{			CompiledExpression argumentExpr = (CompiledExpression) iter.next( );			// the argument contains the nested aggregate expression			if ( argumentExpr instanceof AggregateExpression )			{				if ( canBeCalculated( new AggregateObject( (AggregateExpression) argumentExpr ) ) )					passLevel--;				hasNesetedAggregate = true;				// throw new DataException(				// ResourceConstants.UNSUPPORTED_DIRECT_NESTED_AGGREGATE );			}			else if ( argumentExpr instanceof ComplexExpression )			{				flatternAggregateExpression( (ComplexExpression) argumentExpr );			}		}		// get the aggregate current group level		currentGroupLevel = getCurrentGroupLevel( aggregateObj, context );		if ( exprType == IExpressionProcessor.GROUP_COLUMN_EXPR				|| exprType == IExpressionProcessor.FILTER_ON_GROUP_EXPR				|| exprType == IExpressionProcessor.SORT_ON_GROUP_EXPR )		{			aggregateObj.setPassLevel( 1 );		}		else			aggregateObj.setPassLevel( ++passLevel );		int id = registerAggregate( aggregateObj );		if ( id >= 0 )			replaceAggregateNode( id, parent, callNode );		setTotalPassLevel( passLevel );		return aggregateExpression;	}