Open Source Repository

Home /beanshell/bsh-2.0b4 | Repository Home


bsh/BSHAssignment.java
/*****************************************************************************
 *                                                                           *
 *  This file is part of the BeanShell Java Scripting distribution.          *
 *  Documentation and updates may be found at http://www.beanshell.org/      *
 *                                                                           *
 *  Sun Public License Notice:                                               *
 *                                                                           *
 *  The contents of this file are subject to the Sun Public License Version  *
 *  1.0 (the "License"); you may not use this file except in compliance with *
 *  the License. A copy of the License is available at http://www.sun.com    * 
 *                                                                           *
 *  The Original Code is BeanShell. The Initial Developer of the Original    *
 *  Code is Pat Niemeyer. Portions created by Pat Niemeyer are Copyright     *
 *  (C) 2000.  All Rights Reserved.                                          *
 *                                                                           *
 *  GNU Public License Notice:                                               *
 *                                                                           *
 *  Alternatively, the contents of this file may be used under the terms of  *
 *  the GNU Lesser General Public License (the "LGPL"), in which case the    *
 *  provisions of LGPL are applicable instead of those above. If you wish to *
 *  allow use of your version of this file only under the  terms of the LGPL *
 *  and not to allow others to use your version of this file under the SPL,  *
 *  indicate your decision by deleting the provisions above and replace      *
 *  them with the notice and other provisions required by the LGPL.  If you  *
 *  do not delete the provisions above, a recipient may use your version of  *
 *  this file under either the SPL or the LGPL.                              *
 *                                                                           *
 *  Patrick Niemeyer (pat@pat.net)                                           *
 *  Author of Learning Java, O'Reilly & Associates                           *
 *  http://www.pat.net/~pat/                                                 *
 *                                                                           *
 *****************************************************************************/


package bsh;

class BSHAssignment extends SimpleNode implements ParserConstants
{
    public int operator;

    BSHAssignment(int id) { super(id)}

    public Object eval(
    CallStack callstack, Interpreter interpreter
    throws EvalError
    {
        BSHPrimaryExpression lhsNode = 
      (BSHPrimaryExpression)jjtGetChild(0);

    if lhsNode == null )
      throw new InterpreterError"Error, null LHSnode" );

    boolean strictJava = interpreter.getStrictJava();
        LHS lhs = lhsNode.toLHScallstack, interpreter);
        if lhs == null )
            throw new InterpreterError"Error, null LHS" );

    // For operator-assign operations save the lhs value before evaluating
    // the rhs.  This is correct Java behavior for postfix operations
    // e.g. i=1; i+=i++; // should be 2 not 3
    Object lhsValue = null;
    if operator != ASSIGN // assign doesn't need the pre-value
      try {
        lhsValue = lhs.getValue();
      catch UtilEvalError e ) {
        throw e.toEvalErrorthis, callstack );
      }

        SimpleNode rhsNode = (SimpleNode)jjtGetChild(1);

        Object rhs;
    
    // implement "blocks" foo = { };
    // if ( rhsNode instanceof BSHBlock )
    //    rsh =
    // else
        rhs = rhsNode.eval(callstack, interpreter);

        if rhs == Primitive.VOID )
            throw new EvalError("Void assignment.", this, callstack );

    try {
      switch(operator)
      {
        case ASSIGN:
          return lhs.assignrhs, strictJava );

        case PLUSASSIGN:
          return lhs.assign
            operation(lhsValue, rhs, PLUS), strictJava );

              case MINUSASSIGN:
          return lhs.assign
            operation(lhsValue, rhs, MINUS), strictJava );

        case STARASSIGN:
          return lhs.assign
            operation(lhsValue, rhs, STAR), strictJava );

              case SLASHASSIGN:
          return lhs.assign
            operation(lhsValue, rhs, SLASH), strictJava );

              case ANDASSIGN:
        case ANDASSIGNX:
          return lhs.assign
            operation(lhsValue, rhs, BIT_AND), strictJava );

              case ORASSIGN:
              case ORASSIGNX:
                  return lhs.assign
            operation(lhsValue, rhs, BIT_OR), strictJava );

              case XORASSIGN:
                  return lhs.assign
            operation(lhsValue, rhs, XOR), strictJava );

              case MODASSIGN:
                  return lhs.assign
            operation(lhsValue, rhs, MOD), strictJava );

              case LSHIFTASSIGN:
              case LSHIFTASSIGNX:
                  return lhs.assign
            operation(lhsValue, rhs, LSHIFT), strictJava );

              case RSIGNEDSHIFTASSIGN:
              case RSIGNEDSHIFTASSIGNX:
                  return lhs.assign
          operation(lhsValue, rhs, RSIGNEDSHIFT ), strictJava );

              case RUNSIGNEDSHIFTASSIGN:
              case RUNSIGNEDSHIFTASSIGNX:
                  return lhs.assign
            operation(lhsValue, rhs, RUNSIGNEDSHIFT)
            strictJava );

        default:
          throw new InterpreterError(
            "unimplemented operator in assignment BSH");
      }
    catch UtilEvalError e ) {
      throw e.toEvalErrorthis, callstack );
    }
    }

    private Object operationObject lhs, Object rhs, int kind 
    throws UtilEvalError
    {
    /*
      Implement String += value;
      According to the JLS, value may be anything.
      In BeanShell, we'll disallow VOID (undefined) values.
      (or should we map them to the empty string?)
    */
    if lhs instanceof String && rhs != Primitive.VOID ) {
      if kind != PLUS )
        throw new UtilEvalError(
          "Use of non + operator with String LHS" );

      return (String)lhs + rhs;
    }

        if lhs instanceof Primitive || rhs instanceof Primitive )
            if(lhs == Primitive.VOID || rhs == Primitive.VOID)
                throw new UtilEvalError(
          "Illegal use of undefined object or 'void' literal" );
            else if lhs == Primitive.NULL || rhs == Primitive.NULL )
                throw new UtilEvalError(
          "Illegal use of null object or 'null' literal" );


        if( (lhs instanceof Boolean || lhs instanceof Character ||
             lhs instanceof Number || lhs instanceof Primitive&&
            (rhs instanceof Boolean || rhs instanceof Character ||
             rhs instanceof Number || rhs instanceof Primitive) )
        {
            return Primitive.binaryOperation(lhs, rhs, kind);
        }

        throw new UtilEvalError("Non primitive value in operator: " +
            lhs.getClass() " " + tokenImage[kind" " + rhs.getClass() );
    }
}