PageRenderTime 127ms CodeModel.GetById 108ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 1ms

/jEdit/tags/jedit-4-5-pre1/org/gjt/sp/jedit/bsh/BSHAssignment.java

#
Java | 184 lines | 108 code | 31 blank | 45 comment | 29 complexity | e5d0ebaee2044a6ca809c434c17d3401 MD5 | raw file
  1/*****************************************************************************
  2 *                                                                           *
  3 *  This file is part of the BeanShell Java Scripting distribution.          *
  4 *  Documentation and updates may be found at http://www.beanshell.org/      *
  5 *                                                                           *
  6 *  Sun Public License Notice:                                               *
  7 *                                                                           *
  8 *  The contents of this file are subject to the Sun Public License Version  *
  9 *  1.0 (the "License"); you may not use this file except in compliance with *
 10 *  the License. A copy of the License is available at http://www.sun.com    * 
 11 *                                                                           *
 12 *  The Original Code is BeanShell. The Initial Developer of the Original    *
 13 *  Code is Pat Niemeyer. Portions created by Pat Niemeyer are Copyright     *
 14 *  (C) 2000.  All Rights Reserved.                                          *
 15 *                                                                           *
 16 *  GNU Public License Notice:                                               *
 17 *                                                                           *
 18 *  Alternatively, the contents of this file may be used under the terms of  *
 19 *  the GNU Lesser General Public License (the "LGPL"), in which case the    *
 20 *  provisions of LGPL are applicable instead of those above. If you wish to *
 21 *  allow use of your version of this file only under the  terms of the LGPL *
 22 *  and not to allow others to use your version of this file under the SPL,  *
 23 *  indicate your decision by deleting the provisions above and replace      *
 24 *  them with the notice and other provisions required by the LGPL.  If you  *
 25 *  do not delete the provisions above, a recipient may use your version of  *
 26 *  this file under either the SPL or the LGPL.                              *
 27 *                                                                           *
 28 *  Patrick Niemeyer (pat@pat.net)                                           *
 29 *  Author of Learning Java, O'Reilly & Associates                           *
 30 *  http://www.pat.net/~pat/                                                 *
 31 *                                                                           *
 32 *****************************************************************************/
 33
 34
 35package org.gjt.sp.jedit.bsh;
 36
 37class BSHAssignment extends SimpleNode implements ParserConstants
 38{
 39    public int operator;
 40
 41    BSHAssignment(int id) { super(id); }
 42
 43    public Object eval(
 44		CallStack callstack, Interpreter interpreter) 
 45		throws EvalError
 46    {
 47        BSHPrimaryExpression lhsNode = 
 48			(BSHPrimaryExpression)jjtGetChild(0);
 49
 50		if ( lhsNode == null )
 51			throw new InterpreterError( "Error, null LHSnode" );
 52
 53		boolean strictJava = interpreter.getStrictJava();
 54        LHS lhs = lhsNode.toLHS( callstack, interpreter);
 55        if ( lhs == null )
 56            throw new InterpreterError( "Error, null LHS" );
 57
 58		// For operator-assign operations save the lhs value before evaluating
 59		// the rhs.  This is correct Java behavior for postfix operations
 60		// e.g. i=1; i+=i++; // should be 2 not 3
 61		Object lhsValue = null;
 62		if ( operator != ASSIGN ) // assign doesn't need the pre-value
 63			try {
 64				lhsValue = lhs.getValue();
 65			} catch ( UtilEvalError e ) {
 66				throw e.toEvalError( this, callstack );
 67			}
 68
 69        SimpleNode rhsNode = (SimpleNode)jjtGetChild(1);
 70
 71        Object rhs;
 72		
 73		// implement "blocks" foo = { };
 74		// if ( rhsNode instanceof BSHBlock )
 75		//    rsh =
 76		// else
 77        rhs = rhsNode.eval(callstack, interpreter);
 78
 79        if ( rhs == Primitive.VOID )
 80            throw new EvalError("Void assignment.", this, callstack );
 81
 82		try {
 83			switch(operator)
 84			{
 85				case ASSIGN:
 86					return lhs.assign( rhs, strictJava );
 87
 88				case PLUSASSIGN:
 89					return lhs.assign( 
 90						operation(lhsValue, rhs, PLUS), strictJava );
 91
 92	            case MINUSASSIGN:
 93					return lhs.assign( 
 94						operation(lhsValue, rhs, MINUS), strictJava );
 95
 96				case STARASSIGN:
 97					return lhs.assign( 
 98						operation(lhsValue, rhs, STAR), strictJava );
 99
100	            case SLASHASSIGN:
101					return lhs.assign( 
102						operation(lhsValue, rhs, SLASH), strictJava );
103
104	            case ANDASSIGN:
105				case ANDASSIGNX:
106					return lhs.assign( 
107						operation(lhsValue, rhs, BIT_AND), strictJava );
108
109	            case ORASSIGN:
110	            case ORASSIGNX:
111	                return lhs.assign( 
112						operation(lhsValue, rhs, BIT_OR), strictJava );
113
114	            case XORASSIGN:
115	                return lhs.assign( 
116						operation(lhsValue, rhs, XOR), strictJava );
117
118	            case MODASSIGN:
119	                return lhs.assign( 
120						operation(lhsValue, rhs, MOD), strictJava );
121
122	            case LSHIFTASSIGN:
123	            case LSHIFTASSIGNX:
124	                return lhs.assign( 
125						operation(lhsValue, rhs, LSHIFT), strictJava );
126
127	            case RSIGNEDSHIFTASSIGN:
128	            case RSIGNEDSHIFTASSIGNX:
129	                return lhs.assign( 
130					operation(lhsValue, rhs, RSIGNEDSHIFT ), strictJava );
131
132	            case RUNSIGNEDSHIFTASSIGN:
133	            case RUNSIGNEDSHIFTASSIGNX:
134	                return lhs.assign( 
135						operation(lhsValue, rhs, RUNSIGNEDSHIFT), 
136						strictJava );
137
138				default:
139					throw new InterpreterError(
140						"unimplemented operator in assignment BSH");
141			}
142		} catch ( UtilEvalError e ) {
143			throw e.toEvalError( this, callstack );
144		}
145    }
146
147    private Object operation( Object lhs, Object rhs, int kind ) 
148		throws UtilEvalError
149    {
150		/*
151			Implement String += value;
152			According to the JLS, value may be anything.
153			In BeanShell, we'll disallow VOID (undefined) values.
154			(or should we map them to the empty string?)
155		*/
156		if ( lhs instanceof String && rhs != Primitive.VOID ) {
157			if ( kind != PLUS )
158				throw new UtilEvalError(
159					"Use of non + operator with String LHS" );
160
161			return (String)lhs + rhs;
162		}
163
164        if ( lhs instanceof Primitive || rhs instanceof Primitive )
165            if(lhs == Primitive.VOID || rhs == Primitive.VOID)
166                throw new UtilEvalError(
167					"Illegal use of undefined object or 'void' literal" );
168            else if ( lhs == Primitive.NULL || rhs == Primitive.NULL )
169                throw new UtilEvalError(
170					"Illegal use of null object or 'null' literal" );
171
172
173        if( (lhs instanceof Boolean || lhs instanceof Character ||
174             lhs instanceof Number || lhs instanceof Primitive) &&
175            (rhs instanceof Boolean || rhs instanceof Character ||
176             rhs instanceof Number || rhs instanceof Primitive) )
177        {
178            return Primitive.binaryOperation(lhs, rhs, kind);
179        }
180
181        throw new UtilEvalError("Non primitive value in operator: " +
182            lhs.getClass() + " " + tokenImage[kind] + " " + rhs.getClass() );
183    }
184}