22. Trình biên dịch

Trình biên dịch chuyển thông tin về bảng ký hiệu và AST thành đối tượng mã thực thi.

Các giai đoạn trước trả lời các câu hỏi về cấu trúc.```text id="lfk0j9" tokenizer: What lexical units are in the source?

parser: What syntax tree do these tokens form?

symbol table: What scope does each name belong to? Trình biên dịch trả lời các câu hỏi thực thi.text id="ju2gsy" Which bytecode instructions should be emitted? Which constants belong in co_consts? Which names belong in co_names? Which local variables belong in co_varnames? Where should jumps go? How large can the evaluation stack grow? Which exception table entries are needed? Which nested code objects must be created? ```Đầu ra là mộtcodesự vật. Đối tượng mã đó có thể được thực thi bởi vòng đánh giá CPython.

22.1 Vị trí trong Đường dẫn biên dịch

Trình biên dịch nằm sau khi phân tích cú pháp và phân tích phạm vi.```text id="9mc7xw" source ↓ tokenization ↓ parsing ↓ AST ↓ symbol table ↓ compiler passes ↓ code object ↓ interpreter execution


 cp độ Python,`compile()`chc năng hin th giai đon này:```python id="2sweqj"
src = "x = 1 + 2\n"
code = compile(src, "<input>", "exec")

print(code)
```Bn có th kim tra kết qu vi`dis`:

```python id="24znqy"
import dis

code = compile("x = 1 + 2\n", "<input>", "exec")
dis.dis(code)
```## 22.2 Đầu vào chính của Trình biên dịch

Trình biên dch s dng hai sn phm chính t các giai đon trước.

| Đầu vào | Vai trò |
| ------------- | ------------------------------------------------------------------ |
| AST | Mô t các câu lnh, biu thc, toán t và v trí ngun |
| Bng ký hiu | Mô t phân loi phm vi cho tên |

AST nói:```text id="iqtzc2"
there is an assignment
target is Name("x")
value is BinOp(Constant(1), Add, Constant(2))
```Bng ký hiu cho biết:```text id="2kd8cu"
x is local/global in this scope
```Chúng cùng nhau cho phép to mã byte.

Ví d: trình biên dch chn gia:```text id="1lrzcy"
STORE_FAST
STORE_NAME
STORE_GLOBAL
STORE_DEREF
```tùy thuc vào thông tin phm vi.

## 22.3 Đầu ra của trình biên dịch: Đối tượng mã

Trình biên dch phát ra các đối tượng mã.

Đối tượng mã cha mã byte và siêu d liu thc thi.

Các trường quan trng bao gm:```text id="6p1zp9"
co_code             bytecode bytes
co_consts           constants
co_names            global and attribute names
co_varnames         local variable names
co_freevars         free variable names
co_cellvars         cell variable names
co_filename         source filename
co_name             function or module name
co_qualname         qualified name
co_firstlineno      first source line
co_flags            execution flags
co_stacksize        required value stack size
```Ví d:```python id="z2p4ol"
def add(a, b):
    return a + b

code = add.__code__

print(code.co_name)
print(code.co_varnames)
print(code.co_consts)
print(code.co_names)
print(code.co_stacksize)
```Đối tượng mã là d liu thc thi bt biến. Đối tượng hàm bao bc mt đối tượng mã bng ng cnh thi gian chy chng hn như toàn cc, mc định, chú thích và ô đóng.

## 22.4 Biên dịch là đệ quy

Các hàm lng nhau, lambda, mc hiu, lp và biu thc trình to to ra các đối tượng mã lng nhau.

Ví d:```python id="nxf9b9"
def outer(x):
    def inner(y):
        return x + y
    return inner
```Đối tượng mã mô-đun cha mt đối tượng mã chc năng cho`outer`.

các`outer`đối tượng mã cha mt đối tượng mã chc năng cho`inner`.

V mt khái nim:```text id="g7e4jo"
module code object
    constants:
        code object for outer
            constants:
                code object for inner
