File: api.rst

package info (click to toggle)
python-bytecode 0.16.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 780 kB
  • sloc: python: 8,300; makefile: 169; sh: 40
file content (1052 lines) | stat: -rw-r--r-- 31,813 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
************
Bytecode API
************

* Constants: :data:`__version__`, :data:`UNSET`
* Abstract bytecode: :class:`Label`, :class:`Instr`, :class:`Bytecode`
* Line number: :class:`SetLineno`
* Arguments: :class:`CellVar`, :class:`Compare`, :class:`FreeVar`
* Concrete bytecode: :class:`ConcreteInstr`, :class:`ConcreteBytecode`
* Control Flow Graph (CFG): :class:`BasicBlock`, :class:`ControlFlowGraph`
* Base class: :class:`BaseBytecode`


Constants
=========

.. data:: __version__

   Module version string (ex: ``'0.1'``).

.. data:: UNSET

   Singleton used to mark the lack of value. It is different than ``None``.


Functions
=========

.. function:: format_bytecode(bytecode, \*, lineno: bool = False) -> str:

   Format a bytecode to a str representation. :class:`ConcreteBytecode`,
   :class:`Bytecode` and :class:`ControlFlowGraph` are accepted for *bytecode*.

   If *lineno* is true, show also line numbers and instruction index/offset.

   This function is written for debug purpose.

.. function:: dump_bytecode(bytecode, \*, lineno=False)

   Dump a bytecode to the standard output. :class:`ConcreteBytecode`,
   :class:`Bytecode` and :class:`ControlFlowGraph` are accepted for *bytecode*.

   If *lineno* is true, show also line numbers and instruction index/offset.

   This function is written for debug purpose.


Instruction classes
===================

Instr
-----

