//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
// PLEASE DO NOT EDIT WITHOUT THE EXPLICIT CONSENT OF THE AUTHOR! \\
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\

package hlt.language.design.instructions;

/**
 * @version     Last modified on Wed Jun 20 14:29:51 2012 by hak
 * @author      <a href="mailto:hak@acm.org">Hassan A&iuml;t-Kaci</a>
 * @copyright   &copy; <a href="http://www.hassan-ait-kaci.net/">by the author</a>
 */

import hlt.language.design.backend.Runtime;
import hlt.language.design.backend.RuntimeTuple;

public class PushTuple extends Instruction implements PushValue, PushObject
{
  private int _intDim;
  private int _realDim;
  private int _objectDim;

  public PushTuple (int intDim, int realDim, int objectDim)
    {
      setName("PUSH_TUPLE");
      _intDim = intDim;
      _realDim = realDim;
      _objectDim = objectDim;
    }

  final int intDimension ()
    {
      return _intDim;
    }
  
  final int realDimension ()
    {
      return _realDim;
    }
  
  final int objectDimension ()
    {
      return _objectDim;
    }
  
  public final void execute (Runtime r)
    {
      if (_intDim+_realDim+_objectDim == 0)
        r.pushObject(RuntimeTuple.EMPTY);
      else
        {
          int[] intComponents = (_intDim == 0 ? null : new int[_intDim]);
          double[] realComponents = (_realDim == 0 ? null : new double[_realDim]);
          Object[] objectComponents = (_objectDim == 0 ? null : new Object[_objectDim]);

          for (int i=0; i<_intDim; i++) intComponents[i] = r.popInt();
          for (int i=0; i<_realDim; i++) realComponents[i] = r.popReal();
          for (int i=0; i<_objectDim; i++) objectComponents[i] = r.popObject();

          r.pushObject(new RuntimeTuple(intComponents,realComponents,objectComponents));
        }
      r.incIP();
    }

  public final boolean equals (Object object)
    {
      if (this == object)
        return true;

      if (!(object instanceof PushTuple))
        return false;

      PushTuple PushTuple = (PushTuple)object;

      return _intDim    == PushTuple.intDimension()
          && _realDim   == PushTuple.realDimension()
          && _objectDim == PushTuple.objectDimension();
    }

  public final int hashCode ()
    {
      return name().hashCode() + 2*_intDim + 3*_realDim + 5*_objectDim;
    }

  public final String toString ()
    {
      return name() + "(" + _intDim + "," + _realDim + "," + _objectDim + ")";
    }
}