```Trong thi gian chy, thc thi`def outer`to mt đối tượng hàm t`outer`đối tượng mã. Đang thc hin`def inner`bên trong`outer`to mt đối tượng hàm khác, vi các ô đóng khi cn.

## 22.5 Biên soạn câu lệnh

Các câu lnh thường phát ra mã byte để thc hin các hành động.

Ví d:```python id="f8r2kh"
x = 1
```Mu biên dch:```text id="vbnwbg"
compile right-hand expression
store result into target
```Mã byte được đơn gin hóa:```text id="ozi020"
LOAD_CONST 1
STORE_NAME x
```Ví d:```python id="jflq5g"
return x
```Mu biên dch:```text id="j5nviu"
compile return expression
emit RETURN_VALUE
```Mã byte được đơn gin hóa:```text id="5k1c90"
LOAD_FAST x
RETURN_VALUE
```Mã byte chính xác thay đổi theo phiên bn Python, nhưng ý tưởng cu trúc vn n định.

## 22.6 Biên dịch biểu thức

Biu thc phát ra mã byte để li mt giá tr trên ngăn xếp đánh giá.

Ví d:```python id="thj50j"
a + b
```Mu biên dch:```text id="f51gg5"
load a
load b
apply binary operation
```Mã byte được đơn gin hóa:```text id="esgtwo"
LOAD_FAST a
LOAD_FAST b
BINARY_OP +
```Mt câu lnh biu thc thường loi b kết qu ca nó:```python id="77sckz"
f()
```Mu biên dch:```text id="u882gm"
load function
call function
pop result
```Mã byte được đơn gin hóa:```text id="fo9egq"
LOAD_NAME f
CALL
POP_TOP
```Trình biên dch duy trì k lut ngăn xếp. Mi biu thc đều có hiu ng ngăn xếp đã biết.

## 22.7 Biên soạn tên

Mã byte tên ph thuc vào phân loi phm vi.

Ví d:```python id="7v96c6"
def f(a):
    return a

alà một biến cục bộ:text id="spceye" LOAD_FAST a Ví dụ:```python id="o6h1if" x = 1

def f(): return x


`x`mang tính toàn cu t bên trong`f`:

```text id="xmpdg1"
LOAD_GLOBAL x
```Ví d:```python id="yptzi2"
def outer():
    x = 1

    def inner():
        return x

xlà một biến đóng từ bên tronginner:

LOAD_DEREF x
```Đây là lý do tại sao việc phân tích bảng ký hiệu diễn ra trước việc phát mã byte.

## 22.8 Biên dịch mục tiêu

Mục tiêu gán được biên dịch khác với biểu thức giá trị.

Ví dụ:```python id="xpt040"
x = value
```Mục tiêu hoạt động:```text id="jfu667"
STORE_FAST or STORE_NAME or STORE_GLOBAL or STORE_DEREF
```Ví dụ:```python id="rtgk3q"
obj.attr = value
```Mục tiêu hoạt động:```text id="r72bwa"
compile obj
compile value
STORE_ATTR attr
```Ví dụ:```python id="s5jn7u"
items[i] = value
```Mục tiêu hoạt động:```text id="yyzjb4"
compile items
compile i
compile value
STORE_SUBSCR
```Hình dạng AST giống nhau có thể biên dịch khác nhau tùy theo ngữ cảnh.

So sánh:```python id="i5tdmi"
obj.attr
```được sử dụng làm giá trị:```text id="14wnr4"
LOAD_ATTR attr
```Và:```python id="c46iv2"
obj.attr = 1
```được sử dụng làm mục tiêu:```text id="7uswmv"
STORE_ATTR attr
```Bối cảnh AST như`Load`, `Store`, Và`Del`thúc đẩy sự khác biệt này.

## 22.9 Biên soạn luồng điều khiển

Luồng điều khiển yêu cầu nhảy và nhãn.

Ví dụ:```python id="5u72qc"
if x:
    a = 1
else:
    a = 2
```Mẫu biên dịch:```text id="c7me6c"
compile test x
jump to else block if false
compile body
jump to end
else label:
compile else body
end label:
continue
```Hình dạng mã byte được đơn giản hóa:```text id="ukb3dq"
LOAD_NAME x
POP_JUMP_IF_FALSE else_label

