KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jruby > evaluator > AssignmentVisitor


1 /***** BEGIN LICENSE BLOCK *****
2  * Version: CPL 1.0/GPL 2.0/LGPL 2.1
3  *
4  * The contents of this file are subject to the Common Public
5  * License Version 1.0 (the "License"); you may not use this file
6  * except in compliance with the License. You may obtain a copy of
7  * the License at http://www.eclipse.org/legal/cpl-v10.html
8  *
9  * Software distributed under the License is distributed on an "AS
10  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11  * implied. See the License for the specific language governing
12  * rights and limitations under the License.
13  *
14  * Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se>
15  * Copyright (C) 2002-2004 Jan Arne Petersen <jpetersen@uni-bonn.de>
16  * Copyright (C) 2003-2004 Thomas E Enebo <enebo@acm.org>
17  *
18  * Alternatively, the contents of this file may be used under the terms of
19  * either of the GNU General Public License Version 2 or later (the "GPL"),
20  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
21  * in which case the provisions of the GPL or the LGPL are applicable instead
22  * of those above. If you wish to allow use of your version of this file only
23  * under the terms of either the GPL or the LGPL, and not to allow others to
24  * use your version of this file under the terms of the CPL, indicate your
25  * decision by deleting the provisions above and replace them with the notice
26  * and other provisions required by the GPL or the LGPL. If you do not delete
27  * the provisions above, a recipient may use your version of this file under
28  * the terms of any one of the CPL, the GPL or the LGPL.
29  ***** END LICENSE BLOCK *****/

30 package org.jruby.evaluator;
31
32 import java.util.ArrayList JavaDoc;
33 import java.util.Collections JavaDoc;
34 import java.util.Iterator JavaDoc;
35 import org.jruby.Ruby;
36 import org.jruby.RubyArray;
37 import org.jruby.RubyModule;
38 import org.jruby.ast.AttrAssignNode;
39 import org.jruby.ast.CallNode;
40 import org.jruby.ast.ClassVarAsgnNode;
41 import org.jruby.ast.ClassVarDeclNode;
42 import org.jruby.ast.Colon2Node;
43 import org.jruby.ast.ConstDeclNode;
44 import org.jruby.ast.DAsgnNode;
45 import org.jruby.ast.GlobalAsgnNode;
46 import org.jruby.ast.InstAsgnNode;
47 import org.jruby.ast.LocalAsgnNode;
48 import org.jruby.ast.MultipleAsgnNode;
49 import org.jruby.ast.Node;
50 import org.jruby.ast.NodeTypes;
51 import org.jruby.ast.StarNode;
52 import org.jruby.runtime.Block;
53 import org.jruby.runtime.CallType;
54 import org.jruby.runtime.ThreadContext;
55 import org.jruby.runtime.builtin.IRubyObject;
56
57 /**
58  *
59  * @author jpetersen
60  */

