Package org.formulacompiler.compiler.internal.model.optimizer.consteval

Source Code of org.formulacompiler.compiler.internal.model.optimizer.consteval.EvalShadow

/*
* Copyright (c) 2006-2009 by Abacus Research AG, Switzerland.
* All rights reserved.
*
* This file is part of the Abacus Formula Compiler (AFC).
*
* For commercial licensing, please contact sales(at)formulacompiler.com.
*
* AFC is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AFC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AFC.  If not, see <http://www.gnu.org/licenses/>.
*/

package org.formulacompiler.compiler.internal.model.optimizer.consteval;

import org.formulacompiler.compiler.CompilerException;
import org.formulacompiler.compiler.internal.Settings;
import org.formulacompiler.compiler.internal.expressions.DataType;
import org.formulacompiler.compiler.internal.expressions.ExpressionNode;
import org.formulacompiler.compiler.internal.expressions.ExpressionNodeForConstantValue;
import org.formulacompiler.compiler.internal.expressions.ExpressionNodeShadow;
import org.formulacompiler.compiler.internal.expressions.LetDictionary;
import org.formulacompiler.compiler.internal.expressions.TypedResult;
import org.formulacompiler.compiler.internal.logging.Log;
import org.formulacompiler.compiler.internal.model.ExpressionNodeForSubSectionModel;
import org.formulacompiler.compiler.internal.model.interpreter.InterpretedNumericType;
import org.formulacompiler.compiler.internal.model.interpreter.InterpreterException;
import org.formulacompiler.runtime.ComputationException;


public abstract class EvalShadow extends ExpressionNodeShadow
{
  public static final Log LOG = Settings.LOG_CONSTEVAL;


  public static TypedResult evaluate( ExpressionNode _expr, InterpretedNumericType _type ) throws CompilerException
  {
    EvalShadow shadow = shadow( _expr, _type );
    return shadow.evalIn( new EvalShadowContext() );
  }

  protected static EvalShadow shadow( ExpressionNode _expr, InterpretedNumericType _type )
  {
    return (EvalShadow) ExpressionNodeShadow.shadow( _expr, new EvalShadowBuilder( _type ) );
  }


  private final InterpretedNumericType type;

  EvalShadow( ExpressionNode _node, InterpretedNumericType _type )
  {
    super( _node );
    this.type = _type;
  }

  public final InterpretedNumericType type()
  {
    return this.type;
  }


  private EvalShadowContext context;

  protected final TypedResult evalIn( EvalShadowContext _context ) throws CompilerException
  {
    this.context = _context;

    if (LOG.e()) LOG.a( "Eval " ).a( node() ).lf().i();

    final TypedResult res = eval();

    if (LOG.e()) LOG.o().a( "Got " ).a( res ).lf();

    return res;
  }

  protected final EvalShadowContext context()
  {
    return this.context;
  }

  protected final LetDictionary letDict()
  {
    return this.context.letDict;
  }


  protected TypedResult eval() throws CompilerException
  {
    final TypedResult[] argValues = evaluateArguments();
    return evaluateToConstOrExprWithConstantArgsFixed( argValues );
  }


  protected final int cardinality()
  {
    int result = arguments().size();
    while ((result > 0) && (arguments().get( result - 1 ) == null)) {
      result--;
    }
    return result;
  }


  protected final EvalShadow unsubstitutedArgument( int _index )
  {
    return ((EvalShadow) arguments().get( _index )).unsubstituted();
  }

  protected EvalShadow unsubstituted()
  {
    return this;
  }


  private final TypedResult[] evaluateArguments() throws CompilerException
  {
    final int card = cardinality();
    final TypedResult[] argValues = new TypedResult[ card ];
    for (int iArg = 0; iArg < card; iArg++) {
      argValues[ iArg ] = evaluateArgument( iArg );
    }
    return argValues;
  }


  protected final TypedResult evaluateArgument( int _index ) throws CompilerException
  {
    return evaluateArgument( (EvalShadow) arguments().get( _index ) );
  }

  protected final TypedResult evaluateArgument( EvalShadow _arg ) throws CompilerException
  {
    return (_arg == null) ? null : _arg.evalIn( context() );
  }

  protected final TypedResult evaluateArgument( int _index, EvalShadowContext _context ) throws CompilerException
  {
    this.context = _context;
    return evaluateArgument( _index );
  }


  protected TypedResult evaluateToConstOrExprWithConstantArgsFixed( TypedResult... _args ) throws CompilerException
  {
    if (areConstant( _args )) {
      try {
        final TypedResult constResult = evaluateToConst( _args );
        assert null != constResult;
        if (constResult.hasConstantValue()) {
          final Object constValue = constResult.getConstantValue();
          if (constValue instanceof Double) {
            final Double doubleResult = (Double) constValue;
            if (doubleResult.isInfinite() || doubleResult.isNaN()) {
              return evaluateToNode( _args );
            }
          }
        }
        return constResult;
      }
      catch (InterpreterException.IsRuntimeEnvironmentDependent e) {
        return evaluateToNode( _args );
      }
      catch (ArithmeticException e) {
        return evaluateToNode( _args );
      }
      catch (ComputationException e) {
        return evaluateToNode( _args );
      }
    }
    else {
      return evaluateToNode( _args );
    }
  }


  protected final boolean areConstant( TypedResult[] _args )
  {
    for (TypedResult arg : _args)
      if (null != arg && !arg.isConstant()) return false;
    return true;
  }


  protected final boolean isInSubSection( TypedResult _arg )
  {
    return (_arg instanceof ExpressionNodeForSubSectionModel);
  }

  @SuppressWarnings( "unused" )
  protected TypedResult evaluateToNode( TypedResult... _args ) throws InterpreterException
  {
    // No need to clone leaf nodes.
    if (_args.length == 0) return node();

    ExpressionNode result = node().cloneWithoutArguments();
    for (final TypedResult arg : _args) {
      result.addArgument( valueToNode( arg ) );
    }
    return result;
  }

  protected abstract TypedResult evaluateToConst( TypedResult... _args ) throws CompilerException;


  protected final ExpressionNode valueToNode( TypedResult _value )
  {
    if (null == _value) {
      return new ExpressionNodeForConstantValue( null, DataType.NULL );
    }
    if (_value instanceof ExpressionNode) {
      return (ExpressionNode) _value;
    }
    return new ExpressionNodeForConstantValue( _value.getConstantValue(), _value.getDataType() );
  }

  protected final Object[] valuesOf( TypedResult... _values )
  {
    final Object[] vals = new Object[ _values.length ];
    for (int i = 0; i < _values.length; i++) {
      final TypedResult val = _values[ i ];
      vals[ i ] = (null == val) ? null : val.getConstantValue();
    }
    return vals;
  }

}
TOP

Related Classes of org.formulacompiler.compiler.internal.model.optimizer.consteval.EvalShadow

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.