LOAD_CONST 1
STORE_NAME a
JUMP_FORWARD end_label

else_label:
LOAD_CONST 2
STORE_NAME a

end_label:
```Trình biên dịch đầu tiên phát ra các bước nhảy tượng trưng hoặc các nhãn bên trong. Việc lắp ráp sau này phân giải chúng thành các độ lệch byte cụ thể hoặc độ lệch lệnh.

## 22.10 Vòng lặp

Vòng lặp yêu cầu nhãn vào, nhãn thoát và đôi khi là mục tiêu tiếp tục.

Ví dụ:```python id="28xqrv"
while x:
    work()
```Mẫu biên dịch:```text id="aq977s"
loop_start:
compile test
jump to loop_end if false
compile body
jump to loop_start
loop_end:
```Ví dụ:```python id="u0a0kq"
for item in items:
    work(item)
```Mẫu biên dịch:```text id="fs8o3k"
compile iterable
get iterator
loop_start:
get next item or jump to loop_end
store item
compile body
jump to loop_start
loop_end:

breaknhảy đến lối ra vòng lặp.continuenhảy tới điểm tiếp tục vòng lặp.

Các vòng lặp lồng nhau yêu cầu ngăn xếp khối trình biên dịch nênbreakcontinuenhắm mục tiêu vòng lặp kèm theo chính xác.

22.11 Xử lý ngoại lệ

Quá trình biên dịch xử lý ngoại lệ phức tạp hơn vì nó cần siêu dữ liệu luồng điều khiển.

Ví dụ:python id="zbie3d" try: risky() except ValueError: recover() finally: cleanup() Trình biên dịch phải tạo mã byte cho:```text id="7fd19n" normal execution exception matching handler entry handler cleanup finally execution reraising when needed


V mt khái nim:```text id="9wg6kk"
protected bytecode range:
    risky()

handler:
    if exception matches ValueError:
        recover()

finally:
    cleanup()
```Trình biên dch phi bo toàn ng nghĩa ngoi l chính xác ca Python, bao gm`else`, `finally`, `raise`, xâu chui ngoi l và dn dp các biến x lý ngoi l.

## 22.12 Biên dịch định nghĩa hàm

Mt định nghĩa hàm biên dch thành hai lp.

Ví d:```python id="9423bh"
def add(a, b):
    return a + b
```Lp 1: biên dch phn thân hàm thành mt đối tượng mã lng nhau.```text id="8pamlr"
code object for add:
    LOAD_FAST a
    LOAD_FAST b
    BINARY_OP +
    RETURN_VALUE
```Lp 2: biên dch câu lnh bên ngoài to đối tượng hàm.```text id="ndgkj2"
LOAD_CONST <code object add>
MAKE_FUNCTION
STORE_NAME add
```S khác bit này là trung tâm.

Thân hàm không chy khi trình biên dch nhìn thy`def`. Trong thi gian chy, vic thc thi`def`câu lnh to mt đối tượng hàm và liên kết nó vi tên hàm.

## 22.13 Mặc định, Chú thích và Trang trí

Các định nghĩa hàm có th bao gm các giá tr mc định, chú thích và trang trí.

Ví d:```python id="06culw"
@trace
def f(x: int, y=1) -> int:
    return x + y
```Quá trình biên dch phi x lý:```text id="st02n8"
default argument value y=1
parameter annotation x: int
return annotation -> int
function body code object
function object creation
decorator application
name binding
```Th t thi gian chy khái nim:```text id="e9t5yf"
evaluate decorator expressions
evaluate default values
evaluate annotations according to current rules
create function object
apply decorators from bottom to top
bind final function object to name
```Trình biên dch phát ra mã byte thc hin th t này.

## 22.14 Biên soạn định nghĩa lớp

Mt định nghĩa lp cũng biên dch theo lp.

Ví d:```python id="c7bkv3"
class C(Base):
    x = 1

    def f(self):
        return self.x