.. class:: Instr(name: str, arg=UNSET, \*, lineno: Union[int, None, UNSET] = UNSET, location: Optional[InstrLocation] = None)

   Abstract instruction.

   The type of the *arg* parameter (and the :attr:`arg` attribute) depends on
   the operation:

   * If the operation has a jump argument (:meth:`has_jump`, ex:
     ``JUMP_ABSOLUTE``): *arg* must be a :class:`Label` (if the instruction is
     used in :class:`Bytecode`) or a :class:`BasicBlock` (used in
     :class:`ControlFlowGraph`).
   * If the operation has a cell or free argument (ex: ``LOAD_DEREF``): *arg*
     must be a :class:`CellVar` or :class:`FreeVar` instance.
   * If the operation has a local variable (ex: ``LOAD_FAST``): *arg* must be a
     variable name, type ``str``.
   * If the operation has a constant argument (``LOAD_CONST``): *arg* must not
     be a :class:`Label` or :class:`BasicBlock` instance.
   * If the operation has a compare argument (``COMPARE_OP``):
     *arg* must be a :class:`Compare` enum.
   * If the operation has no argument (ex: ``DUP_TOP``), *arg* must not be set.
   * Otherwise (the operation has an argument, ex: ``CALL_FUNCTION``), *arg*
     must be an integer (``int``) in the range ``0``..\ ``2,147,483,647``.

   To replace the operation name and the argument, the :meth:`set` method must
   be used instead of modifying the :attr:`name` attribute and then the
   :attr:`arg` attribute. Otherwise, an exception is raised if the previous
   operation requires an argument and the new operation has no argument (or the
   opposite).

   Attributes:

   .. attribute:: arg

      Argument value.

      It can be :data:`UNSET` if the instruction has no argument.

   .. attribute:: lineno

      Line number (``int >= 1``), or ``None``.

   .. attribute:: name

      Operation name (``str``). Setting the name updates the :attr:`opcode`
      attribute.

   .. attribute:: opcode

      Operation code (``int``). Setting the operation code updates the
      :attr:`name` attribute.

   .. versionchanged:: 0.3
      The ``op`` attribute was renamed to :attr:`opcode`.

   .. attribute:: location

      Detailed location (:class:`InstrLocation`)

   Methods:

   .. method:: require_arg() -> bool

      Does the instruction require an argument?

   .. method:: copy()

      Create a copy of the instruction.

   .. method:: is_final() -> bool

      Is the operation a final operation?

      Final operations:

      * RETURN_VALUE
      * RAISE_VARARGS
      * BREAK_LOOP
      * CONTINUE_LOOP
      * unconditional jumps: :meth:`is_uncond_jump`

   .. method:: has_jump() -> bool

      Does the operation have a jump argument?

      More general than :meth:`is_cond_jump` and :meth:`is_uncond_jump`, it
      includes other operations. Examples:

      * FOR_ITER
      * SETUP_EXCEPT
      * CONTINUE_LOOP

   .. method:: is_cond_jump() -> bool

      Is the operation a conditional jump?

      Conditional jumps:

      * JUMP_IF_FALSE_OR_POP
      * JUMP_IF_TRUE_OR_POP
      * JUMP_FORWARD_IF_FALSE_OR_POP
      * JUMP_BACKWARD_IF_FALSE_OR_POP
      * JUMP_FORWARD_IF_TRUE_OR_POP
      * JUMP_BACKWARD_IF_TRUE_OR_POP
      * POP_JUMP_IF_FALSE
      * POP_JUMP_IF_TRUE

   .. method:: is_uncond_jump() -> bool

      Is the operation an unconditional jump?

      Unconditional jumps:

      * JUMP_FORWARD
      * JUMP_ABSOLUTE
      * JUMP_BACKWARD
      * JUMP_BACKWARD_NO_INTERRUPT

   .. method:: is_abs_jump() -> bool

      Is the operation an absolute jump?

   .. method:: is_forward_rel_jump() -> bool

      Is the operation a forward relative jump?

   .. method:: is_backward_rel_jump() -> bool

      Is the operation a backward relative jump?

   .. method:: set(name: str, arg=UNSET)

      Modify the instruction in-place: replace :attr:`name` and :attr:`arg`
      attributes, and update the :attr:`opcode` attribute.

      .. versionchanged:: 0.3
         The *lineno* parameter has been removed.

   .. method:: stack_effect(jump: bool = None) -> int

      Operation effect on the stack size as computed by
      :func:`dis.stack_effect`.

      The *jump* argument takes one of three values.  None (the default)
      requests the largest stack effect.  This works fine with most
      instructions.  True returns the stack effect for taken branches.  False
      returns the stack effect for non-taken branches.

      .. versionchanged:: 0.8
         ``stack_effect`` was changed from a property to a method in order to
         add the keyword argument *jump*.

    .. method:: pre_and_post_stack_effect(jump: Optional[bool] = None) -> Tuple[int, int]

      Effect of the instruction on the stack before and after its execution.

      The impact on the stack before the instruction reflects how many values
      from the stacks are used/popped. The impact on the stack after the
      instruction execution reflects how many values are pushed back on the
      stack. Those are deduced from :func:`dis.stack_effect` and manual
      analysis.

      The *jump* argument has the same meaning as in
      :py:meth:`Instr.stack_effect`.

      .. versionadded:: 0.12


ConcreteInstr
-------------

.. class:: ConcreteInstr(name: str, arg=UNSET, \*, lineno: int=None)

   Concrete instruction Inherit from :class:`Instr`.

   If the operation requires an argument, *arg* must be an integer (``int``) in
   the range ``0``..\ ``2,147,483,647``. Otherwise, *arg* must not by set.

   Concrete instructions should only be used in :class:`ConcreteBytecode`.

   Attributes:

   .. attribute:: arg

      Argument value: an integer (``int``) in the range ``0``..\
      ``2,147,483,647``, or :data:`UNSET`. Setting the argument value can
      change the instruction size (:attr:`size`).

   .. attribute:: size

      Read-only size of the instruction in bytes (``int``): between ``1`` byte
      (no argument) and ``6`` bytes (extended argument).

   Static method:

   .. staticmethod:: disassemble(code: bytes, offset: int) -> ConcreteInstr

      Create a concrete instruction from a bytecode string.

   Methods:

   .. method:: get_jump_target(instr_offset: int) -> int or None

      Get the absolute target offset of a jump. Return ``None`` if the
      instruction is not a jump.

      The *instr_offset* parameter is the offset of the instruction. It is
      required by relative jumps.

      .. note::

         Starting with Python 3.10, this quantity is expressed in term of
         instruction offset rather than byte offset, and is hence twice smaller
         than in 3.9 for identical code.

   .. method:: assemble() -> bytes

      Assemble the instruction to a bytecode string.

   .. method:: use_cache_opcodes() -> int

      Number of cache opcodes that should follow the instruction.


