Tập 51: Từ JS oracle sang subset DUY

Tự nâng mình lên bằng cách tự kéo dây giày của mình — bootstrap không chỉ là một nghi lễ kỹ thuật, đó là thời điểm ngôn ngữ tự chịu trách nhiệm với sự tồn tại của chính nó.

Một ngôn ngữ lập trình hệ thống có thể dịch ra mã máy, chạy freestanding và chạy trong kernel, nhưng nếu trình biên dịch của nó vẫn phải được viết bằng một ngôn ngữ khác (như JavaScript), nó vẫn chưa thể coi là hoàn toàn trưởng thành. Một compiler tự lực phải được viết bằng chính ngôn ngữ mà nó biên dịch. Đó gọi là quá trình tự trị (self-hosting), và nghi thức biên dịch chéo qua các thế hệ trình biên dịch gọi là bootstrap ceremony.

Nhưng tự trị không phải là một công tắc có thể bật tắt trong một đêm. Đây là giai đoạn nguy hiểm nhất của bất kỳ dự án ngôn ngữ nào, vì người thiết kế rất dễ rơi vào cái bẫy "ảo tưởng chiến thắng" — nghĩ rằng mình đã hoàn thành tự trị trong khi thực tế chỉ mới biên dịch được vài ví dụ phẳng. Việc debug một compiler có lỗi bằng một compiler khác cũng đang có lỗi chính là con đường ngắn nhất dẫn đến sự kiệt sức của kỹ sư.

Chương này kể về cuộc chiến bootstrap của DUY trong các Sprint từ 81 đến 98 (Phase M-O). Để vượt qua vực sâu này mà không bị kiệt sức, chúng tôi phải đóng băng một subset tối giản của ngữ pháp, xây dựng từng module lexer, parser, checker bằng DUY, chạy các so khớp digest với trình biên dịch JS gốc (JS oracle), và thiết lập chuỗi fixed-point bootstrap đầu tiên để đo lường hashes đầu ra.



Nhiều dự án tự trị thất bại vì họ cố gắng làm quá nhiều việc cùng một lúc. Họ viết compiler mới bằng ngôn ngữ mới và cố gắng hỗ trợ toàn bộ các tính năng phức tạp nhất (như generics, region, unsafe) ngay từ ngày đầu. Kết quả là họ phải debug một compiler có lỗi bằng một compiler khác cũng có lỗi, tạo ra một vòng lặp vô tận của sự bối rối và tuyệt vọng. Khi compiler mới sinh ra mã máy bị lỗi, bạn không thể biết lỗi nằm ở mã nguồn compiler mới hay do chính compiler cũ sinh sai mã máy cho nó.

Tôi chọn con đường chia để trị: đóng băng một subset tối giản của DUY để làm ngôn ngữ viết compiler mới.

Subset này chỉ bao gồm những khối cơ bản nhất để diễn đạt logic biên dịch: - Khai báo hàm (fn), khai báo biến (let). - Kiểu dữ liệu nguyên bản (i32, bool). - Cấu trúc điều khiển (if, while, return). - Các phép toán số học và lời gọi hàm.

Mọi tính năng nâng cao như enum, ? operator, region, hay effect đều bị loại bỏ khỏi subset này. Trình biên dịch hiện tại viết bằng JS (chúng tôi gọi là JS oracle) sẽ đóng vai trò làm trọng tài. Nó là nguồn sự thật đáng tin cậy để biên dịch đợt code compiler DUY đầu tiên.

Quyết định này vấp phải sự hoài nghi của người đồng nghiệp AI. AI đề xuất sử dụng toàn bộ tính năng của ngôn ngữ để viết compiler cho đẹp mắt và tận dụng tối đa sức mạnh của hệ kiểu. Nhưng tôi kiên quyết: "Trong chiến trận, khi phải băng qua một bãi mìn, anh không nên mang theo một ba lô đầy đồ trang sức lộng lẫy. Anh cần sự tối giản tối đa để sống sót. Trình biên dịch Stage 1 phải càng đơn giản càng tốt." Quyết định này giữ cho phạm vi chiến dịch đủ hẹp để có thể kiểm soát. Chúng tôi xây từng bước cầu vững chắc dựa trên sự bảo đảm của JS oracle.


Bình luận (0)

Đang tải bình luận...