```Thân lp tr thành mt đối tượng mã.

Khi chy:```text id="s2rsuu"
evaluate base classes
create class namespace
execute class body code object in that namespace
call metaclass machinery
bind resulting class object to name
```Trình biên dch phát ra mã byte gi giao thc xây dng lp bên trong.

Thân lp là mã thc thi được. Nó có th cha các câu lnh tùy ý:```python id="we8528"
class C:
    print("building class")
    x = compute()
```Nhng câu lnh đó chy khi định nghĩa lp được thc thi.

## 22.15 Biên dịch đóng cửa

Vic đóng ca yêu cu công vic phi hp gia phân tích bng ký hiu và to mã byte.

Ví d:```python id="ovqkwa"
def outer():
    x = 1

    def inner():
        return x

    return inner
```Trình biên dch phi:```text id="ovv4rt"
create a cell for x in outer
compile inner with x as a free variable
create inner function with closure tuple
load x through closure access in inner
```Hình dng đơn gin bên trong`outer`:

```text id="3irffr"
MAKE_CELL x
LOAD_CONST 1
STORE_DEREF x
LOAD_CLOSURE x
BUILD_TUPLE 1
LOAD_CONST <code object inner>
MAKE_FUNCTION closure
STORE_FAST inner
LOAD_FAST inner
RETURN_VALUE
```Bên trong`inner`:

```text id="31h0a6"
LOAD_DEREF x
RETURN_VALUE
```Các hướng dn chính xác khác nhau tùy theo phiên bn, nhưng cơ chế đóng vn gi nguyên: các biến được ghi li nm trong các ô.

## 22.16 Biên soạn hiểu

S hiu biết được biên dch thành các đối tượng mã lng nhau.

Ví d:```python id="5w7ihk"
values = [x * x for x in range(5)]
```V mt khái nim, CPython to mã tương t như mt hàm lng nhau ngm cho phn ni dung hiu.

Mã bên ngoài đánh giá ln lp và gi mã hiu. Mã hiu s lp li và xây dng danh sách kết qu.

Điu này gii thích ti sao các biến hiu không rò r vào phm vi xung quanh.```python id="in5tuc"
x = 100
values = [x for x in range(3)]
print(x)
```Bên ngoài`x`còn li`100`.

S hiu biết`x`là cc b ca đối tượng mã hiu.

## 22.17 Biên dịch trình tạo

Các hàm to được biên dch khác vi các hàm thông thường.

Ví d:```python id="esmh0i"
def gen():
    yield 1
    yield 2
```Trình biên dch đánh du đối tượng mã bng các c ca trình to.

Khi được gi,`gen()`không thc thi cơ th ngay lp tc. Nó tr v mt đối tượng máy phát đin.

Phn thân thc thi khi trình to được nâng cao.

Quá trình biên dch phi phát ra đim năng sut:```text id="xk7fji"
LOAD_CONST 1
YIELD_VALUE
resume point
LOAD_CONST 2
YIELD_VALUE
resume point
RETURN_VALUE
```Khung máy phát đin có th tm dng và tiếp tc. C đối tượng mã cho b thc thi biết cách xây dng và thc thi nó.

## 22.18 Biên dịch Coroutine và Async

Các hàm không đồng b to ra các đối tượng mã coroutine.

Ví d:```python id="5d36kx"
async def fetch():
    result = await client.get()
    return result
```Trình biên dch đánh du đối tượng mã là mã coroutine.

Nó phát ra máy móc ch đợi xung quanh các biu thc có th ch đợi.

V mt khái nim:```text id="g68r60"
call client.get()
obtain awaitable
suspend until awaitable completes
store result
return result
```Chc năng không đồng b, trình to không đồng b,`async for`, Và`async with`tt c đều yêu cu các mu mã byte và c mã đặc bit.

## 22.19 Biên dịch khớp mẫu

Khp mu có logic biên dch chuyên dng.

Ví d:```python id="jz9doq"
match value:
    case 0:
        result = "zero"
    case [x, y]:
        result = x + y
