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

package ilog.language.design.base;

/**
 * @version     Last modified on Tue Dec 10 10:20:46 2002 by hak
 * @author      <a href="mailto:hak@ilog.fr">Hassan A&iuml;t-Kaci</a>
 * @copyright   &copy; 2000-2002 <a href="http://www.ilog.fr/">ILOG, S.A.</a>
 */

import ilog.language.design.types.CodeEntry;
import ilog.language.design.backend.Block;
import ilog.language.design.backend.Runtime;

/**
 * A <tt>PushScope</tt> instruction is to a <a href="PushClosure.html"><tt>PushClosure</tt></a>
 * instruction what a <a href="../kernel/Scope.html"><tt>Scope</tt></a> expression is to
 * an <a href="../kernel/Abstraction.html"><tt>Abstraction</tt></a> expression. In other words,
 * it is a <tt>PushClosure</tt> that does not need any frame machinery. Also, if it is marked
 * <i>raw</i>, its application is optimized to dispense with state saving.
 */
public class PushScope extends Instruction implements PushObject
{
  protected int _address;
  protected int _voidArity;
  protected int _intArity;
  protected int _realArity;
  protected int _objectArity;
  protected Instruction[] _code;

  private boolean _isRaw;

  public final boolean isRaw ()
    {
      return _isRaw;
    }

  public final PushScope setIsRaw (boolean flag)
    {
      _isRaw = flag;
      return this;
    }

  public PushScope (int voidArity, int intArity, int realArity, int objectArity)
    {
      setName("PUSH_SCOPE");
      _voidArity = voidArity;
      _intArity = intArity;
      _realArity = realArity;
      _objectArity = objectArity;
    }

  public PushScope (int voidArity, int address, int intArity, int realArity, int objectArity)
    {
      this(voidArity,intArity,realArity,objectArity);
      setAddress(address);
    }

  public boolean isExitable ()
    {
      return false;
    }

  final int address ()
    {
      return _address;
    }
  
  final int voidArity ()
    {
      return _voidArity;
    }
  
  final int intArity ()
    {
      return _intArity;
    }
  
  final int realArity ()
    {
      return _realArity;
    }
  
  final int objectArity ()
    {
      return _objectArity;
    }
  
  final Instruction[] code ()
    {
      return _code;
    }
  
  public final PushScope setAddress (int address)
    {
      _address = address;
      return this;
    }

  public final PushScope setCode (Instruction[] code)
    {
      _code = code;
      return this;
    }

  public final Instruction setReferenceCode (Instruction[] code)
    {
      if (_code != null)
        return this;

      _code = code;
      return this;
    }

  public void execute (Runtime r)
    {
      r.pushObject(new Block(_isRaw,
                             _code,
                             _address,
                             _voidArity,
                             _intArity,
                             _realArity,
                             _objectArity));
      r.incIP();
    }

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

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

      PushScope pushScope = (PushScope)object;

      return _name            == pushScope.name()
          && _address         == pushScope.address()
          && _voidArity       == pushScope.voidArity()
          && _intArity        == pushScope.intArity()
          && _realArity       == pushScope.realArity()
          && _objectArity     == pushScope.objectArity()
          && _isRaw           == pushScope.isRaw()
          && (_code == null ? pushScope.code() == null : _code == pushScope.code());
    }

  public int hashCode ()
    {
      return _name.hashCode() + 2*_address + (_code == null ? 0 : 3*_code.length)
                              + 5*_voidArity + 7*_intArity + 11*_realArity + 13*_objectArity;
    }

  public String toString ()
    {
      return _name
           + "("+ CodeEntry.getId(_code) + "," + _address + ","
           + "<" + _voidArity + "," + _intArity + "," + _realArity + "," + _objectArity + ">)";
    }
}
