40
40
*/
41
41
package com .oracle .graal .python .builtins .objects .cext .capi ;
42
42
43
+ import com .oracle .graal .python .builtins .objects .PNone ;
43
44
import com .oracle .graal .python .builtins .objects .PythonAbstractObject .PInteropGetAttributeNode ;
44
45
import com .oracle .graal .python .builtins .objects .cext .capi .CArrayWrappers .CByteArrayWrapper ;
46
+ import com .oracle .graal .python .builtins .objects .cext .capi .CExtNodes .ToSulongNode ;
45
47
import com .oracle .graal .python .builtins .objects .object .PythonObject ;
46
48
import com .oracle .graal .python .builtins .objects .object .PythonObjectLibrary ;
47
- import com .oracle .graal .python .nodes .attributes .GetAttributeNode ;
49
+ import com .oracle .graal .python .nodes .attributes .ReadAttributeFromObjectNode ;
48
50
import com .oracle .graal .python .runtime .PythonOptions ;
51
+ import com .oracle .truffle .api .CompilerDirectives ;
49
52
import com .oracle .truffle .api .dsl .Cached ;
50
53
import com .oracle .truffle .api .dsl .GenerateUncached ;
51
54
import com .oracle .truffle .api .dsl .ImportStatic ;
57
60
@ ImportStatic ({NativeMember .class , PythonOptions .class })
58
61
public abstract class PyDateTimeMRNode extends Node {
59
62
60
- public abstract Object execute (PythonObject object , String key );
63
+ public enum DateTimeMode {
64
+ DATE ,
65
+ TIME ,
66
+ DATE_TIME
67
+ }
68
+
69
+ static DateTimeMode getModeFromTypeName (String typeName ) {
70
+ if ("date" .equals (typeName )) {
71
+ return DateTimeMode .DATE ;
72
+ } else if ("datetime" .equals (typeName )) {
73
+ return DateTimeMode .DATE_TIME ;
74
+ } else if ("time" .equals (typeName )) {
75
+ return DateTimeMode .TIME ;
76
+ }
77
+ return null ;
78
+ }
79
+
80
+ public abstract Object execute (PythonObject object , String key , DateTimeMode mode );
61
81
62
82
public static final String YEAR = "year" ;
63
83
public static final String MONTH = "month" ;
@@ -66,12 +86,15 @@ public abstract class PyDateTimeMRNode extends Node {
66
86
public static final String MIN = "minute" ;
67
87
public static final String SEC = "second" ;
68
88
public static final String USEC = "microsecond" ;
89
+ public static final String TZINFO = "tzinfo" ;
69
90
70
91
/**
71
92
* Fields are packed into successive bytes, each viewed as unsigned and big-endian, unless
72
93
* otherwise noted:
73
94
*
74
- * <code>
95
+ * PyDateTime_DateTime:
96
+ *
97
+ * <pre>
75
98
* byte offset
76
99
* 0 year 2 bytes, 1-9999
77
100
* 2 month 1 byte, 1-12
@@ -81,10 +104,32 @@ public abstract class PyDateTimeMRNode extends Node {
81
104
* 6 second 1 byte, 0-59
82
105
* 7 usecond 3 bytes, 0-999999
83
106
* 10
84
- * </code>
107
+ * </pre>
108
+ *
109
+ * PyDateTime_Date:
110
+ *
111
+ * <pre>
112
+ * byte offset
113
+ * 0 year 2 bytes, 1-9999
114
+ * 2 month 1 byte, 1-12
115
+ * 3 day 1 byte, 1-31
116
+ * 10
117
+ * </pre>
118
+ *
119
+ * PyDateTime_Time:
120
+ *
121
+ * <pre>
122
+ * byte offset
123
+ * 4 hour 1 byte, 0-23
124
+ * 5 minute 1 byte, 0-59
125
+ * 6 second 1 byte, 0-59
126
+ * 7 usecond 3 bytes, 0-999999
127
+ * 10
128
+ * </pre>
85
129
*/
86
- @ Specialization (guards = "eq(DATETIME_DATA,key)" )
87
- Object doData (PythonObject object , @ SuppressWarnings ("unused" ) String key ,
130
+ @ Specialization (guards = {"eq(DATETIME_DATA, key)" , "cachedMode == mode" , "cachedMode != null" }, limit = "1" )
131
+ static Object doData (PythonObject object , @ SuppressWarnings ("unused" ) String key , @ SuppressWarnings ("unused" ) DateTimeMode mode ,
132
+ @ Cached ("mode" ) DateTimeMode cachedMode ,
88
133
@ Cached PInteropGetAttributeNode getYearNode ,
89
134
@ Cached PInteropGetAttributeNode getMonthNode ,
90
135
@ Cached PInteropGetAttributeNode getDayNode ,
@@ -93,39 +138,63 @@ Object doData(PythonObject object, @SuppressWarnings("unused") String key,
93
138
@ Cached PInteropGetAttributeNode getSecNode ,
94
139
@ Cached PInteropGetAttributeNode getUSecNode ,
95
140
@ CachedLibrary (limit = "getCallSiteInlineCacheMaxDepth()" ) PythonObjectLibrary lib ) {
141
+
96
142
// passing null here should be ok, since we should be in an interop situation
97
- int year = lib .asSize (getYearNode .execute (object , YEAR ));
98
- int month = lib .asSize (getMonthNode .execute (object , MONTH ));
99
- int day = lib .asSize (getDayNode .execute (object , DAY ));
100
- int hour = lib .asSize (getHourNode .execute (object , HOUR ));
101
- int min = lib .asSize (getMinNode .execute (object , MIN ));
102
- int sec = lib .asSize (getSecNode .execute (object , SEC ));
103
- int usec = lib .asSize (getUSecNode .execute (object , USEC ));
104
- assert year >= 0 && year < 0x10000 ;
105
- assert month >= 0 && month < 0x100 ;
106
- assert day >= 0 && day < 0x100 ;
107
- assert hour >= 0 && hour < 0x100 ;
108
- assert min >= 0 && min < 0x100 ;
109
- assert sec >= 0 && sec < 0x100 ;
110
- assert usec >= 0 && sec < 0x1000000 ;
111
- byte [] data = new byte []{(byte ) (year >> 8 ), (byte ) year , (byte ) month , (byte ) day , (byte ) hour , (byte ) min , (byte ) sec , (byte ) (usec >> 16 ), (byte ) (usec >> 8 ), (byte ) usec };
143
+ int year = -1 ;
144
+ int month = -1 ;
145
+ int day = -1 ;
146
+ int hour = -1 ;
147
+ int min = -1 ;
148
+ int sec = -1 ;
149
+ int usec = -1 ;
150
+ if (cachedMode == DateTimeMode .DATE || cachedMode == DateTimeMode .DATE_TIME ) {
151
+ year = lib .asSize (getYearNode .execute (object , YEAR ));
152
+ month = lib .asSize (getMonthNode .execute (object , MONTH ));
153
+ day = lib .asSize (getDayNode .execute (object , DAY ));
154
+ assert year >= 0 && year < 0x10000 ;
155
+ assert month >= 0 && month < 0x100 ;
156
+ assert day >= 0 && day < 0x100 ;
157
+ }
158
+ if (cachedMode == DateTimeMode .TIME || cachedMode == DateTimeMode .DATE_TIME ) {
159
+ hour = lib .asSize (getHourNode .execute (object , HOUR ));
160
+ min = lib .asSize (getMinNode .execute (object , MIN ));
161
+ sec = lib .asSize (getSecNode .execute (object , SEC ));
162
+ usec = lib .asSize (getUSecNode .execute (object , USEC ));
163
+ assert hour >= 0 && hour < 0x100 ;
164
+ assert min >= 0 && min < 0x100 ;
165
+ assert sec >= 0 && sec < 0x100 ;
166
+ assert usec >= 0 && sec < 0x1000000 ;
167
+ }
112
168
169
+ byte [] data ;
170
+ switch (cachedMode ) {
171
+ case DATE :
172
+ data = new byte []{(byte ) (year >> 8 ), (byte ) year , (byte ) month , (byte ) day };
173
+ break ;
174
+ case TIME :
175
+ data = new byte []{(byte ) hour , (byte ) min , (byte ) sec , (byte ) (usec >> 16 ), (byte ) (usec >> 8 ), (byte ) usec };
176
+ break ;
177
+ case DATE_TIME :
178
+ data = new byte []{(byte ) (year >> 8 ), (byte ) year , (byte ) month , (byte ) day , (byte ) hour , (byte ) min , (byte ) sec , (byte ) (usec >> 16 ), (byte ) (usec >> 8 ), (byte ) usec };
179
+ break ;
180
+ default :
181
+ throw CompilerDirectives .shouldNotReachHere ();
182
+ }
113
183
return new CByteArrayWrapper (data );
114
184
}
115
185
116
- protected static GetAttributeNode createAttr (String expected ) {
117
- return GetAttributeNode .create (expected , null );
186
+ @ Specialization (guards = "eq(DATETIME_TZINFO, key)" )
187
+ static Object doTzinfo (PythonObject object , @ SuppressWarnings ("unused" ) String key , @ SuppressWarnings ("unused" ) DateTimeMode mode ,
188
+ @ Cached ReadAttributeFromObjectNode getTzinfoNode ,
189
+ @ Cached ToSulongNode toSulongNode ) {
190
+ Object value = getTzinfoNode .execute (object , TZINFO );
191
+ if (value != PNone .NO_VALUE ) {
192
+ return toSulongNode .execute (value );
193
+ }
194
+ throw CompilerDirectives .shouldNotReachHere ();
118
195
}
119
196
120
197
protected static boolean eq (NativeMember expected , String actual ) {
121
198
return expected .getMemberName ().equals (actual );
122
199
}
123
-
124
- public static PyDateTimeMRNode create () {
125
- return PyDateTimeMRNodeGen .create ();
126
- }
127
-
128
- public static PyDateTimeMRNode getUncached () {
129
- return PyDateTimeMRNodeGen .getUncached ();
130
- }
131
200
}
0 commit comments