Skip to content

Commit

Permalink
Showing 68 changed files with 1,263 additions and 957 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -79,7 +79,6 @@ matrix:
fast_finish: true
allow_failures:
- env: COMMAND=test/truffle/run.sh
- env: COMMAND='ruby tool/jt.rb check_ambiguous_arguments'


branches:
@@ -100,6 +99,7 @@ notifications:
on_failure: always
template:
- "%{repository} (%{branch}:%{commit} by %{author}): %{message} (%{build_url})"
skip_join: true

# update jruby-head installed on Travis CI
webhooks:
45 changes: 40 additions & 5 deletions core/src/main/java/org/jruby/ext/bigdecimal/RubyBigDecimal.java
Original file line number Diff line number Diff line change
@@ -465,6 +465,9 @@ private static RubyBigDecimal getVpValue(ThreadContext context, IRubyObject valu
// Converted to a String because some values -inf cannot happen from Java libs
return newInstance(context, context.runtime.getClass("BigDecimal"), value.asString());
}
if ((value instanceof RubyRational) || (value instanceof RubyFloat)) {
return newInstance(context, context.runtime.getClass("BigDecimal"), value, RubyFixnum.newFixnum(context.runtime, RubyFloat.DIG));
}
return cannotBeCoerced(context, value, must);
}

@@ -493,7 +496,10 @@ private static RubyBigDecimal newInstance(Ruby runtime, IRubyObject recv, RubyFl
// precision can be no more than float digits
if (mathContext.getPrecision() > RubyFloat.DIG + 1) throw runtime.newArgumentError("precision too large");

return new RubyBigDecimal(runtime, (RubyClass) recv, new BigDecimal(arg.getDoubleValue(), mathContext));
double dblVal = arg.getDoubleValue();
if(Double.isInfinite(dblVal) || Double.isNaN(dblVal)) throw runtime.newFloatDomainError("NaN");

return new RubyBigDecimal(runtime, (RubyClass) recv, new BigDecimal(dblVal, mathContext));
}

