Skip to content

Commit

Permalink
Merge branch 'master' into truffle-head
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisseaton committed Jan 30, 2015
2 parents 6ee6976 + 0b8305a commit b35d34d
Show file tree
Hide file tree
Showing 56 changed files with 282 additions and 196 deletions.
17 changes: 11 additions & 6 deletions core/src/main/java/org/jruby/ext/bigdecimal/RubyBigDecimal.java
Expand Up @@ -869,10 +869,16 @@ public IRubyObject op_quo20(ThreadContext context, IRubyObject other) {
}

private IRubyObject op_quo19_20(ThreadContext context, IRubyObject other) {
RubyObject preciseOther = getVpValue19(context, other, true);
RubyBigDecimal preciseOther = getVpValue19(context, other, true);
// regular division with some default precision
// TODO: proper algorithm to set the precision
return op_div(context, preciseOther, getRuntime().newFixnum(200));
// proper algorithm to set the precision
// the precision is multiple of 4
// and the precision is larger than len * 2
int len = value.precision() + preciseOther.value.precision();
int pow = len / 4;
int precision = (pow + 1) * 4 * 2;

return op_div(context, preciseOther, getRuntime().newFixnum(precision));
}

public IRubyObject op_div(ThreadContext context, IRubyObject other) {
Expand Down Expand Up @@ -923,10 +929,9 @@ public IRubyObject op_div(ThreadContext context, IRubyObject other, IRubyObject
// MRI behavior: "If digits is 0, the result is the same as the / operator."
if (scale == 0) return op_quo(context, other);

// TODO: better algorithm to set precision needed
int prec = Math.max(200, scale);
MathContext mathContext = new MathContext(scale, getRoundingMode(context.runtime));
return new RubyBigDecimal(context.runtime,
value.divide(val.value, new MathContext(prec, RoundingMode.HALF_UP))).setResult(scale);
value.divide(val.value, mathContext)).setResult(scale);
}

@JRubyMethod(name = "div")
Expand Down
91 changes: 88 additions & 3 deletions core/src/main/java/org/jruby/runtime/Signature.java
Expand Up @@ -10,6 +10,7 @@
import org.jruby.ast.PreExeNode;
import org.jruby.ast.StarNode;
import org.jruby.ast.UnnamedRestArgNode;
import org.jruby.ast.RequiredKeywordArgumentValueNode;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.TypeConverter;

Expand All @@ -35,6 +36,8 @@ public enum Rest { NONE, NORM, ANON, STAR }
private final boolean kwargs;
private final Arity arity;

private boolean requiredKwargs;

