@@ -171,66 +171,43 @@ dummy_func(void) {
171171 bool rhs_int = sym_matches_type (right , & PyLong_Type );
172172 bool lhs_float = sym_matches_type (left , & PyFloat_Type );
173173 bool rhs_float = sym_matches_type (right , & PyFloat_Type );
174- if ((!lhs_int && !lhs_float ) || (!rhs_int && !rhs_float )) {
174+ if (!((lhs_int || lhs_float ) && (rhs_int || rhs_float ))) {
175+ // There's something other than an int or float involved:
175176 res = sym_new_unknown (ctx );
176- goto binary_op_done ;
177- }
178- if (oparg == NB_POWER || oparg == NB_INPLACE_POWER ) {
179- // This one's fun: the *type* of the result depends on the *values*
180- // being exponentiated. But exponents with one constant part are
181- // reasonably common, so it's probably worth trying to be precise:
182- PyObject * lhs_const = sym_get_const (left );
183- PyObject * rhs_const = sym_get_const (right );
184- if (lhs_int && rhs_int ) {
185- if (rhs_const == NULL ) {
186- // Unknown RHS means either int or float:
187- res = sym_new_unknown (ctx );
188- goto binary_op_done ;
189- }
190- if (!_PyLong_IsNegative ((PyLongObject * )rhs_const )) {
191- // Non-negative RHS means int:
192- res = sym_new_type (ctx , & PyLong_Type );
193- goto binary_op_done ;
194- }
195- // Negative RHS uses float_pow...
177+ }
178+ else if (oparg == NB_POWER || oparg == NB_INPLACE_POWER ) {
179+ // This one's fun... the *type* of the result depends on the
180+ // *values* being exponentiated. However, exponents with one
181+ // constant part are reasonably common, so it's probably worth
182+ // trying to infer some simple cases:
183+ // - A: 1 ** 1 -> 1 (int ** int -> int)
184+ // - B: 1 ** -1 -> 1.0 (int ** int -> float)
185+ // - C: 1.0 ** 1 -> 1.0 (float ** int -> float)
186+ // - D: 1 ** 1.0 -> 1.0 (int ** float -> float)
187+ // - E: -1 ** 0.5 ~> 1j (int ** float -> complex)
188+ // - F: 1.0 ** 1.0 -> 1.0 (float ** float -> float)
189+ // - G: -1.0 ** 0.5 ~> 1j (float ** float -> complex)
190+ if (rhs_float ) {
191+ // Case D, E, F, or G... can't know without the sign of the LHS
192+ // or whether the RHS is whole, which isn't worth the effort:
193+ res = sym_new_unknown (ctx );
196194 }
197- // Negative LHS *and* non-integral RHS means complex. So we need to
198- // disprove at least one to prove a float result:
199- if (rhs_int ) {
200- // Integral RHS means float:
195+ else if (lhs_float ) {
196+ // Case C:
201197 res = sym_new_type (ctx , & PyFloat_Type );
202- goto binary_op_done ;
203198 }
204- if (rhs_const ) {
205- double rhs_double = PyFloat_AS_DOUBLE (rhs_const );
206- if (rhs_double == floor (rhs_double )) {
207- // Integral RHS means float:
208- res = sym_new_type (ctx , & PyFloat_Type );
209- goto binary_op_done ;
210- }
199+ else if (!sym_is_const (right )) {
200+ // Case A or B... can't know without the sign of the RHS:
201+ res = sym_new_unknown (ctx );
211202 }
212- if (lhs_const ) {
213- if (lhs_int ) {
214- if (!_PyLong_IsNegative ((PyLongObject * )lhs_const )) {
215- // Non-negative LHS means float:
216- res = sym_new_type (ctx , & PyFloat_Type );
217- goto binary_op_done ;
218- }
219- }
220- else if (0.0 <= PyFloat_AS_DOUBLE (lhs_const )) {
221- // Non-negative LHS means float:
222- res = sym_new_type (ctx , & PyFloat_Type );
223- goto binary_op_done ;
224- }
225- if (rhs_const ) {
226- // If we have two constants and failed to disprove that it's
227- // complex, then it's complex:
228- res = sym_new_type (ctx , & PyComplex_Type );
229- goto binary_op_done ;
230- }
203+ else if (_PyLong_IsNegative ((PyLongObject * )sym_get_const (right ))) {
204+ // Case B:
205+ res = sym_new_type (ctx , & PyFloat_Type );
206+ }
207+ else {
208+ // Case A:
209+ res = sym_new_type (ctx , & PyLong_Type );
231210 }
232- // Couldn't prove anything. It's either float or complex:
233- res = sym_new_unknown (ctx );
234211 }
235212 else if (oparg == NB_TRUE_DIVIDE || oparg == NB_INPLACE_TRUE_DIVIDE ) {
236213 res = sym_new_type (ctx , & PyFloat_Type );
@@ -241,7 +218,6 @@ dummy_func(void) {
241218 else {
242219 res = sym_new_type (ctx , & PyFloat_Type );
243220 }
244- binary_op_done :
245221 }
246222
247223 op (_BINARY_OP_ADD_INT , (left , right -- res )) {
0 commit comments