Compare
-------

.. class:: Compare

   Enum for the argument of the ``COMPARE_OP`` instruction.

   Equality test:

   * ``Compare.EQ`` (``2``): ``x == y``
   * ``Compare.NE`` (``3``): ``x != y``
   * ``Compare.IS`` (``8``): ``x is y`` removed in Python 3.9+
   * ``Compare.IS_NOT`` (``9``): ``x is not y`` removed in Python 3.9+

   Inequality test:

   * ``Compare.LT`` (``0``): ``x < y``
   * ``Compare.LE`` (``1``): ``x <= y``
   * ``Compare.GT`` (``4``): ``x > y``
   * ``Compare.GE`` (``5``): ``x >= y``

   Other tests:

   * ``Compare.IN`` (``6``): ``x in y`` removed in Python 3.9+
   * ``Compare.NOT_IN`` (``7``): ``x not in y`` removed in Python 3.9+
   * ``Compare.EXC_MATCH`` (``10``): used to compare exceptions
     in ``except:`` blocks. Removed in Python 3.9+


Binary operation
----------------

.. class:: BinaryOp

   Enum for the argument of the ``BINARY_OP`` instruction (3.11+).

   Arithmetic operations

   ``BinaryOp.ADD`` (``0``): ``x + y``
   ``BinaryOp.SUBTRACT`` (``10``): ``x - y``
   ``BinaryOp.MULTIPLY`` (``5``): ``x * y``
   ``BinaryOp.TRUE_DIVIDE`` (``11``): ``x / y``
   ``BinaryOp.FLOOR_DIVIDE`` (``2``): ``x // y``
   ``BinaryOp.REMAINDER`` (``6``): ``x % y``
   ``BinaryOp.MATRIX_MULTIPLY`` (``4``): ``x @ y``
   ``BinaryOp.POWER`` (``8``): ``x ** y``

   Logical and binary operations

   ``BinaryOp.LSHIFT`` (``3``): ``x << y``
   ``BinaryOp.RSHIFT`` (``9``): ``x >> y``
   ``BinaryOp.AND`` (``1``): ``x & y``
   ``BinaryOp.OR`` (``7``): ``x | y``
   ``BinaryOp.XOR`` (``12``): ``x ^ y``

   Inplace operations:

   ``BinaryOp.INPLACE_ADD`` (``13``): ``x += y``
   ``BinaryOp.INPLACE_SUBTRACT`` (``23``): ``x -= y``
   ``BinaryOp.INPLACE_MULTIPLY`` (``18``): ``x *= y``
   ``BinaryOp.INPLACE_TRUE_DIVIDE`` (``24``): ``x /= y``
   ``BinaryOp.INPLACE_FLOOR_DIVIDE`` (``15``): ``x //= y``
   ``BinaryOp.INPLACE_REMAINDER`` (``19``): ``x %= y``
   ``BinaryOp.INPLACE_MATRIX_MULTIPLY`` (``17``): ``x @= y``
   ``BinaryOp.INPLACE_POWER`` (``21``): ``x **= y``
   ``BinaryOp.INPLACE_LSHIFT`` (``16``): ``x <<= y``
   ``BinaryOp.INPLACE_RSHIFT`` (``22``): ``x >>= y``
   ``BinaryOp.INPLACE_AND`` (``14``): ``x &= y``
   ``BinaryOp.INPLACE_OR`` (``20``): ``x |= y``
   ``BinaryOp.INPLACE_XOR`` (``25``): ``x ^= y``


Intrinsic operations
--------------------

