KernelNodes.java

  1. /*
  2.  * Copyright (c) 2013, 2015 Oracle and/or its affiliates. All rights reserved. This
  3.  * code is released under a tri EPL/GPL/LGPL license. You can use it,
  4.  * redistribute it and/or modify it under the terms of the:
  5.  *
  6.  * Eclipse Public License version 1.0
  7.  * GNU General Public License version 2
  8.  * GNU Lesser General Public License version 2.1
  9.  */
  10. package org.jruby.truffle.nodes.core;

  11. import com.oracle.truffle.api.CompilerDirectives;
  12. import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
  13. import com.oracle.truffle.api.Truffle;
  14. import com.oracle.truffle.api.dsl.Specialization;
  15. import com.oracle.truffle.api.frame.*;
  16. import com.oracle.truffle.api.nodes.UnexpectedResultException;
  17. import com.oracle.truffle.api.source.SourceSection;
  18. import org.jruby.common.IRubyWarnings;
  19. import org.jruby.runtime.Visibility;
  20. import org.jruby.truffle.nodes.RubyNode;
  21. import org.jruby.truffle.nodes.cast.BooleanCastNode;
  22. import org.jruby.truffle.nodes.cast.BooleanCastNodeFactory;
  23. import org.jruby.truffle.nodes.control.WhileNode;
  24. import org.jruby.truffle.nodes.dispatch.Dispatch;
  25. import org.jruby.truffle.nodes.dispatch.DispatchHeadNode;
  26. import org.jruby.truffle.nodes.dispatch.PredicateDispatchHeadNode;
  27. import org.jruby.truffle.nodes.globals.WrapInThreadLocalNode;
  28. import org.jruby.truffle.nodes.literal.BooleanLiteralNode;
  29. import org.jruby.truffle.nodes.objects.SingletonClassNode;
  30. import org.jruby.truffle.nodes.objects.SingletonClassNodeFactory;
  31. import org.jruby.truffle.nodes.objectstorage.ReadHeadObjectFieldNode;
  32. import org.jruby.truffle.nodes.objectstorage.WriteHeadObjectFieldNode;
  33. import org.jruby.truffle.nodes.yield.YieldNode;
  34. import org.jruby.truffle.runtime.*;
  35. import org.jruby.truffle.runtime.backtrace.Activation;
  36. import org.jruby.truffle.runtime.backtrace.Backtrace;
  37. import org.jruby.truffle.runtime.backtrace.MRIBacktraceFormatter;
  38. import org.jruby.truffle.runtime.control.RaiseException;
  39. import org.jruby.truffle.runtime.control.ThrowException;
  40. import org.jruby.truffle.runtime.core.*;
  41. import org.jruby.truffle.runtime.hash.HashOperations;
  42. import org.jruby.truffle.runtime.hash.KeyValue;
  43. import org.jruby.truffle.runtime.methods.RubyMethod;
  44. import org.jruby.util.ByteList;
  45. import org.jruby.util.cli.Options;

  46. import java.io.ByteArrayOutputStream;
  47. import java.io.File;
  48. import java.io.IOException;
  49. import java.io.PrintStream;
  50. import java.math.BigInteger;
  51. import java.util.Arrays;
  52. import java.util.Collection;
  53. import java.util.List;
  54. import java.util.Map;

  55. @CoreClass(name = "Kernel")
  56. public abstract class KernelNodes {

  57.     /**
  58.      * Check if operands are the same object or call #==.
  59.      * Known as rb_equal() in MRI. The fact Kernel#=== uses this is pure coincidence.
  60.      */
  61.     @CoreMethod(names = "===", required = 1)
  62.     public abstract static class SameOrEqualNode extends CoreMethodNode {

  63.         @Child protected BasicObjectNodes.ReferenceEqualNode referenceEqualNode;
  64.         @Child protected PredicateDispatchHeadNode equalNode;

  65.         public SameOrEqualNode(RubyContext context, SourceSection sourceSection) {
  66.             super(context, sourceSection);
  67.         }

  68.         public SameOrEqualNode(SameOrEqualNode prev) {
  69.             super(prev);
  70.         }

  71.         protected boolean areSame(VirtualFrame frame, Object left, Object right) {
  72.             if (referenceEqualNode == null) {
  73.                 CompilerDirectives.transferToInterpreterAndInvalidate();
  74.                 referenceEqualNode = insert(BasicObjectNodesFactory.ReferenceEqualNodeFactory.create(getContext(), getSourceSection(), null, null));
  75.             }
  76.             return referenceEqualNode.executeReferenceEqual(frame, left, right);
  77.         }

  78.         protected boolean areEqual(VirtualFrame frame, Object left, Object right) {
  79.             if (equalNode == null) {
  80.                 CompilerDirectives.transferToInterpreterAndInvalidate();
  81.                 equalNode = insert(new PredicateDispatchHeadNode(getContext()));
  82.             }
  83.             return equalNode.call(frame, left, "==", null, right);
  84.         }

  85.         public abstract boolean executeSameOrEqual(VirtualFrame frame, Object a, Object b);

  86.         @Specialization
  87.         public boolean sameOrEqual(VirtualFrame frame, Object a, Object b) {
  88.             if (areSame(frame, a, b))
  89.                 return true;
  90.             return areEqual(frame, a, b);
  91.         }

  92.     }

  93.     @CoreMethod(names = "=~", required = 1, needsSelf = false)
  94.     public abstract static class MatchNode extends CoreMethodNode {

  95.         public MatchNode(RubyContext context, SourceSection sourceSection) {
  96.             super(context, sourceSection);
  97.         }

  98.         public MatchNode(MatchNode prev) {
  99.             super(prev);
  100.         }

  101.         @Specialization
  102.         public RubyNilClass equal(Object other) {
  103.             return getContext().getCoreLibrary().getNilObject();
  104.         }

  105.     }

  106.     @CoreMethod(names = "!~", required = 1)
  107.     public abstract static class NotMatchNode extends CoreMethodNode {

  108.         @Child protected PredicateDispatchHeadNode matchNode;

  109.         public NotMatchNode(RubyContext context, SourceSection sourceSection) {
  110.             super(context, sourceSection);
  111.             matchNode = new PredicateDispatchHeadNode(context);
  112.         }

  113.         public NotMatchNode(NotMatchNode prev) {
  114.             super(prev);
  115.             matchNode = prev.matchNode;
  116.         }

  117.         @Specialization
  118.         public boolean notMatch(VirtualFrame frame, Object self, Object other) {
  119.             return !matchNode.call(frame, self, "=~", null, other);
  120.         }

  121.     }

  122.     @CoreMethod(names = {"<=>"}, required = 1)
  123.     public abstract static class CompareNode extends CoreMethodNode {

  124.         @Child protected DispatchHeadNode equalNode;
  125.         @Child protected BooleanCastNode booleanCast;

  126.         public CompareNode(RubyContext context, SourceSection sourceSection) {
  127.             super(context, sourceSection);
  128.             equalNode = new DispatchHeadNode(context);
  129.             booleanCast = BooleanCastNodeFactory.create(context, sourceSection, null);
  130.         }

  131.         public CompareNode(CompareNode prev) {
  132.             super(prev);
  133.             equalNode = prev.equalNode;
  134.             booleanCast = prev.booleanCast;
  135.         }

  136.         @Specialization
  137.         public Object compare(VirtualFrame frame, RubyBasicObject self, RubyBasicObject other) {
  138.             notDesignedForCompilation();

  139.             if ((self == other) || booleanCast.executeBoolean(frame, equalNode.call(frame, self, "==", null, other))) {
  140.                 return 0;
  141.             }

  142.             return getContext().getCoreLibrary().getNilObject();
  143.         }

  144.     }

  145.     @CoreMethod(names = "abort", isModuleFunction = true)
  146.     public abstract static class AbortNode extends CoreMethodNode {

  147.         public AbortNode(RubyContext context, SourceSection sourceSection) {
  148.             super(context, sourceSection);
  149.         }

  150.         public AbortNode(AbortNode prev) {
  151.             super(prev);
  152.         }

  153.         @Specialization
  154.         public RubyNilClass abort() {
  155.             CompilerDirectives.transferToInterpreter();
  156.             System.exit(1);
  157.             return getContext().getCoreLibrary().getNilObject();
  158.         }
  159.     }

  160.     @CoreMethod(names = "Array", isModuleFunction = true, argumentsAsArray = true)
  161.     public abstract static class ArrayNode extends CoreMethodNode {

  162.         @Child ArrayBuilderNode arrayBuilderNode;

  163.         public ArrayNode(RubyContext context, SourceSection sourceSection) {
  164.             super(context, sourceSection);
  165.             arrayBuilderNode = new ArrayBuilderNode.UninitializedArrayBuilderNode(context);
  166.         }

  167.         public ArrayNode(ArrayNode prev) {
  168.             super(prev);
  169.             arrayBuilderNode = prev.arrayBuilderNode;
  170.         }

  171.         @Specialization(guards = "isOneArrayElement")
  172.         public RubyArray arrayOneArrayElement(Object[] args) {
  173.             return (RubyArray) args[0];
  174.         }

  175.         @Specialization(guards = "!isOneArrayElement")
  176.         public RubyArray array(Object[] args) {
  177.             final int length = args.length;
  178.             Object store = arrayBuilderNode.start(length);

  179.             for (int n = 0; n < length; n++) {
  180.                 store = arrayBuilderNode.append(store, n, args[n]);
  181.             }

  182.             return new RubyArray(getContext().getCoreLibrary().getArrayClass(), arrayBuilderNode.finish(store, length), length);
  183.         }

  184.         protected boolean isOneArrayElement(Object[] args) {
  185.             return args.length == 1 && args[0] instanceof RubyArray;
  186.         }

  187.     }

  188.     @CoreMethod(names = "at_exit", isModuleFunction = true, needsBlock = true)
  189.     public abstract static class AtExitNode extends CoreMethodNode {

  190.         public AtExitNode(RubyContext context, SourceSection sourceSection) {
  191.             super(context, sourceSection);
  192.         }

  193.         public AtExitNode(AtExitNode prev) {
  194.             super(prev);
  195.         }

  196.         @Specialization
  197.         public Object atExit(RubyProc block) {
  198.             notDesignedForCompilation();

  199.             getContext().getAtExitManager().add(block);
  200.             return getContext().getCoreLibrary().getNilObject();
  201.         }
  202.     }

  203.     @CoreMethod(names = "binding", isModuleFunction = true)
  204.     public abstract static class BindingNode extends CoreMethodNode {

  205.         public BindingNode(RubyContext context, SourceSection sourceSection) {
  206.             super(context, sourceSection);
  207.         }

  208.         public abstract RubyBinding executeBinding(VirtualFrame frame);

  209.         @Specialization
  210.         public RubyBinding binding() {
  211.             // Materialize the caller's frame - false means don't use a slow path to get it - we want to optimize it

  212.             final MaterializedFrame callerFrame = Truffle.getRuntime().getCallerFrame()
  213.                     .getFrame(FrameInstance.FrameAccess.MATERIALIZE, false).materialize();

  214.             return new RubyBinding(
  215.                     getContext().getCoreLibrary().getBindingClass(),
  216.                     RubyArguments.getSelf(callerFrame.getArguments()),
  217.                     callerFrame);
  218.         }
  219.     }

  220.     @CoreMethod(names = "block_given?", isModuleFunction = true)
  221.     public abstract static class BlockGivenNode extends CoreMethodNode {

  222.         public BlockGivenNode(RubyContext context, SourceSection sourceSection) {
  223.             super(context, sourceSection);
  224.         }

  225.         public BlockGivenNode(BlockGivenNode prev) {
  226.             super(prev);
  227.         }

  228.         @Specialization
  229.         public boolean blockGiven() {
  230.             notDesignedForCompilation();

  231.             return RubyArguments.getBlock(Truffle.getRuntime().getCallerFrame().getFrame(FrameInstance.FrameAccess.READ_ONLY, false).getArguments()) != null;
  232.         }
  233.     }

  234.     @CoreMethod(names = "caller", isModuleFunction = true, optional = 1)
  235.     public abstract static class CallerNode extends CoreMethodNode {

  236.         public CallerNode(RubyContext context, SourceSection sourceSection) {
  237.             super(context, sourceSection);
  238.         }

  239.         public CallerNode(CallerNode prev) {
  240.             super(prev);
  241.         }

  242.         @Specialization
  243.         public Object caller(UndefinedPlaceholder omit) {
  244.             return caller(1);
  245.         }

  246.         @Specialization
  247.         public Object caller(int omit) {
  248.             notDesignedForCompilation();

  249.             omit += 1; // Always ignore this node

  250.             Backtrace backtrace = RubyCallStack.getBacktrace(this);
  251.             List<Activation> activations = backtrace.getActivations();
  252.             int size = activations.size() - omit;

  253.             if (size < 0) {
  254.                 return getContext().getCoreLibrary().getNilObject();
  255.             }

  256.             Object[] callers = new Object[size];
  257.             for (int n = 0; n < size; n++) {
  258.                 callers[n] = getContext().makeString(MRIBacktraceFormatter.formatCallerLine(activations, n + omit));
  259.             }
  260.             return new RubyArray(getContext().getCoreLibrary().getArrayClass(), callers, callers.length);
  261.         }
  262.     }

  263.     @CoreMethod(names = "catch", isModuleFunction = true, needsBlock = true, required = 1)
  264.     public abstract static class CatchNode extends YieldingCoreMethodNode {

  265.         public CatchNode(RubyContext context, SourceSection sourceSection) {
  266.             super(context, sourceSection);
  267.         }

  268.         public CatchNode(CatchNode prev) {
  269.             super(prev);
  270.         }

  271.         @Specialization
  272.         public Object doCatch(VirtualFrame frame, Object tag, RubyProc block) {
  273.             notDesignedForCompilation();

  274.             try {
  275.                 getContext().getThrowTags().add(tag);

  276.                 return yield(frame, block);
  277.             } catch (ThrowException e) {
  278.                 if (e.getTag().equals(tag)) {
  279.                     // TODO(cs): unset rather than set to Nil?
  280.                     notDesignedForCompilation();
  281.                     getContext().getCoreLibrary().getGlobalVariablesObject().getOperations().setInstanceVariable(getContext().getCoreLibrary().getGlobalVariablesObject(), "$!", getContext().getCoreLibrary().getNilObject());
  282.                     return e.getValue();
  283.                 } else {
  284.                     throw e;
  285.                 }
  286.             } finally {
  287.                 getContext().getThrowTags().remove();
  288.             }
  289.         }
  290.     }

  291.     @CoreMethod(names = "class")
  292.     public abstract static class ClassNode extends CoreMethodNode {

  293.         public ClassNode(RubyContext context, SourceSection sourceSection) {
  294.             super(context, sourceSection);
  295.         }

  296.         public ClassNode(ClassNode prev) {
  297.             super(prev);
  298.         }

  299.         public abstract RubyClass executeGetClass(Object value);

  300.         @Specialization
  301.         public RubyClass getClass(boolean value) {
  302.             notDesignedForCompilation();

  303.             if (value) {
  304.                 return getContext().getCoreLibrary().getTrueClass();
  305.             } else {
  306.                 return getContext().getCoreLibrary().getFalseClass();
  307.             }
  308.         }

  309.         @Specialization
  310.         public RubyClass getClass(int value) {
  311.             return getContext().getCoreLibrary().getFixnumClass();
  312.         }

  313.         @Specialization
  314.         public RubyClass getClass(long value) {
  315.             return getContext().getCoreLibrary().getFixnumClass();
  316.         }

  317.         @Specialization
  318.         public RubyClass getClass(double value) {
  319.             return getContext().getCoreLibrary().getFloatClass();
  320.         }

  321.         @Specialization
  322.         public RubyClass getClass(RubyBasicObject self) {
  323.             return self.getLogicalClass();
  324.         }

  325.     }

  326.     @CoreMethod(names = "clone")
  327.     public abstract static class CloneNode extends CoreMethodNode {

  328.         @Child protected DispatchHeadNode initializeCloneNode;

  329.         public CloneNode(RubyContext context, SourceSection sourceSection) {
  330.             super(context, sourceSection);
  331.             // Calls private initialize_clone on the new copy.
  332.             initializeCloneNode = new DispatchHeadNode(context, true, Dispatch.MissingBehavior.CALL_METHOD_MISSING);
  333.         }

  334.         public CloneNode(CloneNode prev) {
  335.             super(prev);
  336.             initializeCloneNode = prev.initializeCloneNode;
  337.         }

  338.         @Specialization
  339.         public Object clone(VirtualFrame frame, RubyBasicObject self) {
  340.             notDesignedForCompilation();

  341.             final RubyBasicObject newObject = self.getLogicalClass().allocate(this);

  342.             // Copy the singleton class if any.
  343.             if (self.getMetaClass().isSingleton()) {
  344.                 newObject.getSingletonClass(this).initCopy(self.getMetaClass());
  345.             }

  346.             newObject.getOperations().setInstanceVariables(newObject, self.getOperations().getInstanceVariables(self));
  347.             initializeCloneNode.call(frame, newObject, "initialize_clone", null, self);

  348.             return newObject;
  349.         }

  350.     }

  351.     @CoreMethod(names = "dup")
  352.     public abstract static class DupNode extends CoreMethodNode {

  353.         @Child protected DispatchHeadNode initializeDupNode;

  354.         public DupNode(RubyContext context, SourceSection sourceSection) {
  355.             super(context, sourceSection);
  356.             // Calls private initialize_dup on the new copy.
  357.             initializeDupNode = new DispatchHeadNode(context, true, Dispatch.MissingBehavior.CALL_METHOD_MISSING);
  358.         }

  359.         public DupNode(DupNode prev) {
  360.             super(prev);
  361.             initializeDupNode = prev.initializeDupNode;
  362.         }

  363.         @Specialization
  364.         public Object dup(VirtualFrame frame, RubyBasicObject self) {
  365.             // This method is pretty crappy for compilation - it should improve with the OM

  366.             final RubyBasicObject newObject = self.getLogicalClass().allocate(this);
  367.             newObject.getOperations().setInstanceVariables(newObject, self.getOperations().getInstanceVariables(self));
  368.             initializeDupNode.call(frame, newObject, "initialize_dup", null, self);

  369.             return newObject;
  370.         }

  371.     }

  372.     @CoreMethod(names = "eql?", required = 1)
  373.     public abstract static class EqlNode extends BasicObjectNodes.ReferenceEqualNode {
  374.         public EqlNode(RubyContext context, SourceSection sourceSection) {
  375.             super(context, sourceSection);
  376.         }

  377.         public EqlNode(EqlNode prev) {
  378.             super(prev);
  379.         }
  380.     }

  381.     @CoreMethod(names = "eval", isModuleFunction = true, required = 1, optional = 3)
  382.     public abstract static class EvalNode extends CoreMethodNode {

  383.         @Child protected DispatchHeadNode toStr;
  384.         @Child protected BindingNode bindingNode;

  385.         public EvalNode(RubyContext context, SourceSection sourceSection) {
  386.             super(context, sourceSection);
  387.             toStr = new DispatchHeadNode(context);
  388.         }

  389.         public EvalNode(EvalNode prev) {
  390.             super(prev);
  391.             toStr = prev.toStr;
  392.         }

  393.         protected RubyBinding getCallerBinding(VirtualFrame frame) {
  394.             if (bindingNode == null) {
  395.                 CompilerDirectives.transferToInterpreterAndInvalidate();
  396.                 bindingNode = insert(KernelNodesFactory.BindingNodeFactory.create(getContext(), getSourceSection(), new RubyNode[]{}));
  397.             }
  398.             return bindingNode.executeBinding(frame);
  399.         }

  400.         @Specialization
  401.         public Object eval(VirtualFrame frame, RubyString source, UndefinedPlaceholder binding, UndefinedPlaceholder filename, UndefinedPlaceholder lineNumber) {
  402.             notDesignedForCompilation();

  403.             return eval(source, getCallerBinding(frame), filename, lineNumber);
  404.         }

  405.         @Specialization
  406.         public Object eval(RubyString source, RubyBinding binding, UndefinedPlaceholder filename, UndefinedPlaceholder lineNumber) {
  407.             notDesignedForCompilation();

  408.             return getContext().eval(source.getBytes(), binding, this);
  409.         }

  410.         @Specialization
  411.         public Object eval(RubyString source, RubyBinding binding, RubyString filename, UndefinedPlaceholder lineNumber) {
  412.             notDesignedForCompilation();

  413.             // TODO (nirvdrum Dec. 29, 2014) Do something with the supplied filename.
  414.             return getContext().eval(source.getBytes(), binding, this);
  415.         }

  416.         @Specialization
  417.         public Object eval(RubyString source, RubyBinding binding, RubyString filename, int lineNumber) {
  418.             notDesignedForCompilation();

  419.             // TODO (nirvdrum Dec. 29, 2014) Do something with the supplied filename and lineNumber.
  420.             return getContext().eval(source.getBytes(), binding, this);
  421.         }

  422.         @Specialization(guards = "!isRubyString(arguments[0])")
  423.         public Object eval(VirtualFrame frame, RubyBasicObject object, UndefinedPlaceholder binding, UndefinedPlaceholder filename, UndefinedPlaceholder lineNumber) {
  424.             notDesignedForCompilation();

  425.             return eval(frame, object, getCallerBinding(frame), filename, lineNumber);
  426.         }

  427.         @Specialization(guards = "!isRubyString(arguments[0])")
  428.         public Object eval(VirtualFrame frame, RubyBasicObject object, RubyBinding binding, UndefinedPlaceholder filename, UndefinedPlaceholder lineNumber) {
  429.             notDesignedForCompilation();

  430.             Object coerced;

  431.             try {
  432.                 coerced = toStr.call(frame, object, "to_str", null);
  433.             } catch (RaiseException e) {
  434.                 if (e.getRubyException().getLogicalClass() == getContext().getCoreLibrary().getNoMethodErrorClass()) {
  435.                     throw new RaiseException(
  436.                             getContext().getCoreLibrary().typeError(
  437.                                     String.format("no implicit conversion of %s into String", object.getLogicalClass().getName()),
  438.                                     this));
  439.                 } else {
  440.                     throw e;
  441.                 }
  442.             }

  443.             if (coerced instanceof RubyString) {
  444.                 return getContext().eval(((RubyString) coerced).getBytes(), binding, this);
  445.             } else {
  446.                 throw new RaiseException(
  447.                         getContext().getCoreLibrary().typeError(
  448.                                 String.format("can't convert %s to String (%s#to_str gives %s)",
  449.                                         object.getLogicalClass().getName(),
  450.                                         object.getLogicalClass().getName(),
  451.                                         getContext().getCoreLibrary().getLogicalClass(coerced).getName()),
  452.                                 this));
  453.             }
  454.         }

  455.         @Specialization(guards = "!isRubyBinding(arguments[1])")
  456.         public Object eval(RubyBasicObject source, RubyBasicObject badBinding, UndefinedPlaceholder filename, UndefinedPlaceholder lineNumber) {
  457.             throw new RaiseException(
  458.                     getContext().getCoreLibrary().typeError(
  459.                             String.format("wrong argument type %s (expected binding)",
  460.                                     badBinding.getLogicalClass().getName()),
  461.                             this));
  462.         }
  463.     }

  464.     @CoreMethod(names = "exec", isModuleFunction = true, required = 1, argumentsAsArray = true)
  465.     public abstract static class ExecNode extends CoreMethodNode {

  466.         public ExecNode(RubyContext context, SourceSection sourceSection) {
  467.             super(context, sourceSection);
  468.         }

  469.         public ExecNode(ExecNode prev) {
  470.             super(prev);
  471.         }

  472.         @Specialization
  473.         public Object require(Object[] args) {
  474.             notDesignedForCompilation();

  475.             final String[] commandLine = new String[args.length];

  476.             for (int n = 0; n < args.length; n++) {
  477.                 commandLine[n] = args[n].toString();
  478.             }

  479.             exec(getContext(), commandLine);

  480.             return null;
  481.         }

  482.         @TruffleBoundary
  483.         private static void exec(RubyContext context, String[] commandLine) {
  484.             final ProcessBuilder builder = new ProcessBuilder(commandLine);
  485.             builder.inheritIO();

  486.             final RubyHash env = context.getCoreLibrary().getENV();

  487.             for (KeyValue keyValue : HashOperations.verySlowToKeyValues(env)) {
  488.                 builder.environment().put(keyValue.getKey().toString(), keyValue.getValue().toString());
  489.             }

  490.             Process process;

  491.             try {
  492.                 process = builder.start();
  493.             } catch (IOException e) {
  494.                 // TODO(cs): proper Ruby exception
  495.                 throw new RuntimeException(e);
  496.             }

  497.             int exitCode;

  498.             while (true) {
  499.                 try {
  500.                     exitCode = process.waitFor();
  501.                     break;
  502.                 } catch (InterruptedException e) {
  503.                     continue;
  504.                 }
  505.             }

  506.             System.exit(exitCode);
  507.         }

  508.     }

  509.     @CoreMethod(names = "exit", isModuleFunction = true, optional = 1, lowerFixnumParameters = 0)
  510.     public abstract static class ExitNode extends CoreMethodNode {

  511.         public ExitNode(RubyContext context, SourceSection sourceSection) {
  512.             super(context, sourceSection);
  513.         }

  514.         public ExitNode(ExitNode prev) {
  515.             super(prev);
  516.         }

  517.         @Specialization
  518.         public Object exit(UndefinedPlaceholder exitCode) {
  519.             notDesignedForCompilation();

  520.             getContext().shutdown();
  521.             System.exit(0);
  522.             return null;
  523.         }

  524.         @Specialization
  525.         public Object exit(int exitCode) {
  526.             notDesignedForCompilation();

  527.             getContext().shutdown();
  528.             System.exit(exitCode);
  529.             return null;
  530.         }

  531.     }

  532.     @CoreMethod(names = "exit!", isModuleFunction = true)
  533.     public abstract static class ExitBangNode extends CoreMethodNode {

  534.         public ExitBangNode(RubyContext context, SourceSection sourceSection) {
  535.             super(context, sourceSection);
  536.         }

  537.         public ExitBangNode(ExitBangNode prev) {
  538.             super(prev);
  539.         }

  540.         @Specialization
  541.         public RubyNilClass exit() {
  542.             CompilerDirectives.transferToInterpreter();
  543.             System.exit(1);
  544.             return getContext().getCoreLibrary().getNilObject();
  545.         }
  546.     }

  547.     @CoreMethod(names = "extend", argumentsAsArray = true, required = 1)
  548.     public abstract static class ExtendNode extends CoreMethodNode {

  549.         public ExtendNode(RubyContext context, SourceSection sourceSection) {
  550.             super(context, sourceSection);
  551.         }

  552.         public ExtendNode(ExtendNode prev) {
  553.             super(prev);
  554.         }

  555.         @Specialization
  556.         public RubyBasicObject extend(RubyBasicObject self, Object[] args) {
  557.             notDesignedForCompilation();

  558.             for (int n = 0; n < args.length; n++) {
  559.                 self.extend((RubyModule) args[n], this);
  560.             }

  561.             return self;
  562.         }

  563.     }

  564.     @CoreMethod(names = "fork", isModuleFunction = true, argumentsAsArray = true)
  565.     public abstract static class ForkNode extends CoreMethodNode {

  566.         public ForkNode(RubyContext context, SourceSection sourceSection) {
  567.             super(context, sourceSection);
  568.         }

  569.         public ForkNode(ForkNode prev) {
  570.             super(prev);
  571.         }

  572.         @Specialization
  573.         public Object fork(Object[] args) {
  574.             notDesignedForCompilation();
  575.             getContext().getWarnings().warn("Kernel#fork not implemented - defined to satisfy some metaprogramming in RubySpec");
  576.             return getContext().getCoreLibrary().getNilObject();
  577.         }

  578.     }

  579.     @CoreMethod(names = "freeze")
  580.     public abstract static class FreezeNode extends CoreMethodNode {

  581.         public FreezeNode(RubyContext context, SourceSection sourceSection) {
  582.             super(context, sourceSection);
  583.         }

  584.         public FreezeNode(FreezeNode prev) {
  585.             super(prev);
  586.         }

  587.         @Specialization
  588.         public RubyBasicObject freeze(RubyBasicObject self) {
  589.             notDesignedForCompilation();

  590.             self.freeze();
  591.             return self;
  592.         }

  593.     }

  594.     @CoreMethod(names = "frozen?")
  595.     public abstract static class FrozenNode extends CoreMethodNode {

  596.         public FrozenNode(RubyContext context, SourceSection sourceSection) {
  597.             super(context, sourceSection);
  598.         }

  599.         public FrozenNode(FrozenNode prev) {
  600.             super(prev);
  601.         }

  602.         @Specialization
  603.         public boolean isFrozen(RubyBasicObject self) {
  604.             notDesignedForCompilation();

  605.             return self.isFrozen();
  606.         }

  607.     }

  608.     @CoreMethod(names = "gets", isModuleFunction = true)
  609.     public abstract static class GetsNode extends CoreMethodNode {

  610.         public GetsNode(RubyContext context, SourceSection sourceSection) {
  611.             super(context, sourceSection);
  612.         }

  613.         public GetsNode(GetsNode prev) {
  614.             super(prev);
  615.         }

  616.         @Specialization
  617.         public RubyString gets(VirtualFrame frame) {
  618.             notDesignedForCompilation();

  619.             final RubyContext context = getContext();

  620.             final Frame caller = Truffle.getRuntime().getCallerFrame().getFrame(FrameInstance.FrameAccess.READ_WRITE, false);

  621.             final String line;

  622.             final RubyThread runningThread = getContext().getThreadManager().leaveGlobalLock();

  623.             try {
  624.                 line = gets(context);
  625.             } catch (IOException e) {
  626.                 throw new RuntimeException(e);
  627.             } finally {
  628.                 getContext().getThreadManager().enterGlobalLock(runningThread);
  629.             }

  630.             final RubyString rubyLine = context.makeString(line);

  631.             // Set the local variable $_ in the caller

  632.             final FrameSlot slot = caller.getFrameDescriptor().findFrameSlot("$_");

  633.             if (slot != null) {
  634.                 caller.setObject(slot, WrapInThreadLocalNode.wrap(getContext(), rubyLine));
  635.             }

  636.             return rubyLine;
  637.         }

  638.         @TruffleBoundary
  639.         private static String gets(RubyContext context) throws IOException {
  640.             // TODO(CS): having some trouble interacting with JRuby stdin - so using this hack

  641.             final StringBuilder builder = new StringBuilder();

  642.             while (true) {
  643.                 final int c = context.getRuntime().getInstanceConfig().getInput().read();

  644.                 if (c == -1 || c == '\r' || c == '\n') {
  645.                     break;
  646.                 }

  647.                 builder.append((char) c);
  648.             }

  649.             return builder.toString();
  650.         }

  651.     }

  652.     @CoreMethod(names = "hash")
  653.     public abstract static class HashNode extends CoreMethodNode {

  654.         public HashNode(RubyContext context, SourceSection sourceSection) {
  655.             super(context, sourceSection);
  656.         }

  657.         public HashNode(HashNode prev) {
  658.             super(prev);
  659.         }

  660.         @Specialization
  661.         public int hash(int value) {
  662.             // TODO(CS): should check this matches MRI
  663.             return value;
  664.         }

  665.         @Specialization
  666.         public int hash(long value) {
  667.             // TODO(CS): should check this matches MRI
  668.             return Long.valueOf(value).hashCode();
  669.         }

  670.         @Specialization
  671.         public int hash(double value) {
  672.             // TODO(CS): should check this matches MRI
  673.             return Double.valueOf(value).hashCode();
  674.         }

  675.         @Specialization
  676.         public int hash(RubyBasicObject self) {
  677.             return self.hashCode();
  678.         }

  679.     }

  680.     @CoreMethod(names = "initialize_copy", visibility = Visibility.PRIVATE, required = 1)
  681.     public abstract static class InitializeCopyNode extends CoreMethodNode {

  682.         public InitializeCopyNode(RubyContext context, SourceSection sourceSection) {
  683.             super(context, sourceSection);
  684.         }

  685.         public InitializeCopyNode(InitializeCopyNode prev) {
  686.             super(prev);
  687.         }

  688.         @Specialization
  689.         public Object initializeCopy(RubyBasicObject self, RubyBasicObject from) {
  690.             notDesignedForCompilation();

  691.             if (self.getLogicalClass() != from.getLogicalClass()) {
  692.                 CompilerDirectives.transferToInterpreter();
  693.                 throw new RaiseException(getContext().getCoreLibrary().typeError("initialize_copy should take same class object", this));
  694.             }

  695.             return self;
  696.         }

  697.     }

  698.     @CoreMethod(names = {"initialize_dup", "initialize_clone"}, visibility = Visibility.PRIVATE, required = 1)
  699.     public abstract static class InitializeDupCloneNode extends CoreMethodNode {

  700.         @Child protected DispatchHeadNode initializeCopyNode;

  701.         public InitializeDupCloneNode(RubyContext context, SourceSection sourceSection) {
  702.             super(context, sourceSection);
  703.             initializeCopyNode = DispatchHeadNode.onSelf(context);
  704.         }

  705.         public InitializeDupCloneNode(InitializeDupCloneNode prev) {
  706.             super(prev);
  707.             initializeCopyNode = prev.initializeCopyNode;
  708.         }

  709.         @Specialization
  710.         public Object initializeDup(VirtualFrame frame, RubyBasicObject self, RubyBasicObject from) {
  711.             return initializeCopyNode.call(frame, self, "initialize_copy", null, from);
  712.         }

  713.     }

  714.     @CoreMethod(names = "instance_of?", required = 1)
  715.     public abstract static class InstanceOfNode extends CoreMethodNode {

  716.         public InstanceOfNode(RubyContext context, SourceSection sourceSection) {
  717.             super(context, sourceSection);
  718.         }

  719.         public InstanceOfNode(InstanceOfNode prev) {
  720.             super(prev);
  721.         }

  722.         @TruffleBoundary
  723.         @Specialization
  724.         public boolean instanceOf(Object self, RubyClass rubyClass) {
  725.             // TODO(CS): fast path
  726.             return getContext().getCoreLibrary().getLogicalClass(self) == rubyClass;
  727.         }

  728.     }

  729.     @CoreMethod(names = "instance_variable_defined?", required = 1)
  730.     public abstract static class InstanceVariableDefinedNode extends CoreMethodNode {

  731.         public InstanceVariableDefinedNode(RubyContext context, SourceSection sourceSection) {
  732.             super(context, sourceSection);
  733.         }

  734.         public InstanceVariableDefinedNode(InstanceVariableDefinedNode prev) {
  735.             super(prev);
  736.         }

  737.         @Specialization
  738.         public boolean isInstanceVariableDefined(RubyBasicObject object, RubyString name) {
  739.             notDesignedForCompilation();

  740.             return object.isFieldDefined(RubyContext.checkInstanceVariableName(getContext(), name.toString(), this));
  741.         }

  742.         @Specialization
  743.         public boolean isInstanceVariableDefined(RubyBasicObject object, RubySymbol name) {
  744.             notDesignedForCompilation();

  745.             return object.isFieldDefined(RubyContext.checkInstanceVariableName(getContext(), name.toString(), this));
  746.         }

  747.     }

  748.     @CoreMethod(names = "instance_variable_get", required = 1)
  749.     public abstract static class InstanceVariableGetNode extends CoreMethodNode {

  750.         public InstanceVariableGetNode(RubyContext context, SourceSection sourceSection) {
  751.             super(context, sourceSection);
  752.         }

  753.         public InstanceVariableGetNode(InstanceVariableGetNode prev) {
  754.             super(prev);
  755.         }

  756.         @Specialization
  757.         public Object isInstanceVariableGet(RubyBasicObject object, RubyString name) {
  758.             notDesignedForCompilation();

  759.             return object.getInstanceVariable(RubyContext.checkInstanceVariableName(getContext(), name.toString(), this));
  760.         }

  761.         @Specialization
  762.         public Object isInstanceVariableGet(RubyBasicObject object, RubySymbol name) {
  763.             notDesignedForCompilation();

  764.             return object.getInstanceVariable(RubyContext.checkInstanceVariableName(getContext(), name.toString(), this));
  765.         }

  766.     }

  767.     @CoreMethod(names = "instance_variable_set", required = 2)
  768.     public abstract static class InstanceVariableSetNode extends CoreMethodNode {

  769.         public InstanceVariableSetNode(RubyContext context, SourceSection sourceSection) {
  770.             super(context, sourceSection);
  771.         }

  772.         public InstanceVariableSetNode(InstanceVariableSetNode prev) {
  773.             super(prev);
  774.         }

  775.         @Specialization
  776.         public Object isInstanceVariableSet(RubyBasicObject object, RubyString name, Object value) {
  777.             notDesignedForCompilation();

  778.             notDesignedForCompilation();
  779.             object.getOperations().setInstanceVariable(object, RubyContext.checkInstanceVariableName(getContext(), name.toString(), this), value);
  780.             return value;
  781.         }

  782.         @Specialization
  783.         public Object isInstanceVariableSet(RubyBasicObject object, RubySymbol name, Object value) {
  784.             notDesignedForCompilation();

  785.             notDesignedForCompilation();
  786.             object.getOperations().setInstanceVariable(object, RubyContext.checkInstanceVariableName(getContext(), name.toString(), this), value);
  787.             return value;
  788.         }

  789.     }

  790.     @CoreMethod(names = "instance_variables")
  791.     public abstract static class InstanceVariablesNode extends CoreMethodNode {

  792.         public InstanceVariablesNode(RubyContext context, SourceSection sourceSection) {
  793.             super(context, sourceSection);
  794.         }

  795.         public InstanceVariablesNode(InstanceVariablesNode prev) {
  796.             super(prev);
  797.         }

  798.         @Specialization
  799.         public RubyArray instanceVariables(RubyBasicObject self) {
  800.             notDesignedForCompilation();

  801.             final Object[] instanceVariableNames = self.getOperations().getFieldNames(self);

  802.             Arrays.sort(instanceVariableNames);

  803.             final RubyArray array = new RubyArray(getContext().getCoreLibrary().getArrayClass());

  804.             for (Object name : instanceVariableNames) {
  805.                 if (name instanceof String) {
  806.                     array.slowPush(getContext().getSymbolTable().getSymbol((String) name));
  807.                 }
  808.             }

  809.             return array;
  810.         }

  811.     }

  812.     @CoreMethod(names = "Integer", isModuleFunction = true, required = 1)
  813.     public abstract static class IntegerNode extends CoreMethodNode {

  814.         @Child protected DispatchHeadNode toInt;

  815.         public IntegerNode(RubyContext context, SourceSection sourceSection) {
  816.             super(context, sourceSection);
  817.             toInt = new DispatchHeadNode(context);
  818.         }

  819.         public IntegerNode(IntegerNode prev) {
  820.             super(prev);
  821.             toInt = prev.toInt;
  822.         }

  823.         @Specialization
  824.         public int integer(int value) {
  825.             return value;
  826.         }

  827.         @Specialization
  828.         public long integer(long value) {
  829.             return value;
  830.         }

  831.         @Specialization
  832.         public RubyBignum integer(RubyBignum value) {
  833.             return value;
  834.         }

  835.         @Specialization
  836.         public int integer(double value) {
  837.             return (int) value;
  838.         }

  839.         @Specialization
  840.         public Object integer(RubyString value) {
  841.             notDesignedForCompilation();

  842.             if (value.toString().length() == 0) {
  843.                 return 0;
  844.             }

  845.             try {
  846.                 return Integer.parseInt(value.toString());
  847.             } catch (NumberFormatException e) {
  848.                 return bignum(new BigInteger(value.toString()));
  849.             }
  850.         }

  851.         @Specialization
  852.         public Object integer(VirtualFrame frame, Object value) {
  853.             if (toInt.doesRespondTo(frame, "to_int", value)) {
  854.                 return toInt.call(frame, value, "to_int", null);
  855.             } else {
  856.                 CompilerDirectives.transferToInterpreter();
  857.                 throw new RaiseException(getContext().getCoreLibrary().typeErrorCantConvertInto(value, getContext().getCoreLibrary().getIntegerClass(), this));
  858.             }
  859.         }

  860.     }

  861.     @CoreMethod(names = {"is_a?", "kind_of?"}, required = 1)
  862.     public abstract static class IsANode extends CoreMethodNode {

  863.         public IsANode(RubyContext context, SourceSection sourceSection) {
  864.             super(context, sourceSection);
  865.         }

  866.         public IsANode(IsANode prev) {
  867.             super(prev);
  868.         }

  869.         public abstract boolean executeBoolean(Object self, RubyClass rubyClass);

  870.         @Specialization
  871.         public boolean isA(RubyBasicObject self, RubyNilClass nil) {
  872.             return false;
  873.         }

  874.         @TruffleBoundary
  875.         @Specialization
  876.         public boolean isA(Object self, RubyClass rubyClass) {
  877.             // TODO(CS): fast path
  878.             notDesignedForCompilation();
  879.             return ModuleOperations.assignableTo(getContext().getCoreLibrary().getMetaClass(self), rubyClass);
  880.         }

  881.     }

  882.     @CoreMethod(names = "lambda", isModuleFunction = true, needsBlock = true)
  883.     public abstract static class LambdaNode extends CoreMethodNode {

  884.         public LambdaNode(RubyContext context, SourceSection sourceSection) {
  885.             super(context, sourceSection);
  886.         }

  887.         public LambdaNode(LambdaNode prev) {
  888.             super(prev);
  889.         }

  890.         @Specialization
  891.         public RubyProc proc(RubyProc block) {
  892.             notDesignedForCompilation();

  893.             return new RubyProc(getContext().getCoreLibrary().getProcClass(), RubyProc.Type.LAMBDA,
  894.                     block.getSharedMethodInfo(), block.getCallTargetForMethods(), block.getCallTargetForMethods(),
  895.                     block.getDeclarationFrame(), block.getDeclaringModule(), block.getMethod(), block.getSelfCapturedInScope(), block.getBlockCapturedInScope());
  896.         }
  897.     }

  898.     @CoreMethod(names = "load", isModuleFunction = true, required = 1)
  899.     public abstract static class LoadNode extends CoreMethodNode {

  900.         public LoadNode(RubyContext context, SourceSection sourceSection) {
  901.             super(context, sourceSection);
  902.         }

  903.         public LoadNode(LoadNode prev) {
  904.             super(prev);
  905.         }

  906.         @Specialization
  907.         public boolean load(RubyString file) {
  908.             notDesignedForCompilation();

  909.             getContext().loadFile(file.toString(), this);
  910.             return true;
  911.         }
  912.     }

  913.     @CoreMethod(names = "local_variables", needsSelf = false)
  914.     public abstract static class LocalVariablesNode extends CoreMethodNode {

  915.         public LocalVariablesNode(RubyContext context, SourceSection sourceSection) {
  916.             super(context, sourceSection);
  917.         }

  918.         public LocalVariablesNode(LocalVariablesNode prev) {
  919.             super(prev);
  920.         }

  921.         @Specialization
  922.         public RubyArray localVariables() {
  923.             notDesignedForCompilation();

  924.             final RubyArray array = new RubyArray(getContext().getCoreLibrary().getArrayClass());

  925.             for (Object name : Truffle.getRuntime().getCallerFrame().getFrame(FrameInstance.FrameAccess.READ_ONLY, false).getFrameDescriptor().getIdentifiers()) {
  926.                 if (name instanceof String) {
  927.                     array.slowPush(getContext().newSymbol((String) name));
  928.                 }
  929.             }

  930.             return array;
  931.         }

  932.     }

  933.     @CoreMethod(names = "loop", isModuleFunction = true)
  934.     public abstract static class LoopNode extends CoreMethodNode {

  935.         @Child protected WhileNode whileNode;

  936.         public LoopNode(RubyContext context, SourceSection sourceSection) {
  937.             super(context, sourceSection);
  938.             whileNode = new WhileNode(context, sourceSection, BooleanCastNodeFactory.create(context, sourceSection,
  939.                     new BooleanLiteralNode(context, sourceSection, true)),
  940.                     new YieldNode(context, getSourceSection(), new RubyNode[]{}, false)
  941.             );
  942.         }

  943.         public LoopNode(LoopNode prev) {
  944.             super(prev);
  945.             whileNode = prev.whileNode;
  946.         }

  947.         @Specialization
  948.         public Object loop(VirtualFrame frame) {
  949.             return whileNode.execute(frame);
  950.         }
  951.     }

  952.     @CoreMethod(names = "methods", optional = 1)
  953.     public abstract static class MethodsNode extends CoreMethodNode {

  954.         public MethodsNode(RubyContext context, SourceSection sourceSection) {
  955.             super(context, sourceSection);
  956.         }

  957.         public MethodsNode(MethodsNode prev) {
  958.             super(prev);
  959.         }

  960.         @Specialization
  961.         public RubyArray methods(RubyBasicObject self, UndefinedPlaceholder unused) {
  962.             return methods(self, true);
  963.         }

  964.         @Specialization
  965.         public RubyArray methods(RubyBasicObject self, boolean includeInherited) {
  966.             notDesignedForCompilation();

  967.             final RubyArray array = new RubyArray(self.getContext().getCoreLibrary().getArrayClass());

  968.             Map<String, RubyMethod> methods;

  969.             if (includeInherited) {
  970.                 methods = ModuleOperations.getAllMethods(self.getMetaClass());
  971.             } else {
  972.                 methods = self.getMetaClass().getMethods();
  973.             }

  974.             for (RubyMethod method : methods.values()) {
  975.                 if (method.getVisibility() == Visibility.PUBLIC || method.getVisibility() == Visibility.PROTECTED) {
  976.                     array.slowPush(self.getContext().newSymbol(method.getName()));
  977.                 }
  978.             }

  979.             return array;
  980.         }

  981.     }

  982.     @CoreMethod(names = "nil?", needsSelf = false)
  983.     public abstract static class NilNode extends CoreMethodNode {

  984.         public NilNode(RubyContext context, SourceSection sourceSection) {
  985.             super(context, sourceSection);
  986.         }

  987.         public NilNode(NilNode prev) {
  988.             super(prev);
  989.         }

  990.         @Specialization
  991.         public boolean nil() {
  992.             return false;
  993.         }
  994.     }

  995.     @CoreMethod(names = "object_id")
  996.     public abstract static class ObjectIDNode extends BasicObjectNodes.IDNode {

  997.         public ObjectIDNode(RubyContext context, SourceSection sourceSection) {
  998.             super(context, sourceSection);
  999.         }

  1000.         public ObjectIDNode(ObjectIDNode prev) {
  1001.             super(prev);
  1002.         }

  1003.     }

  1004.     /*
  1005.      * Kernel#pretty_inspect is normally part of stdlib, in pp.rb, but we aren't able to execute
  1006.      * that file yet. Instead we implement a very simple version here, which is the solution
  1007.      * suggested by RubySpec.
  1008.      */

  1009.     @CoreMethod(names = "pretty_inspect")
  1010.     public abstract static class PrettyInspectNode extends CoreMethodNode {

  1011.         @Child protected DispatchHeadNode inspectNode;

  1012.         public PrettyInspectNode(RubyContext context, SourceSection sourceSection) {
  1013.             super(context, sourceSection);
  1014.             inspectNode = DispatchHeadNode.onSelf(context);
  1015.         }

  1016.         public PrettyInspectNode(PrettyInspectNode prev) {
  1017.             super(prev);
  1018.             inspectNode = prev.inspectNode;
  1019.         }

  1020.         @Specialization
  1021.         public Object prettyInspect(VirtualFrame frame, Object self) {
  1022.             return inspectNode.call(frame, self, "inspect", null);
  1023.         }
  1024.     }

  1025.     @CoreMethod(names = "print", isModuleFunction = true, argumentsAsArray = true)
  1026.     public abstract static class PrintNode extends CoreMethodNode {

  1027.         @Child protected DispatchHeadNode toS;

  1028.         public PrintNode(RubyContext context, SourceSection sourceSection) {
  1029.             super(context, sourceSection);
  1030.             toS = new DispatchHeadNode(context);
  1031.         }

  1032.         public PrintNode(PrintNode prev) {
  1033.             super(prev);
  1034.             toS = prev.toS;
  1035.         }

  1036.         @Specialization
  1037.         public RubyNilClass print(final VirtualFrame frame, final Object[] args) {
  1038.             final RubyThread runningThread = getContext().getThreadManager().leaveGlobalLock();

  1039.             try {
  1040.                 for (Object arg : args) {
  1041.                     write(((RubyString) toS.call(frame, arg, "to_s", null)).getBytes().bytes());
  1042.                 }
  1043.             } finally {
  1044.                 getContext().getThreadManager().enterGlobalLock(runningThread);
  1045.             }

  1046.             return getContext().getCoreLibrary().getNilObject();
  1047.         }

  1048.         @TruffleBoundary
  1049.         private void write(byte[] bytes) {
  1050.             try{
  1051.                 getContext().getRuntime().getInstanceConfig().getOutput().write(bytes);
  1052.             } catch (IOException e) {
  1053.                 throw new RuntimeException(e);
  1054.             }
  1055.         }

  1056.     }

  1057.     @CoreMethod(names = "private_methods", optional = 1)
  1058.     public abstract static class PrivateMethodsNode extends CoreMethodNode {

  1059.         public PrivateMethodsNode(RubyContext context, SourceSection sourceSection) {
  1060.             super(context, sourceSection);
  1061.         }

  1062.         public PrivateMethodsNode(PrivateMethodsNode prev) {
  1063.             super(prev);
  1064.         }

  1065.         @Specialization
  1066.         public RubyArray private_methods(RubyBasicObject self, UndefinedPlaceholder unused) {
  1067.             return private_methods(self, true);
  1068.         }

  1069.         @Specialization
  1070.         public RubyArray private_methods(RubyBasicObject self, boolean includeInherited) {
  1071.             notDesignedForCompilation();

  1072.             final RubyArray array = new RubyArray(self.getContext().getCoreLibrary().getArrayClass());

  1073.             Map<String, RubyMethod> methods;

  1074.             if (includeInherited) {
  1075.                 methods = ModuleOperations.getAllMethods(self.getMetaClass());
  1076.             } else {
  1077.                 methods = self.getMetaClass().getMethods();
  1078.             }

  1079.             for (RubyMethod method : methods.values()) {
  1080.                 if (method.getVisibility() == Visibility.PRIVATE) {
  1081.                     array.slowPush(self.getContext().newSymbol(method.getName()));
  1082.                 }
  1083.             }

  1084.             return array;
  1085.         }

  1086.     }

  1087.     @CoreMethod(names = "proc", isModuleFunction = true, needsBlock = true)
  1088.     public abstract static class ProcNode extends CoreMethodNode {

  1089.         public ProcNode(RubyContext context, SourceSection sourceSection) {
  1090.             super(context, sourceSection);
  1091.         }

  1092.         public ProcNode(ProcNode prev) {
  1093.             super(prev);
  1094.         }

  1095.         @Specialization
  1096.         public RubyProc proc(RubyProc block) {
  1097.             notDesignedForCompilation();

  1098.             return new RubyProc(getContext().getCoreLibrary().getProcClass(), RubyProc.Type.PROC,
  1099.                     block.getSharedMethodInfo(), block.getCallTarget(), block.getCallTargetForMethods(), block.getDeclarationFrame(),
  1100.                     block.getDeclaringModule(), block.getMethod(), block.getSelfCapturedInScope(), block.getBlockCapturedInScope());
  1101.         }
  1102.     }

  1103.     @CoreMethod(names = "public_methods", optional = 1)
  1104.     public abstract static class PublicMethodsNode extends CoreMethodNode {

  1105.         public PublicMethodsNode(RubyContext context, SourceSection sourceSection) {
  1106.             super(context, sourceSection);
  1107.         }

  1108.         public PublicMethodsNode(PublicMethodsNode prev) {
  1109.             super(prev);
  1110.         }

  1111.         @Specialization
  1112.         public RubyArray methods(RubyBasicObject self, boolean includeInherited) {
  1113.             notDesignedForCompilation();

  1114.             if (!includeInherited) {
  1115.                 getContext().getRuntime().getWarnings().warn(IRubyWarnings.ID.TRUFFLE, Truffle.getRuntime().getCallerFrame().getCallNode().getEncapsulatingSourceSection().getSource().getName(), Truffle.getRuntime().getCallerFrame().getCallNode().getEncapsulatingSourceSection().getStartLine(), "Object#methods always returns inherited methods at the moment");
  1116.             }

  1117.             return methods(self, UndefinedPlaceholder.INSTANCE);
  1118.         }

  1119.         @Specialization
  1120.         public RubyArray methods(RubyBasicObject self, UndefinedPlaceholder includeInherited) {
  1121.             notDesignedForCompilation();

  1122.             final RubyArray array = new RubyArray(self.getContext().getCoreLibrary().getArrayClass());

  1123.             final Map<String, RubyMethod> methods = self.getMetaClass().getMethods();

  1124.             for (RubyMethod method : methods.values()) {
  1125.                 if (method.getVisibility() == Visibility.PUBLIC) {
  1126.                     array.slowPush(self.getContext().newSymbol(method.getName()));
  1127.                 }
  1128.             }

  1129.             return array;
  1130.         }

  1131.     }

  1132.     @CoreMethod(names = "raise", isModuleFunction = true, optional = 3)
  1133.     public abstract static class RaiseNode extends CoreMethodNode {

  1134.         @Child protected DispatchHeadNode initialize;

  1135.         public RaiseNode(RubyContext context, SourceSection sourceSection) {
  1136.             super(context, sourceSection);
  1137.             initialize = new DispatchHeadNode(context);
  1138.         }

  1139.         public RaiseNode(RaiseNode prev) {
  1140.             super(prev);
  1141.             initialize = prev.initialize;
  1142.         }

  1143.         @Specialization
  1144.         public Object raise(VirtualFrame frame, UndefinedPlaceholder undefined1, UndefinedPlaceholder undefined2, Object undefined3) {
  1145.             notDesignedForCompilation();

  1146.             return raise(frame, getContext().getCoreLibrary().getRuntimeErrorClass(), getContext().makeString("re-raised - don't have the current exception yet!"), undefined1);
  1147.         }

  1148.         @Specialization
  1149.         public Object raise(VirtualFrame frame, RubyString message, UndefinedPlaceholder undefined1, Object undefined2) {
  1150.             notDesignedForCompilation();

  1151.             return raise(frame, getContext().getCoreLibrary().getRuntimeErrorClass(), message, undefined1);
  1152.         }

  1153.         @Specialization
  1154.         public Object raise(VirtualFrame frame, RubyClass exceptionClass, UndefinedPlaceholder undefined1, Object undefined2) {
  1155.             notDesignedForCompilation();

  1156.             return raise(frame, exceptionClass, getContext().makeString(""), undefined1);
  1157.         }

  1158.         @Specialization
  1159.         public Object raise(VirtualFrame frame, RubyClass exceptionClass, RubyString message, Object undefined1) {
  1160.             notDesignedForCompilation();

  1161.             final Object exception = exceptionClass.allocate(this);
  1162.             initialize.call(frame, exception, "initialize", null, message);

  1163.             if (!(exception instanceof RubyException)) {
  1164.                 CompilerDirectives.transferToInterpreter();
  1165.                 throw new RaiseException(getContext().getCoreLibrary().typeError("exception class/object expected", this));
  1166.             }

  1167.             throw new RaiseException((RubyException) exception);
  1168.         }

  1169.         @Specialization
  1170.         public Object raise(RubyException exception, UndefinedPlaceholder undefined1, Object undefined2) {
  1171.             throw new RaiseException(exception);
  1172.         }

  1173.     }

  1174.     @CoreMethod(names = "rand", isModuleFunction = true, optional = 1)
  1175.     public abstract static class RandNode extends CoreMethodNode {

  1176.         public RandNode(RubyContext context, SourceSection sourceSection) {
  1177.             super(context, sourceSection);
  1178.         }

  1179.         public RandNode(RandNode prev) {
  1180.             super(prev);
  1181.         }

  1182.         @Specialization
  1183.         public double rand(UndefinedPlaceholder undefined) {
  1184.             return getContext().getRandom().nextDouble();
  1185.         }

  1186.         @Specialization(guards = "isZero")
  1187.         public double randZero(int max) {
  1188.             return getContext().getRandom().nextDouble();
  1189.         }

  1190.         @Specialization(guards = "isNonZero")
  1191.         public int randNonZero(int max) {
  1192.             return getContext().getRandom().nextInt(max);
  1193.         }

  1194.         protected boolean isZero(int max) {
  1195.             return max == 0;
  1196.         }

  1197.         protected boolean isNonZero(int max) {
  1198.             return max != 0;
  1199.         }

  1200.     }

  1201.     @CoreMethod(names = "require", isModuleFunction = true, required = 1)
  1202.     public abstract static class RequireNode extends CoreMethodNode {

  1203.         public RequireNode(RubyContext context, SourceSection sourceSection) {
  1204.             super(context, sourceSection);
  1205.         }

  1206.         public RequireNode(RequireNode prev) {
  1207.             super(prev);
  1208.         }

  1209.         @Specialization
  1210.         public boolean require(RubyString feature) {
  1211.             notDesignedForCompilation();

  1212.             try {
  1213.                 getContext().getFeatureManager().require(feature.toString(), this);
  1214.             } catch (IOException e) {
  1215.                 throw new RuntimeException(e);
  1216.             }

  1217.             return true;
  1218.         }
  1219.     }

  1220.     @CoreMethod(names = "require_relative", isModuleFunction = true, required = 1)
  1221.     public abstract static class RequireRelativeNode extends CoreMethodNode {

  1222.         public RequireRelativeNode(RubyContext context, SourceSection sourceSection) {
  1223.             super(context, sourceSection);
  1224.         }

  1225.         public RequireRelativeNode(RequireRelativeNode prev) {
  1226.             super(prev);
  1227.         }

  1228.         @Specialization
  1229.         public boolean require(VirtualFrame frame, RubyString feature) {
  1230.             notDesignedForCompilation();

  1231.             final String sourcePath = Truffle.getRuntime().getCallerFrame().getCallNode().getEncapsulatingSourceSection().getSource().getPath();
  1232.             final String directoryPath = new File(sourcePath).getParent();

  1233.             try {
  1234.                 getContext().getFeatureManager().requireInPath(directoryPath, feature.toString(), this);
  1235.             } catch (IOException e) {
  1236.                 throw new RuntimeException(e);
  1237.             }

  1238.             return true;
  1239.         }
  1240.     }

  1241.     @CoreMethod(names = "respond_to?", required = 1, optional = 1)
  1242.     public abstract static class RespondToNode extends CoreMethodNode {

  1243.         @Child protected DispatchHeadNode dispatch;
  1244.         @Child protected DispatchHeadNode dispatchIgnoreVisibility;

  1245.         public RespondToNode(RubyContext context, SourceSection sourceSection) {
  1246.             super(context, sourceSection);

  1247.             dispatch = new DispatchHeadNode(context, false, Dispatch.MissingBehavior.RETURN_MISSING);
  1248.             dispatchIgnoreVisibility = new DispatchHeadNode(context, true, Dispatch.MissingBehavior.RETURN_MISSING);

  1249.             if (Options.TRUFFLE_DISPATCH_METAPROGRAMMING_ALWAYS_UNCACHED.load()) {
  1250.                 dispatch.forceUncached();
  1251.                 dispatchIgnoreVisibility.forceUncached();
  1252.             }
  1253.         }

  1254.         public RespondToNode(RespondToNode prev) {
  1255.             super(prev);
  1256.             dispatch = prev.dispatch;
  1257.             dispatchIgnoreVisibility = prev.dispatchIgnoreVisibility;
  1258.         }

  1259.         public abstract boolean executeDoesRespondTo(VirtualFrame frame, Object object, Object name, boolean includePrivate);

  1260.         @Specialization
  1261.         public boolean doesRespondTo(VirtualFrame frame, Object object, RubyString name, UndefinedPlaceholder checkVisibility) {
  1262.             return dispatch.doesRespondTo(frame, name, object);
  1263.         }

  1264.         @Specialization
  1265.         public boolean doesRespondTo(VirtualFrame frame, Object object, RubyString name, boolean ignoreVisibility) {
  1266.             if (ignoreVisibility) {
  1267.                 return dispatchIgnoreVisibility.doesRespondTo(frame, name, object);
  1268.             } else {
  1269.                 return dispatch.doesRespondTo(frame, name, object);
  1270.             }
  1271.         }

  1272.         @Specialization
  1273.         public boolean doesRespondTo(VirtualFrame frame, Object object, RubySymbol name, UndefinedPlaceholder checkVisibility) {
  1274.             return dispatch.doesRespondTo(frame, name, object);
  1275.         }

  1276.         @Specialization
  1277.         public boolean doesRespondTo(VirtualFrame frame, Object object, RubySymbol name, boolean ignoreVisibility) {
  1278.             if (ignoreVisibility) {
  1279.                 return dispatchIgnoreVisibility.doesRespondTo(frame, name, object);
  1280.             } else {
  1281.                 return dispatch.doesRespondTo(frame, name, object);
  1282.             }
  1283.         }
  1284.     }

  1285.     @CoreMethod(names = "respond_to_missing?", required = 1, optional = 1, visibility = Visibility.PRIVATE)
  1286.     public abstract static class RespondToMissingNode extends CoreMethodNode {

  1287.         public RespondToMissingNode(RubyContext context, SourceSection sourceSection) {
  1288.             super(context, sourceSection);
  1289.         }

  1290.         public RespondToMissingNode(RespondToMissingNode prev) {
  1291.             super(prev);
  1292.         }

  1293.         @Specialization
  1294.         public boolean doesRespondToMissing(Object object, RubyString name, UndefinedPlaceholder includeAll) {
  1295.             return false;
  1296.         }

  1297.         @Specialization
  1298.         public boolean doesRespondToMissing(Object object, RubySymbol name, UndefinedPlaceholder includeAll) {
  1299.             return false;
  1300.         }

  1301.         @Specialization
  1302.         public boolean doesRespondToMissing(Object object, RubySymbol name, boolean includeAll) {
  1303.             return false;
  1304.         }

  1305.         @Specialization
  1306.         public boolean doesRespondToMissing(Object object, RubyString name, boolean includeAll) {
  1307.             return false;
  1308.         }

  1309.     }

  1310.     @CoreMethod(names = "send", needsBlock = true, required = 1, argumentsAsArray = true)
  1311.     public abstract static class SendNode extends BasicObjectNodes.SendNode {

  1312.         public SendNode(RubyContext context, SourceSection sourceSection) {
  1313.             super(context, sourceSection);
  1314.         }

  1315.         public SendNode(SendNode prev) {
  1316.             super(prev);
  1317.         }

  1318.     }

  1319.     @CoreMethod(names = "set_trace_func", isModuleFunction = true, required = 1)
  1320.     public abstract static class SetTraceFuncNode extends CoreMethodNode {

  1321.         public SetTraceFuncNode(RubyContext context, SourceSection sourceSection) {
  1322.             super(context, sourceSection);
  1323.         }

  1324.         public SetTraceFuncNode(SetTraceFuncNode prev) {
  1325.             super(prev);
  1326.         }

  1327.         @Specialization
  1328.         public RubyNilClass setTraceFunc(RubyNilClass nil) {
  1329.             notDesignedForCompilation();

  1330.             getContext().getTraceManager().setTraceFunc(null);
  1331.             return nil;
  1332.         }

  1333.         @Specialization
  1334.         public RubyProc setTraceFunc(RubyProc traceFunc) {
  1335.             notDesignedForCompilation();

  1336.             getContext().getTraceManager().setTraceFunc(traceFunc);
  1337.             return traceFunc;
  1338.         }
  1339.     }

  1340.     @CoreMethod(names = "singleton_class")
  1341.     public abstract static class SingletonClassMethodNode extends CoreMethodNode {

  1342.         @Child protected SingletonClassNode singletonClassNode;

  1343.         public SingletonClassMethodNode(RubyContext context, SourceSection sourceSection) {
  1344.             super(context, sourceSection);
  1345.             singletonClassNode = SingletonClassNodeFactory.create(context, sourceSection, null);
  1346.         }

  1347.         public SingletonClassMethodNode(SingletonClassMethodNode prev) {
  1348.             super(prev);
  1349.             singletonClassNode = prev.singletonClassNode;
  1350.         }

  1351.         @Specialization
  1352.         public RubyClass singletonClass(Object self) {
  1353.             return singletonClassNode.executeSingletonClass(self);
  1354.         }

  1355.     }

  1356.     @CoreMethod(names = "singleton_methods", optional = 1)
  1357.     public abstract static class SingletonMethodsNode extends CoreMethodNode {

  1358.         public SingletonMethodsNode(RubyContext context, SourceSection sourceSection) {
  1359.             super(context, sourceSection);
  1360.         }

  1361.         public SingletonMethodsNode(SingletonMethodsNode prev) {
  1362.             super(prev);
  1363.         }

  1364.         @Specialization
  1365.         public RubyArray singletonMethods(RubyBasicObject self, boolean includeInherited) {
  1366.             notDesignedForCompilation();

  1367.             final RubyArray array = new RubyArray(self.getContext().getCoreLibrary().getArrayClass());

  1368.             final Collection<RubyMethod> methods;

  1369.             if (includeInherited) {
  1370.                 methods = ModuleOperations.getAllMethods(self.getSingletonClass(this)).values();
  1371.             } else {
  1372.                 methods = self.getSingletonClass(this).getMethods().values();
  1373.             }

  1374.             for (RubyMethod method : methods) {
  1375.                 array.slowPush(RubySymbol.newSymbol(self.getContext(), method.getName()));
  1376.             }

  1377.             return array;
  1378.         }

  1379.         @Specialization
  1380.         public RubyArray singletonMethods(RubyBasicObject self, UndefinedPlaceholder includeInherited) {
  1381.             return singletonMethods(self, false);
  1382.         }

  1383.     }

  1384.     @CoreMethod(names = "String", isModuleFunction = true, required = 1)
  1385.     public abstract static class StringNode extends CoreMethodNode {

  1386.         @Child protected DispatchHeadNode toS;

  1387.         public StringNode(RubyContext context, SourceSection sourceSection) {
  1388.             super(context, sourceSection);
  1389.             toS = new DispatchHeadNode(context);
  1390.         }

  1391.         public StringNode(StringNode prev) {
  1392.             super(prev);
  1393.             toS = prev.toS;
  1394.         }

  1395.         @Specialization
  1396.         public RubyString string(RubyString value) {
  1397.             return value;
  1398.         }

  1399.         @Specialization(guards = "!isRubyString")
  1400.         public Object string(VirtualFrame frame, Object value) {
  1401.             return toS.call(frame, value, "to_s", null);
  1402.         }

  1403.     }

  1404.     @CoreMethod(names = "sleep", isModuleFunction = true, optional = 1)
  1405.     public abstract static class SleepNode extends CoreMethodNode {

  1406.         public SleepNode(RubyContext context, SourceSection sourceSection) {
  1407.             super(context, sourceSection);
  1408.         }

  1409.         public SleepNode(SleepNode prev) {
  1410.             super(prev);
  1411.         }

  1412.         @Specialization
  1413.         public double sleep(UndefinedPlaceholder duration) {
  1414.             return doSleep(0);
  1415.         }

  1416.         @Specialization
  1417.         public double sleep(int duration) {
  1418.             return doSleep(duration);
  1419.         }

  1420.         @Specialization
  1421.         public double sleep(long duration) {
  1422.             return doSleep(duration);
  1423.         }

  1424.         @Specialization
  1425.         public double sleep(double duration) {
  1426.             return doSleep(duration);
  1427.         }

  1428.         @TruffleBoundary
  1429.         private double doSleep(final double duration) {
  1430.             final RubyThread runningThread = getContext().getThreadManager().leaveGlobalLock();

  1431.             try {
  1432.                 final long start = System.nanoTime();

  1433.                 try {
  1434.                     Thread.sleep((long) (duration * 1000));
  1435.                 } catch (InterruptedException e) {
  1436.                     // Ignore interruption
  1437.                 }

  1438.                 final long end = System.nanoTime();

  1439.                 return (end - start) / 1e9;
  1440.             } finally {
  1441.                 getContext().getThreadManager().enterGlobalLock(runningThread);
  1442.             }
  1443.         }

  1444.     }

  1445.     @CoreMethod(names = "sprintf", isModuleFunction = true, argumentsAsArray = true)
  1446.     public abstract static class SPrintfNode extends CoreMethodNode {

  1447.         public SPrintfNode(RubyContext context, SourceSection sourceSection) {
  1448.             super(context, sourceSection);
  1449.         }

  1450.         public SPrintfNode(SPrintfNode prev) {
  1451.             super(prev);
  1452.         }

  1453.         @Specialization
  1454.         public RubyString sprintf(Object[] args) {
  1455.             notDesignedForCompilation();

  1456.             final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
  1457.             final PrintStream printStream = new PrintStream(outputStream);

  1458.             if (args.length > 0) {
  1459.                 final String format = args[0].toString();
  1460.                 final List<Object> values = Arrays.asList(args).subList(1, args.length);

  1461.                 final RubyThread runningThread = getContext().getThreadManager().leaveGlobalLock();

  1462.                 try {
  1463.                     StringFormatter.format(getContext(), printStream, format, values);
  1464.                 } finally {
  1465.                     getContext().getThreadManager().enterGlobalLock(runningThread);
  1466.                 }
  1467.             }

  1468.             return getContext().makeString(new ByteList(outputStream.toByteArray()));
  1469.         }
  1470.     }

  1471.     @CoreMethod(names = "system", isModuleFunction = true, argumentsAsArray = true)
  1472.     public abstract static class SystemNode extends CoreMethodNode {

  1473.         public SystemNode(RubyContext context, SourceSection sourceSection) {
  1474.             super(context, sourceSection);
  1475.         }

  1476.         public SystemNode(SystemNode prev) {
  1477.             super(prev);
  1478.         }

  1479.         @Specialization
  1480.         public Object fork(Object[] args) {
  1481.             notDesignedForCompilation();
  1482.             getContext().getWarnings().warn("Kernel#system not implemented - defined to satisfy some metaprogramming in RubySpec");
  1483.             return getContext().getCoreLibrary().getNilObject();
  1484.         }

  1485.     }

  1486.     @CoreMethod(names = "taint")
  1487.     public abstract static class TaintNode extends CoreMethodNode {

  1488.         @Child protected WriteHeadObjectFieldNode writeTaintNode;

  1489.         public TaintNode(RubyContext context, SourceSection sourceSection) {
  1490.             super(context, sourceSection);
  1491.             writeTaintNode = new WriteHeadObjectFieldNode(RubyBasicObject.TAINTED_IDENTIFIER);
  1492.         }

  1493.         public TaintNode(TaintNode prev) {
  1494.             super(prev);
  1495.             writeTaintNode = prev.writeTaintNode;
  1496.         }

  1497.         @Specialization
  1498.         public Object taint(boolean object) {
  1499.             return frozen(object);
  1500.         }

  1501.         @Specialization
  1502.         public Object taint(int object) {
  1503.             return frozen(object);
  1504.         }

  1505.         @Specialization
  1506.         public Object taint(long object) {
  1507.             return frozen(object);
  1508.         }

  1509.         @Specialization
  1510.         public Object taint(double object) {
  1511.             return frozen(object);
  1512.         }

  1513.         private Object frozen(Object object) {
  1514.             CompilerDirectives.transferToInterpreter();
  1515.             throw new RaiseException(getContext().getCoreLibrary().frozenError(getContext().getCoreLibrary().getLogicalClass(object).getName(), this));
  1516.         }


  1517.         @Specialization
  1518.         public Object taint(RubyBasicObject object) {
  1519.             writeTaintNode.execute(object, true);
  1520.             return object;
  1521.         }

  1522.     }

  1523.     @CoreMethod(names = "tainted?")
  1524.     public abstract static class TaintedNode extends CoreMethodNode {

  1525.         @Child protected ReadHeadObjectFieldNode readTaintNode;

  1526.         public TaintedNode(RubyContext context, SourceSection sourceSection) {
  1527.             super(context, sourceSection);
  1528.             readTaintNode = new ReadHeadObjectFieldNode(RubyBasicObject.TAINTED_IDENTIFIER);
  1529.         }

  1530.         public TaintedNode(TaintedNode prev) {
  1531.             super(prev);
  1532.             readTaintNode = prev.readTaintNode;
  1533.         }

  1534.         @Specialization
  1535.         public boolean tainted(boolean object) {
  1536.             return false;
  1537.         }

  1538.         @Specialization
  1539.         public boolean tainted(int object) {
  1540.             return false;
  1541.         }

  1542.         @Specialization
  1543.         public boolean tainted(long object) {
  1544.             return false;
  1545.         }

  1546.         @Specialization
  1547.         public boolean tainted(double object) {
  1548.             return false;
  1549.         }

  1550.         @Specialization
  1551.         public boolean tainted(RubyBasicObject object) {
  1552.             try {
  1553.                 return readTaintNode.isSet(object) && readTaintNode.executeBoolean(object);
  1554.             } catch (UnexpectedResultException e) {
  1555.                 throw new UnsupportedOperationException();
  1556.             }
  1557.         }

  1558.     }

  1559.     @CoreMethod(names = "throw", isModuleFunction = true, required = 1, optional = 1)
  1560.     public abstract static class ThrowNode extends CoreMethodNode {

  1561.         public ThrowNode(RubyContext context, SourceSection sourceSection) {
  1562.             super(context, sourceSection);
  1563.         }

  1564.         public ThrowNode(ThrowNode prev) {
  1565.             super(prev);
  1566.         }

  1567.         @Specialization
  1568.         public Object doThrow(Object tag, UndefinedPlaceholder value) {
  1569.             return doThrow(tag, (Object) value);
  1570.         }

  1571.         @Specialization
  1572.         public Object doThrow(Object tag, Object value) {
  1573.             notDesignedForCompilation();

  1574.             if (!getContext().getThrowTags().contains(tag)) {
  1575.                 throw new RaiseException(new RubyException(
  1576.                         getContext().getCoreLibrary().getArgumentErrorClass(),
  1577.                         getContext().makeString(String.format("uncaught throw \"%s\"", tag)),
  1578.                         RubyCallStack.getBacktrace(this)));
  1579.             }

  1580.             if (value instanceof UndefinedPlaceholder) {
  1581.                 throw new ThrowException(tag, getContext().getCoreLibrary().getNilObject());
  1582.             } else {
  1583.                 throw new ThrowException(tag, value);
  1584.             }
  1585.         }

  1586.     }

  1587.     public abstract static class ToHexStringNode extends CoreMethodNode {

  1588.         public ToHexStringNode(RubyContext context, SourceSection sourceSection) {
  1589.             super(context, sourceSection);
  1590.         }

  1591.         public ToHexStringNode(ToHexStringNode prev) {
  1592.             super(prev);
  1593.         }

  1594.         public abstract String executeToHexString(Object value);

  1595.         @Specialization
  1596.         public String toHexString(int value) {
  1597.             return toHexString((long) value);
  1598.         }

  1599.         @Specialization
  1600.         public String toHexString(long value) {
  1601.             return Long.toHexString(value);
  1602.         }

  1603.         @Specialization
  1604.         public String toHexString(RubyBignum value) {
  1605.             return value.toHexString();
  1606.         }

  1607.     }

  1608.     @CoreMethod(names = {"to_s", "inspect"})
  1609.     public abstract static class ToSNode extends CoreMethodNode {

  1610.         @Child protected ClassNode classNode;
  1611.         @Child protected BasicObjectNodes.IDNode idNode;
  1612.         @Child protected ToHexStringNode toHexStringNode;

  1613.         public ToSNode(RubyContext context, SourceSection sourceSection) {
  1614.             super(context, sourceSection);
  1615.             classNode = KernelNodesFactory.ClassNodeFactory.create(context, sourceSection, new RubyNode[]{null});
  1616.             idNode = BasicObjectNodesFactory.IDNodeFactory.create(context, sourceSection, new RubyNode[]{null});
  1617.             toHexStringNode = KernelNodesFactory.ToHexStringNodeFactory.create(context, sourceSection, new RubyNode[]{null});
  1618.         }

  1619.         public abstract RubyString executeToS(VirtualFrame frame, Object self);

  1620.         @Specialization
  1621.         public RubyString toS(VirtualFrame frame, Object self) {
  1622.             notDesignedForCompilation();

  1623.             String className = classNode.executeGetClass(self).getName();

  1624.             if (className == null) {
  1625.                 className = "Class";
  1626.             }

  1627.             Object id = idNode.executeObjectID(frame, self);
  1628.             String hexID = toHexStringNode.executeToHexString(id);

  1629.             return getContext().makeString("#<" + className + ":0x" + hexID + ">");
  1630.         }

  1631.     }

  1632.     @CoreMethod(names = "untaint")
  1633.     public abstract static class UntaintNode extends CoreMethodNode {

  1634.         @Child protected WriteHeadObjectFieldNode writeTaintNode;

  1635.         public UntaintNode(RubyContext context, SourceSection sourceSection) {
  1636.             super(context, sourceSection);
  1637.             writeTaintNode = new WriteHeadObjectFieldNode(RubyBasicObject.TAINTED_IDENTIFIER);
  1638.         }

  1639.         public UntaintNode(UntaintNode prev) {
  1640.             super(prev);
  1641.             writeTaintNode = prev.writeTaintNode;
  1642.         }

  1643.         @Specialization
  1644.         public Object taint(boolean object) {
  1645.             return frozen(object);
  1646.         }

  1647.         @Specialization
  1648.         public Object taint(int object) {
  1649.             return frozen(object);
  1650.         }

  1651.         @Specialization
  1652.         public Object taint(long object) {
  1653.             return frozen(object);
  1654.         }

  1655.         @Specialization
  1656.         public Object taint(double object) {
  1657.             return frozen(object);
  1658.         }

  1659.         private Object frozen(Object object) {
  1660.             CompilerDirectives.transferToInterpreter();
  1661.             throw new RaiseException(getContext().getCoreLibrary().frozenError(getContext().getCoreLibrary().getLogicalClass(object).getName(), this));
  1662.         }


  1663.         @Specialization
  1664.         public Object taint(RubyBasicObject object) {
  1665.             writeTaintNode.execute(object, false);
  1666.             return object;
  1667.         }

  1668.     }

  1669. }