Skip to content

Commit

Permalink
[Truffle] time_s_from_array primitive.
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisseaton committed Feb 14, 2015
1 parent efa0527 commit 1b5b3d7
Show file tree
Hide file tree
Showing 20 changed files with 95 additions and 60 deletions.
1 change: 0 additions & 1 deletion spec/truffle/tags/core/time/day_tags.txt
@@ -1,3 +1,2 @@
fails:Time#day returns the day of the month (1..n) for a local Time
fails:Time#day returns the day of the month for a UTC Time
fails:Time#day returns the day of the month for a Time with a fixed offset
2 changes: 0 additions & 2 deletions spec/truffle/tags/core/time/gm_tags.txt
@@ -1,4 +1,3 @@
fails:Time.gm creates a time based on given values, interpreted as UTC (GMT)
fails:Time.gm creates a time based on given C-style gmtime arguments, interpreted as UTC (GMT)
fails:Time.gm interprets pre-Gregorian reform dates using Gregorian proleptic calendar
fails:Time.gm interprets Julian-Gregorian gap dates using Gregorian proleptic calendar
Expand Down Expand Up @@ -27,7 +26,6 @@ fails:Time.gm interprets all numerals as base 10
fails:Time.gm handles fractional seconds as a Float
fails:Time.gm handles fractional seconds as a Rational
fails:Time.gm handles years from 0 as such
fails:Time.gm accepts various year ranges
fails:Time.gm raises an ArgumentError for out of range month
fails:Time.gm raises an ArgumentError for out of range day
fails:Time.gm raises an ArgumentError for out of range hour
Expand Down
1 change: 0 additions & 1 deletion spec/truffle/tags/core/time/hour_tags.txt
@@ -1,3 +1,2 @@
fails:Time#hour returns the hour of the day (0..23) for a local Time
fails:Time#hour returns the hour of the day for a UTC Time
fails:Time#hour returns the hour of the day for a Time with a fixed offset
3 changes: 0 additions & 3 deletions spec/truffle/tags/core/time/inspect_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/time/local_tags.txt
Expand Up @@ -27,7 +27,6 @@ fails:Time.local interprets all numerals as base 10
fails:Time.local handles fractional seconds as a Float
fails:Time.local handles fractional seconds as a Rational
fails:Time.local handles years from 0 as such
fails:Time.local accepts various year ranges
fails:Time.local raises an ArgumentError for out of range month
fails:Time.local raises an ArgumentError for out of range day
fails:Time.local raises an ArgumentError for out of range hour
Expand Down
1 change: 0 additions & 1 deletion spec/truffle/tags/core/time/mday_tags.txt
@@ -1,3 +1,2 @@
fails:Time#mday returns the day of the month (1..n) for a local Time
fails:Time#mday returns the day of the month for a UTC Time
fails:Time#mday returns the day of the month for a Time with a fixed offset
1 change: 0 additions & 1 deletion spec/truffle/tags/core/time/min_tags.txt
@@ -1,3 +1,2 @@
fails:Time#min returns the minute of the hour (0..59) for a local Time
fails:Time#min returns the minute of the hour for a UTC Time
fails:Time#min returns the minute of the hour for a Time with a fixed offset
1 change: 0 additions & 1 deletion spec/truffle/tags/core/time/mktime_tags.txt
Expand Up @@ -27,7 +27,6 @@ fails:Time.mktime interprets all numerals as base 10
fails:Time.mktime handles fractional seconds as a Float
fails:Time.mktime handles fractional seconds as a Rational
fails:Time.mktime handles years from 0 as such
fails:Time.mktime accepts various year ranges
fails:Time.mktime raises an ArgumentError for out of range month
fails:Time.mktime raises an ArgumentError for out of range day
fails:Time.mktime raises an ArgumentError for out of range hour
Expand Down
1 change: 0 additions & 1 deletion spec/truffle/tags/core/time/mon_tags.txt
@@ -1,3 +1,2 @@
fails:Time#mon returns the month of the year for a local Time
fails:Time#mon returns the month of the year for a UTC Time
fails:Time#mon returns the four digit year for a Time with a fixed offset
1 change: 0 additions & 1 deletion spec/truffle/tags/core/time/month_tags.txt
@@ -1,3 +1,2 @@
fails:Time#month returns the month of the year for a local Time
fails:Time#month returns the month of the year for a UTC Time
fails:Time#month returns the four digit year for a Time with a fixed offset
1 change: 0 additions & 1 deletion spec/truffle/tags/core/time/new_tags.txt
Expand Up @@ -24,7 +24,6 @@ fails:Time.new interprets all numerals as base 10
fails:Time.new handles fractional seconds as a Float
fails:Time.new handles fractional seconds as a Rational
fails:Time.new handles years from 0 as such
fails:Time.new accepts various year ranges
fails:Time.new raises an ArgumentError for out of range month
fails:Time.new raises an ArgumentError for out of range day
fails:Time.new raises an ArgumentError for out of range hour
Expand Down
28 changes: 0 additions & 28 deletions spec/truffle/tags/core/time/strftime_tags.txt
@@ -1,29 +1,5 @@
fails:Time#strftime supports week of year format with %U and %W
fails:Time#strftime supports 12-hr formatting with %l
fails:Time#strftime supports AM/PM formatting with %p
fails:Time#strftime returns the abbreviated weekday with %a
fails:Time#strftime returns the full weekday with %A
fails:Time#strftime returns the abbreviated month with %b
fails:Time#strftime returns the full month with %B
fails:Time#strftime returns the day of the month with %d
fails:Time#strftime returns the 24-based hour with %H
fails:Time#strftime returns the 12-based hour with %I
fails:Time#strftime returns the Julian date with %j
fails:Time#strftime returns the month with %m
fails:Time#strftime returns the minute with %M
fails:Time#strftime returns the second with %S
fails:Time#strftime returns the enumerated day of the week with %w
fails:Time#strftime returns the date alone with %x
fails:Time#strftime returns the time alone with %X
fails:Time#strftime returns the year wihout a century with %y
fails:Time#strftime returns the year with %Y
fails:Time#strftime returns the timezone with %Z
fails:Time#strftime supports am/pm formatting with %P
fails:Time#strftime returns the fractional seconds digits, default is 9 digits (nanosecond) with %N
fails:Time#strftime supports GNU modificators
fails:Time#strftime supports the '-' modifier to drop leading zeros
fails:Time#strftime supports the '-' modifier for padded format directives
fails:Time#strftime passes the format string's encoding to the result string
fails:Time#strftime with %L formats the milliseconds of a second
fails:Time#strftime with %N formats the nanoseconds of of the second with %N
fails:Time#strftime with %N formats the milliseconds of of the second with %3N
Expand All @@ -33,8 +9,4 @@ fails:Time#strftime with %N formats the picoseconds of of the second with %12N
fails:Time#strftime with %z formats a UTC time offset as '+0000'
fails:Time#strftime with %z formats a local time with positive UTC offset as '+HHMM'
fails:Time#strftime with %z formats a local time with negative UTC offset as '-HHMM'
fails:Time#strftime with %z formats a time with fixed positive offset as '+HHMM'
fails:Time#strftime with %z formats a time with fixed negative offset as '-HHMM'
fails:Time#strftime with %z formats a time with fixed offset as '+/-HH:MM' with ':' specifier
fails:Time#strftime with %z formats a time with fixed offset as '+/-HH:MM:SS' with '::' specifier
fails:Time#strftime with %z rounds fixed offset to the nearest second
3 changes: 0 additions & 3 deletions spec/truffle/tags/core/time/to_s_tags.txt

