Câu trả lời ngắn gọn là: bạn đúng trong sự nghi ngờ của mình, bạn luôn cần một trình thông dịch khác được viết bằng X hoặc trình biên dịch từ Y sang một số ngôn ngữ khác mà bạn đã có trình thông dịch. Thông dịch viên thực thi, trình biên dịch chỉ dịch từ ngôn ngữ này sang ngôn ngữ khác, tại một số điểm trong hệ thống của bạn, phải có một trình thông dịch, ngay cả khi đó chỉ là CPU.
Cho dù bạn có viết bao nhiêu trình thông dịch mới bằng ngôn ngữ Y , bạn sẽ luôn phải sử dụng trình thông dịch đầu tiên được viết bằng X để phiên dịch các thông dịch viên tiếp theo. Đây dường như là một vấn đề đơn giản vì bản chất của phiên dịch viên.
Chính xác. Những gì bạn có thể làm là viết một trình biên dịch từ Y đến X (hoặc một ngôn ngữ khác mà bạn có một thông dịch viên), và bạn thậm chí có thể làm điều đó trong Y . Sau đó, bạn có thể chạy trình biên dịch Y được viết bằng Y trên trình thông dịch Y viết bằng X (hoặc trên trình thông dịch Y được viết bằng Y chạy trên trình thông dịch Y viết bằng X hoặc trên trình thông dịch Y viết bằng Y chạy trên trình thông dịch Y viết bằng Y chạy trên Ytrình thông dịch được viết bằng X , hoặc quảng cáo infinitum) để biên dịch trình thông dịch Y của bạn được viết bằng Y thành X , để sau đó bạn có thể thực hiện nó trên trình thông dịch X. Bằng cách đó, bạn đã thoát khỏi trình thông dịch Y được viết bằng X , nhưng bây giờ bạn cần trình thông dịch X (mặc dù chúng tôi biết rằng chúng tôi đã có một trình thông dịch X , vì nếu không, chúng tôi không thể chạy trình thông dịch X được viết bằng Y ) và bạn trước tiên phải viết một trình biên dịch Y -to - X .
Tuy nhiên , về mặt trái, bài viết Wikipedia về phiên dịch viên thực sự nói về phiên dịch viên tự lưu trữ. Đây là một đoạn trích nhỏ có liên quan:
Trình thông dịch tự là một trình thông dịch ngôn ngữ lập trình được viết bằng ngôn ngữ lập trình có thể tự phiên dịch; một ví dụ là một thông dịch viên BASIC được viết bằng BASIC. Tự phiên dịch có liên quan đến trình biên dịch tự lưu trữ.
Nếu không có trình biên dịch tồn tại cho ngôn ngữ được diễn giải, việc tạo trình thông dịch tự yêu cầu thực hiện ngôn ngữ bằng ngôn ngữ máy chủ (có thể là ngôn ngữ lập trình hoặc trình biên dịch khác). Bằng cách có một trình thông dịch đầu tiên như thế này, hệ thống được khởi động và các phiên bản mới của trình thông dịch có thể được phát triển bằng chính ngôn ngữ
Nó vẫn chưa rõ ràng với tôi, làm thế nào chính xác điều này sẽ được thực hiện. Dường như không có vấn đề gì, bạn sẽ luôn bị buộc phải sử dụng phiên bản đầu tiên của trình thông dịch được viết bằng ngôn ngữ máy chủ.
Chính xác. Lưu ý rằng bài viết Wikipedia nói rõ ràng rằng bạn cần triển khai ngôn ngữ thứ hai và không nói rằng bạn có thể thoát khỏi ngôn ngữ thứ nhất.
Bây giờ bài viết được đề cập ở trên liên kết đến một bài viết khác trong đó Wikipedia đưa ra một số ví dụ về các phiên dịch viên tự lưu trữ. Tuy nhiên, khi kiểm tra kỹ hơn, có vẻ như phần "phiên dịch" chính của nhiều trình thông dịch tự lưu trữ (đặc biệt là một số phiên dịch phổ biến hơn như PyPy hoặc Rubinius) thực sự được viết bằng các ngôn ngữ khác như C ++ hoặc C.
Một lần nữa, chính xác. Đó là những ví dụ thực sự tồi tệ. Lấy Rubinius, ví dụ. Đúng, đúng là phần Ruby của Rubinius là tự lưu trữ, nhưng nó là một trình biên dịch, không phải là trình thông dịch: nó biên dịch thành mã nguồn Ruby thành mã byte Rubinius. Phần thông dịch OTOH không tự lưu trữ: nó thông dịch mã Rubinius, nhưng nó được viết bằng C ++. Vì vậy, gọi Rubinius là "trình thông dịch tự lưu trữ" là sai: phần tự lưu trữ không phải là trình thông dịch và phần phiên dịch không tự lưu trữ .
PyPy tương tự, nhưng thậm chí còn không chính xác hơn: nó thậm chí không được viết bằng Python ở nơi đầu tiên, nó được viết bằng RPython, một ngôn ngữ khác. Nó về mặt cú pháp tương tự như Python, về mặt ngữ nghĩa là một "tập hợp con mở rộng", nhưng thực ra nó là một ngôn ngữ được gõ tĩnh gần như ở cùng mức độ trừu tượng như Java và triển khai của nó là một trình biên dịch có nhiều phụ trợ để biên dịch RPython thành mã nguồn C, ECMAScript mã nguồn, mã byte CIL, mã byte JVM hoặc mã nguồn Python.
Vì vậy, những gì tôi mô tả ở trên có thể? Một thông dịch viên tự lưu trữ có thể độc lập với máy chủ ban đầu của nó? Nếu vậy, làm thế nào chính xác điều này sẽ được thực hiện?
Không, không phải của riêng mình. Bạn cần phải giữ trình thông dịch gốc hoặc viết trình biên dịch và biên dịch trình thông dịch tự của bạn.
Có được một số meta-tròn máy ảo, chẳng hạn như Klein (viết bằng Tự ) và Maxine (viết bằng Java). Tuy nhiên, lưu ý rằng ở đây định nghĩa của "meta-tròn" vẫn khác: các VM này không được viết bằng ngôn ngữ mà chúng thực thi: Klein thực thi Self bytecode nhưng được viết bằng Self, Maxine thực thi JVM bytecode nhưng được viết bằng Java. Tuy nhiên, mã nguồn Self / Java của VM thực sự được biên dịch thành mã byte Self / JVM và sau đó được VM thực thi, do đó, khi VM được thực thi, nó sẽ ở ngôn ngữ mà nó thực thi. Phù.
Cũng lưu ý rằng điều này khác với các máy ảo như SqueakVM và Jike RVM . Jike được viết bằng Java và SqueakVM được viết bằng tiếng lóng (một tập hợp cú pháp và ngữ nghĩa được gõ tĩnh của Smalltalk gần như ở cùng mức độ trừu tượng như một trình biên dịch cấp cao) và cả hai đều được biên dịch tĩnh thành mã gốc trước khi chúng được chạy. Họ không chạy trong chính mình. Tuy nhiên, bạn có thể tự chạy chúng trên đầu (hoặc trên đầu máy ảo / JVM nhỏ khác). Nhưng đó không phải là "siêu vòng tròn" theo nghĩa này.
Maxine và Klein, OTOH làmchạy bên trong chính mình; họ thực thi mã byte riêng bằng cách sử dụng triển khai riêng của họ. Đây thực sự là tâm trí! Nó cho phép một số cơ hội tối ưu hóa thú vị, ví dụ vì VM tự thực thi cùng với chương trình người dùng, nó có thể gọi nội tuyến từ chương trình người dùng đến VM và ngược lại, ví dụ như gọi đến bộ thu gom rác hoặc bộ cấp phát bộ nhớ có thể được đưa vào người dùng mã và các cuộc gọi lại phản chiếu trong mã người dùng có thể được nhập vào VM. Ngoài ra, tất cả các thủ thuật tối ưu hóa thông minh mà các máy ảo hiện đại thực hiện, trong đó chúng xem chương trình thực thi và tối ưu hóa nó tùy thuộc vào khối lượng công việc và dữ liệu thực tế, VM có thể áp dụng các thủ thuật tương tự cho chính nó trong khi nó đang thực thi chương trình người dùng trong khi chương trình người dùng đang thực hiện khối lượng công việc cụ thể. Nói cách khác, VM rất chuyên môn hóa cho điều đóchương trình cụ thể chạy mà khối lượng công việc cụ thể.
Tuy nhiên, lưu ý rằng tôi đã bỏ qua việc sử dụng từ "thông dịch viên" ở trên và luôn luôn sử dụng "thực thi"? Chà, những VM đó không được xây dựng xung quanh các trình thông dịch, chúng được xây dựng xung quanh các trình biên dịch (JIT). Sau đó, có một trình thông dịch được thêm vào Maxine, nhưng bạn luôn cần trình biên dịch: bạn phải chạy VM một lần trên một VM khác (ví dụ: Oracle HotSpot trong trường hợp Maxine), để VM có thể tự biên dịch. Trong trường hợp của Maxine, JIT sẽ biên dịch pha khởi động của chính nó, sau đó tuần tự hóa mã gốc đã biên dịch thành hình ảnh VM bootstrap và dán một bộ tải khởi động rất đơn giản ở phía trước (thành phần duy nhất của VM được viết bằng C, mặc dù đó chỉ là để thuận tiện , nó cũng có thể có trong Java). Bây giờ bạn có thể sử dụng Maxine để thực thi chính nó.