// $Id: Xobject.java,v 1.19 2001/02/05 10:38:41 msato Exp $
// $RWC_Release: Omni-1.6 $
// $RWC_Copyright:
//  Omni Compiler Software Version 1.5-1.6
//  Copyright (C) 2002 PC Cluster Consortium
//  
//  This software is free software; you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License version
//  2.1 published by the Free Software Foundation.
//  
//  Omni Compiler Software Version 1.0-1.4
//  Copyright (C) 1999, 2000, 2001.
//   Tsukuba Research Center, Real World Computing Partnership, Japan.
//  
//  Please check the Copyright and License information in the files named
//  COPYRIGHT and LICENSE under the top  directory of the Omni Compiler
//  Software release kit.
//  
//  
//  $
package exc.object;

/**
 * abstract class of expression object in Xcode
 */
public class Xobject extends PropObject {
  int code;
  Xtype type;

  public Xobject(int code,Xtype type){
    this.code = code;
    this.type = type;
  }

  public int Opcode(){
    return code;
  }
    
  public Xtype Type(){
    return type;
  }
    
  //
  // dummy functions at base class 
  //
  public int getInt(){
    fatal("getInt",this);
    return 0; 
  }
  public String getString(){
    fatal("getStr",this);
    return null;
  }
  public String getSym(){
    fatal("getSym",this);
    return null;
  }
  public String getName(){
    switch(code){
    case Xcode.FCOMM_VAR:
    case Xcode.FCOMM_VAR_ADDR:
    case Xcode.FCOMM_ARRAY_ADDR:
      return (((XobjList)this).left().getSym());
    }
    fatal("getName",this);
    return null;
  }
  public double getFloat(){
    fatal("getFloat",this);
    return 0.0;
  }
  public long getLong(){
    fatal("getLong",this);
    return 0L;
  }
  public int getIntHIGH(){
    fatal("getIntHIGH",this);
    return 0;
  }
  public int getIntLOW(){
    fatal("getIntLOW",this);
    return 0;
  }
  public Xobject getArg(int i){
    fatal("getArg(int)",this);
    return null;
  }
  public void setArg(int i,Xobject x){
    fatal("setArg(int,Xobject)",this);
  }
  public int Nargs(){
    fatal("Nargs",this);
    return 0;
  }
  public XobjArgs getArgs(){
    fatal("getArgs",this);
    return null;
  }
  public void setArgs(XobjArgs l){
    fatal("setArgs",this);
  }
  public Xobject operand(){
    fatal("left",this);
    return null;
  }
  public Xobject left(){
    fatal("left",this);
    return null;
  }
  public Xobject right(){
    fatal("right",this);
    return null;
  }
  public void setOperand(Xobject x){
    fatal("setOperand",this);
  }
  public void setLeft(Xobject x){
    fatal("setLeft",this);
  }
  public void setRight(Xobject x){
    fatal("setRight",this);
  }
  public void add(Xobject a){
    fatal("add",this);
  }
  public Xobject copy(){
    fatal("copy",this);
    return null;
  }
  public void setLineNo(LineNo ln){ fatal("setLineNo",this); }
  public LineNo getLineNo() { return null; }

  public boolean equals(Object x){
    if(!(x instanceof Xobject)) return false;
    return equals((Xobject)x);
  }	
  public boolean equals(Xobject x){
    if(this == x) return true;
    return (code == x.code && (type == x.type || type.equals(x.type)));
  }

  static void fatal(String msg,Xobject o){
    System.err.println("Fatal Xobj:"+msg+" at "+o);
    Thread.dumpStack();
    System.exit(1);
  }

  public String OpcodeName(){
    String name = (code >= Xcode.MAX_CODE)? 
      ("code<"+Integer.toString(code)+">"): Xcode.getName(code);
    if(type == null) return name;
    else return name+":"+type;
  }

  public String toString(){
    return "<"+OpcodeName()+">";
  }
    
  public boolean isVariable(){
    switch(code){
    case Xcode.PARAM_VAR:
      if(type.isArray()) return false;	// array parameter
    case Xcode.VAR:
    case Xcode.LVAR:
    case Xcode.FPARAM_VAR:
    case Xcode.FCOMM_VAR:
    case Xcode.REG:
      return true;
    default:
      return false;
    }
  }

