* Eliminate visibility checking for almost all fcall and vcall paths.
[jruby.git] / src / org / jruby / RubyKernel.java
blob8be785509d1181f76c010327b4284de045ed5a21
1 /*
2 ***** BEGIN LICENSE BLOCK *****
3 * Version: CPL 1.0/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Common Public
6 * License Version 1.0 (the "License"); you may not use this file
7 * except in compliance with the License. You may obtain a copy of
8 * the License at http://www.eclipse.org/legal/cpl-v10.html
10 * Software distributed under the License is distributed on an "AS
11 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
12 * implied. See the License for the specific language governing
13 * rights and limitations under the License.
15 * Copyright (C) 2001 Chad Fowler <chadfowler@chadfowler.com>
16 * Copyright (C) 2001 Alan Moore <alan_moore@gmx.net>
17 * Copyright (C) 2001-2002 Benoit Cerrina <b.cerrina@wanadoo.fr>
18 * Copyright (C) 2001-2004 Jan Arne Petersen <jpetersen@uni-bonn.de>
19 * Copyright (C) 2002-2006 Thomas E Enebo <enebo@acm.org>
20 * Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se>
21 * Copyright (C) 2004-2005 Charles O Nutter <headius@headius.com>
22 * Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
23 * Copyright (C) 2005 Kiel Hodges <jruby-devel@selfsosoft.com>
24 * Copyright (C) 2006 Evan Buswell <evan@heron.sytes.net>
25 * Copyright (C) 2006 Ola Bini <ola@ologix.com>
26 * Copyright (C) 2006 Michael Studman <codehaus@michaelstudman.com>
27 * Copyright (C) 2006 Miguel Covarrubias <mlcovarrubias@gmail.com>
28 * Copyright (C) 2007 Nick Sieger <nicksieger@gmail.com>
30 * Alternatively, the contents of this file may be used under the terms of
31 * either of the GNU General Public License Version 2 or later (the "GPL"),
32 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
33 * in which case the provisions of the GPL or the LGPL are applicable instead
34 * of those above. If you wish to allow use of your version of this file only
35 * under the terms of either the GPL or the LGPL, and not to allow others to
36 * use your version of this file under the terms of the CPL, indicate your
37 * decision by deleting the provisions above and replace them with the notice
38 * and other provisions required by the GPL or the LGPL. If you do not delete
39 * the provisions above, a recipient may use your version of this file under
40 * the terms of any one of the CPL, the GPL or the LGPL.
41 ***** END LICENSE BLOCK *****/
42 package org.jruby;
44 import java.io.ByteArrayOutputStream;
45 import java.math.BigInteger;
46 import java.util.ArrayList;
47 import static org.jruby.anno.FrameField.*;
48 import org.jruby.anno.JRubyMethod;
49 import org.jruby.anno.JRubyModule;
51 import org.jruby.ast.util.ArgsUtil;
52 import org.jruby.common.IRubyWarnings.ID;
53 import org.jruby.evaluator.ASTInterpreter;
54 import org.jruby.exceptions.JumpException;
55 import org.jruby.exceptions.MainExitException;
56 import org.jruby.exceptions.RaiseException;
57 import org.jruby.internal.runtime.JumpTarget;
58 import org.jruby.javasupport.util.RuntimeHelpers;
59 import org.jruby.runtime.Block;
60 import org.jruby.runtime.CallType;
61 import org.jruby.runtime.Frame;
62 import org.jruby.runtime.MethodIndex;
63 import org.jruby.runtime.ThreadContext;
64 import org.jruby.runtime.Visibility;
65 import static org.jruby.runtime.Visibility.*;
66 import org.jruby.runtime.builtin.IRubyObject;
67 import org.jruby.runtime.load.IAutoloadMethod;
68 import org.jruby.runtime.load.LoadService;
69 import org.jruby.util.IdUtil;
70 import org.jruby.util.ShellLauncher;
71 import org.jruby.util.TypeConverter;
73 /**
74 * Note: For CVS history, see KernelModule.java.
76 @JRubyModule(name="Kernel")
77 public class RubyKernel {
78 public final static Class<?> IRUBY_OBJECT = IRubyObject.class;
80 public static RubyModule createKernelModule(Ruby runtime) {
81 RubyModule module = runtime.defineModule("Kernel");
82 runtime.setKernel(module);
84 module.defineAnnotatedMethods(RubyKernel.class);
85 module.defineAnnotatedMethods(RubyObject.class);
87 runtime.setRespondToMethod(module.searchMethod("respond_to?"));
89 module.setFlag(RubyObject.USER7_F, false); //Kernel is the only Module that doesn't need an implementor
91 return module;
94 @JRubyMethod(name = "at_exit", frame = true, module = true, visibility = PRIVATE)
95 public static IRubyObject at_exit(ThreadContext context, IRubyObject recv, Block block) {
96 return context.getRuntime().pushExitBlock(context.getRuntime().newProc(Block.Type.PROC, block));
99 @JRubyMethod(name = "autoload?", required = 1, module = true, visibility = PRIVATE)
100 public static IRubyObject autoload_p(ThreadContext context, final IRubyObject recv, IRubyObject symbol) {
101 Ruby runtime = context.getRuntime();
102 RubyModule module = recv instanceof RubyModule ? (RubyModule) recv : runtime.getObject();
103 String name = module.getName() + "::" + symbol.asJavaString();
105 IAutoloadMethod autoloadMethod = runtime.getLoadService().autoloadFor(name);
106 if (autoloadMethod == null) return runtime.getNil();
108 return runtime.newString(autoloadMethod.file());
111 @JRubyMethod(name = "autoload", required = 2, frame = true, module = true, visibility = PRIVATE)
112 public static IRubyObject autoload(final IRubyObject recv, IRubyObject symbol, final IRubyObject file) {
113 Ruby runtime = recv.getRuntime();
114 final LoadService loadService = runtime.getLoadService();
115 String nonInternedName = symbol.asJavaString();
117 if (!IdUtil.isValidConstantName(nonInternedName)) {
118 throw runtime.newNameError("autoload must be constant name", nonInternedName);
121 RubyString fileString = file.convertToString();
123 if (fileString.isEmpty()) {
124 throw runtime.newArgumentError("empty file name");
127 final String baseName = symbol.asJavaString().intern(); // interned, OK for "fast" methods
128 final RubyModule module = recv instanceof RubyModule ? (RubyModule) recv : runtime.getObject();
129 String nm = module.getName() + "::" + baseName;
131 IRubyObject existingValue = module.fastFetchConstant(baseName);
132 if (existingValue != null && existingValue != RubyObject.UNDEF) return runtime.getNil();
134 module.fastStoreConstant(baseName, RubyObject.UNDEF);
136 loadService.addAutoload(nm, new IAutoloadMethod() {
137 public String file() {
138 return file.toString();
141 * @see org.jruby.runtime.load.IAutoloadMethod#load(Ruby, String)
143 public IRubyObject load(Ruby runtime, String name) {
144 boolean required = loadService.require(file());
146 // File to be loaded by autoload has already been or is being loaded.
147 if (!required) return null;
149 return module.fastGetConstant(baseName);
152 return runtime.getNil();
155 @JRubyMethod(name = "method_missing", rest = true, frame = true, module = true, visibility = PRIVATE)
156 public static IRubyObject method_missing(ThreadContext context, IRubyObject recv, IRubyObject[] args, Block block) {
157 Ruby runtime = context.getRuntime();
159 if (args.length == 0 || !(args[0] instanceof RubySymbol)) throw runtime.newArgumentError("no id given");
161 Visibility lastVis = context.getLastVisibility();
162 CallType lastCallType = context.getLastCallType();
164 // create a lightweight thunk
165 IRubyObject msg = new RubyNameError.RubyNameErrorMessage(runtime,
166 recv,
167 args[0],
168 lastVis,
169 lastCallType);
170 final IRubyObject[]exArgs;
171 final RubyClass exc;
172 if (lastCallType != CallType.VARIABLE) {
173 exc = runtime.getNoMethodError();
174 exArgs = new IRubyObject[]{msg, args[0], RubyArray.newArrayNoCopy(runtime, args, 1)};
175 } else {
176 exc = runtime.getNameError();
177 exArgs = new IRubyObject[]{msg, args[0]};
180 throw new RaiseException((RubyException)exc.newInstance(context, exArgs, Block.NULL_BLOCK));
183 @JRubyMethod(name = "open", required = 1, optional = 2, frame = true, module = true, visibility = PRIVATE)
184 public static IRubyObject open(ThreadContext context, IRubyObject recv, IRubyObject[] args, Block block) {
185 String arg = args[0].convertToString().toString();
186 Ruby runtime = context.getRuntime();
188 if (arg.startsWith("|")) {
189 String command = arg.substring(1);
190 // exec process, create IO with process
191 return RubyIO.popen(context, runtime.getIO(), new IRubyObject[] {runtime.newString(command)}, block);
194 return RubyFile.open(context, runtime.getFile(), args, block);
197 @JRubyMethod(name = "getc", module = true, visibility = PRIVATE)
198 public static IRubyObject getc(ThreadContext context, IRubyObject recv) {
199 context.getRuntime().getWarnings().warn(ID.DEPRECATED_METHOD, "getc is obsolete; use STDIN.getc instead", "getc", "STDIN.getc");
200 IRubyObject defin = context.getRuntime().getGlobalVariables().get("$stdin");
201 return defin.callMethod(context, "getc");
204 @JRubyMethod(name = "gets", optional = 1, module = true, visibility = PRIVATE)
205 public static IRubyObject gets(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
206 return RubyArgsFile.gets(context, context.getRuntime().getGlobalVariables().get("$<"), args);
209 @JRubyMethod(name = "abort", optional = 1, module = true, visibility = PRIVATE)
210 public static IRubyObject abort(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
211 if(args.length == 1) {
212 context.getRuntime().getGlobalVariables().get("$stderr").callMethod(context,"puts",args[0]);
214 throw new MainExitException(1,true);
217 @JRubyMethod(name = "Array", required = 1, module = true, visibility = PRIVATE)
218 public static IRubyObject new_array(ThreadContext context, IRubyObject recv, IRubyObject object) {
219 IRubyObject value = object.checkArrayType();
221 if (value.isNil()) {
222 if (object.getMetaClass().searchMethod("to_a").getImplementationClass() != context.getRuntime().getKernel()) {
223 value = object.callMethod(context, MethodIndex.TO_A, "to_a");
224 if (!(value instanceof RubyArray)) throw context.getRuntime().newTypeError("`to_a' did not return Array");
225 return value;
226 } else {
227 return context.getRuntime().newArray(object);
230 return value;
233 @JRubyMethod(name = "Complex", required = 0, optional = 2, module = true, visibility = PRIVATE, compat = CompatVersion.RUBY1_9)
234 public static IRubyObject new_complex(ThreadContext context, IRubyObject recv, IRubyObject[]args) {
235 return context.getRuntime().getComplex().callMethod(context, "convert", args);
238 @JRubyMethod(name = "Rational", required = 0, optional = 2, module = true, visibility = PRIVATE, compat = CompatVersion.RUBY1_9)
239 public static IRubyObject new_rational(ThreadContext context, IRubyObject recv, IRubyObject[]args) {
240 return context.getRuntime().getRational().callMethod(context, "convert", args);
243 @JRubyMethod(name = "Float", required = 1, module = true, visibility = PRIVATE)
244 public static IRubyObject new_float(IRubyObject recv, IRubyObject object) {
245 if(object instanceof RubyFixnum){
246 return RubyFloat.newFloat(object.getRuntime(), ((RubyFixnum)object).getDoubleValue());
247 }else if(object instanceof RubyFloat){
248 return object;
249 }else if(object instanceof RubyBignum){
250 return RubyFloat.newFloat(object.getRuntime(), RubyBignum.big2dbl((RubyBignum)object));
251 }else if(object instanceof RubyString){
252 if(((RubyString)object).getByteList().realSize == 0){ // rb_cstr_to_dbl case
253 throw recv.getRuntime().newArgumentError("invalid value for Float(): " + object.inspect());
255 return RubyNumeric.str2fnum(recv.getRuntime(),(RubyString)object,true);
256 }else if(object.isNil()){
257 throw recv.getRuntime().newTypeError("can't convert nil into Float");
258 } else {
259 RubyFloat rFloat = (RubyFloat)TypeConverter.convertToType(object, recv.getRuntime().getFloat(), MethodIndex.TO_F, "to_f");
260 if (Double.isNaN(rFloat.getDoubleValue())) throw recv.getRuntime().newArgumentError("invalid value for Float()");
261 return rFloat;
265 @JRubyMethod(name = "Integer", required = 1, module = true, visibility = PRIVATE)
266 public static IRubyObject new_integer(ThreadContext context, IRubyObject recv, IRubyObject object) {
267 if (object instanceof RubyFloat) {
268 double val = ((RubyFloat)object).getDoubleValue();
269 if (val > (double) RubyFixnum.MAX && val < (double) RubyFixnum.MIN) {
270 return RubyNumeric.dbl2num(context.getRuntime(),((RubyFloat)object).getDoubleValue());
272 } else if (object instanceof RubyFixnum || object instanceof RubyBignum) {
273 return object;
274 } else if (object instanceof RubyString) {
275 return RubyNumeric.str2inum(context.getRuntime(),(RubyString)object,0,true);
278 IRubyObject tmp = TypeConverter.convertToType(object, context.getRuntime().getInteger(), MethodIndex.TO_INT, "to_int", false);
279 if (tmp.isNil()) return object.convertToInteger(MethodIndex.TO_I, "to_i");
280 return tmp;
283 @JRubyMethod(name = "String", required = 1, module = true, visibility = PRIVATE)
284 public static IRubyObject new_string(ThreadContext context, IRubyObject recv, IRubyObject object) {
285 return TypeConverter.convertToType(object, context.getRuntime().getString(), MethodIndex.TO_S, "to_s");
288 @JRubyMethod(name = "p", rest = true, module = true, visibility = PRIVATE)
289 public static IRubyObject p(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
290 Ruby runtime = context.getRuntime();
291 IRubyObject defout = runtime.getGlobalVariables().get("$>");
293 for (int i = 0; i < args.length; i++) {
294 if (args[i] != null) {
295 defout.callMethod(context, "write", RubyObject.inspect(context, args[i]));
296 defout.callMethod(context, "write", runtime.newString("\n"));
300 if (defout instanceof RubyFile) {
301 ((RubyFile)defout).flush();
304 return context.getRuntime().getNil();
307 /** rb_f_putc
309 @JRubyMethod(name = "putc", required = 1, module = true, visibility = PRIVATE)
310 public static IRubyObject putc(ThreadContext context, IRubyObject recv, IRubyObject ch) {
311 IRubyObject defout = context.getRuntime().getGlobalVariables().get("$>");
312 return defout.callMethod(context, "putc", ch);
315 @JRubyMethod(name = "puts", rest = true, module = true, visibility = PRIVATE)
316 public static IRubyObject puts(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
317 IRubyObject defout = context.getRuntime().getGlobalVariables().get("$>");
319 defout.callMethod(context, "puts", args);
321 return context.getRuntime().getNil();
324 @JRubyMethod(name = "print", rest = true, module = true, visibility = PRIVATE)
325 public static IRubyObject print(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
326 IRubyObject defout = context.getRuntime().getGlobalVariables().get("$>");
328 defout.callMethod(context, "print", args);
330 return context.getRuntime().getNil();
333 @JRubyMethod(name = "printf", rest = true, module = true, visibility = PRIVATE)
334 public static IRubyObject printf(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
335 if (args.length != 0) {
336 IRubyObject defout = context.getRuntime().getGlobalVariables().get("$>");
338 if (!(args[0] instanceof RubyString)) {
339 defout = args[0];
340 args = ArgsUtil.popArray(args);
343 defout.callMethod(context, "write", RubyKernel.sprintf(recv, args));
346 return context.getRuntime().getNil();
349 @JRubyMethod(name = "readline", optional = 1, module = true, visibility = PRIVATE)
350 public static IRubyObject readline(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
351 IRubyObject line = gets(context, recv, args);
353 if (line.isNil()) throw context.getRuntime().newEOFError();
355 return line;
358 @JRubyMethod(name = "readlines", optional = 1, module = true, visibility = PRIVATE)
359 public static RubyArray readlines(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
360 return RubyArgsFile.readlines(context, context.getRuntime().getGlobalVariables().get("$<"), args);
363 /** Returns value of $_.
365 * @throws TypeError if $_ is not a String or nil.
366 * @return value of $_ as String.
368 private static RubyString getLastlineString(ThreadContext context, Ruby runtime) {
369 IRubyObject line = context.getPreviousFrame().getLastLine();
371 if (line.isNil()) {
372 throw runtime.newTypeError("$_ value need to be String (nil given).");
373 } else if (!(line instanceof RubyString)) {
374 throw runtime.newTypeError("$_ value need to be String (" + line.getMetaClass().getName() + " given).");
375 } else {
376 return (RubyString) line;
381 * Variable-arity version for compatibility. Not bound to Ruby.
382 * @deprecated Use the one or two-arg versions.
384 public static IRubyObject sub_bang(ThreadContext context, IRubyObject recv, IRubyObject[] args, Block block) {
385 return getLastlineString(context, context.getRuntime()).sub_bang(context, args, block);
388 @JRubyMethod(name = "sub!", frame = true, module = true, visibility = PRIVATE, reads = LASTLINE)
389 public static IRubyObject sub_bang(ThreadContext context, IRubyObject recv, IRubyObject arg0, Block block) {
390 return getLastlineString(context, context.getRuntime()).sub_bang(context, arg0, block);
393 @JRubyMethod(name = "sub!", frame = true, module = true, visibility = PRIVATE, reads = LASTLINE)
394 public static IRubyObject sub_bang(ThreadContext context, IRubyObject recv, IRubyObject arg0, IRubyObject arg1, Block block) {
395 return getLastlineString(context, context.getRuntime()).sub_bang(context, arg0, arg1, block);
399 * Variable-arity version for compatibility. Not bound to Ruby.
400 * @deprecated Use the one or two-arg versions.
402 public static IRubyObject sub(ThreadContext context, IRubyObject recv, IRubyObject[] args, Block block) {
403 RubyString str = (RubyString) getLastlineString(context, context.getRuntime()).dup();
405 if (!str.sub_bang(context, args, block).isNil()) {
406 context.getPreviousFrame().setLastLine(str);
409 return str;
412 @JRubyMethod(name = "sub", frame = true, module = true, visibility = PRIVATE, reads = LASTLINE, writes = LASTLINE)
413 public static IRubyObject sub(ThreadContext context, IRubyObject recv, IRubyObject arg0, Block block) {
414 RubyString str = (RubyString) getLastlineString(context, context.getRuntime()).dup();
416 if (!str.sub_bang(context, arg0, block).isNil()) {
417 context.getPreviousFrame().setLastLine(str);
420 return str;
423 @JRubyMethod(name = "sub", frame = true, module = true, visibility = PRIVATE, reads = LASTLINE, writes = LASTLINE)
424 public static IRubyObject sub(ThreadContext context, IRubyObject recv, IRubyObject arg0, IRubyObject arg1, Block block) {
425 RubyString str = (RubyString) getLastlineString(context, context.getRuntime()).dup();
427 if (!str.sub_bang(context, arg0, arg1, block).isNil()) {
428 context.getPreviousFrame().setLastLine(str);
431 return str;
435 * Variable-arity version for compatibility. Not bound to Ruby.
436 * @deprecated Use the one or two-arg versions.
438 public static IRubyObject gsub_bang(ThreadContext context, IRubyObject recv, IRubyObject[] args, Block block) {
439 return getLastlineString(context, context.getRuntime()).gsub_bang(context, args, block);
442 @JRubyMethod(name = "gsub!", frame = true, module = true, visibility = PRIVATE, reads = LASTLINE, writes = LASTLINE)
443 public static IRubyObject gsub_bang(ThreadContext context, IRubyObject recv, IRubyObject arg0, Block block) {
444 return getLastlineString(context, context.getRuntime()).gsub_bang(context, arg0, block);
447 @JRubyMethod(name = "gsub!", frame = true, module = true, visibility = PRIVATE, reads = LASTLINE, writes = LASTLINE)
448 public static IRubyObject gsub_bang(ThreadContext context, IRubyObject recv, IRubyObject arg0, IRubyObject arg1, Block block) {
449 return getLastlineString(context, context.getRuntime()).gsub_bang(context, arg0, arg1, block);
453 * Variable-arity version for compatibility. Not bound to Ruby.
454 * @deprecated Use the one or two-arg versions.
456 public static IRubyObject gsub(ThreadContext context, IRubyObject recv, IRubyObject[] args, Block block) {
457 RubyString str = (RubyString) getLastlineString(context, context.getRuntime()).dup();
459 if (!str.gsub_bang(context, args, block).isNil()) {
460 context.getPreviousFrame().setLastLine(str);
463 return str;
466 @JRubyMethod(name = "gsub", frame = true, module = true, visibility = PRIVATE, reads = LASTLINE, writes = LASTLINE)
467 public static IRubyObject gsub(ThreadContext context, IRubyObject recv, IRubyObject arg0, Block block) {
468 RubyString str = (RubyString) getLastlineString(context, context.getRuntime()).dup();
470 if (!str.gsub_bang(context, arg0, block).isNil()) {
471 context.getPreviousFrame().setLastLine(str);
474 return str;
477 @JRubyMethod(name = "gsub", frame = true, module = true, visibility = PRIVATE, reads = LASTLINE, writes = LASTLINE)
478 public static IRubyObject gsub(ThreadContext context, IRubyObject recv, IRubyObject arg0, IRubyObject arg1, Block block) {
479 RubyString str = (RubyString) getLastlineString(context, context.getRuntime()).dup();
481 if (!str.gsub_bang(context, arg0, arg1, block).isNil()) {
482 context.getPreviousFrame().setLastLine(str);
485 return str;
488 @JRubyMethod(name = "chop!", frame = true, module = true, visibility = PRIVATE, reads = LASTLINE, writes = LASTLINE)
489 public static IRubyObject chop_bang(ThreadContext context, IRubyObject recv, Block block) {
490 return getLastlineString(context, context.getRuntime()).chop_bang();
493 @JRubyMethod(name = "chop", frame = true, module = true, visibility = PRIVATE, reads = LASTLINE, writes = LASTLINE)
494 public static IRubyObject chop(ThreadContext context, IRubyObject recv, Block block) {
495 RubyString str = getLastlineString(context, context.getRuntime());
497 if (str.getByteList().realSize > 0) {
498 str = (RubyString) str.dup();
499 str.chop_bang();
500 context.getPreviousFrame().setLastLine(str);
503 return str;
507 * Variable-arity version for compatibility. Not bound to Ruby.
508 * @deprecated Use the zero or one-arg versions.
510 public static IRubyObject chomp_bang(ThreadContext context, IRubyObject recv, IRubyObject[] args, Block block) {
511 return getLastlineString(context, context.getRuntime()).chomp_bang(args);
514 @JRubyMethod(name = "chomp!", frame = true, module = true, visibility = PRIVATE, reads = LASTLINE, writes = LASTLINE)
515 public static IRubyObject chomp_bang(ThreadContext context, IRubyObject recv) {
516 return getLastlineString(context, context.getRuntime()).chomp_bang();
519 @JRubyMethod(name = "chomp!", frame = true, module = true, visibility = PRIVATE, reads = LASTLINE, writes = LASTLINE)
520 public static IRubyObject chomp_bang(ThreadContext context, IRubyObject recv, IRubyObject arg0) {
521 return getLastlineString(context, context.getRuntime()).chomp_bang(arg0);
525 * Variable-arity version for compatibility. Not bound to Ruby.
526 * @deprecated Use the zero or one-arg versions.
528 public static IRubyObject chomp(ThreadContext context, IRubyObject recv, IRubyObject[] args, Block block) {
529 RubyString str = getLastlineString(context, context.getRuntime());
530 RubyString dup = (RubyString) str.dup();
532 if (dup.chomp_bang(args).isNil()) {
533 return str;
536 context.getPreviousFrame().setLastLine(dup);
537 return dup;
540 @JRubyMethod(name = "chomp", frame = true, module = true, visibility = PRIVATE, reads = LASTLINE, writes = LASTLINE)
541 public static IRubyObject chomp(ThreadContext context, IRubyObject recv) {
542 RubyString str = getLastlineString(context, context.getRuntime());
543 RubyString dup = (RubyString) str.dup();
545 if (dup.chomp_bang().isNil()) {
546 return str;
549 context.getPreviousFrame().setLastLine(dup);
550 return dup;
553 @JRubyMethod(name = "chomp", frame = true, module = true, visibility = PRIVATE, reads = LASTLINE, writes = LASTLINE)
554 public static IRubyObject chomp(ThreadContext context, IRubyObject recv, IRubyObject arg0) {
555 RubyString str = getLastlineString(context, context.getRuntime());
556 RubyString dup = (RubyString) str.dup();
558 if (dup.chomp_bang(arg0).isNil()) {
559 return str;
562 context.getPreviousFrame().setLastLine(dup);
563 return dup;
567 * Variable arity version for compatibility. Not bound to a Ruby method.
569 * @param context The thread context for the current thread
570 * @param recv The receiver of the method (usually a class that has included Kernel)
571 * @return
572 * @deprecated Use the versions with zero, one, or two args.
574 public static IRubyObject split(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
575 return getLastlineString(context, context.getRuntime()).split(context, args);
578 @JRubyMethod(name = "split", frame = true, module = true, visibility = PRIVATE, reads = LASTLINE, writes = {LASTLINE, BACKREF})
579 public static IRubyObject split(ThreadContext context, IRubyObject recv) {
580 return getLastlineString(context, context.getRuntime()).split(context);
583 @JRubyMethod(name = "split", frame = true, module = true, visibility = PRIVATE, reads = LASTLINE, writes = {LASTLINE, BACKREF})
584 public static IRubyObject split(ThreadContext context, IRubyObject recv, IRubyObject arg0) {
585 return getLastlineString(context, context.getRuntime()).split(context, arg0);
588 @JRubyMethod(name = "split", frame = true, module = true, visibility = PRIVATE, reads = LASTLINE, writes = {LASTLINE, BACKREF})
589 public static IRubyObject split(ThreadContext context, IRubyObject recv, IRubyObject arg0, IRubyObject arg1) {
590 return getLastlineString(context, context.getRuntime()).split(context, arg0, arg1);
593 @JRubyMethod(name = "scan", required = 1, frame = true, module = true, visibility = PRIVATE, reads = {LASTLINE, BACKREF}, writes = {LASTLINE, BACKREF})
594 public static IRubyObject scan(ThreadContext context, IRubyObject recv, IRubyObject pattern, Block block) {
595 return getLastlineString(context, context.getRuntime()).scan(context, pattern, block);
598 @JRubyMethod(name = "select", required = 1, optional = 3, module = true, visibility = PRIVATE)
599 public static IRubyObject select(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
600 return RubyIO.select_static(context, context.getRuntime(), args);
603 @JRubyMethod(name = "sleep", optional = 1, module = true, visibility = PRIVATE)
604 public static IRubyObject sleep(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
605 long milliseconds;
607 if (args.length == 0) {
608 // Zero sleeps forever
609 milliseconds = 0;
610 } else {
611 if (!(args[0] instanceof RubyNumeric)) {
612 throw context.getRuntime().newTypeError("can't convert " + args[0].getMetaClass().getName() + "into time interval");
614 milliseconds = (long) (args[0].convertToFloat().getDoubleValue() * 1000);
615 if (milliseconds < 0) {
616 throw context.getRuntime().newArgumentError("time interval must be positive");
617 } else if (milliseconds == 0) {
618 // Explicit zero in MRI returns immediately
619 return context.getRuntime().newFixnum(0);
622 long startTime = System.currentTimeMillis();
624 RubyThread rubyThread = context.getThread();
626 do {
627 long loopStartTime = System.currentTimeMillis();
628 try {
629 rubyThread.sleep(milliseconds);
630 } catch (InterruptedException iExcptn) {
632 milliseconds -= (System.currentTimeMillis() - loopStartTime);
633 } while (milliseconds > 0);
635 return context.getRuntime().newFixnum(Math.round((System.currentTimeMillis() - startTime) / 1000.0));
638 // FIXME: Add at_exit and finalizers to exit, then make exit_bang not call those.
639 @JRubyMethod(name = "exit", optional = 1, module = true, visibility = PRIVATE)
640 public static IRubyObject exit(IRubyObject recv, IRubyObject[] args) {
641 exit(recv.getRuntime(), args, false);
642 return recv.getRuntime().getNil(); // not reached
645 @JRubyMethod(name = "exit!", optional = 1, module = true, visibility = PRIVATE)
646 public static IRubyObject exit_bang(IRubyObject recv, IRubyObject[] args) {
647 exit(recv.getRuntime(), args, true);
648 return recv.getRuntime().getNil(); // not reached
651 private static void exit(Ruby runtime, IRubyObject[] args, boolean hard) {
652 runtime.secure(4);
654 int status = 1;
655 if (args.length > 0) {
656 RubyObject argument = (RubyObject)args[0];
657 if (argument instanceof RubyFixnum) {
658 status = RubyNumeric.fix2int(argument);
659 } else {
660 status = argument.isFalse() ? 1 : 0;
664 if (hard) {
665 throw new MainExitException(status, true);
666 } else {
667 throw runtime.newSystemExit(status);
672 /** Returns an Array with the names of all global variables.
675 @JRubyMethod(name = "global_variables", module = true, visibility = PRIVATE)
676 public static RubyArray global_variables(ThreadContext context, IRubyObject recv) {
677 Ruby runtime = context.getRuntime();
678 RubyArray globalVariables = runtime.newArray();
680 for (String globalVariableName : runtime.getGlobalVariables().getNames()) {
681 globalVariables.append(runtime.newString(globalVariableName));
684 return globalVariables;
687 /** Returns an Array with the names of all local variables.
690 @JRubyMethod(name = "local_variables", module = true, visibility = PRIVATE)
691 public static RubyArray local_variables(ThreadContext context, IRubyObject recv) {
692 final Ruby runtime = context.getRuntime();
693 RubyArray localVariables = runtime.newArray();
695 for (String name: context.getCurrentScope().getAllNamesInScope()) {
696 if (IdUtil.isLocal(name)) localVariables.append(runtime.newString(name));
699 return localVariables;
702 @JRubyMethod(name = "binding", frame = true, module = true, visibility = PRIVATE)
703 public static RubyBinding binding(ThreadContext context, IRubyObject recv, Block block) {
704 return RubyBinding.newBindingForEval(context);
707 @JRubyMethod(name = {"block_given?", "iterator?"}, frame = true, module = true, visibility = PRIVATE)
708 public static RubyBoolean block_given_p(ThreadContext context, IRubyObject recv, Block block) {
709 return context.getRuntime().newBoolean(context.getPreviousFrame().getBlock().isGiven());
713 @Deprecated
714 public static IRubyObject sprintf(IRubyObject recv, IRubyObject[] args) {
715 return sprintf(recv.getRuntime().getCurrentContext(), recv, args);
718 @JRubyMethod(name = {"sprintf", "format"}, required = 1, rest = true, module = true, visibility = PRIVATE)
719 public static IRubyObject sprintf(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
720 if (args.length == 0) {
721 throw context.getRuntime().newArgumentError("sprintf must have at least one argument");
724 RubyString str = RubyString.stringValue(args[0]);
726 RubyArray newArgs = context.getRuntime().newArrayNoCopy(args);
727 newArgs.shift();
729 return str.op_format(context, newArgs);
732 @JRubyMethod(name = {"raise", "fail"}, optional = 3, frame = true, module = true, visibility = PRIVATE)
733 public static IRubyObject raise(ThreadContext context, IRubyObject recv, IRubyObject[] args, Block block) {
734 // FIXME: Pass block down?
735 Ruby runtime = context.getRuntime();
737 if (args.length == 0) {
738 IRubyObject lastException = runtime.getGlobalVariables().get("$!");
739 if (lastException.isNil()) {
740 throw new RaiseException(runtime, runtime.getRuntimeError(), "", false);
742 throw new RaiseException((RubyException) lastException);
745 IRubyObject exception;
747 if (args.length == 1) {
748 if (args[0] instanceof RubyString) {
749 throw new RaiseException((RubyException)runtime.getRuntimeError().newInstance(context, args, block));
752 if (!args[0].respondsTo("exception")) {
753 throw runtime.newTypeError("exception class/object expected");
755 exception = args[0].callMethod(context, "exception");
756 } else {
757 if (!args[0].respondsTo("exception")) {
758 throw runtime.newTypeError("exception class/object expected");
761 exception = args[0].callMethod(context, "exception", args[1]);
764 if (!runtime.fastGetClass("Exception").isInstance(exception)) {
765 throw runtime.newTypeError("exception object expected");
768 if (args.length == 3) {
769 ((RubyException) exception).set_backtrace(args[2]);
772 if (runtime.getDebug().isTrue()) {
773 printExceptionSummary(context, runtime, (RubyException) exception);
776 throw new RaiseException((RubyException) exception);
779 private static void printExceptionSummary(ThreadContext context, Ruby runtime, RubyException rEx) {
780 Frame currentFrame = context.getCurrentFrame();
782 String msg = String.format("Exception `%s' at %s:%s - %s\n",
783 rEx.getMetaClass(),
784 currentFrame.getFile(), currentFrame.getLine() + 1,
785 rEx.to_s());
787 IRubyObject errorStream = runtime.getGlobalVariables().get("$stderr");
788 errorStream.callMethod(context, "write", runtime.newString(msg));
792 * Require.
793 * MRI allows to require ever .rb files or ruby extension dll (.so or .dll depending on system).
794 * we allow requiring either .rb files or jars.
795 * @param recv ruby object used to call require (any object will do and it won't be used anyway).
796 * @param name the name of the file to require
798 @JRubyMethod(name = "require", required = 1, frame = true, module = true, visibility = PRIVATE)
799 public static IRubyObject require(IRubyObject recv, IRubyObject name, Block block) {
800 Ruby runtime = recv.getRuntime();
802 if (runtime.getLoadService().require(name.convertToString().toString())) {
803 return runtime.getTrue();
805 return runtime.getFalse();
808 @JRubyMethod(name = "load", required = 1, optional = 1, frame = true, module = true, visibility = PRIVATE)
809 public static IRubyObject load(IRubyObject recv, IRubyObject[] args, Block block) {
810 Ruby runtime = recv.getRuntime();
811 RubyString file = args[0].convertToString();
812 boolean wrap = args.length == 2 ? args[1].isTrue() : false;
814 runtime.getLoadService().load(file.getByteList().toString(), wrap);
816 return runtime.getTrue();
819 @JRubyMethod(name = "eval", required = 1, optional = 3, frame = true, module = true, visibility = PRIVATE)
820 public static IRubyObject eval(ThreadContext context, IRubyObject recv, IRubyObject[] args, Block block) {
821 Ruby runtime = context.getRuntime();
823 // string to eval
824 RubyString src = args[0].convertToString();
825 runtime.checkSafeString(src);
827 IRubyObject scope = args.length > 1 && !args[1].isNil() ? args[1] : null;
828 String file;
829 if (args.length > 2) {
830 file = args[2].convertToString().toString();
831 } else if (scope == null) {
832 file = "(eval)";
833 } else {
834 file = null;
836 int line;
837 if (args.length > 3) {
838 line = (int) args[3].convertToInteger().getLongValue();
839 } else if (scope == null) {
840 line = 0;
841 } else {
842 line = -1;
844 if (scope == null) scope = RubyBinding.newBindingForEval(context);
846 return ASTInterpreter.evalWithBinding(context, src, scope, file, line);
849 @JRubyMethod(name = "callcc", frame = true, module = true, visibility = PRIVATE)
850 public static IRubyObject callcc(ThreadContext context, IRubyObject recv, Block block) {
851 Ruby runtime = context.getRuntime();
852 runtime.getWarnings().warn(ID.EMPTY_IMPLEMENTATION, "Kernel#callcc: Continuations are not implemented in JRuby and will not work", "Kernel#callcc");
853 IRubyObject cc = runtime.getContinuation().callMethod(context, "new");
854 cc.dataWrapStruct(block);
855 return block.yield(context, cc);
858 @JRubyMethod(name = "caller", optional = 1, frame = true, module = true, visibility = PRIVATE)
859 public static IRubyObject caller(ThreadContext context, IRubyObject recv, IRubyObject[] args, Block block) {
860 int level = args.length > 0 ? RubyNumeric.fix2int(args[0]) : 1;
862 if (level < 0) {
863 throw context.getRuntime().newArgumentError("negative level(" + level + ')');
866 return context.createCallerBacktrace(context.getRuntime(), level);
869 @JRubyMethod(name = "catch", required = 1, frame = true, module = true, visibility = PRIVATE)
870 public static IRubyObject rbCatch(ThreadContext context, IRubyObject recv, IRubyObject tag, Block block) {
871 CatchTarget target = new CatchTarget(tag.asJavaString());
872 try {
873 context.pushCatch(target);
874 return block.yield(context, tag);
875 } catch (JumpException.ThrowJump tj) {
876 if (tj.getTarget() == target) return (IRubyObject) tj.getValue();
878 throw tj;
879 } finally {
880 context.popCatch();
884 public static class CatchTarget implements JumpTarget {
885 private final String tag;
886 public CatchTarget(String tag) { this.tag = tag; }
887 public String getTag() { return tag; }
890 @JRubyMethod(name = "throw", required = 1, frame = true, optional = 1, module = true, visibility = PRIVATE)
891 public static IRubyObject rbThrow(ThreadContext context, IRubyObject recv, IRubyObject[] args, Block block) {
892 Ruby runtime = context.getRuntime();
894 String tag = args[0].asJavaString();
895 CatchTarget[] catches = context.getActiveCatches();
897 String message = "uncaught throw `" + tag + "'";
899 // Ordering of array traversal not important, just intuitive
900 for (int i = catches.length - 1 ; i >= 0 ; i--) {
901 if (tag.equals(catches[i].getTag())) {
902 //Catch active, throw for catch to handle
903 throw new JumpException.ThrowJump(catches[i], args.length > 1 ? args[1] : runtime.getNil());
907 // No catch active for this throw
908 RubyThread currentThread = context.getThread();
909 if (currentThread == runtime.getThreadService().getMainThread()) {
910 throw runtime.newNameError(message, tag);
911 } else {
912 throw runtime.newThreadError(message + " in thread 0x" + Integer.toHexString(RubyInteger.fix2int(currentThread.id())));
916 @JRubyMethod(name = "trap", required = 1, frame = true, optional = 1, module = true, visibility = PRIVATE)
917 public static IRubyObject trap(ThreadContext context, IRubyObject recv, IRubyObject[] args, Block block) {
918 context.getRuntime().getLoadService().require("jsignal");
919 return RuntimeHelpers.invoke(context, recv, "__jtrap", args, block);
922 @JRubyMethod(name = "warn", required = 1, module = true, visibility = PRIVATE)
923 public static IRubyObject warn(ThreadContext context, IRubyObject recv, IRubyObject message) {
924 Ruby runtime = context.getRuntime();
926 if (!runtime.getVerbose().isNil()) {
927 IRubyObject out = runtime.getGlobalVariables().get("$stderr");
928 out.callMethod(context, "puts", new IRubyObject[] { message });
930 return runtime.getNil();
933 @JRubyMethod(name = "set_trace_func", required = 1, frame = true, module = true, visibility = PRIVATE)
934 public static IRubyObject set_trace_func(ThreadContext context, IRubyObject recv, IRubyObject trace_func, Block block) {
935 if (trace_func.isNil()) {
936 context.getRuntime().setTraceFunction(null);
937 } else if (!(trace_func instanceof RubyProc)) {
938 throw context.getRuntime().newTypeError("trace_func needs to be Proc.");
939 } else {
940 context.getRuntime().setTraceFunction((RubyProc) trace_func);
942 return trace_func;
945 @JRubyMethod(name = "trace_var", required = 1, optional = 1, frame = true, module = true, visibility = PRIVATE)
946 public static IRubyObject trace_var(ThreadContext context, IRubyObject recv, IRubyObject[] args, Block block) {
947 if (args.length == 0) throw context.getRuntime().newArgumentError(0, 1);
948 RubyProc proc = null;
949 String var = args.length > 1 ? args[0].toString() : null;
950 // ignore if it's not a global var
951 if (var.charAt(0) != '$') return context.getRuntime().getNil();
952 if (args.length == 1) proc = RubyProc.newProc(context.getRuntime(), block, Block.Type.PROC);
953 if (args.length == 2) {
954 proc = (RubyProc)TypeConverter.convertToType(args[1], context.getRuntime().getProc(), 0, "to_proc", true);
957 context.getRuntime().getGlobalVariables().setTraceVar(var, proc);
959 return context.getRuntime().getNil();
962 @JRubyMethod(name = "untrace_var", required = 1, optional = 1, frame = true, module = true, visibility = PRIVATE)
963 public static IRubyObject untrace_var(ThreadContext context, IRubyObject recv, IRubyObject[] args, Block block) {
964 if (args.length == 0) throw context.getRuntime().newArgumentError(0, 1);
965 String var = args.length >= 1 ? args[0].toString() : null;
967 // ignore if it's not a global var
968 if (var.charAt(0) != '$') return context.getRuntime().getNil();
970 if (args.length > 1) {
971 ArrayList<IRubyObject> success = new ArrayList<IRubyObject>();
972 for (int i = 1; i < args.length; i++) {
973 if (context.getRuntime().getGlobalVariables().untraceVar(var, args[i])) {
974 success.add(args[i]);
977 return RubyArray.newArray(context.getRuntime(), success);
978 } else {
979 context.getRuntime().getGlobalVariables().untraceVar(var);
982 return context.getRuntime().getNil();
985 @JRubyMethod(name = "singleton_method_added", required = 1, frame = true, module = true, visibility = PRIVATE)
986 public static IRubyObject singleton_method_added(ThreadContext context, IRubyObject recv, IRubyObject symbolId, Block block) {
987 return context.getRuntime().getNil();
990 @JRubyMethod(name = "singleton_method_removed", required = 1, frame = true, module = true, visibility = PRIVATE)
991 public static IRubyObject singleton_method_removed(ThreadContext context, IRubyObject recv, IRubyObject symbolId, Block block) {
992 return context.getRuntime().getNil();
995 @JRubyMethod(name = "singleton_method_undefined", required = 1, frame = true, module = true, visibility = PRIVATE)
996 public static IRubyObject singleton_method_undefined(ThreadContext context, IRubyObject recv, IRubyObject symbolId, Block block) {
997 return context.getRuntime().getNil();
1000 @JRubyMethod(name = {"proc", "lambda"}, frame = true, module = true, visibility = PRIVATE, compat = CompatVersion.RUBY1_8)
1001 public static RubyProc proc(ThreadContext context, IRubyObject recv, Block block) {
1002 return context.getRuntime().newProc(Block.Type.LAMBDA, block);
1005 @Deprecated
1006 public static RubyProc proc(IRubyObject recv, Block block) {
1007 return recv.getRuntime().newProc(Block.Type.LAMBDA, block);
1010 @JRubyMethod(name = {"lambda"}, frame = true, module = true, visibility = PRIVATE, compat = CompatVersion.RUBY1_9)
1011 public static RubyProc lambda(ThreadContext context, IRubyObject recv, Block block) {
1012 return context.getRuntime().newProc(Block.Type.LAMBDA, block);
1015 @JRubyMethod(name = {"proc"}, frame = true, module = true, visibility = PRIVATE, compat = CompatVersion.RUBY1_9)
1016 public static RubyProc proc_1_9(ThreadContext context, IRubyObject recv, Block block) {
1017 return context.getRuntime().newProc(Block.Type.PROC, block);
1020 @JRubyMethod(name = "loop", frame = true, module = true, visibility = PRIVATE)
1021 public static IRubyObject loop(ThreadContext context, IRubyObject recv, Block block) {
1022 while (true) {
1023 block.yield(context, context.getRuntime().getNil());
1025 context.pollThreadEvents();
1029 @JRubyMethod(name = "test", required = 2, optional = 1, module = true, visibility = PRIVATE)
1030 public static IRubyObject test(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
1031 if (args.length == 0) throw context.getRuntime().newArgumentError("wrong number of arguments");
1033 int cmd;
1034 if (args[0] instanceof RubyFixnum) {
1035 cmd = (int)((RubyFixnum) args[0]).getLongValue();
1036 } else if (args[0] instanceof RubyString &&
1037 ((RubyString) args[0]).getByteList().length() > 0) {
1038 // MRI behavior: use first byte of string value if len > 0
1039 cmd = ((RubyString) args[0]).getByteList().charAt(0);
1040 } else {
1041 cmd = (int) args[0].convertToInteger().getLongValue();
1044 // MRI behavior: raise ArgumentError for 'unknown command' before
1045 // checking number of args.
1046 switch(cmd) {
1047 case 'A': case 'b': case 'c': case 'C': case 'd': case 'e': case 'f': case 'g': case 'G':
1048 case 'k': case 'M': case 'l': case 'o': case 'O': case 'p': case 'r': case 'R': case 's':
1049 case 'S': case 'u': case 'w': case 'W': case 'x': case 'X': case 'z': case '=': case '<':
1050 case '>': case '-':
1051 break;
1052 default:
1053 throw context.getRuntime().newArgumentError("unknown command ?" + (char) cmd);
1056 // MRI behavior: now check arg count
1058 switch(cmd) {
1059 case '-': case '=': case '<': case '>':
1060 if (args.length != 3) throw context.getRuntime().newArgumentError(args.length, 3);
1061 break;
1062 default:
1063 if (args.length != 2) throw context.getRuntime().newArgumentError(args.length, 2);
1064 break;
1067 switch (cmd) {
1068 case 'A': // ?A | Time | Last access time for file1
1069 return context.getRuntime().newFileStat(args[1].convertToString().toString(), false).atime();
1070 case 'b': // ?b | boolean | True if file1 is a block device
1071 return RubyFileTest.blockdev_p(recv, args[1]);
1072 case 'c': // ?c | boolean | True if file1 is a character device
1073 return RubyFileTest.chardev_p(recv, args[1]);
1074 case 'C': // ?C | Time | Last change time for file1
1075 return context.getRuntime().newFileStat(args[1].convertToString().toString(), false).ctime();
1076 case 'd': // ?d | boolean | True if file1 exists and is a directory
1077 return RubyFileTest.directory_p(recv, args[1]);
1078 case 'e': // ?e | boolean | True if file1 exists
1079 return RubyFileTest.exist_p(recv, args[1]);
1080 case 'f': // ?f | boolean | True if file1 exists and is a regular file
1081 return RubyFileTest.file_p(recv, args[1]);
1082 case 'g': // ?g | boolean | True if file1 has the \CF{setgid} bit
1083 return RubyFileTest.setgid_p(recv, args[1]);
1084 case 'G': // ?G | boolean | True if file1 exists and has a group ownership equal to the caller's group
1085 return RubyFileTest.grpowned_p(recv, args[1]);
1086 case 'k': // ?k | boolean | True if file1 exists and has the sticky bit set
1087 return RubyFileTest.sticky_p(recv, args[1]);
1088 case 'M': // ?M | Time | Last modification time for file1
1089 return context.getRuntime().newFileStat(args[1].convertToString().toString(), false).mtime();
1090 case 'l': // ?l | boolean | True if file1 exists and is a symbolic link
1091 return RubyFileTest.symlink_p(recv, args[1]);
1092 case 'o': // ?o | boolean | True if file1 exists and is owned by the caller's effective uid
1093 return RubyFileTest.owned_p(recv, args[1]);
1094 case 'O': // ?O | boolean | True if file1 exists and is owned by the caller's real uid
1095 return RubyFileTest.rowned_p(recv, args[1]);
1096 case 'p': // ?p | boolean | True if file1 exists and is a fifo
1097 return RubyFileTest.pipe_p(recv, args[1]);
1098 case 'r': // ?r | boolean | True if file1 is readable by the effective uid/gid of the caller
1099 return RubyFileTest.readable_p(recv, args[1]);
1100 case 'R': // ?R | boolean | True if file is readable by the real uid/gid of the caller
1101 // FIXME: Need to implement an readable_real_p in FileTest
1102 return RubyFileTest.readable_p(recv, args[1]);
1103 case 's': // ?s | int/nil | If file1 has nonzero size, return the size, otherwise nil
1104 return RubyFileTest.size_p(recv, args[1]);
1105 case 'S': // ?S | boolean | True if file1 exists and is a socket
1106 return RubyFileTest.socket_p(recv, args[1]);
1107 case 'u': // ?u | boolean | True if file1 has the setuid bit set
1108 return RubyFileTest.setuid_p(recv, args[1]);
1109 case 'w': // ?w | boolean | True if file1 exists and is writable by effective uid/gid
1110 return RubyFileTest.writable_p(recv, args[1]);
1111 case 'W': // ?W | boolean | True if file1 exists and is writable by the real uid/gid
1112 // FIXME: Need to implement an writable_real_p in FileTest
1113 return RubyFileTest.writable_p(recv, args[1]);
1114 case 'x': // ?x | boolean | True if file1 exists and is executable by the effective uid/gid
1115 return RubyFileTest.executable_p(recv, args[1]);
1116 case 'X': // ?X | boolean | True if file1 exists and is executable by the real uid/gid
1117 return RubyFileTest.executable_real_p(recv, args[1]);
1118 case 'z': // ?z | boolean | True if file1 exists and has a zero length
1119 return RubyFileTest.zero_p(recv, args[1]);
1120 case '=': // ?= | boolean | True if the modification times of file1 and file2 are equal
1121 return context.getRuntime().newFileStat(args[1].convertToString().toString(), false).mtimeEquals(args[2]);
1122 case '<': // ?< | boolean | True if the modification time of file1 is prior to that of file2
1123 return context.getRuntime().newFileStat(args[1].convertToString().toString(), false).mtimeLessThan(args[2]);
1124 case '>': // ?> | boolean | True if the modification time of file1 is after that of file2
1125 return context.getRuntime().newFileStat(args[1].convertToString().toString(), false).mtimeGreaterThan(args[2]);
1126 case '-': // ?- | boolean | True if file1 and file2 are identical
1127 return RubyFileTest.identical_p(recv, args[1], args[2]);
1128 default:
1129 throw new InternalError("unreachable code reached!");
1133 @JRubyMethod(name = "`", required = 1, module = true, visibility = PRIVATE)
1134 public static IRubyObject backquote(ThreadContext context, IRubyObject recv, IRubyObject aString) {
1135 Ruby runtime = context.getRuntime();
1136 ByteArrayOutputStream output = new ByteArrayOutputStream();
1138 RubyString string = aString.convertToString();
1139 int resultCode = ShellLauncher.runAndWait(runtime, new IRubyObject[] {string}, output);
1141 runtime.getGlobalVariables().set("$?", RubyProcess.RubyStatus.newProcessStatus(runtime, resultCode));
1143 return RubyString.newString(runtime, output.toByteArray());
1146 @JRubyMethod(name = "srand", optional = 1, module = true, visibility = PRIVATE)
1147 public static RubyInteger srand(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
1148 Ruby runtime = context.getRuntime();
1149 long oldRandomSeed = runtime.getRandomSeed();
1151 if (args.length > 0) {
1152 RubyInteger integerSeed = args[0].convertToInteger(MethodIndex.TO_INT, "to_int");
1153 runtime.setRandomSeed(integerSeed.getLongValue());
1154 } else {
1155 // Not sure how well this works, but it works much better than
1156 // just currentTimeMillis by itself.
1157 runtime.setRandomSeed(System.currentTimeMillis() ^
1158 recv.hashCode() ^ runtime.incrementRandomSeedSequence() ^
1159 runtime.getRandom().nextInt(Math.max(1, Math.abs((int)runtime.getRandomSeed()))));
1161 runtime.getRandom().setSeed(runtime.getRandomSeed());
1162 return runtime.newFixnum(oldRandomSeed);
1165 @JRubyMethod(name = "rand", optional = 1, module = true, visibility = PRIVATE)
1166 public static RubyNumeric rand(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
1167 Ruby runtime = context.getRuntime();
1168 long ceil;
1169 if (args.length == 0) {
1170 ceil = 0;
1171 } else if (args.length == 1) {
1172 if (args[0] instanceof RubyBignum) {
1173 byte[] bigCeilBytes = ((RubyBignum) args[0]).getValue().toByteArray();
1174 BigInteger bigCeil = new BigInteger(bigCeilBytes).abs();
1176 byte[] randBytes = new byte[bigCeilBytes.length];
1177 runtime.getRandom().nextBytes(randBytes);
1179 BigInteger result = new BigInteger(randBytes).abs().mod(bigCeil);
1181 return new RubyBignum(runtime, result);
1184 RubyInteger integerCeil = (RubyInteger)RubyKernel.new_integer(context, recv, args[0]);
1185 ceil = Math.abs(integerCeil.getLongValue());
1186 } else {
1187 throw runtime.newArgumentError("wrong # of arguments(" + args.length + " for 1)");
1190 if (ceil == 0) {
1191 return RubyFloat.newFloat(runtime, runtime.getRandom().nextDouble());
1193 if (ceil > Integer.MAX_VALUE) {
1194 return runtime.newFixnum(Math.abs(runtime.getRandom().nextLong()) % ceil);
1197 return runtime.newFixnum(runtime.getRandom().nextInt((int) ceil));
1200 @JRubyMethod(name = "syscall", required = 1, optional = 9, module = true, visibility = PRIVATE)
1201 public static IRubyObject syscall(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
1202 throw context.getRuntime().newNotImplementedError("Kernel#syscall is not implemented in JRuby");
1205 @JRubyMethod(name = {"system"}, required = 1, rest = true, module = true, visibility = PRIVATE)
1206 public static RubyBoolean system(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
1207 Ruby runtime = context.getRuntime();
1208 int resultCode;
1209 try {
1210 resultCode = ShellLauncher.runAndWait(runtime, args);
1211 } catch (Exception e) {
1212 resultCode = 127;
1214 runtime.getGlobalVariables().set("$?", RubyProcess.RubyStatus.newProcessStatus(runtime, resultCode));
1215 return runtime.newBoolean(resultCode == 0);
1218 @JRubyMethod(name = {"exec"}, required = 1, rest = true, module = true, visibility = PRIVATE)
1219 public static IRubyObject exec(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
1220 Ruby runtime = context.getRuntime();
1221 int resultCode;
1222 try {
1223 // TODO: exec should replace the current process.
1224 // This could be possible with JNA.
1225 resultCode = ShellLauncher.execAndWait(runtime, args);
1226 } catch (Exception e) {
1227 throw runtime.newErrnoENOENTError("cannot execute");
1230 return exit(recv, new IRubyObject[] {runtime.newFixnum(resultCode)});
1233 @JRubyMethod(name = "fork", module = true, visibility = PRIVATE)
1234 public static IRubyObject fork(ThreadContext context, IRubyObject recv, Block block) {
1235 Ruby runtime = context.getRuntime();
1237 if (!RubyInstanceConfig.FORK_ENABLED) {
1238 throw runtime.newNotImplementedError("fork is unsafe and disabled by default on JRuby");
1241 if (block.isGiven()) {
1242 int pid = runtime.getPosix().fork();
1244 if (pid == 0) {
1245 try {
1246 block.yield(context, runtime.getNil());
1247 } catch (RaiseException re) {
1248 if (re.getException() instanceof RubySystemExit) {
1249 throw re;
1251 return exit_bang(recv, new IRubyObject[] {RubyFixnum.minus_one(runtime)});
1252 } catch (Throwable t) {
1253 return exit_bang(recv, new IRubyObject[] {RubyFixnum.minus_one(runtime)});
1255 return exit_bang(recv, new IRubyObject[] {RubyFixnum.zero(runtime)});
1256 } else {
1257 return runtime.newFixnum(pid);
1259 } else {
1260 int result = runtime.getPosix().fork();
1262 if (result == -1) {
1263 return runtime.getNil();
1266 return runtime.newFixnum(result);
1270 @JRubyMethod(frame = true, module = true)
1271 public static IRubyObject tap(ThreadContext context, IRubyObject recv, Block block) {
1272 block.yield(context, recv);
1273 return recv;