.. class:: Intrinsic1Op

   Enum for the argument of the ``CALL_INTRINSIC_1`` instruction (3.12+).

   ``INTRINSIC_1_INVALID``
   ``INTRINSIC_PRINT``
   ``INTRINSIC_IMPORT_STAR``
   ``INTRINSIC_STOPITERATION_ERROR``
   ``INTRINSIC_ASYNC_GEN_WRAP``
   ``INTRINSIC_UNARY_POSITIVE``
   ``INTRINSIC_LIST_TO_TUPLE``
   ``INTRINSIC_TYPEVAR``
   ``INTRINSIC_PARAMSPEC``
   ``INTRINSIC_TYPEVARTUPLE``
   ``INTRINSIC_SUBSCRIPT_GENERIC``
   ``INTRINSIC_TYPEALIAS``

.. class:: Intrinsic2Op

   Enum for the argument of the ``CALL_INTRINSIC_2`` instruction (3.12+).

   ``INTRINSIC_2_INVALID``
   ``INTRINSIC_PREP_RERAISE_STAR``
   ``INTRINSIC_TYPEVAR_WITH_BOUND``
   ``INTRINSIC_TYPEVAR_WITH_CONSTRAINTS``
   ``INTRINSIC_SET_FUNCTION_TYPE_PARAMS``


CellVar and FreeVar
-------------------

The following classes are used to represent the argument of opcode listed in
``opcode.hasfree`` which includes:

- MAKE_CELL
- LOAD_CLOSURE
- LOAD_DEREF
- STORE_DEREF
- DELETE_DEREF
- LOAD_CLASSDEREF
- LOAD_FROM_DICT_OR_DEREF

.. class:: CellVar

   Argument of an opcode referring to a variable held in a cell.

   Cell variables cannot always be inferred only from the instructions
   (``__class__`` used by super() is implicit) and as a consequence cellvars are
   explicitly listed on all bytecode objects.

   Attributes:

   .. attribute:: name

      Name of the cell variable (``str``).

.. class:: FreeVar

   Argument of opcode referring to a free variable.

   Free variables cannot always be inferred only from the instructions
   (``__class__`` used by super() is implicit) and as a consequence freevars are
   explicitly listed on all bytecode objects.

   Attributes:

   .. attribute:: name

      Name of the free variable (``str``).


Label
-----

.. class:: Label

   Pseudo-instruction used as targets of jump instructions.

   Label targets are "resolved" by :class:`Bytecode.to_concrete_bytecode`.

   Labels must only be used in :class:`Bytecode`.


SetLineno
---------

.. class:: SetLineno(lineno: int)

   Pseudo-instruction to set the line number of following instructions.

   *lineno* must be greater or equal than ``1``.

   .. attribute:: lineno

      Line number (``int``), read-only attribute.

InstrLocation
-------------

.. class:: InstrLocation(lineno: Optional[int], end_lineno: Optional[int],        col_offset: Optional[int], end_col_offset: Optional[int])

   Detailed location for an instruction.

   .. attribute:: lineno

      Line number on which the instruction starts.

   .. attribute:: end_lineno

      Line number on which the instruction ends.

   .. attribute:: col_offset

      Column offset within the start line at which the instruction starts.

   .. attribute:: end_col_offset

      Column offset within the end line at which the instruction starts.

   .. classmethod:: from_positions(cls, position: dis.Positions) -> InstrLocation

      Build an InstrLocation from a dis.Position object.


TryBegin
--------

.. class:: TryBegin(target: Union[Label, BasicBlock], push_lasti: bool, stack_depth: Union[int, UNSET] = UNSET)

   Pseudo instruction marking the beginning of an exception table entry.

   TryBegin can never be nested.

   Used in Python 3.11+ in :class:`Bytecode` and :class:`BasicBlock`.

   .. attribute:: target

      Target :class:`Label` or :class:`BasicBlock` to which to jump to if an exception
      occurs on an instruction sitting between this :class:`TryBegin` and the
      matching :class:`TryEnd`.

   .. attribute:: push_lasti

      Is the instruction offset at which an exception occurred pushed on the stack
      before the exception itself when handling an exception.

   .. attribute:: stack_depth

      Stack depth that will be restored by the interpreter by popping from the stack
      when handling an exception, before pushing the exception possibly preceded by
      the instruction offset depending on :attr:`TryBegin.push_lasti`.

   .. method:: copy() -> TryBegin

      Create a copy of the TryBegin.