61 public class AssignmentVisitor {
62     public static IRubyObject assign(Ruby runtime, ThreadContext context, IRubyObject self, Node node, IRubyObject value, Block block, boolean check) {
63         IRubyObject result = null;
64         
65         switch (node.nodeId) {
66         case NodeTypes.ATTRASSIGNNODE: {
67             AttrAssignNode iVisited = (AttrAssignNode) node;
68             
69             IRubyObject receiver = EvaluationState.eval(runtime, context, iVisited.getReceiverNode(), self, block);
70             
71             // If reciever is self then we do the call the same way as vcall
72
CallType callType = (receiver == self ? CallType.VARIABLE : CallType.NORMAL);
73
74             if (iVisited.getArgsNode() == null) { // attribute set.
75
receiver.callMethod(context, iVisited.getName(), new IRubyObject[] {value}, callType);
76             } else { // element set
77
RubyArray args = (RubyArray)EvaluationState.eval(runtime, context, iVisited.getArgsNode(), self, block);
78                 args.append(value);
79                 receiver.callMethod(context, iVisited.getName(), args.toJavaArray(), callType);
80             }
81             break;
82         }
83         case NodeTypes.CALLNODE: {
84             CallNode iVisited = (CallNode)node;
85             
86             IRubyObject receiver = EvaluationState.eval(runtime, context, iVisited.getReceiverNode(), self, block);
87
88             if (iVisited.getArgsNode() == null) { // attribute set.
89
receiver.callMethod(context, iVisited.getName(), new IRubyObject[] {value}, CallType.NORMAL);
90             } else { // element set
91
RubyArray args = (RubyArray)EvaluationState.eval(runtime, context, iVisited.getArgsNode(), self, block);
92                 args.append(value);
93                 receiver.callMethod(context, iVisited.getName(), args.toJavaArray(), CallType.NORMAL);
94             }
95             break;
96         }
97         case NodeTypes.CLASSVARASGNNODE: {
98             ClassVarAsgnNode iVisited = (ClassVarAsgnNode)node;
99             context.getRubyClass().setClassVar(iVisited.getName(), value);
100             break;
101         }
102         case NodeTypes.CLASSVARDECLNODE: {
103             ClassVarDeclNode iVisited = (ClassVarDeclNode)node;
104             if (runtime.getVerbose().isTrue()
105                     && context.getRubyClass().isSingleton()) {
106                 runtime.getWarnings().warn(iVisited.getPosition(),
107                         "Declaring singleton class variable.");
108             }
109             context.getRubyClass().setClassVar(iVisited.getName(), value);
110             break;
111         }
112         case NodeTypes.CONSTDECLNODE: {
113             ConstDeclNode iVisited = (ConstDeclNode)node;
114             Node constNode = iVisited.getConstNode();
115
116             IRubyObject module;
117
118             if (constNode == null) {
119                 // FIXME: why do we check RubyClass and then use CRef?
120
if (context.getRubyClass() == null) {
121                     // TODO: wire into new exception handling mechanism
122
throw runtime.newTypeError("no class/module to define constant");
123                 }
124                 module = (RubyModule) context.peekCRef().getValue();
125             } else if (constNode instanceof Colon2Node) {
126                 module = EvaluationState.eval(runtime, context, ((Colon2Node) iVisited.getConstNode()).getLeftNode(), self, block);
127             } else { // Colon3
128
module = runtime.getObject();
129             }
130
131             ((RubyModule) module).setConstant(iVisited.getName(), value);
132             break;
133         }
134         case NodeTypes.DASGNNODE: {
135             DAsgnNode iVisited = (DAsgnNode)node;
136             context.getCurrentScope().setValue(iVisited.getIndex(), value, iVisited.getDepth());
137             break;
138         }
139         case NodeTypes.GLOBALASGNNODE: {
140             GlobalAsgnNode iVisited = (GlobalAsgnNode)node;
141             runtime.getGlobalVariables().set(iVisited.getName(), value);
142             break;
143         }
144         case NodeTypes.INSTASGNNODE: {
145             InstAsgnNode iVisited = (InstAsgnNode)node;
146             self.setInstanceVariable(iVisited.getName(), value);
147             break;
148         }
149         case NodeTypes.LOCALASGNNODE: {
150             LocalAsgnNode iVisited = (LocalAsgnNode)node;
151             
152             //System.out.println("Assigning to " + iVisited.getName() + "@"+ iVisited.getPosition());
153
//context.printScope();
154
context.getCurrentScope().setValue(iVisited.getIndex(), value, iVisited.getDepth());
155             break;
156         }
157         case NodeTypes.MULTIPLEASGNNODE: {
158             MultipleAsgnNode iVisited = (MultipleAsgnNode)node;
159             if (!(value instanceof RubyArray)) {
160                 value = RubyArray.newArray(runtime, value);
161             }
162             result = multiAssign(runtime, context, self, iVisited, (RubyArray) value, check);
163             break;
164         }
165         default:
166             throw new RuntimeException JavaDoc("Invalid node encountered in interpreter: \"" + node.getClass().getName() + "\", please report this at www.jruby.org");
167         }
168
169         return result;
170     }
171     
172     public static IRubyObject multiAssign(Ruby runtime, ThreadContext context, IRubyObject self, MultipleAsgnNode node, RubyArray value, boolean callAsProc) {
173         // Assign the values.
174
int valueLen = value.getLength();
175         int varLen = node.getHeadNode() == null ? 0 : node.getHeadNode().size();
176         
177         Iterator JavaDoc iter = node.getHeadNode() != null ? node.getHeadNode().iterator() : Collections.EMPTY_LIST.iterator();
178         for (int i = 0; i < valueLen && iter.hasNext(); i++) {
179             Node lNode = (Node) iter.next();
180             assign(runtime, context, self, lNode, value.eltInternal(i), Block.NULL_BLOCK, callAsProc);
181         }
182
183         if (callAsProc && iter.hasNext()) {
184             throw runtime.newArgumentError("Wrong # of arguments (" + valueLen + " for " + varLen + ")");
185         }
186
187         Node argsNode = node.getArgsNode();
188         if (argsNode != null) {
189             if (argsNode instanceof StarNode) {
190                 // no check for '*'
191
} else if (varLen < valueLen) {
192                 ArrayList JavaDoc newList = new ArrayList JavaDoc(value.getList().subList(varLen, valueLen));
193                 assign(runtime, context, self, argsNode, runtime.newArray(newList), Block.NULL_BLOCK, callAsProc);
194             } else {
195                 assign(runtime, context, self, argsNode, runtime.newArray(0), Block.NULL_BLOCK, callAsProc);
196             }
197         } else if (callAsProc && valueLen < varLen) {
198             throw runtime.newArgumentError("Wrong # of arguments (" + valueLen + " for " + varLen + ")");
199         }
200
201         while (iter.hasNext()) {
202             assign(runtime, context, self, (Node)iter.next(), runtime.getNil(), Block.NULL_BLOCK, callAsProc);
203         }
204         
205         return value;
206     }
207 }
208
Popular Tags