  public boolean isLocalVar(){
    switch(code){
    case Xcode.LVAR:
    case Xcode.PARAM_VAR:
    case Xcode.REG:
      return true;
    default:
      return false;
    }
  }

  public boolean isTempVar(){
    return code == Xcode.REG;
  }

  public boolean isVarAddr(){
    switch(code){
    case Xcode.VAR_ADDR:
    case Xcode.LVAR_ADDR:
    case Xcode.PARAM_ADDR:
    case Xcode.FPARAM_VAR_ADDR:
    case Xcode.FCOMM_VAR_ADDR:
      /* case Xcode.REG: */
      return true;
    default:
      return false;
    }
  }

  public boolean isLocalVarAddr(){
    switch(code){
    case Xcode.LVAR_ADDR:
    case Xcode.PARAM_ADDR:
    case Xcode.FPARAM_VAR_ADDR:
      return true;
    default:
      return false;
    }
  }

  public boolean isArrayAddr(){
    switch(code){
    case Xcode.ARRAY_ADDR:
    case Xcode.LARRAY_ADDR:
    case Xcode.PARAM_ADDR:
    case Xcode.FPARAM_ARRAY_ADDR:
    case Xcode.FCOMM_ARRAY_ADDR:
      return true;
    case Xcode.PARAM_VAR:
      if(type.isArray()) return true; // array parameter
    default:
      return false;
    }
  }

  /* for Fortran common */
  public boolean isFCOMM(){
    switch(code){
    case Xcode.FCOMM_VAR_ADDR:
    case Xcode.FCOMM_ARRAY_ADDR:
    case Xcode.FCOMM_VAR:
      return true;
    default:
      return false;
    }
  }
  public Xobject getFCOMM(){  return right().left(); }
  public void setFCOMM(Xobject comm){  right().setLeft(comm);  }

  public boolean isConstant(){
    if(!isTerminal()) return false;
    switch(code){
    case Xcode.ARRAY_ADDR:
    case Xcode.LARRAY_ADDR:
    case Xcode.PARAM_ADDR:
    case Xcode.FPARAM_ARRAY_ADDR:
    case Xcode.FCOMM_ARRAY_ADDR:
    case Xcode.FPARAM_VAR_ADDR:
    case Xcode.FCOMM_VAR_ADDR:
    case Xcode.VAR_ADDR:
    case Xcode.LVAR_ADDR:
    case Xcode.INT_CONSTANT:
    case Xcode.LONG_CONSTANT:
    case Xcode.STRING_CONSTANT:
    case Xcode.LONGLONG_CONSTANT:
    case Xcode.FLOAT_CONSTANT:
    case Xcode.MOE_CONSTANT:
    case Xcode.SIZE_OF_EXPR: /* ??? */
    case Xcode.IDENT:  /* ??? */
      return true;
    }
    return false;
  }
  public boolean isZeroConstant(){
    return code == Xcode.INT_CONSTANT && getInt() == 0;
  }
  public boolean isOneConstant(){
    return code == Xcode.INT_CONSTANT && getInt() == 1;
  }
  public boolean isIntConstant(){
    return code == Xcode.INT_CONSTANT;
  }
  public boolean isSet(){
    return code == Xcode.ASSIGN_EXPR;
  }
  public boolean isBinaryOp(){
    if(code >= Xcode.MAX_CODE) return false;
    return Xcode.kind[code] == 'B';
  }
  public boolean isUnaryOp(){
    if(code >= Xcode.MAX_CODE) return false;
    return Xcode.kind[code] == 'U';
  }
  public boolean isAsgOp(){
    if(code >= Xcode.MAX_CODE) return false;
    return Xcode.kind[code] == 'A';
  }
  public boolean isTerminal(){
    if(code >= Xcode.MAX_CODE) return false;
    return Xcode.kind[code] == 'T';
  }

  /* 
   * allocating new codes 
   */
  static int max_code = Xcode.MAX_CODE;
  public static int newCode() { return max_code++; }

  public boolean isExternalCode() { return code >= Xcode.MAX_CODE; }
}