TryEnd
------

.. class:: TryEnd(entry: TryBegin)

   Pseudo instruction marking the end of an exception table entry.

   .. note::

      In a :class:`BasicBlock`, one may find a :class:`TryEnd` instance after a final
      instruction. This results from the exception enclosing the final instruction.
      Since :class:`TryEnd` is only a pseudo-instruction this does not violate
      the guarantee made by a :class:`BasicBlock` which only applies to instructions.

   .. note::

      A jump may cause to exit an exception table entry. If the jump is unconditional
      the instruction is final and the above applies. For conditional jumps, within
      a :class:`ControlFlowGraph`, we insert a :class:`TryEnd` at the beginning of
      the target block to explicitly signal that we left the exception table entry
      region. As a consequence, multiple :class:`TryExit` corresponding to a single
      :class:`TryBegin` can exist. :class:`TryEnd` corresponding to exiting an
      exception table entry through a conditional jump always appear before the
      first instruction of the target block. However, care needs to be taken since
      that block may be reached through a different path in which no :class:`TryBegin`
      was encountered. In such cases, the :class:`TryEnd` should be ignored.


Bytecode classes
================

BaseBytecode
------------

.. class:: BaseBytecode

   Base class of bytecode classes.

   Attributes:

   .. attribute:: argcount

      Argument count (``int``), default: ``0``.

   .. attribute:: cellvars

      Names of the cell variables (``list`` of ``str``), default: empty list.

   .. attribute:: docstring

      Documentation string aka "docstring" (``str``), ``None``, or
      :data:`UNSET`.  Default: :data:`UNSET`.

      If set, it is used by :meth:`ConcreteBytecode.to_code` as the first
      constant of the created Python code object.

   .. attribute:: filename

      Code filename (``str``), default: ``'<string>'``.

   .. attribute:: first_lineno

      First line number (``int``), default: ``1``.

   .. attribute:: flags

      Flags (``int``).

   .. attribute:: freevars

      List of free variable names (``list`` of ``str``), default: empty list.

   .. attribute:: posonlyargcount

      Positional-only argument count (``int``), default: ``0``.

      New in Python 3.8

   .. attribute:: kwonlyargcount

      Keyword-only argument count (``int``), default: ``0``.

   .. attribute:: name

      Code name (``str``), default: ``'<module>'``.

   .. attribute:: qualname

      Qualified code name (``str``).

      New in Python 3.11

   .. versionchanged:: 0.3
      Attribute ``kw_only_argcount`` renamed to :attr:`kwonlyargcount`.


Bytecode
--------

