def test_single_if_else_w_following_undetermined(self): def impl(x): x_is_none_work = False if x is None: x_is_none_work = True else: dead = 7 # noqa: F841 # no effect if x_is_none_work: y = 10 else: y = -3 return y self.assert_prune(impl, (types.NoneType('none'),), [False, None], None) self.assert_prune(impl, (types.IntegerLiteral(10),), [True, None], 10) def impl(x): x_is_none_work = False if x is None: x_is_none_work = True else: pass # force the True branch exit to be on backbone if x_is_none_work: y = 10 else: y = -3 return y self.assert_prune(impl, (types.NoneType('none'),), [None, None], None) self.assert_prune(impl, (types.IntegerLiteral(10),), [True, None], 10)
def test_single_if(self): def impl(x): if 1 == 0: return 3.14159 self.assert_prune(impl, (types.NoneType('none'),), [True], None) def impl(x): if 1 == 1: return 3.14159 self.assert_prune(impl, (types.NoneType('none'),), [False], None) def impl(x): if x is None: return 3.14159 self.assert_prune(impl, (types.NoneType('none'),), [False], None) self.assert_prune(impl, (types.IntegerLiteral(10),), [True], 10) def impl(x): if x == 10: return 3.14159 self.assert_prune(impl, (types.NoneType('none'),), [True], None) self.assert_prune(impl, (types.IntegerLiteral(10),), [None], 10) def impl(x): if x == 10: z = 3.14159 # noqa: F841 # no effect self.assert_prune(impl, (types.NoneType('none'),), [True], None) self.assert_prune(impl, (types.IntegerLiteral(10),), [None], 10)
def test_double_if_else_non_literal_const(self): def impl(x): one_hundred = 100 if x == one_hundred: y = 3.14159 else: y = 1.61803 return y # no prune as compilation specialization on literal value not permitted self.assert_prune(impl, (types.IntegerLiteral(10), ), [None], 10) self.assert_prune(impl, (types.IntegerLiteral(100), ), [None], 100)
def test_single_if_const_val(self): def impl(x): if x == 100: return 3.14159 self.assert_prune(impl, (types.NoneType('none'), ), [True], None) self.assert_prune(impl, (types.IntegerLiteral(100), ), [None], 100) def impl(x): # switch the condition order if 100 == x: return 3.14159 self.assert_prune(impl, (types.NoneType('none'), ), [True], None) self.assert_prune(impl, (types.IntegerLiteral(100), ), [None], 100)
def test_single_if_else_two_const_val(self): def impl(x, y): if x == y: return 3.14159 else: return 1.61803 self.assert_prune(impl, (types.IntegerLiteral(100),) * 2, [None], 100, 100) self.assert_prune(impl, (types.NoneType('none'),) * 2, [False], None, None) self.assert_prune(impl, (types.IntegerLiteral(100), types.NoneType('none'),), [True], 100, None) self.assert_prune(impl, (types.IntegerLiteral(100), types.IntegerLiteral(1000)), [None], 100, 1000)
def test_single_if_else(self): def impl(x): if x is None: return 3.14159 else: return 1.61803 self.assert_prune(impl, (types.NoneType('none'), ), [False], None) self.assert_prune(impl, (types.IntegerLiteral(10), ), [True], 10)
def test_cond_is_kwarg_value(self): def impl(x=1000): if x == 1000: y = 10 else: y = 40 if x != 1000: z = 100 else: z = 400 return z, y self.assert_prune(impl, (types.Omitted(1000),), [None, None], 1000) self.assert_prune(impl, (types.IntegerLiteral(1000),), [None, None], 1000) self.assert_prune(impl, (types.IntegerLiteral(0),), [None, None], 0) self.assert_prune(impl, (types.NoneType('none'),), [True, False], None)
def test_freevar_bake_in(self): _FREEVAR = 123 def impl(x): if _FREEVAR == 123: return x else: return x + 10 self.assert_prune(impl, (types.IntegerLiteral(1), ), [False], 1) _FREEVAR = 12 def impl(x): if _FREEVAR == 123: return x else: return x + 10 self.assert_prune(impl, (types.IntegerLiteral(1), ), [True], 1)
def test_issue_868(self): ''' Summary: multiplying a scalar by a non-scalar would cause a crash in type inference because TimeDeltaMixOp always assumed at least one of its operands was an NPTimeDelta in its generic() method. ''' with self.assertRaises(TypingError) as raises: compile_isolated(issue_868, (types.Array(types.int32, 1, 'C'), )) expected = ( "Invalid use of Function(<built-in function mul>) with argument(s) of type(s): (UniTuple({0} x 1), {1})" .format(str(types.intp), types.IntegerLiteral(2))) self.assertIn(expected, str(raises.exception)) self.assertIn("[1] During: typing of", str(raises.exception))
def test_global_bake_in(self): def impl(x): if _GLOBAL == 123: return x else: return x + 10 self.assert_prune(impl, (types.IntegerLiteral(1), ), [False], 1) global _GLOBAL tmp = _GLOBAL try: _GLOBAL = 5 def impl(x): if _GLOBAL == 123: return x else: return x + 10 self.assert_prune(impl, (types.IntegerLiteral(1), ), [True], 1) finally: _GLOBAL = tmp
def test_single_two_branches_same_cond(self): def impl(x): if x is None: y = 10 else: y = 40 if x is not None: z = 100 else: z = 400 return z, y self.assert_prune(impl, (types.NoneType('none'),), [False, True], None) self.assert_prune(impl, (types.IntegerLiteral(10),), [True, False], 10)
def test_cond_is_kwarg_none(self): def impl(x=None): if x is None: y = 10 else: y = 40 if x is not None: z = 100 else: z = 400 return z, y self.assert_prune(impl, (types.Omitted(None),), [False, True], None) self.assert_prune(impl, (types.NoneType('none'),), [False, True], None) self.assert_prune(impl, (types.IntegerLiteral(10),), [True, False], 10)
def test_double_if_else_rt_const(self): def impl(x): one_hundred = 100 x_is_none_work = 4 if x is None: x_is_none_work = 100 else: dead = 7 # noqa: F841 # no effect if x_is_none_work == one_hundred: y = 10 else: y = -3 return y, x_is_none_work self.assert_prune(impl, (types.NoneType('none'),), [False, None], None) self.assert_prune(impl, (types.IntegerLiteral(10),), [True, None], 10)
def test_cond_rewrite_is_correct(self): # this checks that when a condition is replaced, it is replace by a # true/false bit that correctly represents the evaluated condition def fn(x): if x is None: return 10 return 12 def check(func, arg_tys, bit_val): func_ir = compile_to_ir(func) # check there is 1 branch before_branches = self.find_branches(func_ir) self.assertEqual(len(before_branches), 1) # check the condition in the branch is a binop condition_var = before_branches[0].cond condition_defn = ir_utils.get_definition(func_ir, condition_var) self.assertEqual(condition_defn.op, 'binop') # do the prune, this should kill the dead branch and rewrite the #'condition to a true/false const bit if self._DEBUG: print("=" * 80) print("before prune") func_ir.dump() dead_branch_prune(func_ir, arg_tys) if self._DEBUG: print("=" * 80) print("after prune") func_ir.dump() # after mutation, the condition should be a const value `bit_val` new_condition_defn = ir_utils.get_definition( func_ir, condition_var) self.assertTrue(isinstance(new_condition_defn, ir.Const)) self.assertEqual(new_condition_defn.value, bit_val) check(fn, (types.NoneType('none'), ), 1) check(fn, (types.IntegerLiteral(10), ), 0)