Package org.formulacompiler.compiler.internal.bytecode

Source Code of org.formulacompiler.compiler.internal.bytecode.HelperCompilerForFoldDatabase

/*
* 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.bytecode;

import java.util.Collection;
import java.util.List;

import org.formulacompiler.compiler.CompilerException;
import org.formulacompiler.compiler.internal.expressions.ArrayDescriptor;
import org.formulacompiler.compiler.internal.expressions.DataType;
import org.formulacompiler.compiler.internal.expressions.ExpressionNode;
import org.formulacompiler.compiler.internal.expressions.ExpressionNodeForArrayReference;
import org.formulacompiler.compiler.internal.expressions.ExpressionNodeForFoldDatabase;
import org.formulacompiler.compiler.internal.expressions.LetDictionary.LetEntry;
import org.formulacompiler.compiler.internal.model.ExpressionNodeForSubSectionModel;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.GeneratorAdapter;

final class HelperCompilerForFoldDatabase extends HelperCompilerForFoldApply
{
  private final ExpressionNodeForFoldDatabase db;
  private final ExpressionNodeForArrayReference table;
  private final ArrayDescriptor tableDescriptor;
  private final String[] colNames;
  private final DataType[] colTypes;
  private final ExpressionNode filterExpr;

  public HelperCompilerForFoldDatabase( SectionCompiler _section, ExpressionNodeForFoldDatabase _applyNode,
      Iterable<LetEntry> _closure )
  {
    super( _section, _applyNode, _closure );
    this.db = _applyNode;
    this.table = _applyNode.table();
    this.tableDescriptor = _applyNode.table().arrayDescriptor();
    this.colNames = _applyNode.filterColumnNames();
    this.colTypes = _applyNode.filterColumnTypes();
    this.filterExpr = _applyNode.filter();
  }

  @Override
  protected boolean argumentsAreVectors()
  {
    return false;
  }


  @Override
  protected void compileTraversal() throws CompilerException
  {
    final int colIdx = this.db.staticFoldedColumnIndex();
    if (colIdx < 0) {
      final ExpressionNode colIdxExpr = this.db.foldedColumnIndex();
      compileColumnSwitch( colIdxExpr );
    }
    else {
      compileFixedColumnTraversal( colIdx );
    }
  }


  private void compileColumnSwitch( ExpressionNode _colIdxExpr ) throws CompilerException
  {
    final ExpressionCompilerForNumbers num = numericCompiler();
    final ExpressionNodeForFoldDatabase node = this.db;

    num.compileInt( _colIdxExpr );
    compileTableSwitch( node.foldableColumnKeys(), new TableSwitchGenerator()
    {

      @Override
      protected void generateCase( int _key, Label _end ) throws CompilerException
      {
        final int iCol = _key - 1;
        compileFixedColumnTraversal( iCol );
        mv().goTo( _end );
      }

      @Override
      protected void generateDefault() throws CompilerException
      {
        final ExpressionCompiler retCompiler = expressionCompiler( node.getDataType() );
        if (null != node.fold().whenEmpty()) {
          retCompiler.compile( node.fold().whenEmpty() );
        }
        else {
          retCompiler.compileZero();
        }
        mv().visitInsn( retCompiler.typeCompiler().returnOpcode() );
      }

    } );

  }


  private MethodCompiler matcher;

  private final void compileFixedColumnTraversal( int _foldedCol ) throws CompilerException
  {
    final List<ExpressionNode> elts = this.table.arguments();
    final int nElt = elts.size();
    int iElt = 0;
    while (iElt < nElt) {
      iElt = compileRowTraversal( _foldedCol, elts, iElt );
    }
  }


  private int compileRowTraversal( int _foldedCol, List<ExpressionNode> _elts, int _iElt ) throws CompilerException
  {
    final ExpressionNode elt = _elts.get( _iElt );
    if (elt instanceof ExpressionNodeForArrayReference) {
      compileRowTraversal( _foldedCol, elt.arguments(), 0 );
      return _iElt + 1;
    }
    else if (elt instanceof ExpressionNodeForSubSectionModel) {
      compileSubSectionTraversal( _foldedCol, (ExpressionNodeForSubSectionModel) elt );
      return _iElt + 1;
    }
    else {
      final GeneratorAdapter mv = mv();
      final int iFoldedElt = _iElt + _foldedCol;
      final ExpressionNode foldedElt = _elts.get( iFoldedElt );
      final Label noMatch = mv.newLabel();
      compileCallToMatcherAndBuildItInFirstPass( _elts, _iElt );
      compileSkipFoldIfNoMatch( noMatch );
      compileElementFold( foldedElt );
      mv.mark( noMatch );
      return _iElt + this.tableDescriptor.numberOfColumns();
    }
  }


  private void compileSubSectionTraversal( final int _foldedCol, final ExpressionNodeForSubSectionModel _sub )
      throws CompilerException
  {
    compileSubSectionTraversal( _sub, new SubSectionTraversal()
    {

      public void compile( Collection<ExpressionNode> _elements ) throws CompilerException
      {
        compileRowTraversal( _foldedCol, _sub.arguments(), 0 );
      }

    } );
  }


  private void compileElementFold( ExpressionNode _foldedElt ) throws CompilerException
  {
    final String eltName = this.db.fold().eltName( 0 );
    letDict().let( eltName, _foldedElt.getDataType(), _foldedElt );
    try {
      compileFoldStepsWithEltsBound();
    }
    finally {
      letDict().unlet( eltName );
    }
  }


  private void compileCallToMatcherAndBuildItInFirstPass( List<ExpressionNode> _elts, int _iElt )
      throws CompilerException
  {
    final int nCols = this.tableDescriptor.numberOfColumns();
    final GeneratorAdapter mv = mv();
    try {
      for (int iCol = 0; iCol < nCols; iCol++) {
        final ExpressionNode elt = _elts.get( _iElt + iCol );
        letDict().let( this.colNames[ iCol ], this.colTypes[ iCol ], elt );
      }
      final Iterable<LetEntry> closure = closureOf( this.filterExpr );
      if (this.matcher == null) {
        this.matcher = new HelperCompilerForDatabaseMatch( section(), this.filterExpr, closure );
        this.matcher.compile();
      }
      mv().loadThis();
      compileClosure( closure );
      mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL, section().classInternalName(), this.matcher.methodName(),
          this.matcher.methodDescriptor() );
    }
    finally {
      letDict().unlet( nCols );
    }
  }


  private void compileSkipFoldIfNoMatch( final Label _noMatch )
  {
    mv().ifZCmp( Opcodes.IFEQ, _noMatch );
  }

}
TOP

Related Classes of org.formulacompiler.compiler.internal.bytecode.HelperCompilerForFoldDatabase

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.