.. class:: Bytecode

   Abstract bytecode: list of abstract instructions (:class:`Instr`).
   Inherit from :class:`BaseBytecode` and :class:`list`.

   A bytecode must only contain objects of the 4 following types:

   * :class:`Label`
   * :class:`SetLineno`
   * :class:`Instr`
   * :class:`TryBegin`
   * :class:`TryEnd`

   .. versionchanged:: 0.14.0

      It is not possible anymore to use concrete instructions (:class:`ConcreteInstr`)
      in :class:`Bytecode`.

   Attributes:

   .. attribute:: argnames

      List of the argument names (``list`` of ``str``), default: empty list.

   Static methods:

   .. staticmethod:: from_code(code) -> Bytecode

      Create an abstract bytecode from a Python code object.

   Methods:

   .. method:: legalize()

      Check the validity of all the instruction and remove the :class:`SetLineno`
      instances after updating the instructions.

   .. method:: to_concrete_bytecode(compute_jumps_passes: int = None, compute_exception_stack_depths: bool = True) -> ConcreteBytecode

      Convert to concrete bytecode with concrete instructions.

      Resolve jump targets: replace abstract labels (:class:`Label`) with
      concrete instruction offsets (relative or absolute, depending on the
      jump operation).  It will also add EXTENDED_ARG prefixes to jump
      instructions to ensure that the target instructions can be reached.

      If *compute_jumps_passes* is not None, it sets the upper limit for the
      number of passes that can be made to generate EXTENDED_ARG prefixes for
      jump instructions. If None then an internal default is used.  The number
      of passes is, in theory, limited only by the number of input
      instructions, however a much smaller default is used because the
      algorithm converges quickly on most code.  For example, running CPython
      3.6.5 unittests on OS X 11.13 results in 264996 compiled methods, only
      one of which requires 5 passes, and none requiring more.

      If *compute_exception_stack_depths*  is True, the stack depth for each
      exception table entry will be computed (which requires to convert the
      the bytecode to a :class:`ControlFlowGraph`)

   .. method:: to_code(compute_jumps_passes: int = None, stacksize: int = None, *, check_pre_and_post: bool = True, compute_exception_stack_depths: bool = True) -> types.CodeType

      Convert to a Python code object.

      It is based on :meth:`to_concrete_bytecode` and so resolve jump targets.

      *compute_jumps_passes*: see :meth:`to_concrete_bytecode`

      *stacksize*: see :meth:`ConcreteBytecode.to_code`

      *check_pre_and_post*: see :meth:`ConcreteBytecode.to_code`

      *compute_exception_stack_depths*: see :meth:`to_concrete_bytecode`

   .. method:: compute_stacksize(*, check_pre_and_post: bool = True) -> int

      Compute the stacksize needed to execute the code. Will raise an
      exception if the bytecode is invalid.

      This computation requires to build the control flow graph associated with
      the code.

      *check_pre_and_post* Allows caller to disable checking for stack underflow

    .. method:: update_flags(is_async: bool = None) -> None

      Update the object flags by calling :py:func:infer_flags on itself.


ConcreteBytecode
----------------

.. class:: ExceptionTableEntry

   Entry for a given line in the exception table.

   All offsets are expressed in instructions not in bytes.

   Attributes:

   .. attribute:: start_offset

      Offset (``int``) in instruction between the beginning of the bytecode and
      the beginning of this entry.

   .. attribute:: stop_offset

      Offset (``int``) in instruction between the beginning of the bytecode and
      the end of this entry. This offset is inclusive meaning that the instruction
      it points to is included in the try/except handling.

   .. attribute:: target

      Offset (``int``) in instruction to the first instruction of the exception
      handling block.

   .. attribute:: stack_depth

      Minimal stack depth (``int``) in the block delineated by start and stop
      offset of the exception table entry. Used to restore the stack (by
      popping items) when entering the exception handling block.

   .. attribute:: push_lasti

      ``bool`` indicating if the offset, at which an exception was raised, should
      be pushed on the stack before the exception itself (which is pushed as a single value).


.. class:: ConcreteBytecode

   List of concrete instructions (:class:`ConcreteInstr`).
   Inherit from :class:`BaseBytecode`.

   A concrete bytecode must only contain objects of the 2 following types:

   * :class:`SetLineno`
   * :class:`ConcreteInstr`

   :class:`Label`, :class:`TryBegin`, :class:`TryEnd` and :class:`Instr` must
   not be used in concrete bytecode.

   Attributes:

   .. attribute:: consts

      List of constants (``list``), default: empty list.

   .. attribute:: names

      List of names (``list`` of ``str``), default: empty list.

   .. attribute:: varnames

      List of variable names (``list`` of ``str``), default: empty list.

   .. attribute:: exception_table

      List of :class:`ExceptionTableEntry` describing portion of the bytecode
      in which exceptions are caught and where there are handled.
      Used only in Python 3.11+

   Static methods:

   .. staticmethod:: from_code(code, \*, extended_arg=false) -> ConcreteBytecode

      Create a concrete bytecode from a Python code object.

      If *extended_arg* is true, create ``EXTENDED_ARG`` instructions.
      Otherwise, concrete instruction use extended argument (size of ``6``
      bytes rather than ``3`` bytes).

   Methods:

   .. method:: legalize()

      Check the validity of all the instruction and remove the :class:`SetLineno`
      instances after updating the instructions.


   .. method:: to_code(stacksize: int = None, *, check_pre_and_post: bool = True, compute_exception_stack_depths: bool = True) -> types.CodeType

      Convert to a Python code object.

      *stacksize* Allows caller to explicitly specify a stacksize.  If not
      specified a :class:`ControlFlowGraph` is created internally in order to call
      :meth:`ControlFlowGraph.compute_stacksize`.  It's cheaper to pass a value if
      the value is known.

      *check_pre_and_post* Allows caller to disable checking for stack underflow

      If *compute_exception_stack_depths*  is True, the stack depth for each
      exception table entry will be computed (which requires to convert the
      the bytecode to a :class:`ControlFlowGraph`)

   .. method:: to_bytecode() -> Bytecode

      Convert to abstract bytecode with abstract instructions.

   .. method:: compute_stacksize(*, check_pre_and_post: bool = True) -> int

      Compute the stacksize needed to execute the code. Will raise an
      exception if the bytecode is invalid.

      This computation requires to build the control flow graph associated with
      the code.

      *check_pre_and_post* Allows caller to disable checking for stack underflow

   .. method:: update_flags(is_async: bool = None)

      Update the object flags by calling :py:func:infer_flags on itself.


