Skip to content

Commit

Permalink
Showing 1,774 changed files with 43,823 additions and 24,520 deletions.
11 changes: 7 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -28,18 +28,20 @@ env:
- JT='test specs :core'
- JT='test specs :library'
- JT='test specs :truffle'
- JT='test mri'
- JT='test integration'
- JTR='ci --batch ../lib/ruby/truffle/jruby+truffle/gem_ci/travis.txt'

matrix:
include:
- env: COMMAND=test/check_versions.sh
jdk: oraclejdk8
- env: JT=check_ambiguous_arguments
jdk: oraclejdk8
#- env: JT=check_ambiguous_arguments
# jdk: oraclejdk8
allow_failures:
- env: PHASE='-Prake -Dtask=test:mri:fullint'
- env: JT=check_ambiguous_arguments
jdk: oraclejdk8
- env: JT='test mri'
- env: JTR='ci --batch ../lib/ruby/truffle/jruby+truffle/gem_ci/travis.txt'
# NOTE: build seems to never start (waited for any to finish for more than a day) - probably a travis-ci bug
#- env: PHASE='-Pmain'
# sudo: required
@@ -54,6 +56,7 @@ branches:
- truffle-head
- /^test-.*$/
- /^ha-feature/
- ruby-2.3

script: tool/travis_runner.sh
install: travis_retry ./mvnw -Pbootstrap clean install -B -Dinvoker.skip -Dmaven.test.skip
3 changes: 1 addition & 2 deletions core/pom.rb
Original file line number Diff line number Diff line change
@@ -51,7 +51,7 @@
jar 'com.github.jnr:jffi:${jffi.version}'
jar 'com.github.jnr:jffi:${jffi.version}:native'

