-
-
Notifications
You must be signed in to change notification settings - Fork 925
Commit
to_f
on arbitrary objects in %f format string.
- 9.4.12.0
- 9.4.11.0
- 9.4.10.0
- 9.4.9.0
- 9.4.8.0
- 9.4.7.0
- 9.4.6.0
- 9.4.5.0
- 9.4.4.0
- 9.4.3.0
- 9.4.2.0
- 9.4.1.0
- 9.4.0.0
- 9.3.15.0
- 9.3.14.0
- 9.3.13.0
- 9.3.12.0
- 9.3.11.0
- 9.3.10.0
- 9.3.9.0
- 9.3.8.0
- 9.3.7.0
- 9.3.6.0
- 9.3.5.0
- 9.3.4.0
- 9.3.3.0
- 9.3.2.0
- 9.3.1.0
- 9.3.0.0
- 9.2.21.0
- 9.2.20.1
- 9.2.20.0
- 9.2.19.0
- 9.2.18.0
- 9.2.17.0
- 9.2.16.0
- 9.2.15.0
- 9.2.14.0
- 9.2.13.0
- 9.2.12.0
- 9.2.11.1
- 9.2.11.0
- 9.2.10.0
- 9.2.9.0
- 9.2.8.0
- 9.2.7.0
- 9.2.6.0
- 9.2.5.0
- 9.2.4.1
- 9.2.4.0
- 9.2.3.0
- 9.2.2.0
- 9.2.1.0
- 9.2.0.0
- 9.1.17.0
- 9.1.16.0
- 9.1.15.0
- 9.1.14.0
- 9.1.13.0
- 9.1.12.0
- 9.1.11.0
- 9.1.10.0
- 9.1.9.0
- 9.1.8.0
- 9.1.7.0
- 9.1.6.0
- 9.1.5.0
- 9.1.4.0
- 9.1.3.0
- 9.1.2.0
- 9.1.1.0
- 9.1.0.0
- 9.0.5.0
- 9.0.4.0
- 9.0.3.0
- 9.0.1.0
- 9.0.0.0
- 9.0.0.0.rc2
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
/* | ||
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This | ||
* code is released under a tri EPL/GPL/LGPL license. You can use it, | ||
* redistribute it and/or modify it under the terms of the: | ||
* | ||
* Eclipse Public License version 1.0 | ||
* GNU General Public License version 2 | ||
* GNU Lesser General Public License version 2.1 | ||
*/ | ||
|
||
package org.jruby.truffle.nodes.coerce; | ||
|
||
import com.oracle.truffle.api.CompilerDirectives; | ||
import com.oracle.truffle.api.dsl.NodeChild; | ||
import com.oracle.truffle.api.dsl.Specialization; | ||
import com.oracle.truffle.api.frame.VirtualFrame; | ||
import com.oracle.truffle.api.source.SourceSection; | ||
import org.jruby.truffle.nodes.RubyNode; | ||
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode; | ||
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory; | ||
import org.jruby.truffle.runtime.RubyContext; | ||
import org.jruby.truffle.runtime.control.RaiseException; | ||
import org.jruby.truffle.runtime.core.RubyBasicObject; | ||
|
||
@NodeChild(value = "child", type = RubyNode.class) | ||
public abstract class ToFNode extends RubyNode { | ||
|
||
@Child private CallDispatchHeadNode toFNode; | ||
|
||
public ToFNode(RubyContext context, SourceSection sourceSection) { | ||
super(context, sourceSection); | ||
} | ||
|
||
public double doDouble(VirtualFrame frame, Object value) { | ||
final Object doubleObject = executeDouble(frame, value); | ||
|
||
if (doubleObject instanceof Double) { | ||
return (double) doubleObject; | ||
} | ||
|
||
CompilerDirectives.transferToInterpreter(); | ||
throw new UnsupportedOperationException("executeDouble must return a double, instead it returned a " + doubleObject.getClass().getName()); | ||
} | ||
|
||
public abstract Object executeDouble(VirtualFrame frame, Object value); | ||
|
||
@Specialization | ||
public double coerceInt(int value) { | ||
return value; | ||
} | ||
|
||
@Specialization | ||
public double coerceLong(long value) { | ||
return value; | ||
} | ||
|
||
@Specialization | ||
public double coerceDouble(double value) { | ||
return value; | ||
} | ||
|
||
@Specialization | ||
public double coerceBoolean(VirtualFrame frame, boolean value) { | ||
return coerceObject(frame, value); | ||
} | ||
|
||
@Specialization | ||
public double coerceRubyBasicObject(VirtualFrame frame, RubyBasicObject object) { | ||
return coerceObject(frame, object); | ||
} | ||
|
||
private double coerceObject(VirtualFrame frame, Object object) { | ||
if (toFNode == null) { | ||
CompilerDirectives.transferToInterpreter(); | ||
toFNode = insert(DispatchHeadNodeFactory.createMethodCall(getContext())); | ||
} | ||
|
||
final Object coerced; | ||
|
||
try { | ||
coerced = toFNode.call(frame, object, "to_f", null); | ||
} catch (RaiseException e) { | ||
if (e.getRubyException().getLogicalClass() == getContext().getCoreLibrary().getNoMethodErrorClass()) { | ||
CompilerDirectives.transferToInterpreter(); | ||
throw new RaiseException(getContext().getCoreLibrary().typeErrorNoImplicitConversion(object, "Float", this)); | ||
} else { | ||
throw e; | ||
} | ||
} | ||
|
||
if (getContext().getCoreLibrary().getLogicalClass(coerced) == getContext().getCoreLibrary().getFloatClass()) { | ||
return (double) coerced; | ||
} else { | ||
CompilerDirectives.transferToInterpreter(); | ||
throw new RaiseException(getContext().getCoreLibrary().typeErrorBadCoercion(object, "Float", "to_f", coerced, this)); | ||
} | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,12 +9,19 @@ | |
*/ | ||
package org.jruby.truffle.pack.nodes.type; | ||
|
||
import com.oracle.truffle.api.CompilerDirectives; | ||
import com.oracle.truffle.api.Truffle; | ||
import com.oracle.truffle.api.dsl.NodeChild; | ||
import com.oracle.truffle.api.dsl.NodeChildren; | ||
import com.oracle.truffle.api.dsl.Specialization; | ||
import com.oracle.truffle.api.frame.FrameDescriptor; | ||
import com.oracle.truffle.api.frame.VirtualFrame; | ||
import org.jruby.truffle.nodes.coerce.ToFNode; | ||
import org.jruby.truffle.nodes.coerce.ToFNodeGen; | ||
import org.jruby.truffle.pack.nodes.PackNode; | ||
import org.jruby.truffle.runtime.RubyArguments; | ||
import org.jruby.truffle.runtime.RubyContext; | ||
import org.jruby.truffle.runtime.core.RubyBasicObject; | ||
|
||
/** | ||
* Convert a value to a {@code double}. | ||
|
@@ -24,6 +31,8 @@ | |
}) | ||
public abstract class ToDoubleNode extends PackNode { | ||
|
||
@Child private ToFNode toFNode; | ||
|
||
public ToDoubleNode(RubyContext context) { | ||
super(context); | ||
} | ||
|
@@ -45,4 +54,14 @@ public double toDouble(VirtualFrame frame, double value) { | |
return value; | ||
} | ||
|
||
@Specialization | ||
public Object toDouble(RubyBasicObject value) { | ||
if (toFNode == null) { | ||
CompilerDirectives.transferToInterpreter(); | ||
toFNode = insert(ToFNodeGen.create(getContext(), getSourceSection(), null)); | ||
} | ||
|
||
final VirtualFrame frame = Truffle.getRuntime().createVirtualFrame(RubyArguments.pack(null, null, value, null, new Object[]{}), new FrameDescriptor()); | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
chrisseaton
Contributor
|
||
return toFNode.doDouble(frame, value); | ||
} | ||
} |
@chrisseaton @eregon This seems to work, but please let me know if there's a better way to build up a new frame for the call.