prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  PR #856 introduced regression in macro expansion of more than one block
  PR #856 caused macro expansion to effectively cease after performing macro expansion in one block, due to the logic in `numba/macro.py`:
  
  ``` python
  for blk in blocks.values():
      module_getattr_folding(constants, blk)
      expanded = expanded or expand_macros_in_block(constants, blk)
  ```
  
  
  </issue>
  <code>
  [start of numba/macro.py]
  1 """
  2 Macro handling passes
  3 
  4 Macros are expanded on block-by-block
  5 """
  6 from __future__ import absolute_import, print_function, division
  7 from numba import ir
  8 
  9 
  10 class MacroError(Exception):
  11     '''
  12     An exception thrown during macro expansion
  13     '''
  14     pass
  15 
  16 
  17 def expand_macros(blocks):
  18     '''
  19     Performs macro expansion on blocks
  20 
  21     Args
  22     ----
  23     blocks: list
  24         the blocks to macro-expand
  25     return: bool
  26         True if any macros were expanded
  27     '''
  28     constants = {}
  29     expanded = False
  30     for blk in blocks.values():
  31         module_getattr_folding(constants, blk)
  32         expanded = expanded or expand_macros_in_block(constants, blk)
  33     return expanded
  34 
  35 def module_getattr_folding(constants, block):
  36     '''
  37     Performs constant-folding of getattr instructions within a block. Any
  38     constants defined within the block are also added to the constant pool.
  39 
  40     Args
  41     ----
  42     constants: dict
  43         The pool of constants to use, which will be updated with any new
  44         constants in this block
  45     block: ir.Block
  46         The block to perform constant folding on
  47     '''
  48     for inst in block.body:
  49         if isinstance(inst, ir.Assign):
  50             rhs = inst.value
  51 
  52             if isinstance(rhs, ir.Global):
  53                 constants[inst.target.name] = rhs.value
  54 
  55             elif isinstance(rhs, ir.Expr) and rhs.op == 'getattr':
  56                 if rhs.value.name in constants:
  57                     base = constants[rhs.value.name]
  58                     constants[inst.target.name] = getattr(base, rhs.attr)
  59 
  60             elif isinstance(rhs, ir.Const):
  61                 constants[inst.target.name] = rhs.value
  62 
  63             elif isinstance(rhs, ir.Var) and rhs.name in constants:
  64                 constants[inst.target.name] = constants[rhs.name]
  65 
  66             elif isinstance(rhs, ir.FreeVar):
  67                 constants[inst.target.name] = rhs.value
  68 
  69 def expand_macros_in_block(constants, block):
  70     '''
  71     Performs macro expansion on a block.
  72 
  73     Args
  74     ----
  75     constants: dict
  76         The pool of constants which contains the values which contains mappings
  77         from variable names to callee names
  78     block: ir.Block
  79         The block to perform macro expansion on
  80     return: bool
  81         True if any macros were expanded
  82     '''
  83     expanded = False
  84     for inst in block.body:
  85         if isinstance(inst, ir.Assign):
  86             rhs = inst.value
  87             if isinstance(rhs, ir.Expr) and rhs.op == 'call':
  88                 callee = rhs.func
  89                 macro = constants.get(callee.name)
  90                 if isinstance(macro, Macro):
  91                     # Rewrite calling macro
  92                     assert macro.callable
  93                     args = [constants[arg.name] for arg in rhs.args]
  94                     kws = dict((k, constants[v.name]) for k, v in rhs.kws)
  95                     try:
  96                         result = macro.func(*args, **kws)
  97                     except BaseException as e:
  98                         msg = str(e)
  99                         headfmt = "Macro expansion failed at {line}"
  100                         head = headfmt.format(line=inst.loc)
  101                         newmsg = "{0}:\n{1}".format(head, msg)
  102                         raise MacroError(newmsg)
  103                     if result:
  104                         # Insert a new function
  105                         result.loc = rhs.loc
  106                         inst.value = ir.Expr.call(func=result, args=rhs.args,
  107                                                   kws=rhs.kws, loc=rhs.loc)
  108                         expanded = True
  109             elif isinstance(rhs, ir.Expr) and rhs.op == 'getattr':
  110                 # Rewrite get attribute to macro call
  111                 # Non-calling macro must be triggered by get attribute
  112                 base = constants.get(rhs.value.name)
  113                 if base is not None:
  114                     value = getattr(base, rhs.attr)
  115                     if isinstance(value, Macro):
  116                         macro = value
  117                         if not macro.callable:
  118                             intr = ir.Intrinsic(macro.name, macro.func, args=())
  119                             inst.value = ir.Expr.call(func=intr, args=(),
  120                                                       kws=(), loc=rhs.loc)
  121                             expanded = True
  122     return expanded
  123 
  124 
  125 class Macro(object):
  126     '''
  127     A macro object is expanded to a function call
  128 
  129     Args
  130     ----
  131     name: str
  132         Name of this Macro
  133     func: function
  134         Function that evaluates the macro expansion
  135     callable: bool
  136         True if the Macro represents a callable function.
  137         False if it is represents some other type.
  138     argnames: list
  139         If ``callable`` is True, this holds a list of the names of arguments
  140         to the function.
  141     '''
  142 
  143     __slots__ = 'name', 'func', 'callable', 'argnames'
  144 
  145     def __init__(self, name, func, callable=False, argnames=None):
  146         self.name = name
  147         self.func = func
  148         self.callable = callable
  149         self.argnames = argnames
  150 
  151     def __repr__(self):
  152         return '<macro %s -> %s>' % (self.name, self.func)
  153 
  154
  [end of numba/macro.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/numba/macro.py b/numba/macro.py
  --- a/numba/macro.py
  +++ b/numba/macro.py
  @@ -29,7 +29,8 @@
       expanded = False
       for blk in blocks.values():
           module_getattr_folding(constants, blk)
  -        expanded = expanded or expand_macros_in_block(constants, blk)
  +        block_expanded = expand_macros_in_block(constants, blk)
  +        expanded = expanded or block_expanded
       return expanded
   
   def module_getattr_folding(constants, block):
  
verification_info: {"golden_diff": "diff --git a/numba/macro.py b/numba/macro.py\n--- a/numba/macro.py\n+++ b/numba/macro.py\n@@ -29,7 +29,8 @@\n     expanded = False\n     for blk in blocks.values():\n         module_getattr_folding(constants, blk)\n-        expanded = expanded or expand_macros_in_block(constants, blk)\n+        block_expanded = expand_macros_in_block(constants, blk)\n+        expanded = expanded or block_expanded\n     return expanded\n \n def module_getattr_folding(constants, block):\n", "issue": "PR #856 introduced regression in macro expansion of more than one block\nPR #856 caused macro expansion to effectively cease after performing macro expansion in one block, due to the logic in `numba/macro.py`:\n\n``` python\nfor blk in blocks.values():\n    module_getattr_folding(constants, blk)\n    expanded = expanded or expand_macros_in_block(constants, blk)\n```\n\n", "before_files": [{"content": "\"\"\"\nMacro handling passes\n\nMacros are expanded on block-by-block\n\"\"\"\nfrom __future__ import absolute_import, print_function, division\nfrom numba import ir\n\n\nclass MacroError(Exception):\n    '''\n    An exception thrown during macro expansion\n    '''\n    pass\n\n\ndef expand_macros(blocks):\n    '''\n    Performs macro expansion on blocks\n\n    Args\n    ----\n    blocks: list\n        the blocks to macro-expand\n    return: bool\n        True if any macros were expanded\n    '''\n    constants = {}\n    expanded = False\n    for blk in blocks.values():\n        module_getattr_folding(constants, blk)\n        expanded = expanded or expand_macros_in_block(constants, blk)\n    return expanded\n\ndef module_getattr_folding(constants, block):\n    '''\n    Performs constant-folding of getattr instructions within a block. Any\n    constants defined within the block are also added to the constant pool.\n\n    Args\n    ----\n    constants: dict\n        The pool of constants to use, which will be updated with any new\n        constants in this block\n    block: ir.Block\n        The block to perform constant folding on\n    '''\n    for inst in block.body:\n        if isinstance(inst, ir.Assign):\n            rhs = inst.value\n\n            if isinstance(rhs, ir.Global):\n                constants[inst.target.name] = rhs.value\n\n            elif isinstance(rhs, ir.Expr) and rhs.op == 'getattr':\n                if rhs.value.name in constants:\n                    base = constants[rhs.value.name]\n                    constants[inst.target.name] = getattr(base, rhs.attr)\n\n            elif isinstance(rhs, ir.Const):\n                constants[inst.target.name] = rhs.value\n\n            elif isinstance(rhs, ir.Var) and rhs.name in constants:\n                constants[inst.target.name] = constants[rhs.name]\n\n            elif isinstance(rhs, ir.FreeVar):\n                constants[inst.target.name] = rhs.value\n\ndef expand_macros_in_block(constants, block):\n    '''\n    Performs macro expansion on a block.\n\n    Args\n    ----\n    constants: dict\n        The pool of constants which contains the values which contains mappings\n        from variable names to callee names\n    block: ir.Block\n        The block to perform macro expansion on\n    return: bool\n        True if any macros were expanded\n    '''\n    expanded = False\n    for inst in block.body:\n        if isinstance(inst, ir.Assign):\n            rhs = inst.value\n            if isinstance(rhs, ir.Expr) and rhs.op == 'call':\n                callee = rhs.func\n                macro = constants.get(callee.name)\n                if isinstance(macro, Macro):\n                    # Rewrite calling macro\n                    assert macro.callable\n                    args = [constants[arg.name] for arg in rhs.args]\n                    kws = dict((k, constants[v.name]) for k, v in rhs.kws)\n                    try:\n                        result = macro.func(*args, **kws)\n                    except BaseException as e:\n                        msg = str(e)\n                        headfmt = \"Macro expansion failed at {line}\"\n                        head = headfmt.format(line=inst.loc)\n                        newmsg = \"{0}:\\n{1}\".format(head, msg)\n                        raise MacroError(newmsg)\n                    if result:\n                        # Insert a new function\n                        result.loc = rhs.loc\n                        inst.value = ir.Expr.call(func=result, args=rhs.args,\n                                                  kws=rhs.kws, loc=rhs.loc)\n                        expanded = True\n            elif isinstance(rhs, ir.Expr) and rhs.op == 'getattr':\n                # Rewrite get attribute to macro call\n                # Non-calling macro must be triggered by get attribute\n                base = constants.get(rhs.value.name)\n                if base is not None:\n                    value = getattr(base, rhs.attr)\n                    if isinstance(value, Macro):\n                        macro = value\n                        if not macro.callable:\n                            intr = ir.Intrinsic(macro.name, macro.func, args=())\n                            inst.value = ir.Expr.call(func=intr, args=(),\n                                                      kws=(), loc=rhs.loc)\n                            expanded = True\n    return expanded\n\n\nclass Macro(object):\n    '''\n    A macro object is expanded to a function call\n\n    Args\n    ----\n    name: str\n        Name of this Macro\n    func: function\n        Function that evaluates the macro expansion\n    callable: bool\n        True if the Macro represents a callable function.\n        False if it is represents some other type.\n    argnames: list\n        If ``callable`` is True, this holds a list of the names of arguments\n        to the function.\n    '''\n\n    __slots__ = 'name', 'func', 'callable', 'argnames'\n\n    def __init__(self, name, func, callable=False, argnames=None):\n        self.name = name\n        self.func = func\n        self.callable = callable\n        self.argnames = argnames\n\n    def __repr__(self):\n        return '<macro %s -> %s>' % (self.name, self.func)\n\n", "path": "numba/macro.py"}]}