1 30 31 package org.jruby.evaluator; 32 33 import java.util.HashMap ; 34 import java.util.Iterator ; 35 import java.util.Map ; 36 37 import org.jruby.Ruby; 38 import org.jruby.MetaClass; 39 import org.jruby.RubyArray; 40 import org.jruby.RubyBignum; 41 import org.jruby.RubyClass; 42 import org.jruby.RubyException; 43 import org.jruby.RubyFloat; 44 import org.jruby.RubyHash; 45 import org.jruby.RubyKernel; 46 import org.jruby.RubyModule; 47 import org.jruby.RubyObject; 48 import org.jruby.RubyProc; 49 import org.jruby.RubyRange; 50 import org.jruby.RubyRegexp; 51 import org.jruby.RubyString; 52 import org.jruby.ast.AliasNode; 53 import org.jruby.ast.ArgsCatNode; 54 import org.jruby.ast.ArgsNode; 55 import org.jruby.ast.ArgsPushNode; 56 import org.jruby.ast.ArrayNode; 57 import org.jruby.ast.AttrAssignNode; 58 import org.jruby.ast.BackRefNode; 59 import org.jruby.ast.BeginNode; 60 import org.jruby.ast.BignumNode; 61 import org.jruby.ast.BinaryOperatorNode; 62 import org.jruby.ast.BlockNode; 63 import org.jruby.ast.BlockPassNode; 64 import org.jruby.ast.BreakNode; 65 import org.jruby.ast.CallNode; 66 import org.jruby.ast.CaseNode; 67 import org.jruby.ast.ClassNode; 68 import org.jruby.ast.ClassVarAsgnNode; 69 import org.jruby.ast.ClassVarDeclNode; 70 import org.jruby.ast.ClassVarNode; 71 import org.jruby.ast.Colon2Node; 72 import org.jruby.ast.Colon3Node; 73 import org.jruby.ast.ConstDeclNode; 74 import org.jruby.ast.ConstNode; 75 import org.jruby.ast.DAsgnNode; 76 import org.jruby.ast.DRegexpNode; 77 import org.jruby.ast.DStrNode; 78 import org.jruby.ast.DSymbolNode; 79 import org.jruby.ast.DVarNode; 80 import org.jruby.ast.DXStrNode; 81 import org.jruby.ast.DefinedNode; 82 import org.jruby.ast.DefnNode; 83 import org.jruby.ast.DefsNode; 84 import org.jruby.ast.DotNode; 85 import org.jruby.ast.EnsureNode; 86 import org.jruby.ast.EvStrNode; 87 import org.jruby.ast.FCallNode; 88 import org.jruby.ast.FixnumNode; 89 import org.jruby.ast.FlipNode; 90 import org.jruby.ast.FloatNode; 91 import org.jruby.ast.ForNode; 92 import org.jruby.ast.GlobalAsgnNode; 93 import org.jruby.ast.GlobalVarNode; 94 import org.jruby.ast.HashNode; 95 import org.jruby.ast.IfNode; 96 import org.jruby.ast.InstAsgnNode; 97 import org.jruby.ast.InstVarNode; 98 import org.jruby.ast.IterNode; 99 import org.jruby.ast.ListNode; 100 import org.jruby.ast.LocalAsgnNode; 101 import org.jruby.ast.LocalVarNode; 102 import org.jruby.ast.Match2Node; 103 import org.jruby.ast.Match3Node; 104 import org.jruby.ast.MatchNode; 105 import org.jruby.ast.ModuleNode; 106 import org.jruby.ast.MultipleAsgnNode; 107 import org.jruby.ast.NewlineNode; 108 import org.jruby.ast.NextNode; 109 import org.jruby.ast.Node; 110 import org.jruby.ast.NodeTypes; 111 import org.jruby.ast.NotNode; 112 import org.jruby.ast.NthRefNode; 113 import org.jruby.ast.OpAsgnNode; 114 import org.jruby.ast.OpAsgnOrNode; 115 import org.jruby.ast.OpElementAsgnNode; 116 import org.jruby.ast.OptNNode; 117 import org.jruby.ast.OrNode; 118 import org.jruby.ast.RegexpNode; 119 import org.jruby.ast.RescueBodyNode; 120 import org.jruby.ast.RescueNode; 121 import org.jruby.ast.ReturnNode; 122 import org.jruby.ast.RootNode; 123 import org.jruby.ast.SClassNode; 124 import org.jruby.ast.SValueNode; 125 import org.jruby.ast.SplatNode; 126 import org.jruby.ast.StrNode; 127 import org.jruby.ast.SuperNode; 128 import org.jruby.ast.SymbolNode; 129 import org.jruby.ast.ToAryNode; 130 import org.jruby.ast.UndefNode; 131 import org.jruby.ast.UntilNode; 132 import org.jruby.ast.VAliasNode; 133 import org.jruby.ast.VCallNode; 134 import org.jruby.ast.WhenNode; 135 import org.jruby.ast.WhileNode; 136 import org.jruby.ast.XStrNode; 137 import org.jruby.ast.YieldNode; 138 import org.jruby.ast.ZSuperNode; 139 import org.jruby.ast.types.INameNode; 140 import org.jruby.ast.util.ArgsUtil; 141 import org.jruby.exceptions.JumpException; 142 import org.jruby.exceptions.RaiseException; 143 import org.jruby.exceptions.JumpException.JumpType; 144 import org.jruby.internal.runtime.methods.DefaultMethod; 145 import org.jruby.internal.runtime.methods.DynamicMethod; 146 import org.jruby.internal.runtime.methods.WrapperMethod; 147 import org.jruby.lexer.yacc.ISourcePosition; 148 import org.jruby.parser.StaticScope; 149 import org.jruby.runtime.Block; 150 import org.jruby.runtime.CallType; 151 import org.jruby.runtime.DynamicScope; 152 import org.jruby.runtime.ForBlock; 153 import org.jruby.runtime.ThreadContext; 154 import org.jruby.runtime.Visibility; 155 import org.jruby.runtime.builtin.IRubyObject; 156 import org.jruby.util.ByteList; 157 import org.jruby.util.KCode; 158 import org.jruby.util.collections.SinglyLinkedList; 159 160 public class EvaluationState { 161 public static IRubyObject eval(Ruby runtime, ThreadContext context, Node node, IRubyObject self, Block block) { 162 try { 163 return evalInternal(runtime, context, node, self, block); 164 } catch (StackOverflowError sfe) { 165 throw runtime.newSystemStackError("stack level too deep"); 166 } 167 } 168 169 171 private static RubyModule getClassVariableBase(ThreadContext context, Ruby runtime) { 172 SinglyLinkedList cref = context.peekCRef(); 173 RubyModule rubyClass = (RubyModule) cref.getValue(); 174 if (rubyClass.isSingleton()) { 175 cref = cref.getNext(); 176 rubyClass = (RubyModule) cref.getValue(); 177 if (cref.getNext() == null) { 178 runtime.getWarnings().warn("class variable access from toplevel singleton method"); 179 } 180 } 181 return rubyClass; 182 } 183 184 private static IRubyObject evalInternal(Ruby runtime, ThreadContext context, Node node, IRubyObject self, Block aBlock) { 185 bigloop: do { 186 if (node == null) return runtime.getNil(); 187 188 switch (node.nodeId) { 189 case NodeTypes.ALIASNODE: { 190 AliasNode iVisited = (AliasNode) node; 191 192 if (context.getRubyClass() == null) { 193 throw runtime.newTypeError("no class to make alias"); 194 } 195 196 context.getRubyClass().defineAlias(iVisited.getNewName(), iVisited.getOldName()); 197 context.getRubyClass().callMethod(context, "method_added", runtime.newSymbol(iVisited.getNewName())); 198 199 return runtime.getNil(); 200 } 201 case NodeTypes.ANDNODE: { 202 BinaryOperatorNode iVisited = (BinaryOperatorNode) node; 203 204 IRubyObject result = evalInternal(runtime,context, iVisited.getFirstNode(), self, aBlock); 205 if (!result.isTrue()) return result; 206 node = iVisited.getSecondNode(); 207 continue bigloop; 208 } 209 case NodeTypes.ARGSCATNODE: { 210 ArgsCatNode iVisited = (ArgsCatNode) node; 211 212 IRubyObject args = evalInternal(runtime,context, iVisited.getFirstNode(), self, aBlock); 213 IRubyObject secondArgs = splatValue(runtime, evalInternal(runtime,context, iVisited.getSecondNode(), self, aBlock)); 214 RubyArray list = args instanceof RubyArray ? (RubyArray) args : runtime.newArray(args); 215 216 return list.concat(secondArgs); 217 } 218 case NodeTypes.ARGSPUSHNODE: { 219 ArgsPushNode iVisited = (ArgsPushNode) node; 220 221 RubyArray args = (RubyArray) evalInternal(runtime,context, iVisited.getFirstNode(), self, aBlock).dup(); 222 return args.append(evalInternal(runtime,context, iVisited.getSecondNode(), self, aBlock)); 223 } 224 case NodeTypes.ARRAYNODE: { 231 ArrayNode iVisited = (ArrayNode) node; 232 IRubyObject[] array = new IRubyObject[iVisited.size()]; 233 int i = 0; 234 for (Iterator iterator = iVisited.iterator(); iterator.hasNext();) { 235 Node next = (Node) iterator.next(); 236 237 array[i++] = evalInternal(runtime,context, next, self, aBlock); 238 } 239 240 return runtime.newArrayNoCopy(array); 241 } 242 case NodeTypes.ATTRASSIGNNODE: { 246 AttrAssignNode iVisited = (AttrAssignNode) node; 247 248 IRubyObject receiver = evalInternal(runtime,context, iVisited.getReceiverNode(), self, aBlock); 249 IRubyObject[] args = setupArgs(runtime, context, iVisited.getArgsNode(), self); 250 251 assert receiver.getMetaClass() != null : receiver.getClass().getName(); 252 253 CallType callType = (receiver == self ? CallType.VARIABLE : CallType.NORMAL); 255 256 receiver.callMethod(context, iVisited.getName(), args, callType); 257 258 return args[args.length - 1]; 259 } 260 case NodeTypes.BACKREFNODE: { 261 BackRefNode iVisited = (BackRefNode) node; 262 IRubyObject backref = context.getBackref(); 263 switch (iVisited.getType()) { 264 case '~': 265 return backref; 266 case '&': 267 return RubyRegexp.last_match(backref); 268 case '`': 269 return RubyRegexp.match_pre(backref); 270 case '\'': 271 return RubyRegexp.match_post(backref); 272 case '+': 273 return RubyRegexp.match_last(backref); 274 } 275 break; 276 } 277 case NodeTypes.BEGINNODE: { 278 BeginNode iVisited = (BeginNode) node; 279 280 node = iVisited.getBodyNode(); 281 continue bigloop; 282 } 283 case NodeTypes.BIGNUMNODE: { 284 BignumNode iVisited = (BignumNode) node; 285 return RubyBignum.newBignum(runtime, iVisited.getValue()); 286 } 287 case NodeTypes.BLOCKNODE: { 294 BlockNode iVisited = (BlockNode) node; 295 296 IRubyObject result = runtime.getNil(); 297 for (Iterator iter = iVisited.iterator(); iter.hasNext();) { 298 result = evalInternal(runtime,context, (Node) iter.next(), self, aBlock); 299 } 300 301 return result; 302 } 303 case NodeTypes.BLOCKPASSNODE: 304 assert false: "Call nodes and friends deal with this"; 305 case NodeTypes.BREAKNODE: { 306 BreakNode iVisited = (BreakNode) node; 307 308 IRubyObject result = evalInternal(runtime,context, iVisited.getValueNode(), self, aBlock); 309 310 JumpException je = new JumpException(JumpException.JumpType.BreakJump); 311 312 je.setValue(result); 313 314 throw je; 315 } 316 case NodeTypes.CALLNODE: { 317 CallNode iVisited = (CallNode) node; 318 319 IRubyObject receiver = evalInternal(runtime,context, iVisited.getReceiverNode(), self, aBlock); 320 IRubyObject[] args = setupArgs(runtime, context, iVisited.getArgsNode(), self); 321 322 assert receiver.getMetaClass() != null : receiver.getClass().getName(); 323 324 Block block = getBlock(runtime, context, self, aBlock, iVisited.getIterNode()); 325 326 if (!block.isGiven()) { 328 RubyModule module = receiver.getMetaClass(); 329 if (module.index != 0) { 330 return receiver.callMethod(context, module, 331 runtime.getSelectorTable().table[module.index][iVisited.index], 332 iVisited.getName(), args, CallType.NORMAL); 333 } 334 } 335 336 try { 337 while (true) { 338 try { 339 return receiver.callMethod(context, iVisited.getName(), args, 340 CallType.NORMAL, block); 341 } catch (JumpException je) { 342 switch (je.getJumpType().getTypeId()) { 343 case JumpType.RETRY: 344 break; 346 default: 347 throw je; 348 } 349 } 350 } 351 } catch (JumpException je) { 352 switch (je.getJumpType().getTypeId()) { 353 case JumpType.BREAK: 354 return (IRubyObject) je.getValue(); 355 default: 356 throw je; 357 } 358 } 359 } 360 case NodeTypes.CASENODE: { 361 CaseNode iVisited = (CaseNode) node; 362 IRubyObject expression = null; 363 if (iVisited.getCaseNode() != null) { 364 expression = evalInternal(runtime,context, iVisited.getCaseNode(), self, aBlock); 365 } 366 367 context.pollThreadEvents(); 368 369 IRubyObject result = runtime.getNil(); 370 371 Node firstWhenNode = iVisited.getFirstWhenNode(); 372 while (firstWhenNode != null) { 373 if (!(firstWhenNode instanceof WhenNode)) { 374 node = firstWhenNode; 375 continue bigloop; 376 } 377 378 WhenNode whenNode = (WhenNode) firstWhenNode; 379 380 if (whenNode.getExpressionNodes() instanceof ArrayNode) { 381 for (Iterator iter = ((ArrayNode) whenNode.getExpressionNodes()).iterator(); iter 382 .hasNext();) { 383 Node tag = (Node) iter.next(); 384 385 context.setPosition(tag.getPosition()); 386 if (isTrace(runtime)) { 387 callTraceFunction(runtime, context, "line", self); 388 } 389 390 if (tag instanceof WhenNode) { 393 RubyArray expressions = (RubyArray) evalInternal(runtime,context, ((WhenNode) tag) 394 .getExpressionNodes(), self, aBlock); 395 396 for (int j = 0,k = expressions.getLength(); j < k; j++) { 397 IRubyObject condition = expressions.eltInternal(j); 398 399 if ((expression != null && condition.callMethod(context, "===", expression) 400 .isTrue()) 401 || (expression == null && condition.isTrue())) { 402 node = ((WhenNode) firstWhenNode).getBodyNode(); 403 continue bigloop; 404 } 405 } 406 continue; 407 } 408 409 result = evalInternal(runtime,context, tag, self, aBlock); 410 411 if ((expression != null && result.callMethod(context, "===", expression).isTrue()) 412 || (expression == null && result.isTrue())) { 413 node = whenNode.getBodyNode(); 414 continue bigloop; 415 } 416 } 417 } else { 418 result = evalInternal(runtime,context, whenNode.getExpressionNodes(), self, aBlock); 419 420 if ((expression != null && result.callMethod(context, "===", expression).isTrue()) 421 || (expression == null && result.isTrue())) { 422 node = ((WhenNode) firstWhenNode).getBodyNode(); 423 continue bigloop; 424 } 425 } 426 427 context.pollThreadEvents(); 428 429 firstWhenNode = whenNode.getNextCase(); 430 } 431 432 return runtime.getNil(); 433 } 434 case NodeTypes.CLASSNODE: { 435 ClassNode iVisited = (ClassNode) node; 436 Node superNode = iVisited.getSuperNode(); 437 RubyClass superClass = null; 438 if(superNode != null) { 439 IRubyObject _super = evalInternal(runtime,context, superNode, self, aBlock); 440 if(!(_super instanceof RubyClass)) { 441 throw runtime.newTypeError("superclass must be a Class (" + RubyObject.trueFalseNil(_super) + ") given"); 442 } 443 superClass = superNode == null ? null : (RubyClass)_super; 444 } 445 Node classNameNode = iVisited.getCPath(); 446 String name = ((INameNode) classNameNode).getName(); 447 RubyModule enclosingClass = getEnclosingModule(runtime, context, classNameNode, self, aBlock); 448 RubyClass rubyClass = enclosingClass.defineOrGetClassUnder(name, superClass); 449 450 if (context.getWrapper() != null) { 451 rubyClass.extendObject(context.getWrapper()); 452 rubyClass.includeModule(context.getWrapper()); 453 } 454 return evalClassDefinitionBody(runtime, context, iVisited.getScope(), iVisited.getBodyNode(), rubyClass, self, aBlock); 455 } 456 case NodeTypes.CLASSVARASGNNODE: { 457 ClassVarAsgnNode iVisited = (ClassVarAsgnNode) node; 458 IRubyObject result = evalInternal(runtime,context, iVisited.getValueNode(), self, aBlock); 459 RubyModule rubyClass = getClassVariableBase(context, runtime); 460 461 if (rubyClass == null) { 462 rubyClass = self.getMetaClass(); 463 } 464 rubyClass.setClassVar(iVisited.getName(), result); 465 466 return result; 467 } 468 case NodeTypes.CLASSVARDECLNODE: { 469 470 ClassVarDeclNode iVisited = (ClassVarDeclNode) node; 471 472 RubyModule rubyClass = getClassVariableBase(context, runtime); 473 if (rubyClass == null) { 474 throw runtime.newTypeError("no class/module to define class variable"); 475 } 476 IRubyObject result = evalInternal(runtime,context, iVisited.getValueNode(), self, aBlock); 477 rubyClass.setClassVar(iVisited.getName(), result); 478 479 return result; 480 } 481 case NodeTypes.CLASSVARNODE: { 482 ClassVarNode iVisited = (ClassVarNode) node; 483 RubyModule rubyClass = getClassVariableBase(context, runtime); 484 485 if (rubyClass == null) { 486 rubyClass = self.getMetaClass(); 487 } 488 489 return rubyClass.getClassVar(iVisited.getName()); 490 } 491 case NodeTypes.COLON2NODE: { 492 Colon2Node iVisited = (Colon2Node) node; 493 Node leftNode = iVisited.getLeftNode(); 494 495 if (leftNode == null) { 499 return runtime.getObject().getConstantFrom(iVisited.getName()); 500 } else { 501 IRubyObject result = evalInternal(runtime,context, iVisited.getLeftNode(), self, aBlock); 502 if (result instanceof RubyModule) { 503 return ((RubyModule) result).getConstantFrom(iVisited.getName()); 504 } else { 505 return result.callMethod(context, iVisited.getName(), aBlock); 506 } 507 } 508 } 509 case NodeTypes.COLON3NODE: { 510 Colon3Node iVisited = (Colon3Node) node; 511 return runtime.getObject().getConstantFrom(iVisited.getName()); 512 } 513 case NodeTypes.CONSTDECLNODE: { 514 ConstDeclNode iVisited = (ConstDeclNode) node; 515 Node constNode = iVisited.getConstNode(); 516 517 IRubyObject result = evalInternal(runtime,context, iVisited.getValueNode(), self, aBlock); 518 IRubyObject module; 519 520 if (constNode == null) { 521 if (context.getRubyClass() == null) { 523 throw runtime.newTypeError("no class/module to define constant"); 525 } 526 module = (RubyModule) context.peekCRef().getValue(); 527 } else if (constNode instanceof Colon2Node) { 528 module = evalInternal(runtime,context, ((Colon2Node) iVisited.getConstNode()).getLeftNode(), self, aBlock); 529 } else { module = runtime.getObject(); 531 } 532 533 ((RubyModule) module).setConstant(iVisited.getName(), result); 535 536 return result; 537 } 538 case NodeTypes.CONSTNODE: { 539 ConstNode iVisited = (ConstNode) node; 540 return context.getConstant(iVisited.getName()); 541 } 542 case NodeTypes.DASGNNODE: { 543 DAsgnNode iVisited = (DAsgnNode) node; 544 545 IRubyObject result = evalInternal(runtime,context, iVisited.getValueNode(), self, aBlock); 546 547 context.getCurrentScope().setValue(iVisited.getIndex(), result, iVisited.getDepth()); 549 550 return result; 551 } 552 case NodeTypes.DEFINEDNODE: { 553 DefinedNode iVisited = (DefinedNode) node; 554 String definition = getDefinition(runtime, context, iVisited.getExpressionNode(), self, aBlock); 555 if (definition != null) { 556 return runtime.newString(definition); 557 } else { 558 return runtime.getNil(); 559 } 560 } 561 case NodeTypes.DEFNNODE: { 562 DefnNode iVisited = (DefnNode) node; 563 564 RubyModule containingClass = context.getRubyClass(); 565 566 if (containingClass == null) { 567 throw runtime.newTypeError("No class to add method."); 568 } 569 570 String name = iVisited.getName(); 571 572 if (containingClass == runtime.getObject() && name == "initialize") { 573 runtime.getWarnings().warn("redefining Object#initialize may cause infinite loop"); 574 } 575 576 Visibility visibility = context.getCurrentVisibility(); 577 if (name == "initialize" || visibility.isModuleFunction() || context.isTopLevel()) { 578 visibility = Visibility.PRIVATE; 579 } 580 581 DefaultMethod newMethod = new DefaultMethod(containingClass, iVisited.getScope(), 582 iVisited.getBodyNode(), (ArgsNode) iVisited.getArgsNode(), visibility, context.peekCRef()); 583 584 containingClass.addMethod(name, newMethod); 585 586 if (context.getCurrentVisibility().isModuleFunction()) { 587 containingClass.getSingletonClass().addMethod( 588 name, 589 new WrapperMethod(containingClass.getSingletonClass(), newMethod, 590 Visibility.PUBLIC)); 591 containingClass.callMethod(context, "singleton_method_added", runtime.newSymbol(name)); 592 } 593 594 if (containingClass.isSingleton()) { 596 ((MetaClass) containingClass).getAttachedObject().callMethod( 597 context, "singleton_method_added", runtime.newSymbol(iVisited.getName())); 598 } else { 599 containingClass.callMethod(context, "method_added", runtime.newSymbol(name)); 600 } 601 602 return runtime.getNil(); 603 } 604 case NodeTypes.DEFSNODE: { 605 DefsNode iVisited = (DefsNode) node; 606 IRubyObject receiver = evalInternal(runtime,context, iVisited.getReceiverNode(), self, aBlock); 607 608 RubyClass rubyClass; 609 610 if (receiver.isNil()) { 611 rubyClass = runtime.getNilClass(); 612 } else if (receiver == runtime.getTrue()) { 613 rubyClass = runtime.getClass("TrueClass"); 614 } else if (receiver == runtime.getFalse()) { 615 rubyClass = runtime.getClass("FalseClass"); 616 } else { 617 if (runtime.getSafeLevel() >= 4 && !receiver.isTaint()) { 618 throw runtime.newSecurityError("Insecure; can't define singleton method."); 619 } 620 if (receiver.isFrozen()) { 621 throw runtime.newFrozenError("object"); 622 } 623 if (receiver.getMetaClass() == runtime.getFixnum() || receiver.getMetaClass() == runtime.getClass("Symbol")) { 624 throw runtime.newTypeError("can't define singleton method \"" + iVisited.getName() 625 + "\" for " + receiver.getType()); 626 } 627 628 rubyClass = receiver.getSingletonClass(); 629 } 630 631 if (runtime.getSafeLevel() >= 4) { 632 Object method = rubyClass.getMethods().get(iVisited.getName()); 633 if (method != null) { 634 throw runtime.newSecurityError("Redefining method prohibited."); 635 } 636 } 637 638 DefaultMethod newMethod = new DefaultMethod(rubyClass, iVisited.getScope(), 639 iVisited.getBodyNode(), (ArgsNode) iVisited.getArgsNode(), 640 Visibility.PUBLIC, context.peekCRef()); 641 642 rubyClass.addMethod(iVisited.getName(), newMethod); 643 receiver.callMethod(context, "singleton_method_added", runtime.newSymbol(iVisited.getName())); 644 645 return runtime.getNil(); 646 } 647 case NodeTypes.DOTNODE: { 648 DotNode iVisited = (DotNode) node; 649 return RubyRange.newRange(runtime, 650 evalInternal(runtime,context, iVisited.getBeginNode(), self, aBlock), 651 evalInternal(runtime,context, iVisited.getEndNode(), self, aBlock), 652 iVisited.isExclusive()); 653 } 654 case NodeTypes.DREGEXPNODE: { 655 DRegexpNode iVisited = (DRegexpNode) node; 656 657 RubyString string = runtime.newString(new ByteList()); 658 for (Iterator iterator = iVisited.iterator(); iterator.hasNext();) { 659 Node iterNode = (Node) iterator.next(); 660 if (iterNode instanceof StrNode) { 661 string.getByteList().append(((StrNode) iterNode).getValue()); 662 } else { 663 string.append(evalInternal(runtime,context, iterNode, self, aBlock)); 664 } 665 } 666 667 String lang = null; 668 int opts = iVisited.getOptions(); 669 if((opts & 16) != 0) { lang = "n"; 671 } else if((opts & 48) != 0) { lang = "s"; 673 } else if((opts & 64) != 0) { lang = "u"; 675 } 676 677 return RubyRegexp.newRegexp(runtime, string.toString(), iVisited.getOptions(), lang); 678 } 679 case NodeTypes.DSTRNODE: { 680 DStrNode iVisited = (DStrNode) node; 681 682 RubyString string = runtime.newString(new ByteList()); 683 for (Iterator iterator = iVisited.iterator(); iterator.hasNext();) { 684 Node iterNode = (Node) iterator.next(); 685 if (iterNode instanceof StrNode) { 686 string.getByteList().append(((StrNode) iterNode).getValue()); 687 } else { 688 string.append(evalInternal(runtime,context, iterNode, self, aBlock)); 689 } 690 } 691 692 return string; 693 } 694 case NodeTypes.DSYMBOLNODE: { 695 DSymbolNode iVisited = (DSymbolNode) node; 696 697 RubyString string = runtime.newString(new ByteList()); 698 for (Iterator iterator = iVisited.iterator(); iterator.hasNext();) { 699 Node iterNode = (Node) iterator.next(); 700 if (iterNode instanceof StrNode) { 701 string.getByteList().append(((StrNode) iterNode).getValue()); 702 } else { 703 string.append(evalInternal(runtime,context, iterNode, self, aBlock)); 704 } 705 } 706 707 return runtime.newSymbol(string.toString()); 708 } 709 case NodeTypes.DVARNODE: { 710 DVarNode iVisited = (DVarNode) node; 711 712 IRubyObject obj = context.getCurrentScope().getValue(iVisited.getIndex(), iVisited.getDepth()); 714 715 return obj == null ? runtime.getNil() : obj; 717 } 718 case NodeTypes.DXSTRNODE: { 719 DXStrNode iVisited = (DXStrNode) node; 720 721 RubyString string = runtime.newString(new ByteList()); 722 for (Iterator iterator = iVisited.iterator(); iterator.hasNext();) { 723 Node iterNode = (Node) iterator.next(); 724 if (iterNode instanceof StrNode) { 725 string.getByteList().append(((StrNode) iterNode).getValue()); 726 } else { 727 string.append(evalInternal(runtime,context, iterNode, self, aBlock)); 728 } 729 } 730 731 return self.callMethod(context, "`", string); 732 } 733 case NodeTypes.ENSURENODE: { 734 EnsureNode iVisited = (EnsureNode) node; 735 736 if (iVisited.getEnsureNode() != null) { 738 IRubyObject result = runtime.getNil(); 739 740 try { 741 result = evalInternal(runtime,context, iVisited.getBodyNode(), self, aBlock); 742 } finally { 743 evalInternal(runtime,context, iVisited.getEnsureNode(), self, aBlock); 744 } 745 746 return result; 747 } 748 749 node = iVisited.getBodyNode(); 750 continue bigloop; 751 } 752 case NodeTypes.EVSTRNODE: { 753 EvStrNode iVisited = (EvStrNode) node; 754 755 return evalInternal(runtime,context, iVisited.getBody(), self, aBlock).objAsString(); 756 } 757 case NodeTypes.FALSENODE: { 758 context.pollThreadEvents(); 759 return runtime.getFalse(); 760 } 761 case NodeTypes.FCALLNODE: { 762 FCallNode iVisited = (FCallNode) node; 763 764 IRubyObject[] args = setupArgs(runtime, context, iVisited.getArgsNode(), self); 765 Block block = getBlock(runtime, context, self, aBlock, iVisited.getIterNode()); 766 767 try { 768 while (true) { 769 try { 770 IRubyObject result = self.callMethod(context, iVisited.getName(), args, 771 CallType.FUNCTIONAL, block); 772 if (result == null) { 773 result = runtime.getNil(); 774 } 775 776 return result; 777 } catch (JumpException je) { 778 switch (je.getJumpType().getTypeId()) { 779 case JumpType.RETRY: 780 break; 782 default: 783 throw je; 784 } 785 } 786 } 787 } catch (JumpException je) { 788 switch (je.getJumpType().getTypeId()) { 789 case JumpType.BREAK: 790 if (je.isBreakInKernelLoop()) { 792 if (block == je.getTarget()) je.setBreakInKernelLoop(false); 794 795 throw je; 796 } 797 798 return (IRubyObject) je.getValue(); 799 default: 800 throw je; 801 } 802 } 803 } 804 case NodeTypes.FIXNUMNODE: { 805 FixnumNode iVisited = (FixnumNode) node; 806 return iVisited.getFixnum(runtime); 807 } 808 case NodeTypes.FLIPNODE: { 809 FlipNode iVisited = (FlipNode) node; 810 IRubyObject result = runtime.getNil(); 811 812 if (iVisited.isExclusive()) { 813 if (!context.getCurrentScope().getValue(iVisited.getIndex(), iVisited.getDepth()).isTrue()) { 814 result = evalInternal(runtime,context, iVisited.getBeginNode(), self, aBlock).isTrue() ? runtime.getFalse() 815 : runtime.getTrue(); 816 context.getCurrentScope().setValue(iVisited.getIndex(), result, iVisited.getDepth()); 817 return result; 818 } else { 819 if (evalInternal(runtime,context, iVisited.getEndNode(), self, aBlock).isTrue()) { 820 context.getCurrentScope().setValue(iVisited.getIndex(), runtime.getFalse(), iVisited.getDepth()); 821 } 822 return runtime.getTrue(); 823 } 824 } else { 825 if (!context.getCurrentScope().getValue(iVisited.getIndex(), iVisited.getDepth()).isTrue()) { 826 if (evalInternal(runtime,context, iVisited.getBeginNode(), self, aBlock).isTrue()) { 827 context.getCurrentScope().setValue( 828 iVisited.getIndex(), 829 evalInternal(runtime,context, iVisited.getEndNode(), self, aBlock).isTrue() ? runtime.getFalse() 830 : runtime.getTrue(), iVisited.getDepth()); 831 return runtime.getTrue(); 832 } else { 833 return runtime.getFalse(); 834 } 835 } else { 836 if (evalInternal(runtime,context, iVisited.getEndNode(), self, aBlock).isTrue()) { 837 context.getCurrentScope().setValue(iVisited.getIndex(), runtime.getFalse(), iVisited.getDepth()); 838 } 839 return runtime.getTrue(); 840 } 841 } 842 } 843 case NodeTypes.FLOATNODE: { 844 FloatNode iVisited = (FloatNode) node; 845 return RubyFloat.newFloat(runtime, iVisited.getValue()); 846 } 847 case NodeTypes.FORNODE: { 848 ForNode iVisited = (ForNode) node; 849 850 Block block = ForBlock.createBlock(context, iVisited.getVarNode(), 851 context.getCurrentScope(), iVisited.getCallable(), self); 852 853 try { 854 while (true) { 855 try { 856 ISourcePosition position = context.getPosition(); 857 858 IRubyObject recv = null; 859 try { 860 recv = evalInternal(runtime,context, iVisited.getIterNode(), self, aBlock); 861 } finally { 862 context.setPosition(position); 863 } 864 865 return recv.callMethod(context, "each", IRubyObject.NULL_ARRAY, CallType.NORMAL, block); 866 } catch (JumpException je) { 867 switch (je.getJumpType().getTypeId()) { 868 case JumpType.RETRY: 869 break; 871 default: 872 throw je; 873 } 874 } 875 } 876 } catch (JumpException je) { 877 switch (je.getJumpType().getTypeId()) { 878 case JumpType.BREAK: 879 return (IRubyObject) je.getValue(); 880 default: 881 throw je; 882 } 883 } 884 } 885 case NodeTypes.GLOBALASGNNODE: { 886 GlobalAsgnNode iVisited = (GlobalAsgnNode) node; 887 888 IRubyObject result = evalInternal(runtime,context, iVisited.getValueNode(), self, aBlock); 889 890 runtime.getGlobalVariables().set(iVisited.getName(), result); 891 892 if (iVisited.getName() == "$KCODE") { 894 runtime.setKCode(KCode.create(runtime, result.toString())); 895 } 896 897 return result; 898 } 899 case NodeTypes.GLOBALVARNODE: { 900 GlobalVarNode iVisited = (GlobalVarNode) node; 901 return runtime.getGlobalVariables().get(iVisited.getName()); 902 } 903 case NodeTypes.HASHNODE: { 904 HashNode iVisited = (HashNode) node; 905 906 Map hash = null; 907 if (iVisited.getListNode() != null) { 908 hash = new HashMap (iVisited.getListNode().size() / 2); 909 910 for (Iterator iterator = iVisited.getListNode().iterator(); iterator.hasNext();) { 911 IRubyObject key = evalInternal(runtime,context, (Node) iterator.next(), self, aBlock); 914 IRubyObject value = evalInternal(runtime,context, (Node) iterator.next(), self, aBlock); 915 916 hash.put(key, value); 917 } 918 } 919 920 if (hash == null) { 921 return RubyHash.newHash(runtime); 922 } 923 924 return RubyHash.newHash(runtime, hash, runtime.getNil()); 925 } 926 case NodeTypes.IFNODE: { 927 IfNode iVisited = (IfNode) node; 928 IRubyObject result = evalInternal(runtime,context, iVisited.getCondition(), self, aBlock); 929 930 if (result.isTrue()) { 931 node = iVisited.getThenBody(); 932 continue bigloop; 933 } else { 934 node = iVisited.getElseBody(); 935 continue bigloop; 936 } 937 } 938 case NodeTypes.INSTASGNNODE: { 939 InstAsgnNode iVisited = (InstAsgnNode) node; 940 941 IRubyObject result = evalInternal(runtime,context, iVisited.getValueNode(), self, aBlock); 942 self.setInstanceVariable(iVisited.getName(), result); 943 944 return result; 945 } 946 case NodeTypes.INSTVARNODE: { 947 InstVarNode iVisited = (InstVarNode) node; 948 IRubyObject variable = self.getInstanceVariable(iVisited.getName()); 949 950 return variable == null ? runtime.getNil() : variable; 951 } 952 case NodeTypes.ITERNODE: 956 assert false: "Call nodes deal with these directly"; 957 case NodeTypes.LOCALASGNNODE: { 958 LocalAsgnNode iVisited = (LocalAsgnNode) node; 959 IRubyObject result = evalInternal(runtime,context, iVisited.getValueNode(), self, aBlock); 960 961 context.getCurrentScope().setValue(iVisited.getIndex(), result, iVisited.getDepth()); 963 964 return result; 965 } 966 case NodeTypes.LOCALVARNODE: { 967 LocalVarNode iVisited = (LocalVarNode) node; 968 969 IRubyObject result = context.getCurrentScope().getValue(iVisited.getIndex(), iVisited.getDepth()); 971 972 return result == null ? runtime.getNil() : result; 973 } 974 case NodeTypes.MATCH2NODE: { 975 Match2Node iVisited = (Match2Node) node; 976 IRubyObject recv = evalInternal(runtime,context, iVisited.getReceiverNode(), self, aBlock); 977 IRubyObject value = evalInternal(runtime,context, iVisited.getValueNode(), self, aBlock); 978 979 return ((RubyRegexp) recv).match(value); 980 } 981 case NodeTypes.MATCH3NODE: { 982 Match3Node iVisited = (Match3Node) node; 983 IRubyObject recv = evalInternal(runtime,context, iVisited.getReceiverNode(), self, aBlock); 984 IRubyObject value = evalInternal(runtime,context, iVisited.getValueNode(), self, aBlock); 985 986 if (value instanceof RubyString) { 987 return ((RubyRegexp) recv).match(value); 988 } else { 989 return value.callMethod(context, "=~", recv); 990 } 991 } 992 case NodeTypes.MATCHNODE: { 993 MatchNode iVisited = (MatchNode) node; 994 return ((RubyRegexp) evalInternal(runtime,context, iVisited.getRegexpNode(), self, aBlock)).match2(); 995 } 996 case NodeTypes.MODULENODE: { 997 ModuleNode iVisited = (ModuleNode) node; 998 Node classNameNode = iVisited.getCPath(); 999 String name = ((INameNode) classNameNode).getName(); 1000 RubyModule enclosingModule = getEnclosingModule(runtime, context, classNameNode, self, aBlock); 1001 1002 if (enclosingModule == null) { 1003 throw runtime.newTypeError("no outer class/module"); 1004 } 1005 1006 RubyModule module; 1007 if (enclosingModule == runtime.getObject()) { 1008 module = runtime.getOrCreateModule(name); 1009 } else { 1010 module = enclosingModule.defineModuleUnder(name); 1011 } 1012 return evalClassDefinitionBody(runtime, context, iVisited.getScope(), iVisited.getBodyNode(), module, self, aBlock); 1013 } 1014 case NodeTypes.MULTIPLEASGNNODE: { 1015 MultipleAsgnNode iVisited = (MultipleAsgnNode) node; 1016 IRubyObject value = evalInternal(runtime,context, iVisited.getValueNode(), self, aBlock); 1017 1018 if (!(value instanceof RubyArray)) { 1019 value = RubyArray.newArray(runtime, value); 1020 } 1021 return AssignmentVisitor.multiAssign(runtime, context, self, iVisited, (RubyArray) value, false); 1022 } 1023 case NodeTypes.NEWLINENODE: { 1024 NewlineNode iVisited = (NewlineNode) node; 1025 1026 context.setPosition(iVisited.getPosition()); 1028 1029 if (isTrace(runtime)) { 1030 callTraceFunction(runtime, context, "line", self); 1031 } 1032 1033 node = iVisited.getNextNode(); 1035 continue bigloop; 1036 } 1037 case NodeTypes.NEXTNODE: { 1038 NextNode iVisited = (NextNode) node; 1039 1040 context.pollThreadEvents(); 1041 1042 IRubyObject result = evalInternal(runtime,context, iVisited.getValueNode(), self, aBlock); 1043 1044 JumpException je = new JumpException(JumpException.JumpType.NextJump); 1046 1047 je.setTarget(iVisited); 1048 je.setValue(result); 1049 1050 throw je; 1051 } 1052 case NodeTypes.NILNODE: 1053 return runtime.getNil(); 1054 case NodeTypes.NOTNODE: { 1055 NotNode iVisited = (NotNode) node; 1056 1057 IRubyObject result = evalInternal(runtime,context, iVisited.getConditionNode(), self, aBlock); 1058 return result.isTrue() ? runtime.getFalse() : runtime.getTrue(); 1059 } 1060 case NodeTypes.NTHREFNODE: { 1061 NthRefNode iVisited = (NthRefNode) node; 1062 return RubyRegexp.nth_match(iVisited.getMatchNumber(), context.getBackref()); 1063 } 1064 case NodeTypes.OPASGNANDNODE: { 1065 BinaryOperatorNode iVisited = (BinaryOperatorNode) node; 1066 1067 IRubyObject result = evalInternal(runtime,context, iVisited.getFirstNode(), self, aBlock); 1069 if (!result.isTrue()) return result; 1070 node = iVisited.getSecondNode(); 1071 continue bigloop; 1072 } 1073 case NodeTypes.OPASGNNODE: { 1074 OpAsgnNode iVisited = (OpAsgnNode) node; 1075 IRubyObject receiver = evalInternal(runtime,context, iVisited.getReceiverNode(), self, aBlock); 1076 IRubyObject value = receiver.callMethod(context, iVisited.getVariableName()); 1077 1078 if (iVisited.getOperatorName() == "||") { 1079 if (value.isTrue()) { 1080 return value; 1081 } 1082 value = evalInternal(runtime,context, iVisited.getValueNode(), self, aBlock); 1083 } else if (iVisited.getOperatorName() == "&&") { 1084 if (!value.isTrue()) { 1085 return value; 1086 } 1087 value = evalInternal(runtime,context, iVisited.getValueNode(), self, aBlock); 1088 } else { 1089 value = value.callMethod(context, iVisited.getOperatorName(), evalInternal(runtime,context, 1090 iVisited.getValueNode(), self, aBlock)); 1091 } 1092 1093 receiver.callMethod(context, iVisited.getVariableNameAsgn(), value); 1094 1095 context.pollThreadEvents(); 1096 1097 return value; 1098 } 1099 case NodeTypes.OPASGNORNODE: { 1100 OpAsgnOrNode iVisited = (OpAsgnOrNode) node; 1101 String def = getDefinition(runtime, context, iVisited.getFirstNode(), self, aBlock); 1102 1103 IRubyObject result = runtime.getNil(); 1104 if (def != null) { 1105 result = evalInternal(runtime,context, iVisited.getFirstNode(), self, aBlock); 1106 } 1107 if (!result.isTrue()) { 1108 result = evalInternal(runtime,context, iVisited.getSecondNode(), self, aBlock); 1109 } 1110 1111 return result; 1112 } 1113 case NodeTypes.OPELEMENTASGNNODE: { 1114 OpElementAsgnNode iVisited = (OpElementAsgnNode) node; 1115 IRubyObject receiver = evalInternal(runtime,context, iVisited.getReceiverNode(), self, aBlock); 1116 1117 IRubyObject[] args = setupArgs(runtime, context, iVisited.getArgsNode(), self); 1118 1119 IRubyObject firstValue = receiver.callMethod(context, "[]", args); 1120 1121 if (iVisited.getOperatorName() == "||") { 1122 if (firstValue.isTrue()) { 1123 return firstValue; 1124 } 1125 firstValue = evalInternal(runtime,context, iVisited.getValueNode(), self, aBlock); 1126 } else if (iVisited.getOperatorName() == "&&") { 1127 if (!firstValue.isTrue()) { 1128 return firstValue; 1129 } 1130 firstValue = evalInternal(runtime,context, iVisited.getValueNode(), self, aBlock); 1131 } else { 1132 firstValue = firstValue.callMethod(context, iVisited.getOperatorName(), evalInternal(runtime,context, iVisited 1133 .getValueNode(), self, aBlock)); 1134 } 1135 1136 IRubyObject[] expandedArgs = new IRubyObject[args.length + 1]; 1137 System.arraycopy(args, 0, expandedArgs, 0, args.length); 1138 expandedArgs[expandedArgs.length - 1] = firstValue; 1139 return receiver.callMethod(context, "[]=", expandedArgs); 1140 } 1141 case NodeTypes.OPTNNODE: { 1142 OptNNode iVisited = (OptNNode) node; 1143 1144 IRubyObject result = runtime.getNil(); 1145 while (RubyKernel.gets(runtime.getTopSelf(), IRubyObject.NULL_ARRAY).isTrue()) { 1146 loop: while (true) { try { 1148 result = evalInternal(runtime,context, iVisited.getBodyNode(), self, aBlock); 1149 break; 1150 } catch (JumpException je) { 1151 switch (je.getJumpType().getTypeId()) { 1152 case JumpType.REDO: 1153 break; 1155 case JumpType.NEXT: 1156 break loop; 1158 case JumpType.BREAK: 1159 return (IRubyObject) je.getValue(); 1161 default: 1162 throw je; 1163 } 1164 } 1165 } 1166 } 1167 return result; 1168 } 1169 case NodeTypes.ORNODE: { 1170 OrNode iVisited = (OrNode) node; 1171 1172 IRubyObject result = evalInternal(runtime,context, iVisited.getFirstNode(), self, aBlock); 1173 1174 if (!result.isTrue()) { 1175 result = evalInternal(runtime,context, iVisited.getSecondNode(), self, aBlock); 1176 } 1177 1178 return result; 1179 } 1180 case NodeTypes.REDONODE: { 1184 context.pollThreadEvents(); 1185 1186 JumpException je = new JumpException(JumpException.JumpType.RedoJump); 1188 1189 je.setValue(node); 1190 1191 throw je; 1192 } 1193 case NodeTypes.REGEXPNODE: { 1194 RegexpNode iVisited = (RegexpNode) node; 1195 String lang = null; 1196 int opts = iVisited.getOptions(); 1197 if((opts & 16) != 0) { lang = "n"; 1199 } else if((opts & 48) != 0) { lang = "s"; 1201 } else if((opts & 64) != 0) { lang = "u"; 1203 } 1204 try { 1205 return RubyRegexp.newRegexp(runtime, iVisited.getPattern(), lang); 1206 } catch(java.util.regex.PatternSyntaxException e) { 1207 throw runtime.newSyntaxError(e.getMessage()); 1208 } 1209 } 1210 case NodeTypes.RESCUEBODYNODE: { 1211 RescueBodyNode iVisited = (RescueBodyNode) node; 1212 node = iVisited.getBodyNode(); 1213 continue bigloop; 1214 } 1215 case NodeTypes.RESCUENODE: { 1216 RescueNode iVisited = (RescueNode)node; 1217 RescuedBlock : while (true) { 1218 IRubyObject globalExceptionState = runtime.getGlobalVariables().get("$!"); 1219 boolean anotherExceptionRaised = false; 1220 try { 1221 IRubyObject result = evalInternal(runtime,context, iVisited.getBodyNode(), self, aBlock); 1223 1224 if (iVisited.getElseNode() != null) { 1226 if (iVisited.getRescueNode() == null) { 1227 runtime.getWarnings().warn(iVisited.getElseNode().getPosition(), "else without rescue is useless"); 1228 } 1229 result = evalInternal(runtime,context, iVisited.getElseNode(), self, aBlock); 1230 } 1231 1232 return result; 1233 } catch (RaiseException raiseJump) { 1234 RubyException raisedException = raiseJump.getException(); 1235 runtime.getGlobalVariables().set("$!", raisedException); 1239 1240 RescueBodyNode rescueNode = iVisited.getRescueNode(); 1241 1242 while (rescueNode != null) { 1243 Node exceptionNodes = rescueNode.getExceptionNodes(); 1244 ListNode exceptionNodesList; 1245 1246 if (exceptionNodes instanceof SplatNode) { 1247 exceptionNodesList = (ListNode) evalInternal(runtime,context, exceptionNodes, self, aBlock); 1248 } else { 1249 exceptionNodesList = (ListNode) exceptionNodes; 1250 } 1251 1252 if (isRescueHandled(runtime, context, raisedException, exceptionNodesList, self)) { 1253 try { 1254 return evalInternal(runtime,context, rescueNode, self, aBlock); 1255 } catch (JumpException je) { 1256 if (je.getJumpType() == JumpException.JumpType.RetryJump) { 1257 continue RescuedBlock; 1261 1262 } else { 1263 anotherExceptionRaised = true; 1264 throw je; 1265 } 1266 } 1267 } 1268 1269 rescueNode = rescueNode.getOptRescueNode(); 1270 } 1271 1272 throw raiseJump; 1274 } finally { 1275 if (!anotherExceptionRaised) 1277 runtime.getGlobalVariables().set("$!", globalExceptionState); 1278 } 1279 } 1280 } 1281 case NodeTypes.RETRYNODE: { 1282 context.pollThreadEvents(); 1283 1284 JumpException je = new JumpException(JumpException.JumpType.RetryJump); 1285 1286 throw je; 1287 } 1288 case NodeTypes.RETURNNODE: { 1289 ReturnNode iVisited = (ReturnNode) node; 1290 1291 IRubyObject result = evalInternal(runtime,context, iVisited.getValueNode(), self, aBlock); 1292 1293 JumpException je = new JumpException(JumpException.JumpType.ReturnJump); 1294 1295 je.setTarget(iVisited.getTarget()); 1296 je.setValue(result); 1297 1298 throw je; 1299 } 1300 case NodeTypes.ROOTNODE: { 1301 RootNode iVisited = (RootNode) node; 1302 DynamicScope scope = iVisited.getScope(); 1303 1304 if (scope == null) { 1308 scope = new DynamicScope(iVisited.getStaticScope(), null); 1309 } 1310 1311 context.preRootNode(scope); 1313 1314 1316 try { 1317 return eval(runtime, context, iVisited.getBodyNode(), self, aBlock); 1318 } finally { 1319 context.postRootNode(); 1320 } 1321 } 1322 case NodeTypes.SCLASSNODE: { 1323 SClassNode iVisited = (SClassNode) node; 1324 IRubyObject receiver = evalInternal(runtime,context, iVisited.getReceiverNode(), self, aBlock); 1325 1326 RubyClass singletonClass; 1327 1328 if (receiver.isNil()) { 1329 singletonClass = runtime.getNilClass(); 1330 } else if (receiver == runtime.getTrue()) { 1331 singletonClass = runtime.getClass("TrueClass"); 1332 } else if (receiver == runtime.getFalse()) { 1333 singletonClass = runtime.getClass("FalseClass"); 1334 } else if (receiver.getMetaClass() == runtime.getFixnum() || receiver.getMetaClass() == runtime.getClass("Symbol")) { 1335 throw runtime.newTypeError("no virtual class for " + receiver.getMetaClass().getBaseName()); 1336 } else { 1337 if (runtime.getSafeLevel() >= 4 && !receiver.isTaint()) { 1338 throw runtime.newSecurityError("Insecure: can't extend object."); 1339 } 1340 1341 singletonClass = receiver.getSingletonClass(); 1342 } 1343 1344 1345 1346 if (context.getWrapper() != null) { 1347 singletonClass.extendObject(context.getWrapper()); 1348 singletonClass.includeModule(context.getWrapper()); 1349 } 1350 1351 return evalClassDefinitionBody(runtime, context, iVisited.getScope(), iVisited.getBodyNode(), singletonClass, self, aBlock); 1352 } 1353 case NodeTypes.SELFNODE: 1354 return self; 1355 case NodeTypes.SPLATNODE: { 1356 SplatNode iVisited = (SplatNode) node; 1357 return splatValue(runtime, evalInternal(runtime,context, iVisited.getValue(), self, aBlock)); 1358 } 1359 case NodeTypes.STRNODE: { 1363 StrNode iVisited = (StrNode) node; 1364 return runtime.newString((ByteList) iVisited.getValue().clone()); 1365 } 1366 case NodeTypes.SUPERNODE: { 1367 SuperNode iVisited = (SuperNode) node; 1368 1369 1370 if (context.getFrameKlazz() == null) { 1371 String name = context.getFrameName(); 1372 throw runtime.newNameError("Superclass method '" + name 1373 + "' disabled.", name); 1374 } 1375 IRubyObject[] args = setupArgs(runtime, context, iVisited.getArgsNode(), self); 1376 Block block = getBlock(runtime, context, self, aBlock, iVisited.getIterNode()); 1377 1378 if (!block.isGiven()) block = aBlock; 1380 1381 return context.callSuper(args, block); 1382 } 1383 case NodeTypes.SVALUENODE: { 1384 SValueNode iVisited = (SValueNode) node; 1385 return aValueSplat(runtime, evalInternal(runtime,context, iVisited.getValue(), self, aBlock)); 1386 } 1387 case NodeTypes.SYMBOLNODE: { 1388 SymbolNode iVisited = (SymbolNode) node; 1389 return runtime.newSymbol(iVisited.getName()); 1390 } 1391 case NodeTypes.TOARYNODE: { 1392 ToAryNode iVisited = (ToAryNode) node; 1393 return aryToAry(runtime, evalInternal(runtime,context, iVisited.getValue(), self, aBlock)); 1394 } 1395 case NodeTypes.TRUENODE: { 1396 context.pollThreadEvents(); 1397 return runtime.getTrue(); 1398 } 1399 case NodeTypes.UNDEFNODE: { 1400 UndefNode iVisited = (UndefNode) node; 1401 1402 1403 if (context.getRubyClass() == null) { 1404 throw runtime 1405 .newTypeError("No class to undef method '" + iVisited.getName() + "'."); 1406 } 1407 context.getRubyClass().undef(iVisited.getName()); 1408 1409 return runtime.getNil(); 1410 } 1411 case NodeTypes.UNTILNODE: { 1412 UntilNode iVisited = (UntilNode) node; 1413 1414 IRubyObject result = runtime.getNil(); 1415 1416 while (!(result = evalInternal(runtime,context, iVisited.getConditionNode(), self, aBlock)).isTrue()) { 1417 loop: while (true) { try { 1419 result = evalInternal(runtime,context, iVisited.getBodyNode(), self, aBlock); 1420 break loop; 1421 } catch (JumpException je) { 1422 switch (je.getJumpType().getTypeId()) { 1423 case JumpType.REDO: 1424 continue; 1425 case JumpType.NEXT: 1426 break loop; 1427 case JumpType.BREAK: 1428 if (je.getTarget() == aBlock) { 1430 je.setTarget(null); 1431 1432 throw je; 1433 } 1434 1435 return (IRubyObject) je.getValue(); 1436 default: 1437 throw je; 1438 } 1439 } 1440 } 1441 } 1442 1443 return result; 1444 } 1445 case NodeTypes.VALIASNODE: { 1446 VAliasNode iVisited = (VAliasNode) node; 1447 runtime.getGlobalVariables().alias(iVisited.getNewName(), iVisited.getOldName()); 1448 1449 return runtime.getNil(); 1450 } 1451 case NodeTypes.VCALLNODE: { 1452 VCallNode iVisited = (VCallNode) node; 1453 return self.callMethod(context, iVisited.getName(), 1454 IRubyObject.NULL_ARRAY, CallType.VARIABLE); 1455 } 1456 case NodeTypes.WHENNODE: 1457 assert false; 1458 return null; 1459 case NodeTypes.WHILENODE: { 1460 WhileNode iVisited = (WhileNode) node; 1461 1462 IRubyObject result = runtime.getNil(); 1463 boolean firstTest = iVisited.evaluateAtStart(); 1464 1465 while (!firstTest || (result = evalInternal(runtime,context, iVisited.getConditionNode(), self, aBlock)).isTrue()) { 1466 firstTest = true; 1467 loop: while (true) { try { 1469 evalInternal(runtime,context, iVisited.getBodyNode(), self, aBlock); 1470 break loop; 1471 } catch (JumpException je) { 1472 switch (je.getJumpType().getTypeId()) { 1473 case JumpType.REDO: 1474 continue; 1475 case JumpType.NEXT: 1476 break loop; 1477 case JumpType.BREAK: 1478 if (je.getTarget() == aBlock) { 1480 je.setTarget(null); 1481 1482 throw je; 1483 } 1484 1485 return result; 1486 default: 1487 throw je; 1488 } 1489 } 1490 } 1491 } 1492 1493 return result; 1494 } 1495 case NodeTypes.XSTRNODE: { 1496 XStrNode iVisited = (XStrNode) node; 1497 return self.callMethod(context, "`", runtime.newString((ByteList) iVisited.getValue().clone())); 1498 } 1499 case NodeTypes.YIELDNODE: { 1500 YieldNode iVisited = (YieldNode) node; 1501 1502 IRubyObject result = evalInternal(runtime,context, iVisited.getArgsNode(), self, aBlock); 1503 if (iVisited.getArgsNode() == null) { 1504 result = null; 1505 } 1506 1507 Block block = context.getCurrentFrame().getBlock(); 1508 1509 return block.yield(context, result, null, null, iVisited.getCheckState()); 1510 1511 } 1512 case NodeTypes.ZARRAYNODE: { 1513 return runtime.newArray(); 1514 } 1515 case NodeTypes.ZSUPERNODE: { 1516 1517 1518 if (context.getFrameKlazz() == null) { 1519 String name = context.getFrameName(); 1520 throw runtime.newNameError("superclass method '" + name 1521 + "' disabled", name); 1522 } 1523 1524 Block block = getBlock(runtime, context, self, aBlock, ((ZSuperNode) node).getIterNode()); 1525 1526 if (!block.isGiven()) block = context.getCurrentFrame().getBlock(); 1528 1529 return context.callSuper(context.getFrameArgs(), block); 1530 } 1531 default: 1532 throw new RuntimeException ("Invalid node encountered in interpreter: \"" + node.getClass().getName() + "\", please report this at www.jruby.org"); 1533 } 1534 } while (true); 1535 } 1536 1537 private static String getArgumentDefinition(Ruby runtime, ThreadContext context, Node node, String type, IRubyObject self, Block block) { 1538 if (node == null) return type; 1539 1540 if (node instanceof ArrayNode) { 1541 for (Iterator iter = ((ArrayNode)node).iterator(); iter.hasNext(); ) { 1542 if (getDefinitionInner(runtime, context, (Node)iter.next(), self, block) == null) return null; 1543 } 1544 } else if (getDefinitionInner(runtime, context, node, self, block) == null) { 1545 return null; 1546 } 1547 1548 return type; 1549 } 1550 1551 private static String getDefinition(Ruby runtime, ThreadContext context, Node node, IRubyObject self, Block aBlock) { 1552 try { 1553 context.setWithinDefined(true); 1554 return getDefinitionInner(runtime, context, node, self, aBlock); 1555 } finally { 1556 context.setWithinDefined(false); 1557 } 1558 } 1559 1560 private static String getDefinitionInner(Ruby runtime, ThreadContext context, Node node, IRubyObject self, Block aBlock) { 1561 if (node == null) return "expression"; 1562 1563 switch(node.nodeId) { 1564 case NodeTypes.ATTRASSIGNNODE: { 1565 AttrAssignNode iVisited = (AttrAssignNode) node; 1566 1567 if (getDefinitionInner(runtime, context, iVisited.getReceiverNode(), self, aBlock) != null) { 1568 try { 1569 IRubyObject receiver = eval(runtime, context, iVisited.getReceiverNode(), self, aBlock); 1570 RubyClass metaClass = receiver.getMetaClass(); 1571 DynamicMethod method = metaClass.searchMethod(iVisited.getName()); 1572 Visibility visibility = method.getVisibility(); 1573 1574 if (!visibility.isPrivate() && 1575 (!visibility.isProtected() || self.isKindOf(metaClass.getRealClass()))) { 1576 if (metaClass.isMethodBound(iVisited.getName(), false)) { 1577 return getArgumentDefinition(runtime,context, iVisited.getArgsNode(), "assignment", self, aBlock); 1578 } 1579 } 1580 } catch (JumpException excptn) { 1581 } 1582 } 1583 1584 return null; 1585 } 1586 case NodeTypes.BACKREFNODE: 1587 return "$" + ((BackRefNode) node).getType(); 1588 case NodeTypes.CALLNODE: { 1589 CallNode iVisited = (CallNode) node; 1590 1591 if (getDefinitionInner(runtime, context, iVisited.getReceiverNode(), self, aBlock) != null) { 1592 try { 1593 IRubyObject receiver = eval(runtime, context, iVisited.getReceiverNode(), self, aBlock); 1594 RubyClass metaClass = receiver.getMetaClass(); 1595 DynamicMethod method = metaClass.searchMethod(iVisited.getName()); 1596 Visibility visibility = method.getVisibility(); 1597 1598 if (!visibility.isPrivate() && 1599 (!visibility.isProtected() || self.isKindOf(metaClass.getRealClass()))) { 1600 if (metaClass.isMethodBound(iVisited.getName(), false)) { 1601 return getArgumentDefinition(runtime, context, iVisited.getArgsNode(), "method", self, aBlock); 1602 } 1603 } 1604 } catch (JumpException excptn) { 1605 } 1606 } 1607 1608 return null; 1609 } 1610 case NodeTypes.CLASSVARASGNNODE: case NodeTypes.CLASSVARDECLNODE: case NodeTypes.CONSTDECLNODE: 1611 case NodeTypes.DASGNNODE: case NodeTypes.GLOBALASGNNODE: case NodeTypes.LOCALASGNNODE: 1612 case NodeTypes.MULTIPLEASGNNODE: case NodeTypes.OPASGNNODE: case NodeTypes.OPELEMENTASGNNODE: 1613 return "assignment"; 1614 1615 case NodeTypes.CLASSVARNODE: { 1616 ClassVarNode iVisited = (ClassVarNode) node; 1617 1618 if (context.getRubyClass() == null && self.getMetaClass().isClassVarDefined(iVisited.getName())) { 1619 return "class_variable"; 1620 } else if (!context.getRubyClass().isSingleton() && context.getRubyClass().isClassVarDefined(iVisited.getName())) { 1621 return "class_variable"; 1622 } 1623 1624 RubyModule module = (RubyModule) context.getRubyClass().getInstanceVariable("__attached__"); 1625 if (module != null && module.isClassVarDefined(iVisited.getName())) return "class_variable"; 1626 1627 return null; 1628 } 1629 case NodeTypes.COLON2NODE: { 1630 Colon2Node iVisited = (Colon2Node) node; 1631 1632 try { 1633 IRubyObject left = EvaluationState.eval(runtime, context, iVisited.getLeftNode(), self, aBlock); 1634 if (left instanceof RubyModule && 1635 ((RubyModule) left).getConstantAt(iVisited.getName()) != null) { 1636 return "constant"; 1637 } else if (left.getMetaClass().isMethodBound(iVisited.getName(), true)) { 1638 return "method"; 1639 } 1640 } catch (JumpException excptn) {} 1641 1642 return null; 1643 } 1644 case NodeTypes.CONSTNODE: 1645 if (context.getConstantDefined(((ConstNode) node).getName())) { 1646 return "constant"; 1647 } 1648 return null; 1649 case NodeTypes.DVARNODE: 1650 return "local-variable(in-block)"; 1651 case NodeTypes.FALSENODE: 1652 return "false"; 1653 case NodeTypes.FCALLNODE: { 1654 FCallNode iVisited = (FCallNode) node; 1655 if (self.getMetaClass().isMethodBound(iVisited.getName(), false)) { 1656 return getArgumentDefinition(runtime, context, iVisited.getArgsNode(), "method", self, aBlock); 1657 } 1658 1659 return null; 1660 } 1661 case NodeTypes.GLOBALVARNODE: 1662 if (runtime.getGlobalVariables().isDefined(((GlobalVarNode) node).getName())) { 1663 return "global-variable"; 1664 } 1665 return null; 1666 case NodeTypes.INSTVARNODE: 1667 if (self.getInstanceVariable(((InstVarNode) node).getName()) != null) { 1668 return "instance-variable"; 1669 } 1670 return null; 1671 case NodeTypes.LOCALVARNODE: 1672 return "local-variable"; 1673 case NodeTypes.MATCH2NODE: case NodeTypes.MATCH3NODE: 1674 return "method"; 1675 case NodeTypes.NILNODE: 1676 return "nil"; 1677 case NodeTypes.NTHREFNODE: 1678 return "$" + ((NthRefNode) node).getMatchNumber(); 1679 case NodeTypes.SELFNODE: 1680 return "state.getSelf()"; 1681 case NodeTypes.SUPERNODE: { 1682 SuperNode iVisited = (SuperNode) node; 1683 String name = context.getFrameName(); 1684 RubyModule klazz = context.getFrameKlazz(); 1685 if (name != null && klazz != null && klazz.getSuperClass().isMethodBound(name, false)) { 1686 return getArgumentDefinition(runtime, context, iVisited.getArgsNode(), "super", self, aBlock); 1687 } 1688 1689 return null; 1690 } 1691 case NodeTypes.TRUENODE: 1692 return "true"; 1693 case NodeTypes.VCALLNODE: { 1694 VCallNode iVisited = (VCallNode) node; 1695 if (self.getMetaClass().isMethodBound(iVisited.getName(), false)) { 1696 return "method"; 1697 } 1698 1699 return null; 1700 } 1701 case NodeTypes.YIELDNODE: 1702 return aBlock.isGiven() ? "yield" : null; 1703 case NodeTypes.ZSUPERNODE: { 1704 String name = context.getFrameName(); 1705 RubyModule klazz = context.getFrameKlazz(); 1706 if (name != null && klazz != null && klazz.getSuperClass().isMethodBound(name, false)) { 1707 return "super"; 1708 } 1709 return null; 1710 } 1711 default: 1712 try { 1713 EvaluationState.eval(runtime, context, node, self, aBlock); 1714 return "expression"; 1715 } catch (JumpException jumpExcptn) {} 1716 } 1717 1718 return null; 1719 } 1720 1721 private static IRubyObject aryToAry(Ruby runtime, IRubyObject value) { 1722 if (value instanceof RubyArray) return value; 1723 1724 if (value.respondsTo("to_ary")) { 1725 return value.convertToType("Array", "to_ary", false); 1726 } 1727 1728 return runtime.newArray(value); 1729 } 1730 1731 1734 private static IRubyObject evalClassDefinitionBody(Ruby runtime, ThreadContext context, StaticScope scope, 1735 Node bodyNode, RubyModule type, IRubyObject self, Block block) { 1736 context.preClassEval(scope, type); 1737 1738 try { 1739 if (isTrace(runtime)) { 1740 callTraceFunction(runtime, context, "class", type); 1741 } 1742 1743 return evalInternal(runtime,context, bodyNode, type, block); 1744 } finally { 1745 context.postClassEval(); 1746 1747 if (isTrace(runtime)) { 1748 callTraceFunction(runtime, context, "end", null); 1749 } 1750 } 1751 } 1752 1753 1759 private static boolean isTrace(Ruby runtime) { 1760 return runtime.getTraceFunction() != null; 1761 } 1762 1763 private static void callTraceFunction(Ruby runtime, ThreadContext context, String event, IRubyObject zelf) { 1764 String name = context.getFrameName(); 1765 RubyModule type = context.getFrameKlazz(); 1766 runtime.callTraceFunction(context, event, context.getPosition(), zelf, name, type); 1767 } 1768 1769 public static IRubyObject splatValue(Ruby runtime, IRubyObject value) { 1770 if (value.isNil()) { 1771 return runtime.newArray(value); 1772 } 1773 1774 return arrayValue(runtime, value); 1775 } 1776 1777 public static IRubyObject aValueSplat(Ruby runtime, IRubyObject value) { 1778 if (!(value instanceof RubyArray) || ((RubyArray) value).length().getLongValue() == 0) { 1779 return runtime.getNil(); 1780 } 1781 1782 RubyArray array = (RubyArray) value; 1783 1784 return array.getLength() == 1 ? array.first(IRubyObject.NULL_ARRAY) : array; 1785 } 1786 1787 public static RubyArray arrayValue(Ruby runtime, IRubyObject value) { 1788 IRubyObject newValue = value.convertToType("Array", "to_ary", false); 1789 if (newValue.isNil()) { 1790 if (value.getMetaClass().searchMethod("to_a").getImplementationClass() != runtime 1793 .getKernel()) { 1794 newValue = value.convertToType("Array", "to_a", false); 1795 if (newValue.getType() != runtime.getClass("Array")) { 1796 throw runtime.newTypeError("`to_a' did not return Array"); 1797 } 1798 } else { 1799 newValue = runtime.newArray(value); 1800 } 1801 } 1802 1803 return (RubyArray) newValue; 1804 } 1805 1806 private static IRubyObject[] setupArgs(Ruby runtime, ThreadContext context, Node node, IRubyObject self) { 1807 if (node == null) return IRubyObject.NULL_ARRAY; 1808 1809 if (node instanceof ArrayNode) { 1810 ArrayNode argsArrayNode = (ArrayNode) node; 1811 ISourcePosition position = context.getPosition(); 1812 int size = argsArrayNode.size(); 1813 IRubyObject[] argsArray = new IRubyObject[size]; 1814 1815 for (int i = 0; i < size; i++) { 1816 argsArray[i] = evalInternal(runtime,context, argsArrayNode.get(i), self, Block.NULL_BLOCK); 1817 } 1818 1819 context.setPosition(position); 1820 1821 return argsArray; 1822 } 1823 1824 return ArgsUtil.convertToJavaArray(evalInternal(runtime,context, node, self, Block.NULL_BLOCK)); 1825 } 1826 1827 private static RubyModule getEnclosingModule(Ruby runtime, ThreadContext context, Node node, IRubyObject self, Block block) { 1828 RubyModule enclosingModule = null; 1829 1830 if (node instanceof Colon2Node) { 1831 IRubyObject result = evalInternal(runtime,context, ((Colon2Node) node).getLeftNode(), self, block); 1832 1833 if (result != null && !result.isNil()) { 1834 enclosingModule = (RubyModule) result; 1835 } 1836 } else if (node instanceof Colon3Node) { 1837 enclosingModule = runtime.getObject(); 1838 } 1839 1840 if (enclosingModule == null) { 1841 enclosingModule = (RubyModule) context.peekCRef().getValue(); 1842 } 1843 1844 return enclosingModule; 1845 } 1846 1847 private static boolean isRescueHandled(Ruby runtime, ThreadContext context, RubyException currentException, ListNode exceptionNodes, 1848 IRubyObject self) { 1849 if (exceptionNodes == null) { 1850 return currentException.isKindOf(runtime.getClass("StandardError")); 1851 } 1852 1853 IRubyObject[] args = setupArgs(runtime, context, exceptionNodes, self); 1854 1855 for (int i = 0; i < args.length; i++) { 1856 if (!args[i].isKindOf(runtime.getClass("Module"))) { 1857 throw runtime.newTypeError("class or module required for rescue clause"); 1858 } 1859 if (args[i].callMethod(context, "===", currentException).isTrue()) return true; 1860 } 1861 return false; 1862 } 1863 1864 public static Block getBlock(Ruby runtime, ThreadContext context, IRubyObject self, Block currentBlock, Node blockNode) { 1865 if (blockNode == null) return Block.NULL_BLOCK; 1866 1867 if (blockNode instanceof IterNode) { 1868 IterNode iterNode = (IterNode) blockNode; 1869 return Block.createBlock(context, iterNode.getVarNode(), 1871 new DynamicScope(iterNode.getScope(), context.getCurrentScope()), 1872 iterNode.getCallable(), self); 1873 } else if (blockNode instanceof BlockPassNode) { 1874 BlockPassNode blockPassNode = (BlockPassNode) blockNode; 1875 IRubyObject proc = evalInternal(runtime,context, blockPassNode.getBodyNode(), self, currentBlock); 1876 1877 if (proc.isNil()) return Block.NULL_BLOCK; 1879 1880 if (!(proc instanceof RubyProc)) { 1882 proc = proc.convertToType("Proc", "to_proc", false); 1883 1884 if (!(proc instanceof RubyProc)) { 1885 throw runtime.newTypeError("wrong argument type " 1886 + proc.getMetaClass().getName() + " (expected Proc)"); 1887 } 1888 } 1889 1890 1892 if (currentBlock.isGiven()) { 1893 RubyProc procObject = currentBlock.getProcObject(); 1894 if (procObject != null && procObject == proc) return currentBlock; 1896 } 1897 1898 return ((RubyProc) proc).getBlock(); 1899 } 1900 1901 assert false: "Trying to get block from something which cannot deliver"; 1902 return null; 1903 } 1904} 1905 | Popular Tags |