private static RubyBigDecimal newInstance(Ruby runtime, IRubyObject recv, RubyBignum arg, MathContext mathContext) {
@@ -600,7 +606,8 @@ public static RubyBigDecimal newInstance(IRubyObject recv, IRubyObject[] args) {
@JRubyMethod(name = "new", meta = true)
public static RubyBigDecimal newInstance(ThreadContext context, IRubyObject recv, IRubyObject arg) {
if (arg instanceof RubyBigDecimal) return newInstance(context.runtime, recv, (RubyBigDecimal) arg);
if (arg instanceof RubyFloat || arg instanceof RubyRational) throw context.runtime.newArgumentError("can't omit precision for a rational");
if (arg instanceof RubyRational) throw context.runtime.newArgumentError("can't omit precision for a Rational.");
if (arg instanceof RubyFloat) throw context.runtime.newArgumentError("can't omit precision for a Float.");
if (arg instanceof RubyFixnum) return newInstance(context.runtime, recv, (RubyFixnum) arg, MathContext.UNLIMITED);
if (arg instanceof RubyBignum) return newInstance(context.runtime, recv, (RubyBignum) arg, MathContext.UNLIMITED);
return newInstance(context, recv, arg, MathContext.UNLIMITED);
@@ -1192,9 +1199,6 @@ public IRubyObject coerce(IRubyObject other) {

@JRubyMethod
public RubyArray coerce(ThreadContext context, IRubyObject other) {
if (other instanceof RubyFloat) {
return context.runtime.newArray(other, to_f());
}
return context.runtime.newArray(getVpValue(context, other, true), this);
}

@@ -1518,6 +1522,37 @@ public IRubyObject to_int() {
}
}

@JRubyMethod(name = "to_r")
public IRubyObject to_r(ThreadContext context) {
checkFloatDomain();

RubyArray i = split(context);
long sign = (long)i.get(0);
String digits = (String)i.get(1).toString();
long base = (long)i.get(2);
long power = (long)i.get(3);
long denomi_power = power - digits.length();

IRubyObject bigDigits = RubyBignum.newBignum(getRuntime(), (String)digits).op_mul(context, sign);
RubyBignum numerator;
if(bigDigits instanceof RubyBignum) {
numerator = (RubyBignum)bigDigits;
}
else {
numerator = RubyBignum.newBignum(getRuntime(), bigDigits.toString());
}
IRubyObject num, den;
if(denomi_power < 0) {
num = numerator;
den = RubyFixnum.newFixnum(getRuntime(), base).op_mul(context, RubyFixnum.newFixnum(getRuntime(), -denomi_power));
}
else {
num = numerator.op_pow(context, RubyFixnum.newFixnum(getRuntime(), base).op_mul(context, RubyFixnum.newFixnum(getRuntime(), denomi_power)));
den = RubyFixnum.newFixnum(getRuntime(), 1);
}
return RubyRational.newInstance(context, context.runtime.getRational(), num, den);
}

public IRubyObject to_int19() {
return to_int();
}
16 changes: 16 additions & 0 deletions core/src/main/java/org/jruby/parser/ParserSupport.java
Original file line number Diff line number Diff line change
@@ -36,10 +36,13 @@
package org.jruby.parser;

import java.math.BigInteger;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.util.ArrayList;
import java.util.List;
import org.jcodings.Encoding;
import org.jruby.RubyBignum;
import org.jruby.RubyEncoding;
import org.jruby.RubyRegexp;
import org.jruby.ast.*;
import org.jruby.ast.types.ILiteralNode;
@@ -879,6 +882,19 @@ public void setLexer(RubyLexer lexer) {
public DStrNode createDStrNode(ISourcePosition position) {
return new DStrNode(position, lexer.getEncoding());
}

public Node asSymbol(ISourcePosition position, String value) {
// FIXME: tLABEL and identifiers could return ByteList and not String and make String on-demand for method names
// or lvars. This would prevent this re-extraction of bytes from a string with proper charset
try {
Charset charset = lexer.getEncoding().getCharset();
if (charset != null) return new SymbolNode(position, new ByteList(value.getBytes(charset), lexer.getEncoding()));
} catch (UnsupportedCharsetException e) {}

// for non-charsets we are screwed here since bytes will file.encoding and not what we read them as (see above FIXME for
// a much more invasive solution.
return new SymbolNode(position, new ByteList(value.getBytes(), lexer.getEncoding()));
}

public Node asSymbol(ISourcePosition position, Node value) {
return value instanceof StrNode ? new SymbolNode(position, ((StrNode) value).getValue()) :
16 changes: 7 additions & 9 deletions core/src/main/java/org/jruby/parser/RubyParser.java
Original file line number Diff line number Diff line change
@@ -34,7 +34,6 @@
import java.io.IOException;

import org.jruby.ast.ArgsNode;
import org.jruby.ast.ArgumentNode;
import org.jruby.ast.ArrayNode;
import org.jruby.ast.AssignableNode;
import org.jruby.ast.BackRefNode;
@@ -103,7 +102,6 @@
import org.jruby.ast.SelfNode;
import org.jruby.ast.StarNode;
import org.jruby.ast.StrNode;
import org.jruby.ast.SymbolNode;
import org.jruby.ast.TrueNode;
import org.jruby.ast.UnnamedRestArgNode;
import org.jruby.ast.UntilNode;
@@ -147,7 +145,7 @@ public void setWarnings(IRubyWarnings warnings) {
support.setWarnings(warnings);
lexer.setWarnings(warnings);
}
// line 151 "-"
// line 149 "-"
// %token constants
public static final int kCLASS = 257;
public static final int kMODULE = 258;
@@ -4270,7 +4268,7 @@ public Object yyparse (RubyLexer yyLex) throws java.io.IOException {
};
states[454] = new ParserState() {
@Override public Object execute(ParserSupport support, RubyLexer lexer, Object yyVal, Object[] yyVals, int yyTop) {
yyVal = new SymbolNode(lexer.getPosition(), new ByteList(((String)yyVals[0+yyTop]).getBytes(), lexer.getEncoding()));
yyVal = support.asSymbol(lexer.getPosition(), ((String)yyVals[0+yyTop]));
return yyVal;
}
};
@@ -4580,11 +4578,11 @@ public Object yyparse (RubyLexer yyLex) throws java.io.IOException {
/* EvStrNode :"#{some expression}"*/
/* Ruby 1.9 allows empty strings as symbols*/
if (((Node)yyVals[-1+yyTop]) == null) {
yyVal = new SymbolNode(lexer.getPosition(), new ByteList(new byte[0], lexer.getEncoding()));
yyVal = support.asSymbol(lexer.getPosition(), "");
} else if (((Node)yyVals[-1+yyTop]) instanceof DStrNode) {
yyVal = new DSymbolNode(((Node)yyVals[-1+yyTop]).getPosition(), ((DStrNode)yyVals[-1+yyTop]));
} else if (((Node)yyVals[-1+yyTop]) instanceof StrNode) {
yyVal = new SymbolNode(((Node)yyVals[-1+yyTop]).getPosition(), ((StrNode)yyVals[-1+yyTop]).getValue());
yyVal = support.asSymbol(((Node)yyVals[-1+yyTop]).getPosition(), ((Node)yyVals[-1+yyTop]));
} else {
yyVal = new DSymbolNode(((Node)yyVals[-1+yyTop]).getPosition());
((DSymbolNode)yyVal).add(((Node)yyVals[-1+yyTop]));
@@ -5250,7 +5248,7 @@ public Object yyparse (RubyLexer yyLex) throws java.io.IOException {
};
states[611] = new ParserState() {
@Override public Object execute(ParserSupport support, RubyLexer lexer, Object yyVal, Object[] yyVals, int yyTop) {
SymbolNode label = new SymbolNode(support.getPosition(((Node)yyVals[0+yyTop])), new ByteList(((String)yyVals[-1+yyTop]).getBytes(), lexer.getEncoding()));
Node label = support.asSymbol(support.getPosition(((Node)yyVals[0+yyTop])), ((String)yyVals[-1+yyTop]));
yyVal = new KeyValuePair<Node,Node>(label, ((Node)yyVals[0+yyTop]));
return yyVal;
}
@@ -5301,7 +5299,7 @@ public Object yyparse (RubyLexer yyLex) throws java.io.IOException {
}
};
}
// line 2533 "RubyParser.y"
// line 2531 "RubyParser.y"

/** The parse method use an lexer stream and parse it to an AST node
* structure
@@ -5316,4 +5314,4 @@ public RubyParserResult parse(ParserConfiguration configuration) throws IOExcept
return support.getResult();
}
}
// line 9885 "-"
// line 9883 "-"
10 changes: 4 additions & 6 deletions core/src/main/java/org/jruby/parser/RubyParser.y
Original file line number Diff line number Diff line change
@@ -40,7 +40,6 @@ import org.jruby.ast.BlockArgNode;
import org.jruby.ast.BlockNode;
import org.jruby.ast.BlockPassNode;
import org.jruby.ast.BreakNode;
import org.jruby.ast.CallNode;
import org.jruby.ast.ClassNode;
import org.jruby.ast.ClassVarNode;
import org.jruby.ast.ClassVarAsgnNode;
@@ -99,7 +98,6 @@ import org.jruby.ast.SClassNode;
import org.jruby.ast.SelfNode;
import org.jruby.ast.StarNode;
import org.jruby.ast.StrNode;
import org.jruby.ast.SymbolNode;
import org.jruby.ast.TrueNode;
import org.jruby.ast.UnnamedRestArgNode;
import org.jruby.ast.UntilNode;
@@ -1864,7 +1862,7 @@ literal : numeric {
$$ = $1;
}
| symbol {
$$ = new SymbolNode(lexer.getPosition(), new ByteList($1.getBytes(), lexer.getEncoding()));
$$ = support.asSymbol(lexer.getPosition(), $1);
}
| dsym

@@ -2066,11 +2064,11 @@ dsym : tSYMBEG xstring_contents tSTRING_END {
// EvStrNode :"#{some expression}"
// Ruby 1.9 allows empty strings as symbols
if ($2 == null) {
$$ = new SymbolNode(lexer.getPosition(), new ByteList(new byte[0], lexer.getEncoding()));
$$ = support.asSymbol(lexer.getPosition(), "");
} else if ($2 instanceof DStrNode) {
$$ = new DSymbolNode($2.getPosition(), $<DStrNode>2);
} else if ($2 instanceof StrNode) {
$$ = new SymbolNode($2.getPosition(), $<StrNode>2.getValue());
$$ = support.asSymbol($2.getPosition(), $2);
} else {
$$ = new DSymbolNode($2.getPosition());
$<DSymbolNode>$.add($2);
@@ -2480,7 +2478,7 @@ assoc : arg_value tASSOC arg_value {
$$ = new KeyValuePair<Node,Node>($1, $3);
}
| tLABEL arg_value {
SymbolNode label = new SymbolNode(support.getPosition($2), new ByteList($1.getBytes(), lexer.getEncoding()));
Node label = support.asSymbol(support.getPosition($2), $1);
$$ = new KeyValuePair<Node,Node>(label, $2);
}
| tSTRING_BEG string_contents tLABEL_END arg_value {
3 changes: 0 additions & 3 deletions core/src/main/java/org/jruby/util/cli/Options.java
Original file line number Diff line number Diff line change
@@ -147,9 +147,6 @@ public class Options {
public static final Option<Boolean> TRUFFLE_DISPATCH_METHODMISSING_ALWAYS_CLONED = bool(TRUFFLE, "truffle.call.method_missing_always_cloned", true, "Always clone #method_missing call targets.");
public static final Option<Boolean> TRUFFLE_DISPATCH_METHODMISSING_ALWAYS_INLINED = bool(TRUFFLE, "truffle.call.method_missing_always_inlined", true, "Always inline #method_missing call targets.");

public static final Option<Boolean> TRUFFLE_RANDOMIZE_STORAGE_ARRAY = bool(TRUFFLE, "truffle.randomize_storage.array", false, "Randomize Array storage strategy.");
public static final Option<Integer> TRUFFLE_RANDOMIZE_SEED = integer(TRUFFLE, "truffle.randomize.seed", 0, "Seed for any randomization.");

public static final Option<Boolean> TRUFFLE_INCLUDE_CORE_FILE_CALLERS_IN_SET_TRACE_FUNC = bool(TRUFFLE, "truffle.set_trace_func.include_core_file_callers", false, "Include internal core library calls in set_trace_func output.");

public static final Option<Boolean> NATIVE_ENABLED = bool(NATIVE, "native.enabled", true, "Enable/disable native code, including POSIX features and C exts.");
8 changes: 8 additions & 0 deletions core/src/main/java/org/jruby/util/io/EncodingUtils.java
Original file line number Diff line number Diff line change
@@ -1031,10 +1031,12 @@ public static RubyString strConvEncOpts(ThreadContext context, RubyString str, E
EConvResult ret;
int convertedOutput = 0;

// these are in the while clause in MRI
destbytes = newStr.getUnsafeBytes();
int dest = newStr.begin();
dp.p = dest + convertedOutput;
ret = ec.convert(sbytes, sp, start + len, destbytes, dp, dest + olen, 0);

while (ret == EConvResult.DestinationBufferFull) {
int convertedInput = sp.p - start;
int rest = len - convertedInput;
@@ -1048,6 +1050,12 @@ public static RubyString strConvEncOpts(ThreadContext context, RubyString str, E
}
olen += rest < 2 ? 2 : rest;
newStr.ensure(olen);

// these are the while clause in MRI
destbytes = newStr.getUnsafeBytes();
dest = newStr.begin();
dp.p = dest + convertedOutput;
ret = ec.convert(sbytes, sp, start + len, destbytes, dp, dest + olen, 0);
}
ec.close();

62 changes: 50 additions & 12 deletions core/src/main/ruby/jruby/bigdecimal.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
require 'bigdecimal'
require 'bigdecimal/util'

module BigMath
module_function

# call-seq:
# log(decimal, numeric) -> BigDecimal
#
@@ -18,24 +19,27 @@ module BigMath
# BigMath::log(BigMath::E(10), 10).to_s
# #=> "1.000000000000"
#
def log(x, precision)
raise ArgumentError if x.nil?
raise Math::DomainError if x.is_a?(Complex)
raise Math::DomainError if x <= 0
raise ArgumentError unless precision.is_a?(Integer)
raise ArgumentError if precision < 1
return BigDecimal::INFINITY if x == BigDecimal::INFINITY
return BigDecimal::NAN if x.is_a?(BigDecimal) && x.nan?
return BigDecimal::NAN if x.is_a?(Float) && x.nan?
def log(x, prec)
raise ArgumentError if x.nil? || !x.is_a?(Numeric)
raise Math::DomainError if x.is_a?(Complex) || x <= 0
raise ArgumentError unless (true if Integer(prec) rescue false)
prec = prec.to_i
raise ArgumentError if prec < 1
if x.is_a?(BigDecimal) || x.is_a?(Float)
return BigDecimal::INFINITY if x.infinite?
return BigDecimal::NAN if x.nan?
end
x = x.is_a?(Rational) ? x.to_d(Float::DIG) : x.to_d
return BigDecimal::INFINITY if x.infinite?
return BigDecimal::NAN if x.nan?

# this uses the series expansion of the Arctangh (Arc tangens hyperbolicus)
# http://en.wikipedia.org/wiki/Area_hyperbolic_tangent
# where ln(x) = 2 * artanh ((x - 1) / (x + 1))
# d are the elements in the series (getting smaller and smaller)

x = x.to_d
rmpd_double_figures = 16 # from MRI ruby
n = precision + rmpd_double_figures
n = prec + rmpd_double_figures

# offset the calculation to the efficient (0.1)...(10) window
expo = x.exponent
@@ -72,4 +76,38 @@ def log(x, precision)
window_result
end
end

def exp(x, prec)
raise ArgumentError if x.nil? || !x.is_a?(Numeric) || x.is_a?(Complex)
raise ArgumentError unless (true if Integer(prec) rescue false)
prec = prec.to_i
raise ArgumentError if prec < 1
return BigDecimal::NAN if x.is_a?(BigDecimal) && x.nan?
return BigDecimal::NAN if x.is_a?(Float) && x.nan?
x = x.is_a?(Rational) ? x.to_d(Float::DIG) : x.to_d
return BigDecimal::NAN if x.nan?
return x.sign > 0 ? BigDecimal::INFINITY : BigDecimal(0, prec) if x.infinite?

df = BigDecimal.double_fig
n = prec + df
one = BigDecimal(1)
x = -x if neg = x.sign < 0

y = one;
d = y;
i = 1;

while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
m = df if m < df
d = d.mult(x, n)
d = d.div(i, m)
y += d
i += 1;
end
if neg
one.div(y, prec)
else
y.round(prec - y.exponent)
end
end
end
2 changes: 1 addition & 1 deletion core/src/main/ruby/jruby/jruby.rb
Original file line number Diff line number Diff line change
@@ -63,7 +63,7 @@ def parse(content = nil, filename = (default_filename = true; '-'), extra_positi
content = content.to_str
filename = filename.to_str unless default_filename

runtime.parse(reference0(content).byte_list, filename, nil, lineno, extra_position_info)
runtime.java_send :parse, [org.jruby.util.ByteList, java.lang.String, org.jruby.runtime.DynamicScope, Java::int, Java::boolean], reference0(content).byte_list, filename, nil, lineno, extra_position_info
end
end
alias ast_for parse
1 change: 1 addition & 0 deletions core/src/test/java/org/jruby/test/MainTestSuite.java
Original file line number Diff line number Diff line change
@@ -92,6 +92,7 @@ public static Test suite() throws Throwable {
suite.addTestSuite(ParameterizedWriterTest.class);
suite.addTestSuite(TestRubyRational.class);
suite.addTestSuite(TestRecursiveCheck.class);
suite.addTestSuite(TestEncodingAPI.class);
// Disabled test due to difficulty of making WeakRef logic deterministic
// suite.addTestSuite(TestRegexpCache.class);
return suite;
Loading

0 comments on commit c33d16f

Please sign in to comment.