```Trình biên dch phi phát ra mã ti:```text id="1gk5a7"
evaluate subject once
try first pattern
jump to body if matched
try next pattern if failed
bind captured names only on successful match
evaluate guards when present
skip remaining cases after match
```Vic khp mu không h bình thường`if`cú pháp cũng như phép gán thông thường. Nó có các quy tc phù hp và ràng buc riêng.

## 22.20 Xử lý liên tục

Trình biên dch lưu tr các hng s trong`co_consts`.

Ví d:```python id="j0h9t8"
x = 123
y = "hello"
```Các hng s đối tượng mã có th bao gm:```text id="4721fz"
None
123
"hello"
nested code objects
tuples of constants
frozensets used by optimized membership tests
```Thanh tra:```python id="qrm79o"
code = compile("x = 123\ny = 'hello'\n", "<input>", "exec")
print(code.co_consts)
```Các hng s được tham chiếu theo ch mc t các hướng dn mã byte.

## 22.21 Tên và bảng biến

Trình biên dch xây dng mt s bng tên.

| Trường đối tượng mã | Ý nghĩa |
| ----------------- | ----------------------------------------------- |
|`co_names`| Tên được s dng cho toàn cu, thuc tính và nhp khu |
|`co_varnames`| Tên biến cc b nhanh |
|`co_cellvars`| Người dân địa phương b bt bi phm vi lng nhau |
|`co_freevars`| Các biến được ghi li t phm vi kèm theo |

Ví d:```python id="m1cvy7"
x = 1

def f(a):
    b = len(a)
    return x + b
```Bên trong`f`:

```text id="8bgw2w"
co_varnames:
    a, b

co_names:
    len, x
```Nếu vic đóng ca có liên quan,`co_cellvars`Và`co_freevars`xut hin.

## 22.22 Tính toán kích thước ngăn xếp

Mã byte CPython s dng ngăn xếp giá tr.

Trình biên dch phi tính toán độ sâu ngăn xếp ti đa cn thiết cho mt đối tượng mã.

Ví d:```python id="kt5lcp"
x = a + b * c
```Có th phát trin ngăn xếp:```text id="q0x4gy"
LOAD a        stack: a
LOAD b        stack: a, b
LOAD c        stack: a, b, c
MULTIPLY      stack: a, result
ADD           stack: result
STORE x       stack:
```Độ sâu ngăn xếp ti đa: 3.

Đối tượng mã lưu tr cái này dưới dng`co_stacksize`.

Trình thông dch s dng nó để xác định kích thước lưu tr khung.

## 22.23 Bảng số dòng và vị trí

Trình biên dch ghi li ánh x gia mã byte và v trí ngun.

Các ánh x này h tr:```text id="srmq4m"
tracebacks
debuggers
profilers
coverage tools
stepping behavior
error locations
```Ví d:```python id="st4v12"
def f():
    x = 1
    y = 2
    return x + y
```Mi phm vi mã byte có th được liên kết vi thông tin v dòng và ct ngun.

CPython hin đại theo dõi thông tin v trí chính xác hơn các phiên bn cũ hơn, giúp ci thin kh năng theo dõi và g li.

## 22.24 hội

Trình biên dch thường phát ra biu din lnh trung gian trước bytecode cui cùng.

Hi gii quyết:```text id="ic8am2"
labels
jump targets
instruction offsets
extended arguments
line tables
exception tables
final bytecode layout
```Điu này là cn thiết vì độ lch nhy ph thuc vào kích thước lnh và kích thước lnh có th thay đổi khi độ lch yêu cu đối s m rng.

V mt khái nim:```text id="nxzhpt"
emit symbolic instructions
compute instruction offsets
resolve jumps
insert extended arguments if needed
recompute if sizes changed
build final bytecode bytes
build metadata tables
create code object
```## 22.25 Tối ưu hóa AST

CPython thc hin mt s ti ưu hóa  cp độ AST hoc trình biên dch.

Ví d có th bao gm:```text id="45a56p"
constant folding
removing unreachable assert code under optimization
simplifying literal containers for membership tests
basic expression simplifications
```Ví d:```python id="hspw89"
x = 1 + 2
```có th biên dch như th được viết:```python id="99zdo5"
x = 3
```Thanh tra:```python id="3ltxiz"
import dis