jar 'org.jruby.joni:joni:2.1.9'
jar 'org.jruby.joni:joni:2.1.10-SNAPSHOT'
jar 'org.jruby.extras:bytelist:1.0.13'
jar 'org.jruby.jcodings:jcodings:1.0.17'
jar 'org.jruby:dirgra:0.3'
@@ -218,7 +218,6 @@
'forkCount' => '1',
'reuseForks' => 'false',
'systemProperties' => {
'jruby.compat.version' => '1.9',
'jruby.home' => '${basedir}/..'
},
'argLine' => '-Xmx${jruby.test.memory} -XX:MaxPermSize=${jruby.test.memory.permgen} -Dfile.encoding=UTF-8 -Djava.awt.headless=true',
11 changes: 5 additions & 6 deletions core/pom.xml
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ DO NOT MODIFIY - GENERATED CODE
<artifactId>jruby-core</artifactId>
<name>JRuby Core</name>
<properties>
<version.ruby>2.2.3</version.ruby>
<version.ruby>2.3.0</version.ruby>
<prawn.dir>${test.dir}/prawn</prawn.dir>
<spec.tags.dir>${spec.dir}/tags</spec.tags.dir>
<polyglot.dump.pom>pom.xml</polyglot.dump.pom>
@@ -28,7 +28,7 @@ DO NOT MODIFIY - GENERATED CODE
<jruby.test.memory.permgen>2G</jruby.test.memory.permgen>
<installer.gems>${jruby.win32ole.gem}</installer.gems>
<prawn.git.repo>git://github.com/sandal/prawn.git</prawn.git.repo>
<version.ruby.minor>3</version.ruby.minor>
<version.ruby.minor>0</version.ruby.minor>
<tzdata.version>2013d</tzdata.version>
<install4j.executable>/Applications/install4j 4/bin/install4jc</install4j.executable>
<jay.bin>jay</jay.bin>
@@ -40,15 +40,15 @@ DO NOT MODIFIY - GENERATED CODE
<rubyspec.1.8.dir>${rubyspec.dir}/1.8</rubyspec.1.8.dir>
<jruby.launch.memory>1024M</jruby.launch.memory>
<jruby.compile.memory>2G</jruby.compile.memory>
<version.ruby.major>2.2</version.ruby.major>
<version.ruby.major>2.3</version.ruby.major>
<unsafe.version>8.0</unsafe.version>
<release.dir>release</release.dir>
<lib.dir>lib</lib.dir>
<rails.dir>${test.dir}/rails</rails.dir>
<parser.dir>core/src/main/java/org/jruby/parser</parser.dir>
<jruby.basedir>${basedir}/..</jruby.basedir>
<rubyspec.dir>${spec.dir}/ruby</rubyspec.dir>
<version.ruby.revision>51636</version.ruby.revision>
<version.ruby.revision>52539</version.ruby.revision>
<jruby.test.memory>3G</jruby.test.memory>
<mspec.dir>${spec.dir}/mspec</mspec.dir>
<build.date>${maven.build.timestamp}</build.date>
@@ -174,7 +174,7 @@ DO NOT MODIFIY - GENERATED CODE
<dependency>
<groupId>org.jruby.joni</groupId>
<artifactId>joni</artifactId>
<version>2.1.9</version>
<version>2.1.10-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.jruby.extras</groupId>
@@ -563,7 +563,6 @@ DO NOT MODIFIY - GENERATED CODE
<forkCount>1</forkCount>
<reuseForks>false</reuseForks>
<systemProperties>
<jruby.compat.version>1.9</jruby.compat.version>
<jruby.home>${basedir}/..</jruby.home>
</systemProperties>
<argLine>-Xmx${jruby.test.memory} -XX:MaxPermSize=${jruby.test.memory.permgen} -Dfile.encoding=UTF-8 -Djava.awt.headless=true</argLine>
17 changes: 7 additions & 10 deletions core/src/main/java/org/jruby/NativeException.java
Original file line number Diff line number Diff line change
@@ -42,18 +42,15 @@ public class NativeException extends RubyException {

private final Throwable cause;
public static final String CLASS_NAME = "NativeException";
private final Ruby runtime;

public NativeException(Ruby runtime, RubyClass rubyClass, Throwable cause) {
super(runtime, rubyClass);
this.runtime = runtime;
this.cause = cause;
this.message = runtime.newString(cause.getClass().getName() + ": " + searchStackMessage(cause));
}

private NativeException(Ruby runtime, RubyClass rubyClass) {
super(runtime, rubyClass);
this.runtime = runtime;
this.cause = new Throwable();
this.message = runtime.newString();
}
@@ -84,6 +81,7 @@ public IRubyObject backtrace() {
if (rubyTrace.isNil()) {
return rubyTrace;
}
final Ruby runtime = getRuntime();
RubyArray array = (RubyArray) rubyTrace.dup();
StackTraceElement[] stackTrace = cause.getStackTrace();
for (int i = stackTrace.length - 1; i >= 0; i--) {
@@ -97,12 +95,12 @@ public IRubyObject backtrace() {
final String packageName = index == -1 ? "" : className.substring(0, index) + '/';
line = packageName.replace('.', '/') + element.getFileName() + ':' + element.getLineNumber() + ":in `" + element.getMethodName() + '\'';
}
RubyString string = runtime.newString(line);
array.unshift(string);
array.unshift(runtime.newString(line));
}
return array;
}

@Deprecated // not used
public void trimStackTrace(Member target) {
Throwable t = new Throwable();
StackTraceElement[] origStackTrace = cause.getStackTrace();
@@ -143,19 +141,18 @@ public void trimStackTrace(Member target) {

public void printBacktrace(PrintStream errorStream) {
super.printBacktrace(errorStream);
if (getRuntime().getDebug().isTrue()) {
if (getRuntime().isDebug()) {
errorStream.println("Complete Java stackTrace");
cause.printStackTrace(errorStream);
}
}

public Throwable getCause() {
public final Throwable getCause() {
return cause;
}

private String searchStackMessage(Throwable cause) {
String message = null;

private static String searchStackMessage(Throwable cause) {
String message;
do {
message = cause.getMessage();
cause = cause.getCause();
83 changes: 67 additions & 16 deletions core/src/main/java/org/jruby/Ruby.java
Original file line number Diff line number Diff line change
@@ -1275,13 +1275,21 @@ && getInstanceConfig().getCompileMode() != CompileMode.TRUFFLE) {
// out of base boot mode
bootingCore = false;

// init Ruby-based kernel
if (getInstanceConfig().getCompileMode() != CompileMode.TRUFFLE) {
// init Ruby-based kernel
initRubyKernel();
}

// everything booted, so SizedQueue should be available; set up root fiber
if (getInstanceConfig().getCompileMode() != CompileMode.TRUFFLE) {
// Define blank modules for feature detection in preludes
if (!config.isDisableGems()) {
defineModule("Gem");
}
if (!config.isDisableDidYouMean()) {
defineModule("DidYouMean");
}

initRubyPreludes();

// everything booted, so SizedQueue should be available; set up root fiber
ThreadFiber.initRootFiber(tc);
}

@@ -1332,6 +1340,7 @@ private boolean doesReflectionWork() {
private void bootstrap() {
initCore();
initExceptions();
initLibraries();
}

private void initDefinedMessages() {
@@ -1414,7 +1423,9 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz
singleNilArray = new IRubyObject[] {nilObject};

falseObject = new RubyBoolean.False(this);
falseObject.setFrozen(true);
trueObject = new RubyBoolean.True(this);
trueObject.setFrozen(true);
}

private void initCore() {
@@ -1570,11 +1581,6 @@ private void initCore() {
RubyEnumerator.defineEnumerator(this);
}

// Fiber depends on thread library, so we load it here
new ThreadLibrary().load(this, false);

new ThreadFiberLibrary().load(this, false);

TracePoint.createTracePointClass(this);
}

@@ -1616,6 +1622,9 @@ private void initExceptions() {
interrupt = defineClassIfAllowed("Interrupt", signalException);
typeError = defineClassIfAllowed("TypeError", standardError);
argumentError = defineClassIfAllowed("ArgumentError", standardError);
if (profile.allowClass("UncaughtThrowError")) {
uncaughtThrowError = RubyUncaughtThrowError.createUncaughtThrowErrorClass(this, argumentError);
}
indexError = defineClassIfAllowed("IndexError", standardError);
if (profile.allowClass("StopIteration")) {
stopIteration = RubyStopIteration.createStopIterationClass(this, indexError);
@@ -1655,6 +1664,11 @@ private void initExceptions() {
initErrno();
}

private void initLibraries() {
new ThreadLibrary().load(this, false);
new ThreadFiberLibrary().load(this, false);
}

private RubyClass defineClassIfAllowed(String name, RubyClass superClass) {
// TODO: should probably apply the null object pattern for a
// non-allowed class, rather than null
@@ -1786,6 +1800,14 @@ private void initRubyKernel() {
loadService.loadFromClassLoader(getClassLoader(), "jruby/kernel.rb", false);
}

private void initRubyPreludes() {
// We cannot load any .rb and debug new parser features
if (RubyInstanceConfig.DEBUG_PARSER) return;

// load Ruby parts of core
loadService.loadFromClassLoader(getClassLoader(), "jruby/preludes.rb", false);
}

private void addLazyBuiltin(String name, String shortName, String className) {
addBuiltinIfAllowed(name, new LateLoadingLibrary(shortName, className, getClassLoader()));
}
@@ -2435,6 +2457,10 @@ public RubyClass getArgumentError() {
return argumentError;
}

public RubyClass getUncaughtThrowError() {
return uncaughtThrowError;
}

public RubyClass getIndexError() {
return indexError;
}
@@ -2902,7 +2928,11 @@ public void loadFile(String scriptName, InputStream in, boolean wrap) {
// toss an anonymous module into the search path
RubyModule wrapper = RubyModule.newModule(this);
((RubyBasicObject)self).extend(new IRubyObject[] {wrapper});
((RootNode) parseResult).getStaticScope().setModule(wrapper);
RootNode root = (RootNode) parseResult;
StaticScope top = root.getStaticScope();
StaticScope newTop = staticScopeFactory.newLocalScope(null);
top.setPreviousCRefScope(newTop);
top.setModule(wrapper);
}

runInterpreter(context, parseResult, self);
@@ -3859,12 +3889,14 @@ public RaiseException newNotImplementedError(String message) {
return newRaiseException(getNotImplementedError(), message);
}

@Deprecated
public RaiseException newInvalidEncoding(String message) {
return newRaiseException(fastGetClass("Iconv").getClass("InvalidEncoding"), message);
return newRaiseException(getClass("Iconv").getClass("InvalidEncoding"), message);
}

@Deprecated
public RaiseException newIllegalSequence(String message) {
return newRaiseException(fastGetClass("Iconv").getClass("IllegalSequence"), message);
return newRaiseException(getClass("Iconv").getClass("IllegalSequence"), message);
}

public RaiseException newNoMethodError(String message, String name, IRubyObject args) {
@@ -3875,7 +3907,7 @@ public RaiseException newNameError(String message, String name) {
return newNameError(message, name, null);
}

// This name sucks and should be replaced by newNameErrorfor 9k.
@Deprecated
public RaiseException newNameErrorObject(String message, IRubyObject name) {
RubyException error = new RubyNameError(this, getNameError(), message, name);

@@ -3886,6 +3918,26 @@ public RaiseException newNameError(String message, String name, Throwable origEx
return newNameError(message, name, origException, false);
}

public RaiseException newNameError(String message, IRubyObject recv, IRubyObject name) {
IRubyObject msg = new RubyNameError.RubyNameErrorMessage(this, message, recv, name);
RubyException err = RubyNameError.newNameError(getNameError(), msg, name);

return new RaiseException(err);
}

public RaiseException newNameError(String message, IRubyObject recv, String name) {
RubySymbol nameSym = newSymbol(name);
return newNameError(message, recv, nameSym);
}

public RaiseException newNoMethodError(String message, IRubyObject recv, String name, RubyArray args) {
RubySymbol nameStr = newSymbol(name);
IRubyObject msg = new RubyNameError.RubyNameErrorMessage(this, message, recv, nameStr);
RubyException err = RubyNoMethodError.newNoMethodError(getNoMethodError(), msg, nameStr, args);

return new RaiseException(err);
}

public RaiseException newNameError(String message, String name, Throwable origException, boolean printWhenVerbose) {
if (origException != null) {
if (printWhenVerbose && isVerbose()) {
@@ -3895,8 +3947,7 @@ public RaiseException newNameError(String message, String name, Throwable origEx
}
}

return new RaiseException(new RubyNameError(
this, getNameError(), message, name), false);
return new RaiseException(new RubyNameError(this, getNameError(), message, name), false);
}

public RaiseException newLocalJumpError(RubyLocalJumpError.Reason reason, IRubyObject exitValue, String message) {
@@ -4926,7 +4977,7 @@ public FilenoUtil getFilenoUtil() {
groupStruct, procStatusClass, exceptionClass, runtimeError, ioError,
scriptError, nameError, nameErrorMessage, noMethodError, signalException,
rangeError, dummyClass, systemExit, localJumpError, nativeException,
systemCallError, fatal, interrupt, typeError, argumentError, indexError, stopIteration,
systemCallError, fatal, interrupt, typeError, argumentError, uncaughtThrowError, indexError, stopIteration,
syntaxError, standardError, loadError, notImplementedError, securityError, noMemoryError,
regexpError, eofError, threadError, concurrencyError, systemStackError, zeroDivisionError, floatDomainError, mathDomainError,
encodingError, encodingCompatibilityError, converterNotFoundError, undefinedConversionError,
143 changes: 83 additions & 60 deletions core/src/main/java/org/jruby/RubyArgsFile.java
Original file line number Diff line number Diff line change
@@ -35,23 +35,23 @@
import java.io.File;
import java.io.IOException;

import jnr.posix.FileStat;
import jnr.posix.util.Platform;

import static org.jruby.RubyEnumerator.enumeratorize;
import static org.jruby.runtime.Visibility.PRIVATE;

import org.jruby.anno.FrameField;
import org.jruby.anno.JRubyMethod;
import org.jruby.exceptions.RaiseException;

import jnr.posix.FileStat;
import jnr.posix.util.Platform;

import org.jruby.internal.runtime.GlobalVariable;
import org.jruby.runtime.Block;
import org.jruby.runtime.IAccessor;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ByteList;
import org.jruby.internal.runtime.GlobalVariable;
import org.jruby.util.TypeConverter;

public class RubyArgsFile extends RubyObject {

@@ -68,21 +68,26 @@ public static void initArgsFile(final Ruby runtime) {
IRubyObject argsFile = argfClass.newInstance(runtime.getCurrentContext(), new IRubyObject[] { null }, (Block) null);

runtime.setArgsFile(argsFile);
runtime.getGlobalVariables().defineReadonly("$<", new IAccessor() {
@Override
public IRubyObject getValue() {
return runtime.getArgsFile();
}

@Override
public IRubyObject setValue(IRubyObject newValue) {
throw new UnsupportedOperationException("Not supported yet.");
}
}, GlobalVariable.Scope.GLOBAL);
runtime.getGlobalVariables().defineReadonly("$<", new ArgsFileAccessor(runtime), GlobalVariable.Scope.GLOBAL);
runtime.defineGlobalConstant("ARGF", argsFile);
runtime.defineReadonlyVariable("$FILENAME", runtime.newString("-"), GlobalVariable.Scope.GLOBAL);
}


private static class ArgsFileAccessor implements IAccessor {

private final Ruby runtime;
ArgsFileAccessor(Ruby runtime) { this.runtime = runtime; }

public IRubyObject getValue() {
return runtime.getArgsFile();
}

public IRubyObject setValue(IRubyObject newValue) {
throw new UnsupportedOperationException("Not supported yet.");
}
}

private static final ObjectAllocator ARGF_ALLOCATOR = new ObjectAllocator() {
@Override
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
@@ -92,14 +97,15 @@ public IRubyObject allocate(Ruby runtime, RubyClass klass) {

@JRubyMethod(name = "initialize", visibility = PRIVATE, rest = true)
public IRubyObject initialize(ThreadContext context, IRubyObject[] args) {
final Ruby runtime = context.runtime;
final RubyArray argv;
if (args.length == 1 && args[0] == null) {
argv = context.getRuntime().getObject().getConstant("ARGV").convertToArray();
argv = runtime.getObject().getConstant("ARGV").convertToArray();
} else {
argv = context.getRuntime().newArray(args);
argv = runtime.newArray(args);
}

ArgsFileData data = new ArgsFileData(context.getRuntime(), argv);
ArgsFileData data = new ArgsFileData(runtime, argv);
this.dataWrapStruct(data);
return this;
}
@@ -131,20 +137,21 @@ public boolean next_argv(ThreadContext context) {
currentLineNumber = 0;
}

IRubyObject $FILENAME = runtime.getGlobalVariables().get("$FILENAME");

if (next_p == 1) {
next_p = 0;
if (argv.getLength() > 0) {
IRubyObject arg = argv.shift(context);
RubyString filename = (RubyString)((RubyObject)arg).to_s();
ByteList filenameBytes = filename.getByteList();
if (!filename.op_equal(context, (RubyString) runtime.getGlobalVariables().get("$FILENAME")).isTrue()) {
final RubyString filename = argv.shift(context).convertToString();
if ( ! filename.op_equal(context, $FILENAME).isTrue() ) {
runtime.defineReadonlyVariable("$FILENAME", filename, GlobalVariable.Scope.GLOBAL);
}

if (filenameBytes.length() == 1 && filenameBytes.get(0) == '-') {
if ( filenameEqlDash(filename) ) {
currentFile = runtime.getGlobalVariables().get("$stdin");
} else {
currentFile = RubyFile.open(context, runtime.getFile(), new IRubyObject[]{filename}, Block.NULL_BLOCK);
}
else {
currentFile = RubyFile.open(context, runtime.getFile(), new IRubyObject[]{ filename }, Block.NULL_BLOCK);
String extension = runtime.getInstanceConfig().getInPlaceBackupExtension();
if (extension != null) {
if (Platform.IS_WINDOWS) {
@@ -160,21 +167,28 @@ public boolean next_argv(ThreadContext context) {
next_p = 1;
return false;
}
} else if (next_p == -1) {
}
else if (next_p == -1) {
currentFile = runtime.getGlobalVariables().get("$stdin");
if(!runtime.getGlobalVariables().get("$FILENAME").asJavaString().equals("-")) {
if ( ! filenameEqlDash((RubyString) $FILENAME) ) {
runtime.defineReadonlyVariable("$FILENAME", runtime.newString("-"), GlobalVariable.Scope.GLOBAL);
}
}

return true;
}

private static boolean filenameEqlDash(final RubyString filename) {
final ByteList filenameBytes = filename.getByteList();
return filenameBytes.length() == 1 && filenameBytes.get(0) == '-';
}

public static ArgsFileData getDataFrom(IRubyObject recv) {
ArgsFileData data = (ArgsFileData)recv.dataGetStruct();
ArgsFileData data = (ArgsFileData) recv.dataGetStruct();

if (data == null) {
data = new ArgsFileData(recv.getRuntime(), recv.getRuntime().newEmptyArray());
final Ruby runtime = recv.getRuntime();
data = new ArgsFileData(runtime, runtime.newEmptyArray());
recv.dataWrapStruct(data);
}

@@ -192,7 +206,7 @@ private void createNewFile(File file) {
private void inplaceEditWindows(ThreadContext context, String filename, String extension) throws RaiseException {
File file = new File(filename);

if (!extension.equals("")) {
if (extension.length() > 0) {
String backup = filename + extension;
File backupFile = new File(backup);

@@ -215,7 +229,7 @@ private void inplaceEdit(ThreadContext context, String filename, String extensio
File file = new File(filename);
FileStat stat = runtime.getPosix().stat(filename);

if (!extension.equals("")) {
if (extension.length() > 0) {
file.renameTo(new File(filename + extension));
} else {
file.delete();
@@ -284,20 +298,20 @@ private static IRubyObject argf_getline(ThreadContext context, IRubyObject recv,

boolean retry = true;
IRubyObject line = null;
while(retry) {
while (retry) {
retry = false;
if (!data.next_argv(context)) return context.runtime.getNil();
if ( ! data.next_argv(context) ) return context.nil;

line = data.currentFile.callMethod(context, "gets", args);

if (line.isNil() && data.next_p != -1) {
if ( line.isNil() && data.next_p != -1 ) {
argf_close(context, data.currentFile);
data.next_p = 1;
retry = true;
}
}

if (line != null && !line.isNil()) {
if ( line != null && ! line.isNil() ) {
context.runtime.setCurrentLine(data.currentLineNumber);
}

@@ -507,9 +521,6 @@ public static IRubyObject close(ThreadContext context, IRubyObject recv) {
ArgsFileData data = ArgsFileData.getDataFrom(recv);

data.next_argv(context);
if (isClosed(context, data.currentFile)) {
throw context.runtime.newIOError(RubyIO.CLOSED_STREAM_MSG);
}

argf_close(context, data.currentFile);

@@ -653,7 +664,7 @@ public static IRubyObject getbyte(ThreadContext context, IRubyObject recv) {
}
}

@JRubyMethod(required = 1, optional = 1)
@JRubyMethod(required = 1, optional = 2)
public static IRubyObject read_nonblock(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
return getPartial(context, recv, args, true);
}
@@ -664,37 +675,49 @@ public static IRubyObject readpartial(ThreadContext context, IRubyObject recv, I
}

private static IRubyObject getPartial(ThreadContext context, IRubyObject recv, IRubyObject[] args, boolean nonBlocking) {
ArgsFileData data = ArgsFileData.getDataFrom(recv);

if (args.length > 1) args[1] = args[1].convertToString();
final Ruby runtime = context.runtime;
boolean noException = false;
if ( args.length > 1 ) {
IRubyObject opts = TypeConverter.checkHashType(runtime, args[args.length - 1]);
if ( ! opts.isNil() &&
runtime.getFalse() == ((RubyHash) opts).op_aref(context, runtime.newSymbol("exception")) ) {
noException = true;
}
if ( args.length > 2 || opts.isNil() ) args[1] = args[1].convertToString();
}

if (!data.next_argv(context)) throw context.runtime.newEOFError();
final ArgsFileData data = ArgsFileData.getDataFrom(recv);

IRubyObject tmp;
if (!(data.currentFile instanceof RubyFile)) { // In MRI this is stdin && !FILE
tmp = data.currentFile.callMethod(context, "getpartial", args);
} else {
// In MRI io_getpartial. Not split
if (nonBlocking) {
tmp = ((RubyIO) data.currentFile).read_nonblock(context, args);
} else {
tmp = ((RubyIO) data.currentFile).readpartial(context, args);
}
if ( ! data.next_argv(context) ) {
return RubyIO.nonblockEOF(runtime, noException);
}

if (tmp.isNil()) {
if (data.next_p == -1) throw context.runtime.newEOFError();
IRubyObject res;
// NOTE: this seems no longer relevant, please review :
//if ( ! (data.currentFile instanceof RubyFile) ) { // In MRI this is stdin && !FILE
// res = data.currentFile.callMethod(context, "getpartial", args);
//} else {
// res = ((RubyIO) data.currentFile).getPartial(context, args, nonBlocking, noException);
//}
res = ((RubyIO) data.currentFile).getPartial(context, args, nonBlocking, noException);

if ( res.isNil() ) {
if ( data.next_p == -1 ) {
return RubyIO.nonblockEOF(runtime, noException);
}

argf_close(context, data.currentFile);
data.next_p = 1;
// FIXME: Missing EOF error is no more argv element at this point

if (args.length > 1 && args[1].isNil()) return context.runtime.newString();
if ( data.argv.size() == 0 ) {
return RubyIO.nonblockEOF(runtime, noException);
}

return args[1];
if ( args.length > 1 && args[1] instanceof RubyString ) return args[1];
return RubyString.newEmptyString(runtime);
}

return tmp;
return res;
}

@JRubyMethod
357 changes: 212 additions & 145 deletions core/src/main/java/org/jruby/RubyArray.java

Large diffs are not rendered by default.

47 changes: 28 additions & 19 deletions core/src/main/java/org/jruby/RubyBasicObject.java
Original file line number Diff line number Diff line change
@@ -604,11 +604,10 @@ public final boolean respondsTo(String name) {
final Ruby runtime = getRuntime();

final DynamicMethod respondTo = getMetaClass().searchMethod("respond_to?");
final DynamicMethod respondToMissing = getMetaClass().searchMethod("respond_to_missing?");

// fastest path; builtin respond_to? and respond_to_missing? so we just check isMethodBound
if ( respondTo.equals(runtime.getRespondToMethod()) &&
respondToMissing.equals(runtime.getRespondToMissingMethod()) ) {
getMetaClass().searchMethod("respond_to_missing?").equals(runtime.getRespondToMissingMethod()) ) {
return getMetaClass().isMethodBound(name, false);
}

@@ -1097,14 +1096,17 @@ public IRubyObject hashyInspect() {
public static IRubyObject rbInspect(ThreadContext context, IRubyObject obj) {
Ruby runtime = context.runtime;
RubyString str = obj.callMethod(context, "inspect").asString();
Encoding ext = EncodingUtils.defaultExternalEncoding(runtime);
if (!ext.isAsciiCompatible()) {
if (!str.isAsciiOnly())
throw runtime.newEncodingCompatibilityError("inspected result must be ASCII only if default external encoding is ASCII incompatible");
Encoding enc = runtime.getDefaultInternalEncoding();
if (enc == null) enc = runtime.getDefaultExternalEncoding();
if (!enc.isAsciiCompatible()) {
if (!str.isAsciiOnly()) {
return RubyString.rbStrEscape(context, str);
}
return str;
}
if (str.getEncoding() != ext && !str.isAsciiOnly())
throw runtime.newEncodingCompatibilityError("inspected result must be ASCII only or use the default external encoding");
if (str.getEncoding() != enc && !str.isAsciiOnly()) {
return RubyString.rbStrEscape(context, str);
}
return str;
}
/**
@@ -1537,7 +1539,7 @@ public void copyInstanceVariablesInto(final InstanceVariables other) {
* tainted. Will throw a suitable exception in that case.
*/
public final void ensureInstanceVariablesSettable() {
if (!isFrozen() || isImmediate()) {
if (!isFrozen()) {
return;
}
raiseFrozenError();
@@ -1598,7 +1600,7 @@ public static IRubyObject method_missing19(ThreadContext context, IRubyObject re
throw context.runtime.newArgumentError("no id given");
}

return RubyKernel.methodMissingDirect(context, recv, (RubySymbol)args[0], lastVis, lastCallType, args, block);
return RubyKernel.methodMissingDirect(context, recv, (RubySymbol)args[0], lastVis, lastCallType, args);
}

@JRubyMethod(name = "__send__", omit = true)
@@ -2424,11 +2426,12 @@ public RubyArray singleton_methods(ThreadContext context, IRubyObject[] args) {
* m = l.method("hello")
* m.call #=> "Hello, @iv = Fred"
*/
public IRubyObject method(IRubyObject symbol) {
return getMetaClass().newMethod(this, symbol.asJavaString(), true, null);
public IRubyObject method(IRubyObject name) {
return getMetaClass().newMethod(this, name.asJavaString(), true, null);
}

public IRubyObject method19(IRubyObject symbol) {
public IRubyObject method19(IRubyObject name) {
final RubySymbol symbol = TypeConverter.checkID(name);
return getMetaClass().newMethod(this, symbol.asJavaString(), true, null, true);
}

@@ -2693,7 +2696,7 @@ public IRubyObject op_not_match(ThreadContext context, IRubyObject arg) {
* fred.instance_variable_defined?("@c") #=> false
*/
public IRubyObject instance_variable_defined_p(ThreadContext context, IRubyObject name) {
if (variableTableContains(validateInstanceVariable(name.asJavaString()))) {
if (variableTableContains(validateInstanceVariable(name, name.asJavaString()))) {
return context.runtime.getTrue();
}
return context.runtime.getFalse();
@@ -2721,7 +2724,7 @@ public IRubyObject instance_variable_defined_p(ThreadContext context, IRubyObjec
*/
public IRubyObject instance_variable_get(ThreadContext context, IRubyObject name) {
Object value;
if ((value = variableTableFetch(validateInstanceVariable(name.asJavaString()))) != null) {
if ((value = variableTableFetch(validateInstanceVariable(name, name.asJavaString()))) != null) {
return (IRubyObject)value;
}
return context.runtime.getNil();
@@ -2749,7 +2752,7 @@ public IRubyObject instance_variable_get(ThreadContext context, IRubyObject name
*/
public IRubyObject instance_variable_set(IRubyObject name, IRubyObject value) {
// no need to check for ensureInstanceVariablesSettable() here, that'll happen downstream in setVariable
return (IRubyObject)variableTableStore(validateInstanceVariable(name.asJavaString()), value);
return (IRubyObject)variableTableStore(validateInstanceVariable(name, name.asJavaString()), value);
}

/** rb_obj_remove_instance_variable
@@ -2777,10 +2780,10 @@ public IRubyObject instance_variable_set(IRubyObject name, IRubyObject value) {
public IRubyObject remove_instance_variable(ThreadContext context, IRubyObject name, Block block) {
ensureInstanceVariablesSettable();
IRubyObject value;
if ((value = (IRubyObject)variableTableRemove(validateInstanceVariable(name.asJavaString()))) != null) {
if ((value = (IRubyObject)variableTableRemove(validateInstanceVariable(name, name.asJavaString()))) != null) {
return value;
}
throw context.runtime.newNameError("instance variable " + name.asJavaString() + " not defined", name.asJavaString());
throw context.runtime.newNameError("instance variable " + name.asJavaString() + " not defined", this, name);
}

/** rb_obj_instance_variables
@@ -2873,7 +2876,13 @@ protected static int nonFixnumHashCode(IRubyObject hashValue) {
protected String validateInstanceVariable(String name) {
if (IdUtil.isValidInstanceVariableName(name)) return name;

throw getRuntime().newNameError("`" + name + "' is not allowable as an instance variable name", name);
throw getRuntime().newNameError("`" + name + "' is not allowable as an instance variable name", this, name);
}

protected String validateInstanceVariable(IRubyObject nameObj, String name) {
if (IdUtil.isValidInstanceVariableName(name)) return name;

throw getRuntime().newNameError("`" + name + "' is not allowable as an instance variable name", this, nameObj);
}

/**
58 changes: 35 additions & 23 deletions core/src/main/java/org/jruby/RubyClass.java
Original file line number Diff line number Diff line change
@@ -623,22 +623,25 @@ public IRubyObject finvoke(ThreadContext context, IRubyObject self, String name)
*
* MRI: rb_check_funcall
*/
public IRubyObject finvokeChecked(ThreadContext context, IRubyObject self, String name) {
return finvokeChecked(context, self, name, IRubyObject.NULL_ARRAY);
public final IRubyObject finvokeChecked(ThreadContext context, IRubyObject self, String name) {
return checkFuncallDefault(context, self, name, IRubyObject.NULL_ARRAY);
}

/**
* Safely attempt to invoke the given method name on self, using respond_to? and method_missing as appropriate.
*
* MRI: rb_check_funcall
*/
public IRubyObject finvokeChecked(ThreadContext context, IRubyObject self, String name, IRubyObject... args) {
RubyClass klass = self.getMetaClass();
DynamicMethod me;
if (!checkFuncallRespondTo(context, self.getMetaClass(), self, name))
return null;
public final IRubyObject finvokeChecked(ThreadContext context, IRubyObject self, String name, IRubyObject... args) {
return checkFuncallDefault(context, self, name, args);
}

// MRI: rb_check_funcall_default
private IRubyObject checkFuncallDefault(ThreadContext context, IRubyObject self, String name, IRubyObject[] args) {
final RubyClass klass = self.getMetaClass();
if (!checkFuncallRespondTo(context, klass, self, name)) return null; // return def;

me = searchMethod(name);
DynamicMethod me = searchMethod(name);
if (!checkFuncallCallable(context, me, CallType.FUNCTIONAL, self)) {
return checkFuncallMissing(context, klass, self, name, args);
}
@@ -667,7 +670,7 @@ private static IRubyObject checkFuncallFailed(ThreadContext context, IRubyObject
* MRI: check_funcall_respond_to
*/
private static boolean checkFuncallRespondTo(ThreadContext context, RubyClass klass, IRubyObject recv, String mid) {
Ruby runtime = context.runtime;
final Ruby runtime = context.runtime;
DynamicMethod me = klass.searchMethod("respond_to?");

// NOTE: isBuiltin here would be NOEX_BASIC in MRI, a flag only added to respond_to?, method_missing, and
@@ -683,8 +686,7 @@ private static boolean checkFuncallRespondTo(ThreadContext context, RubyClass kl
} else {
result = me.call(context, recv, klass, "respond_to?", runtime.newSymbol(mid), runtime.getTrue());
}

if (!result.isTrue()) return false;
return result.isTrue();
}
return true;
}
@@ -702,19 +704,29 @@ public static boolean rbMethodCallStatus(ThreadContext context, DynamicMethod me

// MRI: check_funcall_missing
private static IRubyObject checkFuncallMissing(ThreadContext context, RubyClass klass, IRubyObject self, String method, IRubyObject... args) {
Ruby runtime = context.runtime;
if (klass.isMethodBuiltin("method_missing")) {
return null;
}
else {
final IRubyObject $ex = context.getErrorInfo();
try {
return checkFuncallExec(context, self, method, args);
}
catch (RaiseException e) {
context.setErrorInfo($ex); // restore $!
return checkFuncallFailed(context, self, method, runtime.getNoMethodError(), args);
final Ruby runtime = context.runtime;

DynamicMethod me = klass.searchMethod("respond_to_missing?");
// MRI: basic_obj_respond_to_missing ...
if ( me != null && ! me.isUndefined() && ! me.isBuiltin() ) {
IRubyObject ret;
if (me.getArity().getValue() == 1) {
ret = me.call(context, self, klass, "respond_to_missing?", runtime.newSymbol(method));
} else {
ret = me.call(context, self, klass, "respond_to_missing?", runtime.newSymbol(method), runtime.getTrue());
}
if ( ! ret.isTrue() ) return null;
}

if ( klass.isMethodBuiltin("method_missing") ) return null;

final IRubyObject $ex = context.getErrorInfo();
try {
return checkFuncallExec(context, self, method, args);
}
catch (RaiseException e) {
context.setErrorInfo($ex); // restore $!
return checkFuncallFailed(context, self, method, runtime.getNoMethodError(), args);
}
}

37 changes: 10 additions & 27 deletions core/src/main/java/org/jruby/RubyComparable.java
Original file line number Diff line number Diff line change
@@ -146,36 +146,19 @@ private static IRubyObject callCmpMethod(final ThreadContext context, final IRub
if (recv == other) return runtime.getTrue();

final IRubyObject $ex = context.getErrorInfo();
try {
IRubyObject result = runtime.execRecursiveOuter(new Ruby.RecursiveFunction() {
@Override
public IRubyObject call(IRubyObject obj, boolean recur) {
if (recur) return runtime.getNil();
return invokedynamic(context, recv, OP_CMP, other);
}
}, recv);

// This is only to prevent throwing exceptions by cmperr - it has poor performance
if ( result.isNil() ) return returnValueOnError;

return RubyBoolean.newBoolean(runtime, cmpint(context, result, recv, other) == 0);
}
catch (RaiseException e) {
if (e.getException().kind_of_p(context, runtime.getStandardError()).isTrue()) {
cmpFailed(context);
// clear error info resulting from failure to compare (JRUBY-3292)
context.setErrorInfo($ex); // restore previous $! error (if any)
return returnValueOnError;

IRubyObject result = runtime.execRecursiveOuter(new Ruby.RecursiveFunction() {
@Override
public IRubyObject call(IRubyObject obj, boolean recur) {
if (recur) return runtime.getNil();
return invokedynamic(context, recv, OP_CMP, other);
}
throw e;
}
}
}, recv);

private static void cmpFailed(ThreadContext context) {
RubyWarnings warnings = context.runtime.getWarnings();
// This is only to prevent throwing exceptions by cmperr - it has poor performance
if ( result.isNil() ) return returnValueOnError;

warnings.warn("Comparable#== will no more rescue exceptions of #<=> in the next release.");
warnings.warn("Return nil in #<=> if the comparison is inappropriate or avoid such comparison.");
return RubyBoolean.newBoolean(runtime, cmpint(context, result, recv, other) == 0);
}

/** cmp_gt
13 changes: 9 additions & 4 deletions core/src/main/java/org/jruby/RubyComplex.java
Original file line number Diff line number Diff line change
@@ -72,6 +72,7 @@

import static org.jruby.runtime.Helpers.invokedynamic;
import static org.jruby.runtime.invokedynamic.MethodNames.HASH;
import static org.jruby.util.Numeric.safe_mul;

/**
* 1.9 complex.c as of revision: 20011
@@ -539,12 +540,16 @@ public IRubyObject op_sub(ThreadContext context, IRubyObject other) {
public IRubyObject op_mul(ThreadContext context, IRubyObject other) {
if (other instanceof RubyComplex) {
RubyComplex otherComplex = (RubyComplex)other;
boolean arzero = f_zero_p(context, real);
boolean aizero = f_zero_p(context, image);
boolean brzero = f_zero_p(context, otherComplex.real);
boolean bizero = f_zero_p(context, otherComplex.image);
IRubyObject realp = f_sub(context,
f_mul(context, real, otherComplex.real),
f_mul(context, image, otherComplex.image));
safe_mul(context, real, otherComplex.real, arzero, brzero),
safe_mul(context, image, otherComplex.image, aizero, bizero));
IRubyObject imagep = f_add(context,
f_mul(context, real, otherComplex.image),
f_mul(context, image, otherComplex.real));
safe_mul(context, real, otherComplex.image, arzero, bizero),
safe_mul(context, image, otherComplex.real, aizero, brzero));

return newComplex(context, getMetaClass(), realp, imagep);
} else if (other instanceof RubyNumeric && f_real_p(context, other).isTrue()) {
5 changes: 4 additions & 1 deletion core/src/main/java/org/jruby/RubyConverter.java
Original file line number Diff line number Diff line change
@@ -351,10 +351,11 @@ public IRubyObject primitive_convert(ThreadContext context, IRubyObject[] args)
@JRubyMethod
public IRubyObject convert(ThreadContext context, IRubyObject srcBuffer) {
Ruby runtime = context.runtime;
RubyString orig = srcBuffer.convertToString();
IRubyObject dest;

IRubyObject[] newArgs = {
srcBuffer.convertToString().dup(),
orig.dup(),
dest = runtime.newString(),
context.nil,
context.nil,
@@ -382,6 +383,8 @@ public IRubyObject convert(ThreadContext context, IRubyObject srcBuffer) {
}
}

dest.infectBy(orig);

return dest;
}

58 changes: 33 additions & 25 deletions core/src/main/java/org/jruby/RubyDir.java
Original file line number Diff line number Diff line change
@@ -37,15 +37,11 @@
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;

import jnr.posix.FileStat;
import jnr.posix.POSIX;

import org.jruby.anno.JRubyMethod;
import org.jruby.anno.JRubyClass;
@@ -61,7 +57,6 @@
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.Visibility;
import org.jruby.util.Dir;
import org.jruby.util.FileResource;
import org.jruby.util.JRubyFile;
@@ -111,18 +106,18 @@ public static RubyClass createDirClass(Ruby runtime) {
}

private final void checkDir() {
testFrozen("Dir");
update();
checkDirIgnoreClosed();

if (!isOpen) throw getRuntime().newIOError("closed directory");
}

private void update() {
private final void checkDirIgnoreClosed() {
testFrozen("Dir");
// update snapshot (if changed) :
if (snapshot == null || dir.exists() && dir.lastModified() > lastModified) {
lastModified = dir.lastModified();
List<String> snapshotList = new ArrayList<String>();
snapshotList.addAll(getContents(dir));
snapshot = snapshotList.toArray(new String[snapshotList.size()]);
final List<String> contents = getContents(dir);
snapshot = contents.toArray(new String[contents.size()]);
}
}

@@ -186,8 +181,9 @@ private static String getCWD(Ruby runtime) {
return runtime.getCurrentDirectory();
}
try {
return new org.jruby.util.NormalizedFile(runtime.getCurrentDirectory()).getCanonicalPath();
} catch (Exception e) {
return new JRubyFile(runtime.getCurrentDirectory()).getCanonicalPath();
}
catch (Exception e) {
return runtime.getCurrentDirectory();
}
}
@@ -309,8 +305,8 @@ public static IRubyObject chdir(ThreadContext context, IRubyObject recv, IRubyOb
getHomeDirectoryPath(context);
String adjustedPath = RubyFile.adjustRootPathOnWindows(runtime, path.asJavaString(), null);
checkDirIsTwoSlashesOnWindows(runtime, adjustedPath);
String realPath = null;
String oldCwd = runtime.getCurrentDirectory();
final String realPath;
final String oldCwd = runtime.getCurrentDirectory();
if (PROTOCOL_PATTERN.matcher(adjustedPath).matches()) {
realPath = adjustedPath;
}
@@ -515,7 +511,7 @@ public static IRubyObject open19(ThreadContext context, IRubyObject recv, IRubyO
@JRubyMethod(name = "close")
public IRubyObject close() {
// Make sure any read()s after close fail.
checkDir();
checkDirIgnoreClosed();

isOpen = false;

@@ -735,13 +731,18 @@ private static String dirFromPath(final String path, final Ruby runtime) throws
* <code>ArrayList</code> containing the names of the files as Java Strings.
*/
protected static List<String> getContents(FileResource directory) {
String[] contents = directory.list();
List<String> result = new ArrayList<String>();
final String[] contents = directory.list();

final List<String> result;
// If an IO exception occurs (something odd, but possible)
// A directory may return null.
if (contents != null) result.addAll(Arrays.asList(contents));

if (contents != null) {
result = new ArrayList<String>(contents.length);
Collections.addAll(result, contents);
}
else {
result = Collections.emptyList();
}
return result;
}

@@ -750,12 +751,19 @@ protected static List<String> getContents(FileResource directory) {
* <code>ArrayList</code> containing the names of the files as Ruby Strings.
*/
protected static List<RubyString> getContents(FileResource directory, Ruby runtime) {
List<RubyString> result = new ArrayList<RubyString>();
String[] contents = directory.list();
final String[] contents = directory.list();

for (int i = 0; i < contents.length; i++) {
result.add(runtime.newString(contents[i]));
final List<RubyString> result;
if (contents != null) {
result = new ArrayList<RubyString>(contents.length);
for (int i = 0; i < contents.length; i++) {
result.add( runtime.newString(contents[i]) );
}
}
else {
result = Collections.emptyList();
}

return result;
}

58 changes: 29 additions & 29 deletions core/src/main/java/org/jruby/RubyEncoding.java
Original file line number Diff line number Diff line change
@@ -117,28 +117,28 @@ public final Encoding getEncoding() {
if (encoding == null) encoding = getRuntime().getEncodingService().loadEncoding(name);
return encoding;
}

private static Encoding extractEncodingFromObject(IRubyObject obj) {
if (obj instanceof RubyEncoding) return ((RubyEncoding) obj).getEncoding();
if (obj instanceof RubySymbol) return ((RubySymbol) obj).asString().getEncoding();
if (obj instanceof EncodingCapable) return ((EncodingCapable) obj).getEncoding();

return null;
}

public static Encoding areCompatible(IRubyObject obj1, IRubyObject obj2) {
Encoding enc1 = extractEncodingFromObject(obj1);
Encoding enc2 = extractEncodingFromObject(obj2);

if (enc1 == null || enc2 == null) return null;
if (enc1 == enc2) return enc1;

if (obj2 instanceof RubyString && ((RubyString) obj2).getByteList().getRealSize() == 0) return enc1;
if (obj1 instanceof RubyString && ((RubyString) obj1).getByteList().getRealSize() == 0) {
return enc1.isAsciiCompatible() && obj2 instanceof RubyString &&
return enc1.isAsciiCompatible() && obj2 instanceof RubyString &&
((RubyString) obj2).isAsciiOnly() ? enc1 : enc2;
}

if (!enc1.isAsciiCompatible() || !enc2.isAsciiCompatible()) return null;

if (!(obj2 instanceof RubyString) && enc2 instanceof USASCIIEncoding) return enc1;
@@ -263,7 +263,7 @@ public static byte[] encodeUTF16(CharSequence str) {
}

public static byte[] encode(CharSequence cs, Charset charset) {
ByteBuffer buffer = charset.encode(cs.toString());
ByteBuffer buffer = charset.encode(CharBuffer.wrap(cs));
byte[] bytes = new byte[buffer.limit()];
buffer.get(bytes);
return bytes;
@@ -291,7 +291,7 @@ public static String decode(byte[] bytes, int start, int length, Charset charset
public static String decode(byte[] bytes, Charset charset) {
return charset.decode(ByteBuffer.wrap(bytes)).toString();
}

private static class UTF8Coder {
private final CharsetEncoder encoder = UTF8.newEncoder();
private final CharsetDecoder decoder = UTF8.newDecoder();
@@ -303,15 +303,15 @@ private static class UTF8Coder {
private final ByteBuffer byteBuffer = ByteBuffer.allocate(BUF_SIZE);
private final CharBuffer charBuffer = CharBuffer.allocate(BUF_SIZE);

public UTF8Coder() {
UTF8Coder() {
decoder.onMalformedInput(CodingErrorAction.REPLACE);
decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
}

public byte[] encode(CharSequence cs) {
public final byte[] encode(CharSequence cs) {
ByteBuffer buffer;
if (cs.length() > CHAR_THRESHOLD) {
buffer = UTF8.encode(cs.toString());
buffer = UTF8.encode(CharBuffer.wrap(cs));
} else {
buffer = byteBuffer;
CharBuffer cbuffer = charBuffer;
@@ -322,13 +322,13 @@ public byte[] encode(CharSequence cs) {
encoder.encode(cbuffer, buffer, true);
buffer.flip();
}

byte[] bytes = new byte[buffer.limit()];
buffer.get(bytes);
return bytes;
}
public String decode(byte[] bytes, int start, int length) {

public final String decode(byte[] bytes, int start, int length) {
CharBuffer cbuffer;
if (length > CHAR_THRESHOLD) {
cbuffer = UTF8.decode(ByteBuffer.wrap(bytes, start, length));
@@ -342,11 +342,11 @@ public String decode(byte[] bytes, int start, int length) {
decoder.decode(buffer, cbuffer, true);
cbuffer.flip();
}

return cbuffer.toString();
}
public String decode(byte[] bytes) {

public final String decode(byte[] bytes) {
return decode(bytes, 0, bytes.length);
}
}
@@ -366,7 +366,7 @@ private static UTF8Coder getUTF8Coder() {
ref = new SoftReference<UTF8Coder>(coder);
UTF8_CODER.set(ref);
}

return coder;
}

@@ -381,7 +381,7 @@ public static IRubyObject locale_charmap(ThreadContext context, IRubyObject recv
Ruby runtime = context.runtime;
EncodingService service = runtime.getEncodingService();
ByteList name = new ByteList(service.getLocaleEncoding().getName());

return RubyString.newUsAsciiStringNoCopy(runtime, name);
}

@@ -390,25 +390,25 @@ public static IRubyObject locale_charmap(ThreadContext context, IRubyObject recv
public static IRubyObject name_list(ThreadContext context, IRubyObject recv) {
Ruby runtime = context.runtime;
EncodingService service = runtime.getEncodingService();

RubyArray result = runtime.newArray(service.getEncodings().size() + service.getAliases().size());
HashEntryIterator i;
i = service.getEncodings().entryIterator();
while (i.hasNext()) {
CaseInsensitiveBytesHash.CaseInsensitiveBytesHashEntry<Entry> e =
CaseInsensitiveBytesHash.CaseInsensitiveBytesHashEntry<Entry> e =
((CaseInsensitiveBytesHash.CaseInsensitiveBytesHashEntry<Entry>)i.next());
result.append(RubyString.newUsAsciiStringShared(runtime, e.bytes, e.p, e.end - e.p).freeze(context));
}
i = service.getAliases().entryIterator();
i = service.getAliases().entryIterator();
while (i.hasNext()) {
CaseInsensitiveBytesHash.CaseInsensitiveBytesHashEntry<Entry> e =
CaseInsensitiveBytesHash.CaseInsensitiveBytesHashEntry<Entry> e =
((CaseInsensitiveBytesHash.CaseInsensitiveBytesHashEntry<Entry>)i.next());
result.append(RubyString.newUsAsciiStringShared(runtime, e.bytes, e.p, e.end - e.p).freeze(context));
}

result.append(runtime.newString(EXTERNAL));
result.append(runtime.newString(LOCALE));

return result;
}

@@ -423,10 +423,10 @@ public static IRubyObject aliases(ThreadContext context, IRubyObject recv) {
RubyHash result = RubyHash.newHash(runtime);

while (i.hasNext()) {
CaseInsensitiveBytesHash.CaseInsensitiveBytesHashEntry<Entry> e =
CaseInsensitiveBytesHash.CaseInsensitiveBytesHashEntry<Entry> e =
((CaseInsensitiveBytesHash.CaseInsensitiveBytesHashEntry<Entry>)i.next());
IRubyObject alias = RubyString.newUsAsciiStringShared(runtime, e.bytes, e.p, e.end - e.p).freeze(context);
IRubyObject name = RubyString.newUsAsciiStringShared(runtime,
IRubyObject name = RubyString.newUsAsciiStringShared(runtime,
((RubyEncoding)list[e.value.getIndex()]).name).freeze(context);
result.fastASet(alias, name);
}
@@ -496,23 +496,23 @@ public IRubyObject names(ThreadContext context) {
HashEntryIterator i;
i = service.getEncodings().entryIterator();
while (i.hasNext()) {
CaseInsensitiveBytesHash.CaseInsensitiveBytesHashEntry<Entry> e =
CaseInsensitiveBytesHash.CaseInsensitiveBytesHashEntry<Entry> e =
((CaseInsensitiveBytesHash.CaseInsensitiveBytesHashEntry<Entry>)i.next());
if (e.value == entry) {
result.append(RubyString.newUsAsciiStringShared(runtime, e.bytes, e.p, e.end - e.p).freeze(context));
}
}
i = service.getAliases().entryIterator();
i = service.getAliases().entryIterator();
while (i.hasNext()) {
CaseInsensitiveBytesHash.CaseInsensitiveBytesHashEntry<Entry> e =
CaseInsensitiveBytesHash.CaseInsensitiveBytesHashEntry<Entry> e =
((CaseInsensitiveBytesHash.CaseInsensitiveBytesHashEntry<Entry>)i.next());
if (e.value == entry) {
result.append(RubyString.newUsAsciiStringShared(runtime, e.bytes, e.p, e.end - e.p).freeze(context));
}
}
result.append(runtime.newString(EXTERNAL));
result.append(runtime.newString(LOCALE));

return result;
}

46 changes: 19 additions & 27 deletions core/src/main/java/org/jruby/RubyEnumerable.java
Original file line number Diff line number Diff line change
@@ -539,14 +539,23 @@ public int compare(IRubyObject[] o1, IRubyObject[] o2) {

@JRubyMethod
public static IRubyObject grep(ThreadContext context, IRubyObject self, final IRubyObject pattern, final Block block) {
return grep(context, self, pattern, block, true);
}

@JRubyMethod(name = "grep_v")
public static IRubyObject inverseGrep(ThreadContext context, IRubyObject self, final IRubyObject pattern, final Block block) {
return grep(context, self, pattern, block, false);
}

private static IRubyObject grep(ThreadContext context, IRubyObject self, final IRubyObject pattern, final Block block, final boolean isPresent) {
final Ruby runtime = context.runtime;
final RubyArray result = runtime.newArray();

if (block.isGiven()) {
callEach(runtime, context, self, block.getSignature(), new BlockCallback() {
callEach(runtime, context, self, Signature.ONE_REQUIRED, new BlockCallback() {
public IRubyObject call(ThreadContext ctx, IRubyObject[] largs, Block blk) {
IRubyObject larg = packEnumValues(ctx, largs);
if (pattern.callMethod(ctx, "===", larg).isTrue()) {
if (pattern.callMethod(ctx, "===", larg).isTrue() == isPresent) {
IRubyObject value = block.yield(ctx, larg);
synchronized (result) {
result.append(value);
@@ -559,7 +568,7 @@ public IRubyObject call(ThreadContext ctx, IRubyObject[] largs, Block blk) {
callEach(runtime, context, self, Signature.ONE_REQUIRED, new BlockCallback() {
public IRubyObject call(ThreadContext ctx, IRubyObject[] largs, Block blk) {
IRubyObject larg = packEnumValues(ctx, largs);
if (pattern.callMethod(ctx, "===", larg).isTrue()) {
if (pattern.callMethod(ctx, "===", larg).isTrue() == isPresent ) {
synchronized (result) {
result.append(larg);
}
@@ -571,7 +580,6 @@ public IRubyObject call(ThreadContext ctx, IRubyObject[] largs, Block blk) {

return result;
}

public static IRubyObject detectCommon(ThreadContext context, IRubyObject self, final Block block) {
return detectCommon(context, self, null, block);
}
@@ -1867,8 +1875,6 @@ public static IRubyObject chunk(ThreadContext context, IRubyObject self, final I
switch (Arity.checkArgumentCount(context.runtime, args, 0, 1)) {
case 0:
return chunk(context, self, block);
case 1:
return chunk(context, self, args[0], block);
default:
// should never be reached
throw context.runtime.newArgumentError(args.length, 0);
@@ -1877,19 +1883,13 @@ public static IRubyObject chunk(ThreadContext context, IRubyObject self, final I

@JRubyMethod
public static IRubyObject chunk(ThreadContext context, IRubyObject self, final Block block) {
return chunk(context, self, context.nil, block);
}

@JRubyMethod
public static IRubyObject chunk(ThreadContext context, IRubyObject self, final IRubyObject initialState, final Block block) {
if(!block.isGiven()) {
throw context.runtime.newArgumentError("no block given");
}

IRubyObject enumerator = context.runtime.getEnumerator().allocate();
enumerator.getInternalVariables().setInternalVariable("chunk_enumerable", self);
enumerator.getInternalVariables().setInternalVariable("chunk_categorize", RubyProc.newProc(context.runtime, block, block.type));
enumerator.getInternalVariables().setInternalVariable("chunk_initial_state", initialState);

Helpers.invoke(context, enumerator, "initialize",
CallBlock.newCallClosure(self, context.runtime.getEnumerable(), Signature.ONE_ARGUMENT,
@@ -1908,13 +1908,10 @@ public IRubyObject size(IRubyObject[] args) {

private static class ChunkArg {

private ChunkArg(final ThreadContext context, IRubyObject state) {
this.state = state;
private ChunkArg(final ThreadContext context) {
this.prev_elts = this.prev_value = context.nil;
}

final IRubyObject state;

IRubyObject prev_value;
IRubyObject prev_elts;

@@ -1934,9 +1931,8 @@ public IRubyObject call(ThreadContext context, IRubyObject[] args, Block block)
InternalVariables variables = enumerator.getInternalVariables();
final IRubyObject enumerable = (IRubyObject) variables.getInternalVariable("chunk_enumerable");
final RubyProc categorize = (RubyProc) variables.getInternalVariable("chunk_categorize");
final IRubyObject state = (IRubyObject) variables.getInternalVariable("chunk_initial_state");
final IRubyObject yielder = packEnumValues(context, args);
final ChunkArg arg = new ChunkArg(context, (state.isNil() ? null : state.dup()));
final ChunkArg arg = new ChunkArg(context);

final RubySymbol alone = runtime.newSymbol("_alone");
final RubySymbol separator = runtime.newSymbol("_separator");
@@ -1945,16 +1941,12 @@ public IRubyObject call(ThreadContext context, IRubyObject[] args, Block block)
public IRubyObject call(ThreadContext ctx, IRubyObject[] largs, Block blk) {
final IRubyObject larg = packEnumValues(ctx, largs);
final IRubyObject v;
if ( arg.state == null ) {
if ( categorize.getBlock().getSignature().arityValue() == 1 ) {
// if chunk's categorize block has arity one, we pass it the packed args
v = categorize.callMethod(ctx, "call", larg);
} else {
// else we let it spread the args as it sees fit for its arity
v = categorize.callMethod(ctx, "call", largs);
}
if ( categorize.getBlock().getSignature().arityValue() == 1 ) {
// if chunk's categorize block has arity one, we pass it the packed args
v = categorize.callMethod(ctx, "call", larg);
} else {
v = categorize.callMethod(ctx, "call", new IRubyObject[]{ larg, arg.state });
// else we let it spread the args as it sees fit for its arity
v = categorize.callMethod(ctx, "call", largs);
}

if ( v == alone ) {
47 changes: 23 additions & 24 deletions core/src/main/java/org/jruby/RubyException.java
Original file line number Diff line number Diff line change
@@ -70,14 +70,13 @@ public RubyException(Ruby runtime, RubyClass rubyClass, String message) {
super(runtime, rubyClass);

this.message = message == null ? runtime.getNil() : runtime.newString(message);
this.cause = RubyBasicObject.UNDEF;
}

@JRubyMethod(optional = 2, visibility = PRIVATE)
public IRubyObject initialize(IRubyObject[] args, Block block) {
if (args.length == 1) message = args[0];

IRubyObject errinfo = getRuntime().getCurrentContext().getErrorInfo();
if (!errinfo.isNil()) cause = errinfo;
if ( args.length == 1 ) message = args[0];
// cause filled in at RubyKernel#raise ... Exception.new does not fill-in cause!
return this;
}

@@ -100,7 +99,7 @@ private void setBacktrace(IRubyObject obj) {
} else if (obj instanceof RubyString) {
backtrace = RubyArray.newArray(getRuntime(), obj);
} else {
throw getRuntime().newTypeError("backtrace must be Array of String or a single String");
throw getRuntime().newTypeError("backtrace must be Array of String");
}
}

@@ -123,10 +122,8 @@ public RubyException exception(IRubyObject[] args) {
case 0 :
return this;
case 1 :
if(args[0] == this) {
return this;
}
RubyException ret = (RubyException)rbClone();
if (args[0] == this) return this;
RubyException ret = (RubyException) rbClone();
ret.initialize(args, Block.NULL_BLOCK); // This looks wrong, but it's the way MRI does it.
return ret;
default :
@@ -136,12 +133,15 @@ public RubyException exception(IRubyObject[] args) {

@JRubyMethod(name = "to_s")
public IRubyObject to_s(ThreadContext context) {
if (message.isNil()) return context.runtime.newString(getMetaClass().getRealClass().getName());

message.setTaint(isTaint());
if (message.isNil()) {
return context.runtime.newString(getMetaClass().getRealClass().getName());
}
return message.asString();
}

@Deprecated
public IRubyObject to_s19(ThreadContext context) { return to_s(context); }

@JRubyMethod(name = "message")
public IRubyObject message(ThreadContext context) {
return callMethod(context, "to_s");
@@ -195,15 +195,22 @@ public static IRubyObject op_eqq(ThreadContext context, IRubyObject recv, IRubyO

@JRubyMethod(name = "cause")
public IRubyObject cause(ThreadContext context) {
IRubyObject nil = context.nil;
if (cause != nil) return cause;
return nil;
assert cause != null;

if (cause == RubyBasicObject.UNDEF) return context.nil;

return cause;
}

public void setCause(IRubyObject cause) {
this.cause = cause;
}

// NOTE: can not have IRubyObject as NativeException has getCause() returning Throwable
public Object getCause() {
return cause;
}

public void setBacktraceData(BacktraceData backtraceData) {
this.backtraceData = backtraceData;
}
@@ -380,22 +387,14 @@ public static IRubyObject newException(ThreadContext context, RubyClass exceptio
return exceptionClass.callMethod(context, "new", message.convertToString());
}

@Deprecated
public IRubyObject to_s19(ThreadContext context) {
if (message.isNil()) return context.runtime.newString(getMetaClass().getRealClass().getName());

message.setTaint(isTaint());
return message.asString();
}

public IRubyObject getMessage() {
return message;
}

private BacktraceData backtraceData;
private IRubyObject backtrace;
public IRubyObject message;
private IRubyObject cause = getRuntime().getNil();
IRubyObject cause;

public static final int TRACE_HEAD = 8;
public static final int TRACE_TAIL = 4;
34 changes: 30 additions & 4 deletions core/src/main/java/org/jruby/RubyFile.java
Original file line number Diff line number Diff line change
@@ -171,6 +171,8 @@ public static RubyClass createFileClass(Ruby runtime) {
/* disable line code conversion */
constants.setConstant("BINARY", runtime.newFixnum(OpenFlags.O_BINARY.intValue()));
}
// FIXME: Need Windows value for this
constants.setConstant("SHARE_DELETE", runtime.newFixnum(0));
if (OpenFlags.O_SYNC.defined()) {
/* any write operation perform synchronously */
constants.setConstant("SYNC", runtime.newFixnum(OpenFlags.O_SYNC.intValue()));
@@ -222,6 +224,8 @@ public static RubyClass createFileClass(Ruby runtime) {
// readlink is not available on Windows. See below and jruby/jruby#3287.
// TODO: MRI does not implement readlink on Windows, but perhaps we could?
fileClass.searchMethod("readlink").setNotImplemented(true);

fileClass.searchMethod("mkfifo").setNotImplemented(true);
}

return fileClass;
@@ -1217,6 +1221,30 @@ public IRubyObject size(ThreadContext context) {
return RubyFixnum.newFixnum(runtime, size);
}

@JRubyMethod(meta = true)
public static IRubyObject mkfifo(ThreadContext context, IRubyObject recv, IRubyObject path) {
if (Platform.IS_WINDOWS) throw context.runtime.newNotImplementedError("mkfifo");

return mkfifo(context, get_path(context, path), 0666);
}

@JRubyMethod(meta = true)
public static IRubyObject mkfifo(ThreadContext context, IRubyObject recv, IRubyObject path, IRubyObject mode) {
if (Platform.IS_WINDOWS) throw context.runtime.newNotImplementedError("mkfifo");

return mkfifo(context, get_path(context, path), RubyNumeric.num2int(mode));
}

public static IRubyObject mkfifo(ThreadContext context, RubyString path, int mode) {
Ruby runtime = context.runtime;
String decodedPath = JRubyFile.createResource(runtime, path.toString()).absolutePath();

if (runtime.getPosix().mkfifo(decodedPath, mode) != 0) {
throw runtime.newErrnoFromInt(runtime.getPosix().errno(), decodedPath);
}
return RubyFixnum.zero(runtime);
}

public String getPath() {
if (openFile == null) return null;
return openFile.getPath();
@@ -1371,10 +1399,8 @@ public static FileResource fileResource(ThreadContext context, IRubyObject pathO
public static FileResource fileResource(IRubyObject pathOrFile) {
Ruby runtime = pathOrFile.getRuntime();

if (pathOrFile instanceof RubyFile) {
return JRubyFile.createResource(runtime, ((RubyFile) pathOrFile).getPath());
} else if (pathOrFile instanceof RubyIO) {
return JRubyFile.createResource(runtime, ((RubyIO) pathOrFile).openFile.getPath());
if (pathOrFile instanceof RubyIO) {
return JRubyFile.createResource(runtime, ((RubyIO) pathOrFile).getOpenFileChecked().getPath());
}

ThreadContext context = runtime.getCurrentContext();
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/RubyGlobal.java
Original file line number Diff line number Diff line change
@@ -750,7 +750,7 @@ public IRubyObject get() {
@Override
public IRubyObject set(IRubyObject value) {
if (runtime.getGlobalVariables().get("$!").isNil()) {
throw runtime.newArgumentError("$! not set.");
throw runtime.newArgumentError("$! not set");
}
runtime.getGlobalVariables().get("$!").callMethod(value.getRuntime().getCurrentContext(), "set_backtrace", value);
return value;
184 changes: 173 additions & 11 deletions core/src/main/java/org/jruby/RubyHash.java
Original file line number Diff line number Diff line change
@@ -38,8 +38,6 @@
***** END LICENSE BLOCK *****/
package org.jruby;

import static org.jruby.RubyEnumerator.enumeratorize;

import org.jcodings.specific.USASCIIEncoding;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
@@ -48,6 +46,7 @@
import org.jruby.javasupport.JavaUtil;
import org.jruby.runtime.Arity;
import org.jruby.runtime.Block;
import org.jruby.runtime.BlockBody;
import org.jruby.runtime.ClassIndex;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.ObjectAllocator;
@@ -234,24 +233,24 @@ public static final RubyHash newHash(Ruby runtime, Map valueMap, IRubyObject def

private RubyHash(Ruby runtime, RubyClass klass, RubyHash other) {
super(runtime, klass);
this.ifNone = runtime.getNil();
this.ifNone = UNDEF;
threshold = INITIAL_THRESHOLD;
table = other.internalCopyTable(head);
size = other.size;
}

public RubyHash(Ruby runtime, RubyClass klass) {
super(runtime, klass);
this.ifNone = runtime.getNil();
this.ifNone = UNDEF;
allocFirst();
}

public RubyHash(Ruby runtime, int buckets) {
this(runtime, runtime.getNil(), buckets);
this(runtime, UNDEF, buckets);
}

public RubyHash(Ruby runtime) {
this(runtime, runtime.getNil());
this(runtime, UNDEF);
}

public RubyHash(Ruby runtime, IRubyObject defaultValue) {
@@ -708,15 +707,15 @@ public IRubyObject default_value_get(ThreadContext context) {
if ((flags & PROCDEFAULT_HASH_F) != 0) {
return context.nil;
}
return ifNone;
return ifNone == UNDEF ? context.nil : ifNone;
}

@JRubyMethod(name = "default")
public IRubyObject default_value_get(ThreadContext context, IRubyObject arg) {
if ((flags & PROCDEFAULT_HASH_F) != 0) {
return Helpers.invoke(context, ifNone, "call", this, arg);
}
return ifNone;
return ifNone == UNDEF ? context.nil : ifNone;
}

/** rb_hash_set_default
@@ -899,6 +898,110 @@ public void visit(IRubyObject key, IRubyObject value) {
}
}

@JRubyMethod(name = "to_proc")
public RubyProc to_proc(ThreadContext context) {
final Ruby runtime = context.runtime;
return new RubyProc(runtime, runtime.getProc(), new HashBlock(), null, -1);
}

private class HashBlock extends Block {

HashBlock() {
super(BlockBody.NULL_BODY);
this.type = Block.Type.PROC;
}

private void checkArity(ThreadContext context, IRubyObject... args) {
// acts like a Proc but validate args like a lambda :
Signature.ONE_ARGUMENT.checkArity(context.runtime, args);
}

@Override
public Signature getSignature() {
return Signature.ONE_ARGUMENT;
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject[] args) {
checkArity(context, args);
return op_aref(context, args[0]);
}
@Override
public IRubyObject call(ThreadContext context, IRubyObject[] args, Block blockArg) {
return call(context, args);
}

@Override
public IRubyObject call(ThreadContext context) {
checkArity(context); // fails
throw new AssertionError();
}
@Override
public IRubyObject call(ThreadContext context, Block blockArg) {
return call(context);
}
@Override
public IRubyObject yieldSpecific(ThreadContext context) {
return call(context);
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject arg0) {
return op_aref(context, arg0);
}
@Override
public IRubyObject call(ThreadContext context, IRubyObject arg0, Block blockArg) {
return call(context, arg0);
}
@Override
public IRubyObject yieldSpecific(ThreadContext context, IRubyObject arg0) {
return call(context, arg0);
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject arg0, IRubyObject arg1) {
checkArity(context, arg0, arg1); // fails
throw new AssertionError();
}
@Override
public IRubyObject call(ThreadContext context, IRubyObject arg0, IRubyObject arg1, Block blockArg) {
return call(context, arg0, arg1);
}
@Override
public IRubyObject yieldSpecific(ThreadContext context, IRubyObject arg0, IRubyObject arg1) {
return call(context, arg0, arg1); // fails
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2) {
checkArity(context, arg0, arg1, arg2); // fails
throw new AssertionError();
}
@Override
public IRubyObject call(ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block blockArg) {
return call(context, arg0, arg1, arg2);
}
@Override
public IRubyObject yieldSpecific(ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2) {
return call(context, arg0, arg1, arg2); // fails
}

@Override
public IRubyObject yield(ThreadContext context, IRubyObject value) {
return op_aref(context, value);
}
@Override
public IRubyObject yieldNonArray(ThreadContext context, IRubyObject value, IRubyObject self) {
return yield(context, value);
}

@Override
public IRubyObject yieldArray(ThreadContext context, IRubyObject value, IRubyObject self) {
throw new UnsupportedOperationException();
}

}

/** rb_hash_to_s & to_s_hash
*
*/
@@ -1105,6 +1208,45 @@ public IRubyObject op_aref(ThreadContext context, IRubyObject key) {
return ((value = internalGet(key)) == null) ? invokedynamic(context, this, DEFAULT, key) : value;
}

/** hash_le_i
*
*/
private boolean hash_le(RubyHash other) {
return other.directEntrySet().containsAll(directEntrySet());
}

@JRubyMethod(name = "<", required = 1)
public IRubyObject op_lt(ThreadContext context, IRubyObject other) {
final RubyHash otherHash = other.convertToHash();
if (size() >= otherHash.size()) {
return RubyBoolean.newBoolean(context.runtime, false);
}

return RubyBoolean.newBoolean(context.runtime, hash_le(otherHash));
}

@JRubyMethod(name = "<=", required = 1)
public IRubyObject op_le(ThreadContext context, IRubyObject other) {
final RubyHash otherHash = other.convertToHash();
if (size() > otherHash.size()) {
return RubyBoolean.newBoolean(context.runtime, false);
}

return RubyBoolean.newBoolean(context.runtime, hash_le(otherHash));
}

@JRubyMethod(name = ">", required = 1)
public IRubyObject op_gt(ThreadContext context, IRubyObject other) {
final RubyHash otherHash = other.convertToHash();
return otherHash.op_lt(context, this);
}

@JRubyMethod(name = ">=", required = 1)
public IRubyObject op_ge(ThreadContext context, IRubyObject other) {
final RubyHash otherHash = other.convertToHash();
return otherHash.op_le(context, this);
}

/** rb_hash_hash
*
*/
@@ -1542,7 +1684,7 @@ public IRubyObject shift(ThreadContext context) {
if ((flags & PROCDEFAULT_HASH_F) != 0) {
return this.callMethod(context, "default", context.nil);
}
return ifNone;
return ifNone == UNDEF ? context.nil : ifNone;
}

public final boolean fastDelete(IRubyObject key) {
@@ -1780,13 +1922,23 @@ private RubyHash replaceCommon19(final ThreadContext context, IRubyObject other,
*/
@JRubyMethod(name = "values_at", rest = true)
public RubyArray values_at(ThreadContext context, IRubyObject[] args) {
RubyArray result = RubyArray.newArray(getRuntime(), args.length);
RubyArray result = RubyArray.newArray(context.runtime, args.length);
for (int i = 0; i < args.length; i++) {
result.append(op_aref(context, args[i]));
}
return result;
}

@JRubyMethod(name = "fetch_values", rest = true)
public RubyArray fetch_values(ThreadContext context, IRubyObject[] args, Block block) {
RubyArray result = RubyArray.newArray(context.runtime, args.length);

for (int i = 0; i < args.length; i++) {
result.append(fetch(context, args[i], block));
}
return result;
}

@JRubyMethod(name = "assoc")
public IRubyObject assoc(final ThreadContext context, final IRubyObject obj) {
try {
@@ -1932,6 +2084,16 @@ public IRubyObject getIfNone(){
return ifNone;
}

@JRubyMethod(name = "dig", required = 1, rest = true)
public IRubyObject dig(ThreadContext context, IRubyObject[] args) {
return dig(context, args, 0);
}

final IRubyObject dig(ThreadContext context, IRubyObject[] args, int idx) {
final IRubyObject val = op_aref( context, args[idx++] );
return idx == args.length ? val : RubyObject.dig(context, val, args, idx);
}

private static class VisitorIOException extends RuntimeException {
VisitorIOException(Throwable cause) {
super(cause);
@@ -1959,7 +2121,7 @@ public void visit(IRubyObject key, IRubyObject value) {
throw (IOException)e.getCause();
}

if (!hash.ifNone.isNil()) output.dumpObject(hash.ifNone);
if (hash.ifNone != UNDEF) output.dumpObject(hash.ifNone);
}

public static RubyHash unmarshalFrom(UnmarshalStream input, boolean defaultValue) throws IOException {
99 changes: 46 additions & 53 deletions core/src/main/java/org/jruby/RubyIO.java
Original file line number Diff line number Diff line change
@@ -270,10 +270,17 @@ public OpenFile getOpenFile() {
}

public OpenFile getOpenFileChecked() {
checkInitialized();
openFile.checkClosed();
return openFile;
}

// MRI: rb_io_get_fptr
public OpenFile getOpenFileInitialized() {
checkInitialized();
return openFile;
}

private static ObjectAllocator IO_ALLOCATOR = new ObjectAllocator() {
@Override
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
@@ -1330,18 +1337,12 @@ public IRubyObject write_nonblock(ThreadContext context, IRubyObject[] argv) {
Ruby runtime = context.runtime;
IRubyObject str;
IRubyObject opts = context.nil;
boolean no_exceptions = false;

int argc = Arity.checkArgumentCount(context, argv, 1, 2);
if (argc == 2) {
opts = argv[1].convertToHash();
}
str = argv[0];
boolean exception = ArgsUtil.extractKeywordArg(context, "exception", argv) != runtime.getFalse();

if (!opts.isNil() && runtime.getFalse() == ((RubyHash)opts).op_aref(context, runtime.newSymbol("exception")))
no_exceptions = true;
str = argv[0];

return ioWriteNonblock(context, runtime, str, no_exceptions);
return ioWriteNonblock(context, runtime, str, !exception);
}

// MRI: io_write_nonblock
@@ -1941,14 +1942,16 @@ public boolean isClosed() {
* <p>Closes all open resources for the IO. It also removes
* it from our magical all open file descriptor pool.</p>
*
* @return The IO.
* @return The IO. Returns nil if the IO was already closed.
*
* MRI: rb_io_close_m
*/
@JRubyMethod
public IRubyObject close() {
Ruby runtime = getRuntime();

if (isClosed()) {
return runtime.getNil();
}
openFile.checkClosed();
return rbIoClose(runtime);
}
@@ -2038,7 +2041,9 @@ public IRubyObject close_write(ThreadContext context) {
RubyIO write_io;

write_io = GetWriteIO();
fptr = write_io.getOpenFileChecked();
fptr = write_io.getOpenFileInitialized();
if (!fptr.isOpen()) return context.nil;

boolean locked = fptr.lock();
try {
if (fptr.socketChannel() != null) {
@@ -2053,7 +2058,7 @@ public IRubyObject close_write(ThreadContext context) {
return context.nil;
}

if (fptr.isReadable()) {
if (fptr.isReadable() && !fptr.isDuplex()) {
throw runtime.newIOError("closing non-duplex IO for writing");
}
} finally {
@@ -2062,12 +2067,11 @@ public IRubyObject close_write(ThreadContext context) {


if (this != write_io) {
fptr = getOpenFileChecked();
fptr = getOpenFileInitialized();

locked = fptr.lock();
try {
fptr.tiedIOForWriting = null;
fptr.setMode(fptr.getMode() & ~OpenFile.DUPLEX);
} finally {
if (locked) fptr.unlock();
}
@@ -2083,7 +2087,8 @@ public IRubyObject close_read(ThreadContext context) {
OpenFile fptr;
RubyIO write_io;

fptr = getOpenFileChecked();
fptr = getOpenFileInitialized();
if (!fptr.isOpen()) return context.nil;

boolean locked = fptr.lock();
try {
@@ -2102,7 +2107,7 @@ public IRubyObject close_read(ThreadContext context) {
write_io = GetWriteIO();
if (this != write_io) {
OpenFile wfptr;
wfptr = write_io.getOpenFileChecked();
wfptr = write_io.getOpenFileInitialized();

boolean locked2 = wfptr.lock();
try {
@@ -2113,7 +2118,6 @@ public IRubyObject close_read(ThreadContext context) {
this.openFile = wfptr;
/* bind to write_io temporarily to get rid of memory/fd leak */
fptr.tiedIOForWriting = null;
fptr.setMode(fptr.getMode() & ~OpenFile.DUPLEX);
write_io.openFile = fptr;
fptr.cleanup(runtime, false);
/* should not finalize fptr because another thread may be reading it */
@@ -2123,7 +2127,7 @@ public IRubyObject close_read(ThreadContext context) {
}
}

if (fptr.isWritable()) {
if (fptr.isWritable() && !fptr.isDuplex()) {
throw runtime.newIOError("closing non-duplex IO for reading");
}
} finally {
@@ -2763,25 +2767,19 @@ public IRubyObject read_nonblock(ThreadContext context, IRubyObject[] args) {

// MRI: io_read_nonblock
public IRubyObject doReadNonblock(ThreadContext context, IRubyObject[] args, boolean useException) {
Ruby runtime = context.runtime;
IRubyObject ret;
IRubyObject opts;
boolean no_exception = !useException;
final Ruby runtime = context.runtime;

opts = ArgsUtil.getOptionsArg(runtime, args);
boolean exception = ArgsUtil.extractKeywordArg(context, "exception", args) != runtime.getFalse();

if (!opts.isNil() && runtime.getFalse() == ((RubyHash)opts).op_aref(context, runtime.newSymbol("exception")))
no_exception = true;
IRubyObject ret = getPartial(context, args, true, !exception);

ret = getPartial(context, args, true, no_exception);
return ret.isNil() ? nonblockEOF(runtime, !exception) : ret;
}

if (ret.isNil()) {
if (no_exception)
return ret;
else
throw runtime.newEOFError();
}
return ret;
// MRI: io_nonblock_eof(VALUE opts)
static IRubyObject nonblockEOF(final Ruby runtime, final boolean noException) {
if ( noException ) return runtime.getNil();
throw runtime.newEOFError();
}

@JRubyMethod(name = "readpartial", required = 1, optional = 1)
@@ -2796,11 +2794,10 @@ public IRubyObject readpartial(ThreadContext context, IRubyObject[] args) {
}

// MRI: io_getpartial
private IRubyObject getPartial(ThreadContext context, IRubyObject[] args, boolean nonblock, boolean noException) {
IRubyObject getPartial(ThreadContext context, IRubyObject[] args, boolean nonblock, boolean noException) {
Ruby runtime = context.runtime;
OpenFile fptr;
IRubyObject length, str;
int n, len;

switch (args.length) {
case 3:
@@ -2822,7 +2819,8 @@ private IRubyObject getPartial(ThreadContext context, IRubyObject[] args, boolea
str = context.nil;
}

if ((len = RubyNumeric.num2int(length)) < 0) {
final int len;
if ( ( len = RubyNumeric.num2int(length) ) < 0 ) {
throw runtime.newArgumentError("negative length " + len + " given");
}

@@ -2831,15 +2829,14 @@ private IRubyObject getPartial(ThreadContext context, IRubyObject[] args, boolea

fptr = getOpenFileChecked();

boolean locked = fptr.lock();
final boolean locked = fptr.lock(); int n;
try {
fptr.checkByteReadable(context);

if (len == 0)
return str;
if ( len == 0 ) return str;

if ( ! nonblock ) fptr.READ_CHECK(context);

if (!nonblock)
fptr.READ_CHECK(context);
ByteList strByteList = ((RubyString) str).getByteList();
n = fptr.readBufferedData(strByteList.unsafeBytes(), strByteList.begin(), len);
if (n <= 0) {
@@ -2860,26 +2857,22 @@ private IRubyObject getPartial(ThreadContext context, IRubyObject[] args, boolea
if (!nonblock && fptr.waitReadable(context))
continue again;
if (nonblock && (fptr.errno() == Errno.EWOULDBLOCK || fptr.errno() == Errno.EAGAIN)) {
if (noException)
return runtime.newSymbol("wait_readable");
else
throw runtime.newErrnoEAGAINReadableError("read would block");
if (noException) return runtime.newSymbol("wait_readable");
throw runtime.newErrnoEAGAINReadableError("read would block");
}
throw runtime.newEOFError(fptr.getPath());
}
break;
}
}
} finally {
if (locked) fptr.unlock();
}
finally {
if ( locked ) fptr.unlock();
}

((RubyString)str).setReadLength(n);
((RubyString) str).setReadLength(n);

if (n == 0)
return context.nil;
else
return str;
return n == 0 ? context.nil : str;
}

// MRI: rb_io_sysread
34 changes: 33 additions & 1 deletion core/src/main/java/org/jruby/RubyInstanceConfig.java
Original file line number Diff line number Diff line change
@@ -1185,6 +1185,13 @@ public boolean isDisableGems() {
return disableGems;
}

/**
* @see Options#CLI_DID_YOU_MEAN_ENABLE
*/
public boolean isDisableDidYouMean() {
return disableDidYouMean;
}

/**
* @see Options#CLI_RUBYOPT_ENABLE
*/
@@ -1199,6 +1206,13 @@ public void setDisableGems(boolean dg) {
this.disableGems = dg;
}

/**
* @see Options#CLI_DID_YOU_MEAN_ENABLE
*/
public void setDisableDidYouMean(boolean ddym) {
this.disableDidYouMean = ddym;
}

/**
* @see Options#BACKTRACE_STYLE
*/
@@ -1440,6 +1454,22 @@ public void setProfilingService( String service ) {
this.profilingService = service;
}

public boolean isFrozenStringLiteral() {
return frozenStringLiteral;
}

public void setFrozenStringLiteral(boolean frozenStringLiteral) {
this.frozenStringLiteral = frozenStringLiteral;
}

public boolean isDebuggingFrozenStringLiteral() {
return debuggingFrozenStringLiteral;
}

public void setDebuggingFrozenStringLiteral(boolean debuggingFrozenStringLiteral) {
this.debuggingFrozenStringLiteral = debuggingFrozenStringLiteral;
}

public static ClassLoader defaultClassLoader() {
ClassLoader loader = RubyInstanceConfig.class.getClassLoader();

@@ -1534,12 +1564,14 @@ public ClassLoader getCurrentThreadClassLoader() {
private String threadDumpSignal = null;
private boolean hardExit = false;
private boolean disableGems = !Options.CLI_RUBYGEMS_ENABLE.load();
private boolean disableDidYouMean = !Options.CLI_DID_YOU_MEAN_ENABLE.load();
private boolean disableRUBYOPT = !Options.CLI_RUBYOPT_ENABLE.load();
private boolean updateNativeENVEnabled = true;
private boolean kernelGsubDefined;
private boolean hasScriptArgv = false;
private boolean preferIPv4 = Options.PREFER_IPV4.load();

private boolean frozenStringLiteral = false;
private boolean debuggingFrozenStringLiteral = false;
private String jrubyHome;

/**
285 changes: 145 additions & 140 deletions core/src/main/java/org/jruby/RubyKernel.java

Large diffs are not rendered by default.

68 changes: 28 additions & 40 deletions core/src/main/java/org/jruby/RubyMath.java
Original file line number Diff line number Diff line change
@@ -87,27 +87,15 @@ public static double sign(double x, double y) {
double abs = ((x < 0) ? -x : x);
return (y < 0.0) ? -abs : abs;
}

private static RubyFloat needFloat(IRubyObject x) {
if (x instanceof RubyFloat) {
return (RubyFloat)x;
}

if (!x.getRuntime().getNumeric().isInstance(x)) {
TypeConverter.handleUncoercibleObject(true, x, x.getRuntime().getFloat());
}

return (RubyFloat) TypeConverter.convertToType19(x, x.getRuntime().getFloat(), "to_f", true);
}

public static RubyFloat atan2(ThreadContext context, IRubyObject recv, IRubyObject x, IRubyObject y) {
return atan219(context, recv, x, y);
}

@JRubyMethod(name = "atan2", required = 2, module = true, visibility = Visibility.PRIVATE)
public static RubyFloat atan219(ThreadContext context, IRubyObject recv, IRubyObject x, IRubyObject y) {
double valuea = needFloat(x).getDoubleValue();
double valueb = needFloat(y).getDoubleValue();
double valuea = RubyNumeric.num2dbl(x);
double valueb = RubyNumeric.num2dbl(y);

return RubyFloat.newFloat(context.runtime, Math.atan2(valuea, valueb));
}
@@ -118,7 +106,7 @@ public static RubyFloat cos(ThreadContext context, IRubyObject recv, IRubyObject

@JRubyMethod(name = "cos", required = 1, module = true, visibility = Visibility.PRIVATE)
public static RubyFloat cos19(ThreadContext context, IRubyObject recv, IRubyObject x) {
return RubyFloat.newFloat(context.runtime, Math.cos(needFloat(x).getDoubleValue()));
return RubyFloat.newFloat(context.runtime, Math.cos(RubyNumeric.num2dbl(x)));
}

public static RubyFloat sin(ThreadContext context, IRubyObject recv, IRubyObject x) {
@@ -127,7 +115,7 @@ public static RubyFloat sin(ThreadContext context, IRubyObject recv, IRubyObject

@JRubyMethod(name = "sin", required = 1, module = true, visibility = Visibility.PRIVATE)
public static RubyFloat sin19(ThreadContext context, IRubyObject recv, IRubyObject x) {
return RubyFloat.newFloat(context.runtime, Math.sin(needFloat(x).getDoubleValue()));
return RubyFloat.newFloat(context.runtime, Math.sin(RubyNumeric.num2dbl(x)));
}

public static RubyFloat tan(ThreadContext context, IRubyObject recv, IRubyObject x) {
@@ -136,7 +124,7 @@ public static RubyFloat tan(ThreadContext context, IRubyObject recv, IRubyObjec

@JRubyMethod(name = "tan", required = 1, module = true, visibility = Visibility.PRIVATE)
public static RubyFloat tan19(ThreadContext context, IRubyObject recv, IRubyObject x) {
return RubyFloat.newFloat(context.runtime, Math.tan(needFloat(x).getDoubleValue()));
return RubyFloat.newFloat(context.runtime, Math.tan(RubyNumeric.num2dbl(x)));
}

public static RubyFloat asin(ThreadContext context, IRubyObject recv, IRubyObject x) {
@@ -145,7 +133,7 @@ public static RubyFloat asin(ThreadContext context, IRubyObject recv, IRubyObjec

@JRubyMethod(name = "asin", required = 1, module = true, visibility = Visibility.PRIVATE)
public static RubyFloat asin19(ThreadContext context, IRubyObject recv, IRubyObject x) {
double value = needFloat(x).getDoubleValue();
double value = RubyNumeric.num2dbl(x);

if (value < -1.0 || value > 1.0) throw context.runtime.newMathDomainError("asin");

@@ -158,7 +146,7 @@ public static RubyFloat acos(ThreadContext context, IRubyObject recv, IRubyObjec

@JRubyMethod(name = "acos", required = 1, module = true, visibility = Visibility.PRIVATE)
public static RubyFloat acos19(ThreadContext context, IRubyObject recv, IRubyObject x) {
double value = needFloat(x).getDoubleValue();
double value = RubyNumeric.num2dbl(x);

if (value < -1.0 || value > 1.0) throw context.runtime.newMathDomainError("acos");

@@ -171,7 +159,7 @@ public static RubyFloat atan(ThreadContext context, IRubyObject recv, IRubyObjec

@JRubyMethod(name = "atan", required = 1, module = true, visibility = Visibility.PRIVATE)
public static RubyFloat atan19(ThreadContext context, IRubyObject recv, IRubyObject x) {
return RubyFloat.newFloat(context.runtime, Math.atan(needFloat(x).getDoubleValue()));
return RubyFloat.newFloat(context.runtime, Math.atan(RubyNumeric.num2dbl(x)));
}

public static RubyFloat cosh(ThreadContext context, IRubyObject recv, IRubyObject x) {
@@ -180,7 +168,7 @@ public static RubyFloat cosh(ThreadContext context, IRubyObject recv, IRubyObjec

@JRubyMethod(name = "cosh", required = 1, module = true, visibility = Visibility.PRIVATE)
public static RubyFloat cosh19(ThreadContext context, IRubyObject recv, IRubyObject x) {
double value = needFloat(x).getDoubleValue();
double value = RubyNumeric.num2dbl(x);

return RubyFloat.newFloat(context.runtime, (Math.exp(value) + Math.exp(-value)) / 2.0);
}
@@ -191,7 +179,7 @@ public static RubyFloat sinh(ThreadContext context, IRubyObject recv, IRubyObjec

@JRubyMethod(name = "sinh", required = 1, module = true, visibility = Visibility.PRIVATE)
public static RubyFloat sinh19(ThreadContext context, IRubyObject recv, IRubyObject x) {
double value = needFloat(x).getDoubleValue();
double value = RubyNumeric.num2dbl(x);

return RubyFloat.newFloat(context.runtime, (Math.exp(value) - Math.exp(-value)) / 2.0);
}
@@ -202,7 +190,7 @@ public static RubyFloat tanh(ThreadContext context, IRubyObject recv, IRubyObjec

@JRubyMethod(name = "tanh", required = 1, module = true, visibility = Visibility.PRIVATE)
public static RubyFloat tanh19(ThreadContext context, IRubyObject recv, IRubyObject x) {
return RubyFloat.newFloat(context.runtime, Math.tanh(needFloat(x).getDoubleValue()));
return RubyFloat.newFloat(context.runtime, Math.tanh(RubyNumeric.num2dbl(x)));
}

public static RubyFloat acosh(ThreadContext context, IRubyObject recv, IRubyObject x) {
@@ -211,7 +199,7 @@ public static RubyFloat acosh(ThreadContext context, IRubyObject recv, IRubyObje

@JRubyMethod(name = "acosh", required = 1, module = true, visibility = Visibility.PRIVATE)
public static RubyFloat acosh19(ThreadContext context, IRubyObject recv, IRubyObject x) {
double value = needFloat(x).getDoubleValue();
double value = RubyNumeric.num2dbl(x);
double result;

if (Double.isNaN(value)) {
@@ -257,7 +245,7 @@ public static RubyFloat asinh(ThreadContext context, IRubyObject recv, IRubyObje

@JRubyMethod(name = "asinh", required = 1, module = true, visibility = Visibility.PRIVATE)
public static RubyFloat asinh19(ThreadContext context, IRubyObject recv, IRubyObject x) {
double value = needFloat(x).getDoubleValue();
double value = RubyNumeric.num2dbl(x);
double y = Math.abs(value);
double result;

@@ -302,7 +290,7 @@ public static RubyFloat atanh(ThreadContext context, IRubyObject recv, IRubyObje

@JRubyMethod(name = "atanh", required = 1, module = true, visibility = Visibility.PRIVATE)
public static RubyFloat atanh_19(ThreadContext context, IRubyObject recv, IRubyObject x) {
double value = needFloat(x).getDoubleValue();
double value = RubyNumeric.num2dbl(x);

if (value < -1.0 || value > 1.0) throw context.runtime.newMathDomainError("atanh");

@@ -338,7 +326,7 @@ public static RubyFloat exp(ThreadContext context, IRubyObject recv, IRubyObject

@JRubyMethod(name = "exp", required = 1, module = true, visibility = Visibility.PRIVATE)
public static RubyFloat exp19(ThreadContext context, IRubyObject recv, IRubyObject exponent) {
return RubyFloat.newFloat(context.runtime, Math.exp(needFloat(exponent).getDoubleValue()));
return RubyFloat.newFloat(context.runtime, Math.exp(RubyNumeric.num2dbl(exponent)));
}

private static RubyFloat log_common19(IRubyObject recv, double value, double base, String msg) {
@@ -352,10 +340,10 @@ private static RubyFloat log_common19(IRubyObject recv, double value, double bas
*/
@JRubyMethod(name = "log", required = 1, optional = 1, module = true, visibility = Visibility.PRIVATE)
public static RubyFloat log_19(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
double value = needFloat(args[0]).getDoubleValue();
double value = RubyNumeric.num2dbl(args[0]);
double base = Math.E;
if (args.length == 2) {
base = needFloat(args[1]).getDoubleValue();
base = RubyNumeric.num2dbl(args[1]);
}
return log_common19(recv, value, base, "log");
}
@@ -369,7 +357,7 @@ public static RubyFloat log10(ThreadContext context, IRubyObject recv, IRubyObje

@JRubyMethod(name = "log10", required = 1, module = true, visibility = Visibility.PRIVATE)
public static RubyFloat log10_19(ThreadContext context, IRubyObject recv, IRubyObject x) {
return log_common19(recv, needFloat(x).getDoubleValue(), 10, "log10");
return log_common19(recv, RubyNumeric.num2dbl(x), 10, "log10");
}

/** Returns the base 2 logarithm of x.
@@ -381,7 +369,7 @@ public static RubyFloat log2(ThreadContext context, IRubyObject recv, IRubyObjec

@JRubyMethod(name = "log2", required = 1, module = true, visibility = Visibility.PRIVATE)
public static RubyFloat log2_19(ThreadContext context, IRubyObject recv, IRubyObject x) {
return log_common19(recv, needFloat(x).getDoubleValue(), 2, "log2");
return log_common19(recv, RubyNumeric.num2dbl(x), 2, "log2");
}

public static RubyFloat sqrt(ThreadContext context, IRubyObject recv, IRubyObject x) {
@@ -390,7 +378,7 @@ public static RubyFloat sqrt(ThreadContext context, IRubyObject recv, IRubyObjec

@JRubyMethod(name = "sqrt", required = 1, module = true, visibility = Visibility.PRIVATE)
public static RubyFloat sqrt19(ThreadContext context, IRubyObject recv, IRubyObject x) {
double value = needFloat(x).getDoubleValue();
double value = RubyNumeric.num2dbl(x);
double result;

if (value < 0) {
@@ -406,7 +394,7 @@ public static RubyFloat sqrt19(ThreadContext context, IRubyObject recv, IRubyObj

@JRubyMethod(name = "cbrt", required = 1, module = true, visibility = Visibility.PRIVATE)
public static RubyFloat cbrt(ThreadContext context, IRubyObject recv, IRubyObject x) {
double result = Math.cbrt(needFloat(x).getDoubleValue());
double result = Math.cbrt(RubyNumeric.num2dbl(x));

domainCheck(recv, result, "cbrt");

@@ -419,8 +407,8 @@ public static RubyFloat hypot(ThreadContext context, IRubyObject recv, IRubyObje

@JRubyMethod(name = "hypot", required = 2, module = true, visibility = Visibility.PRIVATE)
public static RubyFloat hypot19(ThreadContext context, IRubyObject recv, IRubyObject x, IRubyObject y) {
double valuea = needFloat(x).getDoubleValue();
double valueb = needFloat(y).getDoubleValue();
double valuea = RubyNumeric.num2dbl(x);
double valueb = RubyNumeric.num2dbl(y);
double result;

if (Math.abs(valuea) > Math.abs(valueb)) {
@@ -451,7 +439,7 @@ public static RubyArray frexp(ThreadContext context, IRubyObject recv, IRubyObje

@JRubyMethod(name = "frexp", required = 1, module = true, visibility = Visibility.PRIVATE)
public static RubyArray frexp19(ThreadContext context, IRubyObject recv, IRubyObject other) {
double mantissa = needFloat(other).getDoubleValue();
double mantissa = RubyNumeric.num2dbl(other);
short sign = 1;
long exponent = 0;

@@ -484,7 +472,7 @@ public static RubyFloat ldexp(ThreadContext context, IRubyObject recv, IRubyObje
@JRubyMethod(name = "ldexp", required = 2, module = true, visibility = Visibility.PRIVATE)
public static RubyFloat ldexp19(ThreadContext context, IRubyObject recv, IRubyObject mantissa, IRubyObject exponent) {
return RubyFloat.newFloat(context.runtime,
needFloat(mantissa).getDoubleValue() * Math.pow(2.0, RubyNumeric.num2int(exponent)));
RubyNumeric.num2dbl(mantissa) * Math.pow(2.0, RubyNumeric.num2int(exponent)));
}

public static final double[] ERFC_COEF = {
@@ -510,7 +498,7 @@ public static RubyFloat erf(IRubyObject recv, IRubyObject x) {

@JRubyMethod(name = "erf", required = 1, module = true, visibility = Visibility.PRIVATE)
public static RubyFloat erf19(ThreadContext context, IRubyObject recv, IRubyObject x) {
double value = needFloat(x).getDoubleValue();
double value = RubyNumeric.num2dbl(x);

double result;
double y = Math.abs(value);
@@ -598,7 +586,7 @@ public static RubyFloat erfc(ThreadContext context, IRubyObject recv, IRubyObjec

@JRubyMethod(name = "erfc", required = 1, module = true, visibility = Visibility.PRIVATE)
public static RubyFloat erfc19(ThreadContext context, IRubyObject recv, IRubyObject x) {
double value = needFloat(x).getDoubleValue();
double value = RubyNumeric.num2dbl(x);
double result;
double y = Math.abs(value);

@@ -720,7 +708,7 @@ public static RubyFloat gamma(ThreadContext context, IRubyObject recv, IRubyObje
* @param x a real number
* @return 2-element array [ln(&Gamma;(x)), sgn] for real number x,
* where sgn is the sign of &Gamma;(x) when exponentiated
* @see #gamma(org.jruby.runtime.builtin.IRubyObject, org.jruby.runtime.builtin.IRubyObject)
* @see #gamma(ThreadContext, org.jruby.runtime.builtin.IRubyObject, org.jruby.runtime.builtin.IRubyObject)
*/

@JRubyMethod(name = "lgamma", required = 1, module = true, visibility = Visibility.PRIVATE)
Loading

0 comments on commit b0bf2cb

Please sign in to comment.