4040 */
4141package com .oracle .graal .python .builtins .objects .cext .capi ;
4242
43+ import com .oracle .graal .python .builtins .objects .PNone ;
4344import com .oracle .graal .python .builtins .objects .PythonAbstractObject .PInteropGetAttributeNode ;
4445import com .oracle .graal .python .builtins .objects .cext .capi .CArrayWrappers .CByteArrayWrapper ;
46+ import com .oracle .graal .python .builtins .objects .cext .capi .CExtNodes .ToSulongNode ;
4547import com .oracle .graal .python .builtins .objects .object .PythonObject ;
4648import 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 ;
4850import com .oracle .graal .python .runtime .PythonOptions ;
51+ import com .oracle .truffle .api .CompilerDirectives ;
4952import com .oracle .truffle .api .dsl .Cached ;
5053import com .oracle .truffle .api .dsl .GenerateUncached ;
5154import com .oracle .truffle .api .dsl .ImportStatic ;
5760@ ImportStatic ({NativeMember .class , PythonOptions .class })
5861public abstract class PyDateTimeMRNode extends Node {
5962
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 );
6181
6282 public static final String YEAR = "year" ;
6383 public static final String MONTH = "month" ;
@@ -66,12 +86,15 @@ public abstract class PyDateTimeMRNode extends Node {
6686 public static final String MIN = "minute" ;
6787 public static final String SEC = "second" ;
6888 public static final String USEC = "microsecond" ;
89+ public static final String TZINFO = "tzinfo" ;
6990
7091 /**
7192 * Fields are packed into successive bytes, each viewed as unsigned and big-endian, unless
7293 * otherwise noted:
7394 *
74- * <code>
95+ * PyDateTime_DateTime:
96+ *
97+ * <pre>
7598 * byte offset
7699 * 0 year 2 bytes, 1-9999
77100 * 2 month 1 byte, 1-12
@@ -81,10 +104,32 @@ public abstract class PyDateTimeMRNode extends Node {
81104 * 6 second 1 byte, 0-59
82105 * 7 usecond 3 bytes, 0-999999
83106 * 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>
85129 */
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 ,
88133 @ Cached PInteropGetAttributeNode getYearNode ,
89134 @ Cached PInteropGetAttributeNode getMonthNode ,
90135 @ Cached PInteropGetAttributeNode getDayNode ,
@@ -93,39 +138,63 @@ Object doData(PythonObject object, @SuppressWarnings("unused") String key,
93138 @ Cached PInteropGetAttributeNode getSecNode ,
94139 @ Cached PInteropGetAttributeNode getUSecNode ,
95140 @ CachedLibrary (limit = "getCallSiteInlineCacheMaxDepth()" ) PythonObjectLibrary lib ) {
141+
96142 // 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+ }
112168
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+ }
113183 return new CByteArrayWrapper (data );
114184 }
115185
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 ();
118195 }
119196
120197 protected static boolean eq (NativeMember expected , String actual ) {
121198 return expected .getMemberName ().equals (actual );
122199 }
123-
124- public static PyDateTimeMRNode create () {
125- return PyDateTimeMRNodeGen .create ();
126- }
127-
128- public static PyDateTimeMRNode getUncached () {
129- return PyDateTimeMRNodeGen .getUncached ();
130- }
131200}
0 commit comments