public Signature(int pre, int opt, int post, Rest rest, boolean kwargs) {
this.pre = pre;
this.opt = opt;
Expand All @@ -47,12 +50,36 @@ public Signature(int pre, int opt, int post, Rest rest, boolean kwargs) {
// permit more than required args to be passed to a lambda, so we do not consider
// it a "true" rest arg for arity-checking purposes below in checkArity.
if (rest != Rest.NONE || opt != 0) {
arity = Arity.createArity(-(pre + post + 1));
arity = Arity.createArity(-(required() + 1));
} else {
arity = Arity.fixed(pre + post);
arity = Arity.fixed(required() + getRequiredKeywordCount());
}
}

public Signature(int pre, int opt, int post, Rest rest, boolean kwargs, boolean requiredKwargs) {
this.pre = pre;
this.opt = opt;
this.post = post;
this.rest = rest;
this.kwargs = kwargs;
this.requiredKwargs = requiredKwargs;

// NOTE: Some logic to *assign* variables still uses Arity, which treats Rest.ANON (the
// |a,| form) as a rest arg for destructuring purposes. However ANON does *not*
// permit more than required args to be passed to a lambda, so we do not consider
// it a "true" rest arg for arity-checking purposes below in checkArity.
if (rest != Rest.NONE || opt != 0) {
arity = Arity.createArity(-(required() + 1));
} else {
arity = Arity.fixed(required() + getRequiredKeywordCount());
}
}

private int getRequiredKeywordCount() {
if (requiredKwargs) return 1;
return 0;
}

public int pre() { return pre; }
public int opt() { return opt; }
public Rest rest() { return rest; }
Expand Down Expand Up @@ -102,6 +129,46 @@ public static Signature from(int pre, int opt, int post, Rest rest, boolean kwar
return new Signature(pre, opt, post, rest, kwargs);
}

public static Signature from(int pre, int opt, int post, Rest rest, boolean kwargs, boolean requiredKwargs) {
if (opt == 0 && post == 0 && !kwargs) {
switch (pre) {
case 0:
switch (rest) {
case NONE:
return Signature.NO_ARGUMENTS;
case NORM:
return Signature.OPTIONAL;
}
break;
case 1:
switch (rest) {
case NONE:
return Signature.ONE_ARGUMENT;
case NORM:
return Signature.ONE_REQUIRED;
}
break;
case 2:
switch (rest) {
case NONE:
return Signature.TWO_ARGUMENTS;
case NORM:
return Signature.TWO_REQUIRED;
}
break;
case 3:
switch (rest) {
case NONE:
return Signature.THREE_ARGUMENTS;
case NORM:
return Signature.THREE_REQUIRED;
}
break;
}
}
return new Signature(pre, opt, post, rest, kwargs, requiredKwargs);
}

public static Signature from(IterNode iter) {
if (iter instanceof ForNode) return from((ForNode)iter);
if (iter instanceof PreExeNode) return from((PreExeNode)iter);
Expand All @@ -118,7 +185,25 @@ public static Signature from(IterNode iter) {
rest = restFromArg(restArg);
}

return Signature.from(args.getPreCount(), args.getOptionalArgsCount(), args.getPostCount(), rest, args.hasKwargs());
return Signature.from(args.getPreCount(), args.getOptionalArgsCount(), args.getPostCount(), rest, args.hasKwargs(), hasRequiredKeywordArg(args));
}

private static boolean hasRequiredKeywordArg(ArgsNode args) {
if (args.getKeywords() == null) return false;

for (Node keyWordNode : args.getKeywords().childNodes()) {
for (Node asgnNode : keyWordNode.childNodes()) {
if (isRequiredKeywordArgumentValueNode(asgnNode)) {
return true;
}
}
}
return false;
}


private static boolean isRequiredKeywordArgumentValueNode(Node asgnNode) {
return asgnNode.childNodes().get(0) instanceof RequiredKeywordArgumentValueNode;
}

private static Rest restFromArg(Node restArg) {
Expand Down
44 changes: 36 additions & 8 deletions core/src/main/java/org/jruby/util/io/Sockaddr.java
Expand Up @@ -88,14 +88,27 @@ public static IRubyObject unpack_sockaddr_in(ThreadContext context, IRubyObject

int port = ((val.get(2)&0xff) << 8) + (val.get(3)&0xff);

StringBuilder sb = new StringBuilder()
.append(val.get(4)&0xff)
AddressFamily af = getAddressFamilyFromSockaddr(runtime, val);

StringBuilder sb = new StringBuilder();

if (af == AddressFamily.AF_INET) {
sb.append(val.get(4) & 0xff)
.append(".")
.append(val.get(5)&0xff)
.append(val.get(5) & 0xff)
.append(".")
.append(val.get(6)&0xff)
.append(val.get(6) & 0xff)
.append(".")
.append(val.get(7)&0xff);
.append(val.get(7) & 0xff);

} else { // if af == AddressFamily.AF_INET6
for (int i = 4; i <= 19; i++) {
if (i != 4 && i % 2 == 0) {
sb.append(":");
}
sb.append(Integer.toHexString(val.get(i) & 0xff | 0x100).substring(1));
}
}

IRubyObject[] result = new IRubyObject[]{
runtime.newFixnum(port),
Expand All @@ -117,15 +130,23 @@ public static IRubyObject pack_sockaddr_in(ThreadContext context, int iport, Str
try {
DataOutputStream ds = new DataOutputStream(bufS);

writeSockaddrHeader(AddressFamily.AF_INET, ds);
writeSockaddrPort(ds, iport);

try {
if(host != null && "".equals(host)) {
writeSockaddrHeader(AddressFamily.AF_INET, ds);
writeSockaddrPort(ds, iport);
ds.writeInt(0);
} else {
InetAddress[] addrs = InetAddress.getAllByName(host);
byte[] addr = addrs[0].getAddress();

if (addr.length == 4) {
writeSockaddrHeader(AddressFamily.AF_INET, ds);
} else {
writeSockaddrHeader(AddressFamily.AF_INET6, ds);
}

writeSockaddrPort(ds, iport);

ds.write(addr, 0, addr.length);
}
} catch (UnknownHostException e) {
Expand Down Expand Up @@ -207,6 +228,13 @@ public static void validateSockaddr(Ruby runtime, ByteList val) {
}
}

public static AddressFamily getAddressFamilyFromSockaddr(Ruby runtime, ByteList val) {
int high = val.get(0) & 0xff;
int low = val.get(1) & 0xff;

return AddressFamily.valueOf((high << 8) + low);
}

private static RuntimeException sockerr(Ruby runtime, String msg) {
return new RaiseException(runtime, runtime.getClass("SocketError"), msg, true);
}
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/ruby/jruby/truffle/core.rb
Expand Up @@ -15,7 +15,6 @@
require_relative 'core/rubinius/api/shims/rubinius'
require_relative 'core/rubinius/api/shims/lookuptable'
require_relative 'core/rubinius/api/shims/thread'
require_relative 'core/rubinius/api/shims/enumerator'
require_relative 'core/rubinius/api/shims/undefined'
require_relative 'core/rubinius/api/shims/metrics'

Expand All @@ -34,6 +33,7 @@
# Load common (ordered according to Rubinius' load_order.txt)
require_relative 'core/rubinius/kernel/common/enumerator'
require_relative 'core/rubinius/kernel/common/enumerable'
require_relative 'core/rubinius/kernel/common/exception'
require_relative 'core/rubinius/kernel/common/undefined'
require_relative 'core/rubinius/kernel/common/type'
require_relative 'core/rubinius/kernel/common/array'
Expand Down

This file was deleted.

Expand Up @@ -12,10 +12,14 @@ def self.mathn_loaded?
false
end

module Fiber
class Fiber < ::Fiber

ENABLED = true

def initialize(size, &block)
super &block
end

end

end
Expand Down
Expand Up @@ -24,6 +24,8 @@
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# Only part of Rubinius' array.rb

class Array

def values_at(*args)
Expand Down
@@ -0,0 +1,35 @@
# Copyright (c) 2007-2014, Evan Phoenix and contributors
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of Rubinius nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# Only part of Rubinius' exception.rb

class StopIteration < IndexError
end

class StopIteration
attr_accessor :result
private :result=
end
@@ -0,0 +1,12 @@
require 'bigdecimal'

# https://github.com/jruby/jruby/issues/2524
describe 'BigDecimal precision test with different execution order' do
it 'returns same precision ' do
fraction = BigDecimal.new("0.0095") / 365 * BigDecimal.new(50_000)
r1 = fraction * BigDecimal.new(50_000) / BigDecimal.new(100_000)
r2 = fraction * (BigDecimal.new(50_000) / BigDecimal.new(100_000))
expect(r1).to eq(r2)
end
end

1 change: 0 additions & 1 deletion spec/truffle/tags/core/enumerable/chunk_tags.txt
@@ -1,4 +1,3 @@
fails:Enumerable#chunk returns an Enumerator if given a block
fails:Enumerable#chunk yields the current element and the current chunk to the block
fails:Enumerable#chunk returns elements of the Enumerable in an Array of Arrays, [v, ary], where 'ary' contains the consecutive elements for which the block returned the value 'v'
fails:Enumerable#chunk returns elements for which the block returns :_alone in separate Arrays
Expand Down
1 change: 0 additions & 1 deletion spec/truffle/tags/core/enumerable/collect_tags.txt
@@ -1,2 +1 @@
fails:Enumerable#collect passes through the values yielded by #each_with_index
fails:Enumerable#collect returns an enumerator when no block given
2 changes: 0 additions & 2 deletions spec/truffle/tags/core/enumerable/detect_tags.txt
@@ -1,3 +1 @@
fails:Enumerable#detect passes through the values yielded by #each_with_index
fails:Enumerable#detect returns an enumerator when no block given
fails:Enumerable#detect passes the ifnone proc to the enumerator
1 change: 0 additions & 1 deletion spec/truffle/tags/core/enumerable/drop_tags.txt
@@ -1,3 +1,2 @@
fails:Enumerable#drop passed a number n as an argument tries to convert n to an Integer using #to_int
fails:Enumerable#drop passed a number n as an argument returns [] for empty enumerables
fails:Enumerable#drop passed a number n as an argument returns [] if dropping all
2 changes: 0 additions & 2 deletions spec/truffle/tags/core/enumerable/drop_while_tags.txt
@@ -1,3 +1 @@
fails:Enumerable#drop_while returns no/all elements for {true/false} block
fails:Enumerable#drop_while accepts returns other than true/false
fails:Enumerable#drop_while will only go through what's needed
3 changes: 0 additions & 3 deletions spec/truffle/tags/core/enumerable/each_cons_tags.txt
@@ -1,5 +1,2 @@
fails:Enumerable#each_cons tries to convert n to an Integer using #to_int
fails:Enumerable#each_cons works when n is >= full length
fails:Enumerable#each_cons yields only as much as needed
fails:Enumerable#each_cons returns an enumerator if no block
fails:Enumerable#each_cons gathers whole arrays as elements when each yields multiple
2 changes: 0 additions & 2 deletions spec/truffle/tags/core/enumerable/each_entry_tags.txt
@@ -1,3 +1 @@
fails:Enumerable#each_entry returns an enumerator if no block
fails:Enumerable#each_entry passes through the values yielded by #each_with_index
fails:Enumerable#each_entry passes extra arguments to #each
3 changes: 0 additions & 3 deletions spec/truffle/tags/core/enumerable/each_slice_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/enumerable/each_with_index_tags.txt

This file was deleted.

This file was deleted.

0 comments on commit b35d34d

Please sign in to comment.