import java.math.*;


public class SL_ExprNode extends ParseNode implements TokenTypes {
  // child 0: first subexpression
  // child 1: second subexpression (if operator is binary)
  // (operator = T_EOF means the expr is just the first subexpression) 

  private int opType; 

  public SL_ExprNode() { super(); opType=T_EOF;  }
  public SL_ExprNode(int opType_) { super(); opType = opType_; }
  public int getOperator() { return opType; }
  public int getType()     { return G_EXPR; }
  public ParseNode interpret(SymbolTable st) throws InterpretException {
    
    // fill in some shorthand variables 
    SL_NumberNode child1=null, child2=null;
    try {
      child1 = (SL_NumberNode) getChild(0).interpret(st);
      child2 = (SL_NumberNode) 
	(numChildren()==1? null : getChild(1).interpret(st)); 
    }
    catch (BreakException b) { /* we know this can't happen, but javac doesn't */ }
    catch (ReturnException b) { /* we know this can't happen, but javac doesn't */ }

    BigInteger val1 = child1.getValue();
    BigInteger val2 = (child2==null)? null : child2.getValue();

    BigInteger b0 = new BigInteger("0");
    BigInteger b1 = new BigInteger("1");
    SL_NumberNode no  = new SL_NumberNode(b0);
    SL_NumberNode yes = new SL_NumberNode(b1);
    
    switch(opType) { 
    case T_EOF:    return child1;
    case T_PLUS:   return new SL_NumberNode(val1.add(val2));
    case T_MINUS:  return new SL_NumberNode(val1.subtract(val2));
    case T_TIMES:  return new SL_NumberNode(val1.multiply(val2));
    case T_DIV:    
      if (val2.equals(b0)) throw new InterpretException("Division by zero");
      return new SL_NumberNode(val1.divide(val2));
    case T_MOD: 
      if (val2.equals(b0)) throw new InterpretException("Mod by zero");
      return new SL_NumberNode(val1.mod(val2));
    case T_LT:     return (val1.compareTo(val2)==-1)? yes : no;
    case T_GT:     return (val1.compareTo(val2)==1)?  yes : no;
    case T_NE:     return (val1.compareTo(val2)!=0)?  yes : no;
    case T_EQ:     return (val1.compareTo(val2)==0)?  yes : no;
    case T_GE:     return (val1.compareTo(val2)!=-1)? yes : no;
    case T_LE:     return (val1.compareTo(val2)!=1)?  yes : no;
    case T_AND:    return (val1.equals(b0) || val2.equals(b0))?  no : yes;
    case T_OR:     return (!val1.equals(b0)||!val2.equals(b0))?  yes : no;
    case T_EXCLAM: return val1.equals(b0)? yes : no;
    case T_TILDE:  return new SL_NumberNode(val1.negate());
    }
    throw new InterpretException("Internal error in SL_ExprNode");
  }

  public void print() { 
    // overrides the default print method in ParseNode
    printSpaces();
    sprint("[expr ");
    nesting++;
    if (opType!=T_EOF) sprint(reservedLexemes[opType]);
    printChildren();
    sprint("]");
    nesting--;
  }
}


