---
# System prepended metadata

title: Initial target block selection
tags: [decompiler]

---

---
tags: decompiler
---


# Initial target block selection

Original file (fig 1):
![](https://i.imgur.com/jCyIfL8.png)


Full error output (fig 2):
![](https://i.imgur.com/E9oHec9.png)

CFG (fig 3): 
![](https://i.imgur.com/3tZELu3.png)

For initial target block selection, we first parse the error from uncompyle6 (fig 2) to pin point the initial instruction where the decompiler fails. From the error, we find the offset and the function name where the decompiler fails to parse. Using this information, we know the exact instruction to start from and so in cfg we mark the initial target block as shown in figure 3.

## Realistic example 1:

```python=
import os

def _resolve_relative_to(path, original_root, new_root):
    """
    If the given ``path`` is a relative path, then assume it is relative to ``original_root``. This method will
    update the path to be resolve it relative to ``new_root`` and return.

    Examples
    -------
        # Assume a file called template.txt at location /tmp/original/root/template.txt expressed as relative path
        # We are trying to update it to be relative to /tmp/new/root instead of the /tmp/original/root
        >>> result = _resolve_relative_to("template.txt",  \
                                          "/tmp/original/root", \
                                          "/tmp/new/root")
        >>> result
        ../../original/root/template.txt

    Returns
    -------
    Updated path if the given path is a relative path. None, if the path is not a relative path.
    """

    if (
        not isinstance(path, str)
        or path.startswith("s3://")
        or path.startswith("http://")
        or path.startswith("https://")
        or os.path.isabs(path)
    ):
        # Value is definitely NOT a relative path. It is either a S3 URi or Absolute path or not a string at all
        return None

    # Value is definitely a relative path. Change it relative to the destination directory
    return os.path.relpath(
        os.path.normpath(os.path.join(original_root, path)), new_root  # Absolute original path w.r.t ``original_root``
    )  # Resolve the original path with respect to ``new_root``
```

full output:

```python=
# uncompyle6 version 3.7.4
# Python bytecode 3.7 (3394)
# Decompiled from: Python 3.7.11 (default, Jun 29 2021, 20:31:06) 
# [GCC 8.3.0]
# Embedded file name: samples/target_py/main.py
# Compiled at: 2021-10-02 16:01:17
# Size of source mod 2**32: 1513 bytes
import os

def _resolve_relative_to--- This code section failed: ---

 L.  24         0  LOAD_GLOBAL              isinstance
                2  LOAD_FAST                'path'
                4  LOAD_GLOBAL              str
                6  CALL_FUNCTION_2       2  '2 positional arguments'
                8  POP_JUMP_IF_FALSE    52  'to 52'

 L.  25        10  LOAD_FAST                'path'
               12  LOAD_METHOD              startswith
               14  LOAD_STR                 's3://'
               16  CALL_METHOD_1         1  '1 positional argument'
               18  POP_JUMP_IF_TRUE     52  'to 52'

 L.  26        20  LOAD_FAST                'path'
               22  LOAD_METHOD              startswith
               24  LOAD_STR                 'http://'
               26  CALL_METHOD_1         1  '1 positional argument'
               28  POP_JUMP_IF_TRUE     52  'to 52'

 L.  27        30  LOAD_FAST                'path'
               32  LOAD_METHOD              startswith
               34  LOAD_STR                 'https://'
               36  CALL_METHOD_1         1  '1 positional argument'
               38  POP_JUMP_IF_TRUE     52  'to 52'

 L.  28        40  LOAD_GLOBAL              os
               42  LOAD_ATTR                path
               44  LOAD_METHOD              isabs
               46  LOAD_FAST                'path'
               48  CALL_METHOD_1         1  '1 positional argument'
               50  POP_JUMP_IF_FALSE    56  'to 56'
             52_0  COME_FROM            38  '38'
             52_1  COME_FROM            28  '28'
             52_2  COME_FROM            18  '18'
             52_3  COME_FROM             8  '8'

 L.  31        52  LOAD_CONST               None
               54  RETURN_VALUE     
             56_0  COME_FROM            50  '50'

 L.  34        56  LOAD_GLOBAL              os
               58  LOAD_ATTR                path
               60  LOAD_METHOD              relpath

 L.  35        62  LOAD_GLOBAL              os
               64  LOAD_ATTR                path
               66  LOAD_METHOD              normpath
               68  LOAD_GLOBAL              os
               70  LOAD_ATTR                path
               72  LOAD_METHOD              join
               74  LOAD_FAST                'original_root'
               76  LOAD_FAST                'path'
               78  CALL_METHOD_2         2  '2 positional arguments'
               80  CALL_METHOD_1         1  '1 positional argument'
               82  LOAD_FAST                'new_root'
               84  CALL_METHOD_2         2  '2 positional arguments'
               86  RETURN_VALUE     
               -1  RETURN_LAST      

Parse error at or near `RETURN_VALUE' instruction at offset 86
```

CFG of function: 
![](https://i.imgur.com/PAck9tT.png)



## Realistic example 2:

MWE: https://hackmd.io/@aliahad97/BJNrSJ0pd#Error-152
```python=
import pandas as pd

NoneType = type(None)
def convert(column, field_type='STRING', mode='NULLABLE', fields=[], infer_required=False):
    field_type = field_type.upper()
    mode = mode.upper()

    if field_type == 'INTEGER':
        converted_column = [
            to_integer(value, mode, infer_required) for value in column
        ]
    elif field_type == 'STRING':
        converted_column = [
            to_string(value, mode, infer_required) for value in column
        ]
    elif field_type == 'NUMERIC':
        converted_column = [
            to_numeric(value, mode, infer_required) for value in column
        ]
    elif field_type == 'FLOAT':
        converted_column = [
            to_float(value, mode, infer_required) for value in column
        ]
    elif field_type == 'BOOLEAN':
        converted_column = [
            to_boolean(value, mode, infer_required) for value in column
        ]
    elif field_type == 'BYTES':
        converted_column = [
            to_bytes(value, mode, infer_required) for value in column
        ]
    elif field_type == 'DATETIME':
        converted_column = [
            to_datetime(value, mode, infer_required) for value in column
        ]
    elif field_type == 'DATE':
        converted_column = [
            to_date(value, mode, infer_required) for value in column
        ]
    elif field_type == 'TIME':
        converted_column = [
            to_time(value, mode, infer_required) for value in column
        ]
    elif field_type == 'TIMESTAMP':
        converted_column = [
            to_timestamp(value, mode, infer_required) for value in column
        ]
    elif field_type in ['STRUCT', 'RECORD']:
        if not fields:
            raise ValueError('Fields must be provided for STRUCT/RECORD')
        if mode == 'REPEATED':
            if not isinstance(column[0], list):
                raise ValueError('For REPEATED mode in STRUCT/RECORD a list of dicts must be provided for each row')
            converted_column = []
            for r in column:
                columns = pd.DataFrame(r).to_dict('list')
                output = {}
                for f in fields:
                    output[f.name] = convert(columns.get(f.name, []), f.field_type, f.mode, f.fields)
                converted_column.append(pd.DataFrame(output).to_dict('records'))
        elif mode == 'NULLABLE':
            if not isinstance(column[0], dict):
                raise ValueError('For NULLABLE mode in STRUCT/RECORD only one dict is accepted per row')
            columns = pd.DataFrame(column).to_dict('list')
            output = {}
            for f in fields:
                output[f.name] = convert(columns.get(f.name, []), f.field_type, f.mode, f.fields)
            converted_column = pd.DataFrame(output).to_dict('records')
        
    elif field_type in ['ARRAY', 'GEOGRAPHY']:
        raise NotImplementedError('Types ARRAY and GEOGRAPHY are not yet implemented.')
    else:
        raise ValueError('{} not a valid field_type.'.format(field_type))
    return converted_column
```


Full output:

```
# uncompyle6 version 3.7.4
# Python bytecode 3.7 (3394)
# Decompiled from: Python 3.7.11 (default, Jun 29 2021, 20:31:06) 
# [GCC 8.3.0]
# Embedded file name: samples/target_py/main.py
# Compiled at: 2021-10-02 20:58:27
# Size of source mod 2**32: 3053 bytes
import pandas as pd
NoneType = type(None)

def convert--- This code section failed: ---

 L.   5         0  LOAD_FAST                'field_type'
                2  LOAD_METHOD              upper
                4  CALL_METHOD_0         0  '0 positional arguments'
                6  STORE_FAST               'field_type'

 L.   6         8  LOAD_DEREF               'mode'
               10  LOAD_METHOD              upper
               12  CALL_METHOD_0         0  '0 positional arguments'
               14  STORE_DEREF              'mode'

 L.   8        16  LOAD_FAST                'field_type'
               18  LOAD_STR                 'INTEGER'
               20  COMPARE_OP               ==
               22  POP_JUMP_IF_FALSE    48  'to 48'

 L.  10        24  LOAD_CLOSURE             'infer_required'
               26  LOAD_CLOSURE             'mode'
               28  BUILD_TUPLE_2         2 
               30  LOAD_LISTCOMP            '<code_object <listcomp>>'
               32  LOAD_STR                 'convert.<locals>.<listcomp>'
               34  MAKE_FUNCTION_8          'closure'
               36  LOAD_FAST                'column'
               38  GET_ITER         
               40  CALL_FUNCTION_1       1  '1 positional argument'
               42  STORE_FAST               'converted_column'
            44_46  JUMP_FORWARD        674  'to 674'
             48_0  COME_FROM            22  '22'

 L.  12        48  LOAD_FAST                'field_type'
               50  LOAD_STR                 'STRING'
               52  COMPARE_OP               ==
               54  POP_JUMP_IF_FALSE    80  'to 80'

 L.  14        56  LOAD_CLOSURE             'infer_required'
               58  LOAD_CLOSURE             'mode'
               60  BUILD_TUPLE_2         2 
               62  LOAD_LISTCOMP            '<code_object <listcomp>>'
               64  LOAD_STR                 'convert.<locals>.<listcomp>'
               66  MAKE_FUNCTION_8          'closure'
               68  LOAD_FAST                'column'
               70  GET_ITER         
               72  CALL_FUNCTION_1       1  '1 positional argument'
               74  STORE_FAST               'converted_column'
            76_78  JUMP_FORWARD        674  'to 674'
             80_0  COME_FROM            54  '54'

 L.  16        80  LOAD_FAST                'field_type'
               82  LOAD_STR                 'NUMERIC'
               84  COMPARE_OP               ==
               86  POP_JUMP_IF_FALSE   112  'to 112'

 L.  18        88  LOAD_CLOSURE             'infer_required'
               90  LOAD_CLOSURE             'mode'
               92  BUILD_TUPLE_2         2 
               94  LOAD_LISTCOMP            '<code_object <listcomp>>'
               96  LOAD_STR                 'convert.<locals>.<listcomp>'
               98  MAKE_FUNCTION_8          'closure'
              100  LOAD_FAST                'column'
              102  GET_ITER         
              104  CALL_FUNCTION_1       1  '1 positional argument'
              106  STORE_FAST               'converted_column'
          108_110  JUMP_FORWARD        674  'to 674'
            112_0  COME_FROM            86  '86'

 L.  20       112  LOAD_FAST                'field_type'
              114  LOAD_STR                 'FLOAT'
              116  COMPARE_OP               ==
              118  POP_JUMP_IF_FALSE   144  'to 144'

 L.  22       120  LOAD_CLOSURE             'infer_required'
              122  LOAD_CLOSURE             'mode'
              124  BUILD_TUPLE_2         2 
              126  LOAD_LISTCOMP            '<code_object <listcomp>>'
              128  LOAD_STR                 'convert.<locals>.<listcomp>'
              130  MAKE_FUNCTION_8          'closure'
              132  LOAD_FAST                'column'
              134  GET_ITER         
              136  CALL_FUNCTION_1       1  '1 positional argument'
              138  STORE_FAST               'converted_column'
          140_142  JUMP_FORWARD        674  'to 674'
            144_0  COME_FROM           118  '118'

 L.  24       144  LOAD_FAST                'field_type'
              146  LOAD_STR                 'BOOLEAN'
              148  COMPARE_OP               ==
              150  POP_JUMP_IF_FALSE   176  'to 176'

 L.  26       152  LOAD_CLOSURE             'infer_required'
              154  LOAD_CLOSURE             'mode'
              156  BUILD_TUPLE_2         2 
              158  LOAD_LISTCOMP            '<code_object <listcomp>>'
              160  LOAD_STR                 'convert.<locals>.<listcomp>'
              162  MAKE_FUNCTION_8          'closure'
              164  LOAD_FAST                'column'
              166  GET_ITER         
              168  CALL_FUNCTION_1       1  '1 positional argument'
              170  STORE_FAST               'converted_column'
          172_174  JUMP_FORWARD        674  'to 674'
            176_0  COME_FROM           150  '150'

 L.  28       176  LOAD_FAST                'field_type'
              178  LOAD_STR                 'BYTES'
              180  COMPARE_OP               ==
              182  POP_JUMP_IF_FALSE   208  'to 208'

 L.  30       184  LOAD_CLOSURE             'infer_required'
              186  LOAD_CLOSURE             'mode'
              188  BUILD_TUPLE_2         2 
              190  LOAD_LISTCOMP            '<code_object <listcomp>>'
              192  LOAD_STR                 'convert.<locals>.<listcomp>'
              194  MAKE_FUNCTION_8          'closure'
              196  LOAD_FAST                'column'
              198  GET_ITER         
              200  CALL_FUNCTION_1       1  '1 positional argument'
              202  STORE_FAST               'converted_column'
          204_206  JUMP_FORWARD        674  'to 674'
            208_0  COME_FROM           182  '182'

 L.  32       208  LOAD_FAST                'field_type'
              210  LOAD_STR                 'DATETIME'
              212  COMPARE_OP               ==
              214  POP_JUMP_IF_FALSE   240  'to 240'

 L.  34       216  LOAD_CLOSURE             'infer_required'
              218  LOAD_CLOSURE             'mode'
              220  BUILD_TUPLE_2         2 
              222  LOAD_LISTCOMP            '<code_object <listcomp>>'
              224  LOAD_STR                 'convert.<locals>.<listcomp>'
              226  MAKE_FUNCTION_8          'closure'
              228  LOAD_FAST                'column'
              230  GET_ITER         
              232  CALL_FUNCTION_1       1  '1 positional argument'
              234  STORE_FAST               'converted_column'
          236_238  JUMP_FORWARD        674  'to 674'
            240_0  COME_FROM           214  '214'

 L.  36       240  LOAD_FAST                'field_type'
              242  LOAD_STR                 'DATE'
              244  COMPARE_OP               ==
          246_248  POP_JUMP_IF_FALSE   274  'to 274'

 L.  38       250  LOAD_CLOSURE             'infer_required'
              252  LOAD_CLOSURE             'mode'
              254  BUILD_TUPLE_2         2 
              256  LOAD_LISTCOMP            '<code_object <listcomp>>'
              258  LOAD_STR                 'convert.<locals>.<listcomp>'
              260  MAKE_FUNCTION_8          'closure'
              262  LOAD_FAST                'column'
              264  GET_ITER         
              266  CALL_FUNCTION_1       1  '1 positional argument'
              268  STORE_FAST               'converted_column'
          270_272  JUMP_FORWARD        674  'to 674'
            274_0  COME_FROM           246  '246'

 L.  40       274  LOAD_FAST                'field_type'
              276  LOAD_STR                 'TIME'
              278  COMPARE_OP               ==
          280_282  POP_JUMP_IF_FALSE   308  'to 308'

 L.  42       284  LOAD_CLOSURE             'infer_required'
              286  LOAD_CLOSURE             'mode'
              288  BUILD_TUPLE_2         2 
              290  LOAD_LISTCOMP            '<code_object <listcomp>>'
              292  LOAD_STR                 'convert.<locals>.<listcomp>'
              294  MAKE_FUNCTION_8          'closure'
              296  LOAD_FAST                'column'
              298  GET_ITER         
              300  CALL_FUNCTION_1       1  '1 positional argument'
              302  STORE_FAST               'converted_column'
          304_306  JUMP_FORWARD        674  'to 674'
            308_0  COME_FROM           280  '280'

 L.  44       308  LOAD_FAST                'field_type'
              310  LOAD_STR                 'TIMESTAMP'
              312  COMPARE_OP               ==
          314_316  POP_JUMP_IF_FALSE   342  'to 342'

 L.  46       318  LOAD_CLOSURE             'infer_required'
              320  LOAD_CLOSURE             'mode'
              322  BUILD_TUPLE_2         2 
              324  LOAD_LISTCOMP            '<code_object <listcomp>>'
              326  LOAD_STR                 'convert.<locals>.<listcomp>'
              328  MAKE_FUNCTION_8          'closure'
              330  LOAD_FAST                'column'
              332  GET_ITER         
              334  CALL_FUNCTION_1       1  '1 positional argument'
              336  STORE_FAST               'converted_column'
          338_340  JUMP_FORWARD        674  'to 674'
            342_0  COME_FROM           314  '314'

 L.  48       342  LOAD_FAST                'field_type'
              344  LOAD_CONST               ('STRUCT', 'RECORD')
              346  COMPARE_OP               in
          348_350  POP_JUMP_IF_FALSE   640  'to 640'

 L.  49       352  LOAD_FAST                'fields'
          354_356  POP_JUMP_IF_TRUE    366  'to 366'

 L.  50       358  LOAD_GLOBAL              ValueError
              360  LOAD_STR                 'Fields must be provided for STRUCT/RECORD'
              362  CALL_FUNCTION_1       1  '1 positional argument'
              364  RAISE_VARARGS_1       1  'exception instance'
            366_0  COME_FROM           354  '354'

 L.  51       366  LOAD_DEREF               'mode'
              368  LOAD_STR                 'REPEATED'
              370  COMPARE_OP               ==
          372_374  POP_JUMP_IF_FALSE   516  'to 516'

 L.  52       376  LOAD_GLOBAL              isinstance
              378  LOAD_FAST                'column'
              380  LOAD_CONST               0
              382  BINARY_SUBSCR    
              384  LOAD_GLOBAL              list
              386  CALL_FUNCTION_2       2  '2 positional arguments'
          388_390  POP_JUMP_IF_TRUE    400  'to 400'

 L.  53       392  LOAD_GLOBAL              ValueError
              394  LOAD_STR                 'For REPEATED mode in STRUCT/RECORD a list of dicts must be provided for each row'
              396  CALL_FUNCTION_1       1  '1 positional argument'
              398  RAISE_VARARGS_1       1  'exception instance'
            400_0  COME_FROM           388  '388'

 L.  54       400  BUILD_LIST_0          0 
              402  STORE_FAST               'converted_column'

 L.  55       404  SETUP_LOOP          638  'to 638'
              406  LOAD_FAST                'column'
              408  GET_ITER         
              410  FOR_ITER            512  'to 512'
              412  STORE_FAST               'r'

 L.  56       414  LOAD_GLOBAL              pd
              416  LOAD_METHOD              DataFrame
              418  LOAD_FAST                'r'
              420  CALL_METHOD_1         1  '1 positional argument'
              422  LOAD_METHOD              to_dict
              424  LOAD_STR                 'list'
              426  CALL_METHOD_1         1  '1 positional argument'
              428  STORE_FAST               'columns'

 L.  57       430  BUILD_MAP_0           0 
              432  STORE_FAST               'output'

 L.  58       434  SETUP_LOOP          486  'to 486'
              436  LOAD_FAST                'fields'
              438  GET_ITER         
              440  FOR_ITER            484  'to 484'
              442  STORE_FAST               'f'

 L.  59       444  LOAD_GLOBAL              convert
              446  LOAD_FAST                'columns'
              448  LOAD_METHOD              get
              450  LOAD_FAST                'f'
              452  LOAD_ATTR                name
              454  BUILD_LIST_0          0 
              456  CALL_METHOD_2         2  '2 positional arguments'
              458  LOAD_FAST                'f'
              460  LOAD_ATTR                field_type
              462  LOAD_FAST                'f'
              464  LOAD_ATTR                mode
              466  LOAD_FAST                'f'
              468  LOAD_ATTR                fields
              470  CALL_FUNCTION_4       4  '4 positional arguments'
              472  LOAD_FAST                'output'
              474  LOAD_FAST                'f'
              476  LOAD_ATTR                name
              478  STORE_SUBSCR     
          480_482  JUMP_BACK           440  'to 440'
              484  POP_BLOCK        
            486_0  COME_FROM_LOOP      434  '434'

 L.  60       486  LOAD_FAST                'converted_column'
              488  LOAD_METHOD              append
              490  LOAD_GLOBAL              pd
              492  LOAD_METHOD              DataFrame
              494  LOAD_FAST                'output'
              496  CALL_METHOD_1         1  '1 positional argument'
              498  LOAD_METHOD              to_dict
              500  LOAD_STR                 'records'
              502  CALL_METHOD_1         1  '1 positional argument'
              504  CALL_METHOD_1         1  '1 positional argument'
              506  POP_TOP          
          508_510  JUMP_BACK           410  'to 410'
              512  POP_BLOCK        
              514  JUMP_FORWARD        638  'to 638'
            516_0  COME_FROM           372  '372'

 L.  61       516  LOAD_DEREF               'mode'
              518  LOAD_STR                 'NULLABLE'
              520  COMPARE_OP               ==
          522_524  POP_JUMP_IF_FALSE   674  'to 674'

 L.  62       526  LOAD_GLOBAL              isinstance
              528  LOAD_FAST                'column'
              530  LOAD_CONST               0
              532  BINARY_SUBSCR    
              534  LOAD_GLOBAL              dict
              536  CALL_FUNCTION_2       2  '2 positional arguments'
          538_540  POP_JUMP_IF_TRUE    550  'to 550'

 L.  63       542  LOAD_GLOBAL              ValueError
              544  LOAD_STR                 'For NULLABLE mode in STRUCT/RECORD only one dict is accepted per row'
              546  CALL_FUNCTION_1       1  '1 positional argument'
              548  RAISE_VARARGS_1       1  'exception instance'
            550_0  COME_FROM           538  '538'

 L.  64       550  LOAD_GLOBAL              pd
              552  LOAD_METHOD              DataFrame
              554  LOAD_FAST                'column'
              556  CALL_METHOD_1         1  '1 positional argument'
              558  LOAD_METHOD              to_dict
              560  LOAD_STR                 'list'
              562  CALL_METHOD_1         1  '1 positional argument'
              564  STORE_FAST               'columns'

 L.  65       566  BUILD_MAP_0           0 
              568  STORE_FAST               'output'

 L.  66       570  SETUP_LOOP          622  'to 622'
              572  LOAD_FAST                'fields'
              574  GET_ITER         
              576  FOR_ITER            620  'to 620'
              578  STORE_FAST               'f'

 L.  67       580  LOAD_GLOBAL              convert
              582  LOAD_FAST                'columns'
              584  LOAD_METHOD              get
              586  LOAD_FAST                'f'
              588  LOAD_ATTR                name
              590  BUILD_LIST_0          0 
              592  CALL_METHOD_2         2  '2 positional arguments'
              594  LOAD_FAST                'f'
              596  LOAD_ATTR                field_type
              598  LOAD_FAST                'f'
              600  LOAD_ATTR                mode
              602  LOAD_FAST                'f'
              604  LOAD_ATTR                fields
              606  CALL_FUNCTION_4       4  '4 positional arguments'
              608  LOAD_FAST                'output'
              610  LOAD_FAST                'f'
              612  LOAD_ATTR                name
              614  STORE_SUBSCR     
          616_618  JUMP_BACK           576  'to 576'
              620  POP_BLOCK        
            622_0  COME_FROM_LOOP      570  '570'

 L.  68       622  LOAD_GLOBAL              pd
              624  LOAD_METHOD              DataFrame
              626  LOAD_FAST                'output'
              628  CALL_METHOD_1         1  '1 positional argument'
              630  LOAD_METHOD              to_dict
              632  LOAD_STR                 'records'
              634  CALL_METHOD_1         1  '1 positional argument'
              636  STORE_FAST               'converted_column'
            638_0  COME_FROM           514  '514'
            638_1  COME_FROM_LOOP      404  '404'
              638  JUMP_FORWARD        674  'to 674'
            640_0  COME_FROM           348  '348'

 L.  70       640  LOAD_FAST                'field_type'
              642  LOAD_CONST               ('ARRAY', 'GEOGRAPHY')
              644  COMPARE_OP               in
          646_648  POP_JUMP_IF_FALSE   660  'to 660'

 L.  71       650  LOAD_GLOBAL              NotImplementedError
              652  LOAD_STR                 'Types ARRAY and GEOGRAPHY are not yet implemented.'
              654  CALL_FUNCTION_1       1  '1 positional argument'
              656  RAISE_VARARGS_1       1  'exception instance'
              658  JUMP_FORWARD        674  'to 674'
            660_0  COME_FROM           646  '646'

 L.  73       660  LOAD_GLOBAL              ValueError
              662  LOAD_STR                 '{} not a valid field_type.'
              664  LOAD_METHOD              format
              666  LOAD_FAST                'field_type'
              668  CALL_METHOD_1         1  '1 positional argument'
              670  CALL_FUNCTION_1       1  '1 positional argument'
              672  RAISE_VARARGS_1       1  'exception instance'
            674_0  COME_FROM           658  '658'
            674_1  COME_FROM           638  '638'
            674_2  COME_FROM           522  '522'
            674_3  COME_FROM           338  '338'
            674_4  COME_FROM           304  '304'
            674_5  COME_FROM           270  '270'
            674_6  COME_FROM           236  '236'
            674_7  COME_FROM           204  '204'
            674_8  COME_FROM           172  '172'
            674_9  COME_FROM           140  '140'
           674_10  COME_FROM           108  '108'
           674_11  COME_FROM            76  '76'
           674_12  COME_FROM            44  '44'

 L.  74       674  LOAD_FAST                'converted_column'
              676  RETURN_VALUE     
               -1  RETURN_LAST      

Parse error at or near `COME_FROM_LOOP' instruction at offset 638_1
```

# Updating target block

Updated cfg (fig 4):
![](https://i.imgur.com/WbBYrhA.png)

Output file (fig 5):
![](https://i.imgur.com/sQeClOf.png)


To apply the fix, we first check for rules that apply to the target block itself where in the example above there are none. Then, we immediately move to the direct predecessors (parent) or successors (child) blocks and try to apply rules to match them. In the example we can see that the example matches the rule XXX, and so we apply the transformation as shown in figure 4. 

Diff of files (fig 6):


# Regular Expression example:

For fig 4, we use the following regular expression:

`^([POP_JUMP_IF_FALSE:Arg_i, POP_JUMP_IF_TRUE:Arg_i].*)+[POP_JUMP_IF_FALSE:Arg_N, POP_JUMP_IF_TRUE:Arg_N]$`

- Where each `POP_JUMP_IF_FALSE` corresponds to an `and` and each `POP_JUMP_IF_TRUE` corresponds to an `or`. 

- For each of these, the jump target is the same.

- For each `Arg_i` of instructions, it is greater than the offset of `[POP_JUMP_IF_FALSE:Arg_N, POP_JUMP_IF_TRUE:Arg_N]`.
- All instructions with `Arg_i` less than the offset of `[POP_JUMP_IF_FALSE:Arg_N, POP_JUMP_IF_TRUE:Arg_N]` will be ignored.
- No offset of instruction will be greater than `Arg_i`. 

The above pattern is for a series of `b1 and/or b2 and/or ... and/or bN` where `bN`will always be before the jump target of all `POP_JUMP_IF_FALSE`/`POP_JUMP_IF_TRUE` .

<!-- For the `exit_set` which mark the end of the pattern are as follows:
```
exit_set = [
    90, # name_op('STORE_NAME', 90) 
    95, # name_op('STORE_ATTR', 95) # Index in name list
    97, # name_op('STORE_GLOBAL', 97)     # ""
    125, # def_op('STORE_FAST', 125)       # Local variable number
    83, # def_op('RETURN_VALUE', 83)
    86, # def_op('YIELD_VALUE', 86)
]
``` -->

# Transformation:
For the transformation in the previous example, we follow the following steps.
1. Add `STORE_FAST` and `LOAD_FAST` to introduce a new local variable to store boolean result and then load it immediately for the next boolean expression. (This will be added before the last `POP_JUMP_IF_FALSE`/`POP_JUMP_IF_TRUE`  marking the end of condition)
2. Convert all `POP_JUMP_IF_FALSE`/`POP_JUMP_IF_TRUE` before the instrumented instruction to `JUMP_IF_FALSE_OR_POP`/`JUMP_IF_TRUE_OR_POP` respectively to preserve boolean value for variable added.
3. Assign jump arg of all `JUMP_IF_FALSE_OR_POP`/`JUMP_IF_TRUE_OR_POP` to our newly instrumented instructions.
