code: def _if_statement(test, if_function, else_function) -> None:
      
      if isinstance(test, Addr):
          token = _program_context.set(Program())
          if_function()
          if_program = _program_context.get()
          _program_context.reset(token)
  
          if else_function:
              token = _program_context.set(Program())
              else_function()
              else_program = _program_context.get()
              _program_context.reset(token)
          else:
              else_program = None
  
          program = _program_context.get()
          program.if_then(test, if_program, else_program)
      else:
          if test:
              if_function()
          elif else_function:
              else_function()
docs: Evaluate an if statement within a @magicquil block.
  
      If the test value is a Quil Addr then unwind it into quil code equivalent to an if then statement using jumps. Both
      sides of the if statement need to be evaluated and placed into separate Programs, which is why we create new
      program contexts for their evaluation.
  
      If the test value is not a Quil Addr then fall back to what Python would normally do with an if statement.
  
      Params are:
          if <test>:
              <if_function>
          else:
              <else_function>
  
      NB: This function must be named exactly _if_statement and be in scope for the ast transformer