This file was deleted.

2 changes: 0 additions & 2 deletions spec/truffle/tags/core/time/utc_tags.txt
@@ -1,5 +1,4 @@
fails:Time#utc? returns true if time represents a time in UTC (GMT)
fails:Time.utc creates a time based on given values, interpreted as UTC (GMT)
fails:Time.utc creates a time based on given C-style gmtime arguments, interpreted as UTC (GMT)
fails:Time.utc interprets pre-Gregorian reform dates using Gregorian proleptic calendar
fails:Time.utc interprets Julian-Gregorian gap dates using Gregorian proleptic calendar
Expand Down Expand Up @@ -28,7 +27,6 @@ fails:Time.utc interprets all numerals as base 10
fails:Time.utc handles fractional seconds as a Float
fails:Time.utc handles fractional seconds as a Rational
fails:Time.utc handles years from 0 as such
fails:Time.utc accepts various year ranges
fails:Time.utc raises an ArgumentError for out of range month
fails:Time.utc raises an ArgumentError for out of range day
fails:Time.utc raises an ArgumentError for out of range hour
Expand Down
1 change: 0 additions & 1 deletion spec/truffle/tags/core/time/year_tags.txt
@@ -1,3 +1,2 @@
fails:Time#year returns the four digit year for a local Time as an Integer
fails:Time#year returns the four digit year for a UTC Time as an Integer
fails:Time#year returns the four digit year for a Time with a fixed offset
@@ -0,0 +1,41 @@
/*
* 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.rubinius;

import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.source.SourceSection;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.jruby.truffle.nodes.objectstorage.WriteHeadObjectFieldNode;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyTime;
import org.jruby.truffle.runtime.core.TimeOperations;

class JodaDateTimeToRubyTimeNode extends Node {

private final RubyContext context;

@Child private WriteHeadObjectFieldNode writeIsGMTNode = new WriteHeadObjectFieldNode("@is_gmt");
@Child private WriteHeadObjectFieldNode writeOffsetNode = new WriteHeadObjectFieldNode("@offset");

public JodaDateTimeToRubyTimeNode(RubyContext context, SourceSection sourceSection) {
this.context = context;
}

public RubyTime toDateTime(VirtualFrame frame, DateTime dateTime) {
final long miliseconds = dateTime.getMillis();
final RubyTime time = new RubyTime(context.getCoreLibrary().getTimeClass(), TimeOperations.millisecondsToSeconds(miliseconds), TimeOperations.nanosecondsInCurrentSecond(miliseconds));
writeIsGMTNode.execute(time, dateTime.getZone() == DateTimeZone.UTC);
writeOffsetNode.execute(time, dateTime.getZone().getOffset(miliseconds));
return time;
}

}
Expand Up @@ -27,14 +27,14 @@
* Supports {@link TimePrimitiveNodes} by converting a {@link RubyTime} to a {@link DateTime}. We use a node because
* doing this requires accessing instance variables, which we want to use an inline cache for.
*/
class RubyTimeToDateTimeNode extends Node {
class RubyTimeToJodaDateTimeNode extends Node {

private final RubyContext context;

@Child private ReadHeadObjectFieldNode readIsGMTNode = new ReadHeadObjectFieldNode("@is_gmt");
@Child private ReadHeadObjectFieldNode readOffsetNode = new ReadHeadObjectFieldNode("@offset");

public RubyTimeToDateTimeNode(RubyContext context, SourceSection sourceSection) {
public RubyTimeToJodaDateTimeNode(RubyContext context, SourceSection sourceSection) {
this.context = context;
}

Expand All @@ -59,15 +59,25 @@ public DateTime toDateTime(VirtualFrame frame, RubyTime time) {

@CompilerDirectives.TruffleBoundary
private DateTime toDateTime(long seconds, long nanoseconds, boolean isGMT, Object offset) {
long time = TimeOperations.secondsAndNanosecondsToMiliseconds(seconds, nanoseconds);

final DateTimeZone dateTimeZone;

if (isGMT) {
if (isGMT || offset == null || offset == context.getCoreLibrary().getNilObject()) {
dateTimeZone = DateTimeZone.UTC;
} else if (offset instanceof Integer) {
final int intOffset = (int) offset;

// TODO CS 14-Feb-15 why is this negative? Rbx has some comments about having to reserve it
dateTimeZone = DateTimeZone.forOffsetMillis(-intOffset);

// TODO CS 14-Feb-15 we seem to need to actually apply the offset here as well? And twice?
time -= dateTimeZone.getOffset(time) * 2;
} else {
dateTimeZone = org.jruby.RubyTime.getLocalTimeZone(context.getRuntime());
throw new UnsupportedOperationException(offset.getClass().getName());
}

return new DateTime(TimeOperations.secondsAndNanosecondsToMiliseconds(seconds, nanoseconds), dateTimeZone);
return new DateTime(time, dateTimeZone);
}

}
Expand Up @@ -14,6 +14,7 @@
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.jruby.truffle.nodes.objectstorage.ReadHeadObjectFieldNode;
import org.jruby.truffle.nodes.objectstorage.WriteHeadObjectFieldNode;
import org.jruby.truffle.runtime.RubyContext;
Expand Down Expand Up @@ -155,11 +156,11 @@ public long timeUSeconds(RubyTime time) {
@RubiniusPrimitive(name = "time_decompose")
public static abstract class TimeDecomposePrimitiveNode extends RubiniusPrimitiveNode {

@Child private RubyTimeToDateTimeNode toDateTimeNode;
@Child private RubyTimeToJodaDateTimeNode toDateTimeNode;

public TimeDecomposePrimitiveNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
toDateTimeNode = new RubyTimeToDateTimeNode(context, sourceSection);
toDateTimeNode = new RubyTimeToJodaDateTimeNode(context, sourceSection);
}

public TimeDecomposePrimitiveNode(TimeDecomposePrimitiveNode prev) {
Expand Down Expand Up @@ -194,11 +195,11 @@ public Object[] decompose(DateTime dateTime) {
@RubiniusPrimitive(name = "time_strftime")
public static abstract class TimeStrftimePrimitiveNode extends RubiniusPrimitiveNode {

@Child private RubyTimeToDateTimeNode toDateTimeNode;
@Child private RubyTimeToJodaDateTimeNode toDateTimeNode;

public TimeStrftimePrimitiveNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
toDateTimeNode = new RubyTimeToDateTimeNode(context, sourceSection);
toDateTimeNode = new RubyTimeToJodaDateTimeNode(context, sourceSection);
}

public TimeStrftimePrimitiveNode(TimeStrftimePrimitiveNode prev) {
Expand All @@ -223,18 +224,41 @@ public ByteList format(DateTime time, long nanoseconds, ByteList pattern) {
@RubiniusPrimitive(name = "time_s_from_array", needsSelf = false)
public static abstract class TimeSFromArrayPrimitiveNode extends RubiniusPrimitiveNode {

@Child private JodaDateTimeToRubyTimeNode toRubyTime;

public TimeSFromArrayPrimitiveNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
toRubyTime = new JodaDateTimeToRubyTimeNode(context, sourceSection);
}

public TimeSFromArrayPrimitiveNode(TimeSFromArrayPrimitiveNode prev) {
super(prev);
toRubyTime = prev.toRubyTime;
}

@Specialization
public RubyTime timeSFromArray(VirtualFrame frame, int sec, int min, int hour, int mday, int month, int year,
RubyNilClass nsec, int isdst, boolean fromgmt, int utcoffset) {
final DateTime dateTime;
if (fromgmt) {
dateTime = new DateTime(year, month, mday, hour, min, sec, DateTimeZone.UTC);
} else {
// TODO CS 14-Feb-15 why is this negative? Rbx has some comments about having to reserve it
dateTime = new DateTime(year, month, mday, hour, min, sec, DateTimeZone.forOffsetMillis(-(int) TimeOperations.secondsToMiliseconds(utcoffset)));
}
return toRubyTime.toDateTime(frame, dateTime);
}

@Specialization
public RubyTime timeSFromArray(Object sec, Object min, Object hour, Object mday, Object month, Object year,
Object nsec, Object isdst, Object fromgmt, Object utcoffset) {
throw new UnsupportedOperationException("time_s_from_array");
public RubyTime timeSFromArray(VirtualFrame frame, int sec, int min, int hour, int mday, int month, int year,
RubyNilClass nsec, int isdst, boolean fromgmt, RubyNilClass utcoffset) {
final DateTime dateTime;
if (fromgmt) {
dateTime = new DateTime(year, month, mday, hour, min, sec, DateTimeZone.UTC);
} else {
dateTime = new DateTime(year, month, mday, hour, min, sec, DateTimeZone.forOffsetHours(isdst));
}
return toRubyTime.toDateTime(frame, dateTime);
}

}
Expand Down
Expand Up @@ -31,6 +31,10 @@ public static long millisecondsInCurrentSecond(long milliseconds) {
return milliseconds % 1_000;
}

public static long nanosecondsInCurrentSecond(long milliseconds) {
return millisecondsToNanoseconds(millisecondsInCurrentSecond(milliseconds));
}

public static long millisecondsToNanoseconds(long milliseconds) {
return milliseconds * 1_000_000;
}
Expand Down
4 changes: 4 additions & 0 deletions truffle/src/main/ruby/core/rubinius/common/string.rb
Expand Up @@ -144,4 +144,8 @@ def start_with?(*prefixes)
false
end

def self.try_convert(obj)
Rubinius::Type.try_convert obj, String, :to_str
end

end

0 comments on commit 1b5b3d7

Please sign in to comment.