1 30 package org.jruby.evaluator; 31 32 import java.util.ArrayList ; 33 import java.util.Collections ; 34 import java.util.Iterator ; 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 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 CallType callType = (receiver == self ? CallType.VARIABLE : CallType.NORMAL); 73 74 if (iVisited.getArgsNode() == null) { receiver.callMethod(context, iVisited.getName(), new IRubyObject[] {value}, callType); 76 } else { 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) { receiver.callMethod(context, iVisited.getName(), new IRubyObject[] {value}, CallType.NORMAL); 90 } else { 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 if (context.getRubyClass() == null) { 121 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 { 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 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 ("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 int valueLen = value.getLength(); 175 int varLen = node.getHeadNode() == null ? 0 : node.getHeadNode().size(); 176 177 Iterator 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 } else if (varLen < valueLen) { 192 ArrayList newList = new ArrayList (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 |