dis.dis(compile("x = 1 + 2\n", "<input>", "exec"))
```Ti ưu hóa là bo th. CPython phi bo toàn ng nghĩa ca Python, bao gm các tác dng ph, ngoi l và th t đánh giá.

## 22.26 Thứ tự đánh giá

Trình biên dch phi gi nguyên th t đánh giá ca Python.

Ví d:```python id="0rat4c"
result = f() + g()

f()phải thực hiện trướcg().

Ví dụ:```python id="3cgy5k" obj.attr = value()


Ví d:```python id="9uqpy4"
d[key()] = value()
```Trình biên dch không th t do sp xếp li các thao tác ch vì mt th t khác có th nhanh hơn.

Ng nghĩa động ca Python biến th t đánh giá thành mt phn ca hành vi có th quan sát được.

## 22.27 Xử lý lỗi trong quá trình biên dịch

Mt s li được phát hin trong quá trình biên dch, không phân tích cú pháp.

Ví d:```python id="uxlk51"
return 1
``` cp độ mô-đun.```python id="nlyacf"
break
```bên ngoài mt vòng lp.```python id="kggjx7"
continue
```bên ngoài mt vòng lp.

Trình phân tích cú pháp có th xây dng các nút cho các câu lnh này. Trình biên dch t chi chúng khi ng cnh khiến chúng tr nên bt hp pháp.

Điu này có nghĩa là AST có dng cú pháp có th vn không biên dch được.

## 22.28 API công khai để biên dịch

Python trưng bày quá trình biên dch thông qua`compile()`.

Ví d:```python id="njqphs"
code = compile("x = 1\n", "<input>", "exec")
exec(code)
```Chế độ:

| Chế độ | Ý nghĩa |
| -------- | -------------------------------------- |
|`exec`| Biên dch mt mô-đun hoc chui câu lnh |
|`eval`| Biên dch mt biu thc |
|`single`| Biên dch đầu vào tương tác |

Ví d:```python id="s246ja"
compile("x = 1", "<input>", "exec")
compile("1 + 2", "<input>", "eval")
compile("print(1)", "<input>", "single")

compile()cũng có thể biên dịch AST:```python id="mcvj8n" import ast

tree = ast.parse("x = 1\n") code = compile(tree, "", "exec") exec(code)


Các tệp quan trọng liên quan đến trình biên dịch bao gồm:```text id="jwz8yn"
Python/compile.c
Python/symtable.c
Python/ast.c
Python/ast_opt.c
Python/flowgraph.c
Python/assemble.c
Include/cpython/code.h
Lib/dis.py
Lib/test/test_compile.py
Lib/test/test_dis.py
```Vai trò khái niệm:

| Khu vực | Vai trò |
| -------------- | ---------------------------------- |
|`symtable.c`| Phân loại phạm vi |
|`compile.c`| Biên dịch AST theo hướng dẫn |
|`flowgraph.c`| Xử lý biểu đồ luồng điều khiển |
|`assemble.c`| Tập hợp mã byte cuối cùng |
|`code.h`| Định nghĩa đối tượng mã |
|`dis.py`| Kiểm tra mã byte |
| kiểm tra trình biên dịch | Bảo vệ hành vi và hồi quy |

Tổ chức tệp chính xác có thể thay đổi giữa các phiên bản, nhưng quy trình khái niệm vẫn ổn định.

## 22.30 Mô hình tinh thần tối thiểu

Sử dụng mô hình này:```text id="ti9m3l"
The AST gives syntax.
The symbol table gives scope.
The compiler walks the AST and emits bytecode instructions.
Nested executable constructs produce nested code objects.
Control flow becomes jumps and exception tables.
Names become local, global, or closure bytecode.
Constants and names are stored in code object tables.
Assembly resolves labels, jumps, stack size, and metadata.
The result is an immutable code object ready for execution.
```Các trình biên dịch là nơi CPython biến cú pháp và phạm vi thành các hướng dẫn thực thi.