BasicBlock
----------

.. class:: BasicBlock

   `Basic block <https://en.wikipedia.org/wiki/Basic_block>`_. Inherit from
   :class:`list`.

   A basic block is a straight-line code sequence of abstract instructions
   (:class:`Instr`) with no branches in except to the entry and no branches out
   except at the exit.

   A block must only contain objects of the 4 following types:

   * :class:`SetLineno`
   * :class:`Instr`
   * :class:`TryBegin`
   * :class:`TryEnd`

   .. versionchanged:: 0.14.0

      It is not possible anymore to use concrete instructions (:class:`ConcreteInstr`)
      in :class:`BasicBlock`.

   Only the last instruction can have a jump argument, and the jump argument
   must be a basic block (:class:`BasicBlock`).

   Labels (:class:`Label`) must not be used in blocks.

   Attributes:

   .. attribute:: next_block

      Next basic block (:class:`BasicBlock`), or ``None``.

   Methods:

   .. method:: legalize(first_lineno: int) -> None

      Check the validity of all the instruction and remove the :class:`SetLineno`
      instances after updating the instructions. `first_lineno` specifies
      the line number to use for instruction without a set line number encountered
      before the first :class:`SetLineno` instance.

   .. method:: get_jump() --> BasicBlock | None

      Get the target block (:class:`BasicBlock`) of the jump if the basic block
      ends with an instruction with a jump argument. Otherwise, return
      ``None``.

   .. method:: get_trailing_end(index: int) -> TryEnd | None

      Get the first TryEnd found after the position ``index`` in the block if any.


ControlFlowGraph
----------------

