KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > bsh > BSHAssignment


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
35 package bsh;
36
37 class BSHAssignment extends SimpleNode implements ParserConstants
38 {
39     public int operator;
40
41     BSHAssignment(int id) { super(id); }
42
43     public Object JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc operation( Object JavaDoc lhs, Object JavaDoc 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 JavaDoc && rhs != Primitive.VOID ) {
157             if ( kind != PLUS )
158                 throw new UtilEvalError(
159                     "Use of non + operator with String LHS" );
160
161             return (String JavaDoc)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 JavaDoc || lhs instanceof Character JavaDoc ||
174              lhs instanceof Number JavaDoc || lhs instanceof Primitive) &&
175             (rhs instanceof Boolean JavaDoc || rhs instanceof Character JavaDoc ||
176              rhs instanceof Number JavaDoc || 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 }
185
Popular Tags