.. class:: ControlFlowGraph

   `Control flow graph (CFG)
   <https://en.wikipedia.org/wiki/Control_flow_graph>`_: list of basic blocks
   (:class:`BasicBlock`). A basic block is a straight-line code sequence of
   abstract instructions (:class:`Instr`) with no branches in except to the
   entry and no branches out except at the exit. Inherit from
   :class:`BaseBytecode`.

   Labels (:class:`Label`) must not be used in blocks.

   This class is not designed to emit code, but to analyze and modify existing
   code. Use :class:`Bytecode` to emit code.

   Attributes:

   .. attribute:: argnames

      List of the argument names (``list`` of ``str``), default: empty list.

   Methods:

   .. staticmethod:: from_bytecode(bytecode: Bytecode) -> ControlFlowGraph

      Convert a :class:`Bytecode` object to a :class:`ControlFlowGraph` object:
      convert labels to blocks.

      Splits blocks after final instructions (:meth:`Instr.is_final`) and after
      conditional jumps (:meth:`Instr.is_cond_jump`).

    .. method:: legalize(first_lineno: int)

      Legalize all the blocks of the CFG.

   .. method:: add_block(instructions=None) -> BasicBlock

      Add a new basic block. Return the newly created basic block.

   .. method:: get_block_index(block: BasicBlock) -> int

      Get the index of a block in the bytecode.

      Raise a :exc:`ValueError` if the block is not part of the bytecode.

      .. versionadded:: 0.3

   .. method:: split_block(block: BasicBlock, index: int) -> BasicBlock

      Split a block into two blocks at the specific instruction. Return
      the newly created block, or *block* if index equals ``0``.

   .. method:: get_dead_blocks() -> List[BasicBlock]

      Retrieve all the blocks of the CFG that are unreachable.

   .. method:: to_bytecode() -> Bytecode

      Convert to a bytecode object using labels.

   .. method:: compute_stacksize(*, check_pre_and_post: bool = True, compute_exception_stack_depths: bool = True) -> int

      Compute the stack size required by a bytecode object. Will raise an
      exception if the bytecode is invalid.

      *check_pre_and_post* Allows caller to disable checking for stack underflow

      *compute_exception_stack_depths* Allows caller to disable the computation of
      the stack depth required by exception table entries.

      NOTE:

      The computation will only consider block that can be reached from the entry block.
      In particular, stack size for TryBegin/TryEnd in dead blocks is not updated.

      In some cases, stack usage may be slightly overestimated compared to CPython.
      This occurs when CPython duplicated the code for a finally clause but computed
      stack size before the duplication in which case one could infer a smaller stack
      usage for a TryBegin/TryEnd pair than can be done with the final bytecode
      form.

   .. method:: update_flags(is_async: bool = None)

      Update the object flags by calling :py:func:infer_flags on itself.

   .. method:: to_code(stacksize: int = None, *, check_pre_and_post: bool = True, compute_exception_stack_depths: bool = True)

      Convert to a Python code object.  Refer to descriptions of
      :meth:`Bytecode.to_code` and :meth:`ConcreteBytecode.to_code`.

      *check_pre_and_post* Allows caller to disable checking for stack underflow

      *compute_exception_stack_depths* Allows caller to disable the computation of
      the stack depth required by exception table entries.


Line Numbers
============

The line number can set directly on an instruction using the ``lineno``
parameter of the constructor. Otherwise, the line number if inherited from the
previous instruction, starting at ``first_lineno`` of the bytecode.

:class:`SetLineno` pseudo-instruction can be used to set the line number of
following instructions.

Starting with Python 3.11, instructions now have a starting lineno, and end lineno
along with a starting column offset and an end column offset. :class:`InstrLocation`
is used to store these new detailed information.


Compiler Flags
==============

.. class:: CompilerFlags()

    .. attribute:: OPTIMIZED

        Set if a code object only uses fast locals

    .. attribute:: NEWLOCALS

        Set if the code execution should be done with a new local scope

    .. attribute:: VARARGS

        Set if a code object expects variable number of positional arguments

    .. attribute:: VARKEYWORDS

        Set if a code object expects variable number of keyword arguments

    .. attribute:: NESTED

        Set if a code object correspond to function defined in another function

    .. attribute:: GENERATOR

        Set if a code object is a generator (contains yield instructions)

    .. attribute:: NOFREE

        Set if a code object does not use free variables

    .. attribute:: COROUTINE

        Set if a code object is a coroutine. New in Python 3.5

    .. attribute:: ITERABLE_COROUTINE

        Set if a code object is an iterable coroutine. New in Python 3.5

    .. attribute:: ASYNC_GENERATOR

        Set if a code object is an asynchronous generator. New in Python 3.6

    .. attribute:: FUTURE_GENERATOR_STOP

        Set if a code object is defined in a context in which generator_stop
        has been imported from \_\_future\_\_


.. function:: infer_flags(bytecode, async: bool = None) -> CompilerFlags

    Infer the correct values for the compiler flags for a given bytecode based
    on the instructions. The flags that can be inferred are :

    - OPTIMIZED
    - GENERATOR
    - NOFREE
    - COROUTINE
    - ASYNC_GENERATOR

    Force the code to be marked as asynchronous if True, prevent it from
    being marked as asynchronous if False and simply infer the best
    solution based on the opcode and the existing flag if None.