Tại sao có quá ít trình thông dịch C++

lập trình


Cá nhân tôi chỉ biết có 1 trình thông dịch C++ được Root sử dụng (CINT, được phát triển tại CERN). Nó làm tôi thắc mắc tại sao lại có quá ít và câu trả lời rõ ràng là C++ là một ngôn ngữ rất phức tạp để phân tích cú pháp. Không ai có đầu óc tỉnh táo lại bận tâm đến việc viết trình phân tích cú pháp C++ từ đầu …

Tuy nhiên, có các trình phân tích cú pháp C++ hiện có như một phần của trình biên dịch, một số trong đó là nguồn mở. Tôi chợt nhận ra rằng có thể diễn giải mã lắp ráp được trình phân tích cú pháp phát ra khi đang di chuyển. Điều này sẽ giống như một trình biên dịch JIT phát ra mã byte để máy ảo giải thích. Một vấn đề nảy sinh là việc sử dụng các tệp nguồn khác nhau, nếu không sẽ dẫn đến một số tệp đối tượng cần được liên kết. Đây thực sự là một hạn chế, nhưng không phải là một hạn chế nghiêm trọng nếu bạn hỏi tôi.

Tuy nhiên, có vẻ như chưa có ai làm điều này, điều này thường có nghĩa là nó không dễ dàng như người ta tưởng (không phải ý tưởng của tôi là tầm thường, nhưng vẫn vậy). Tôi đang tự hỏi ý tưởng của tôi sẽ có vấn đề gì… Có ai muốn bình luận không?

Giải pháp 1

Vui lòng xem nhận xét cho câu hỏi của bling (ý tưởng hay về C++/CLI) và bản thân tôi.

Sự thật là: CINT không phải là trình thông dịch C++. CINT không phải là trình thông dịch C++. Điều này được nêu rõ ở đây:

[^].

Ngôn ngữ này là một số ngôn ngữ đơn giản hóa dựa trên C và C++.

Xem thêm: http://root.cern.ch/drupal/content/cling[^].

Còn một giải pháp thay thế được đề cập trong bài viết Wikipedia được tham chiếu ở trên, “Ch” thì sao? Đây không hẳn là trình thông dịch C++, đây là trình thông dịch của một số ngôn ngữ đặc biệt:
http://en.wikipedia.org/wiki/Ch_%28computer_programming%29[^],

[^].

Còn gì nữa không? “Pike”, cũng chỉ dựa trên C và C++ (Wikipedia thậm chí còn nói “bị ảnh hưởng bởi”):
http://en.wikipedia.org/wiki/Pike_%28programming_lingu%29[^],

[^].

Đối với ngôn ngữ C++ “thực”, tôi có một số người tin rằng nó không phù hợp với một thông dịch viên; chủ đề quá phức tạp để thảo luận về những cân nhắc của tôi một cách Nhanh Hỏi & Đáp. Tôi không thể chứng minh điều đó ngay tại đây và không chắc chắn 100%, do có xu hướng nghĩ rằng có thể chứng minh được. Tôi sẽ khá ngạc nhiên nếu ai đó chứng minh tôi sai.

-SA

Giải pháp 3

Trích dẫn:

Cá nhân tôi chỉ biết có 1 trình thông dịch C++ được Root sử dụng (CINT, được phát triển tại CERN). Nó làm tôi thắc mắc tại sao lại có quá ít và câu trả lời rõ ràng là C++ là một ngôn ngữ rất phức tạp để phân tích cú pháp. Không ai có đầu óc tỉnh táo lại bận tâm đến việc viết trình phân tích cú pháp C++ từ đầu …

Có một số câu hỏi quan trọng ở đây: Mục tiêu của bạn là gì và tại sao trình thông dịch C/C++ lại là giải pháp tốt nhất (hoặc ít nhất là hợp lý) cho vấn đề đó? “Mục tiêu của bạn là gì?” và “Tại sao X là giải pháp tốt?” nói chung là những câu hỏi đầu tiên rất hay nên hỏi trước khi lãng phí thời gian quý báu vào việc thực hiện một giải pháp.

C/C++ không thực tế như một ngôn ngữ thông dịch dựa trên bảng điều khiển vì nhiều lý do và mọi người thường không thích lãng phí thời gian vào việc triển khai các công cụ không thực tế (à, có thể những người có nhiều thời gian để vui chơi và học hỏi và/hoặc những công cụ đó). người không thể thấy trước những khía cạnh không thực tế).

Việc triển khai trình thông dịch cho ngôn ngữ động (như python) với các biến được nhập động và “các hàm liên kết động” dễ dàng hơn và ít xảy ra lỗi hơn so với thực hiện tương tự với C/C++. Viết toàn bộ trình phân tích cú pháp, trình biên dịch, trình thông dịch cho một ngôn ngữ động đơn giản khá dễ dàng và nhanh chóng. Bản thân trình thông dịch không cần phải có hiệu suất cao vì nó thường chỉ được sử dụng để thực thi logic cấp cao, mã kết dính. Nếu có điều gì đó quan trọng về hiệu năng thì bạn có thể triển khai nó dưới dạng mô-đun C/C++ gốc cho trình thông dịch của mình và liên kết nó với ngôn ngữ được diễn giải động. Theo tôi, bạn chưa thực sự nghĩ đến những vấn đề có thể xảy ra với trình thông dịch C/C++. Tôi có thể viết một cuốn tiểu thuyết về họ. Dưới đây là những vấn đề thú vị nhất nhưng đủ lớn:

C/C++ yêu cầu khai báo chuyển tiếp. Trong ngôn ngữ được diễn giải thực tế, không có khai báo chuyển tiếp và không có khai báo/định nghĩa riêng biệt. Nhưng đây chỉ là một phần nhỏ của một vấn đề nghiêm trọng hơn: C/C++ không thực tế lắm để được sử dụng làm ngôn ngữ thông dịch. Đây là một tập hợp các vấn đề liên quan đến cả vấn đề thiết kế ngôn ngữ và vấn đề khả năng sử dụng thực tế như một ngôn ngữ được thông dịch. Trong python tôi có thể dễ dàng xác định hàm X gọi hàm Y không tồn tại và tôi được phép xác định hàm Y này sau. Sau đó, tôi có thể thực thi X. Sau đó, nếu muốn, tôi có thể thay đổi hoàn toàn định nghĩa của Y (có thể với một số tham số được khởi tạo mặc định mới để tương thích ngược với định nghĩa trước đó) và một lần thực thi X khác ngay lập tức sử dụng định nghĩa Y mới. Tôi có thể thực thi X ngay cả khi nó gọi một hàm Z chưa được xác định và điều này không thành vấn đề nếu việc thực thi X với các tham số đầu vào thực tế không thực sự chạy vào nhánh sẽ gọi Z. Trong một Trình thông dịch C++ điều gì xảy ra nếu tôi thay đổi định nghĩa của một mẫu rất cơ bản (ví dụ: mảng động) được sử dụng bởi nhiều hàm được xác định trước đó (ví dụ như các hàm nội tuyến)? Làm cách nào để bạn biết được khối mã nào cần biên dịch lại bên trong trình thông dịch của mình để sử dụng các hàm nội tuyến mới? Điều gì xảy ra nếu việc biên dịch lại một số hàm này không thành công với định nghĩa mới? Bạn không gặp vấn đề nghiêm trọng như thế này với các ngôn ngữ động như python. Việc xử lý các tình huống như vậy trong một trình thông dịch không động sẽ là một vấn đề lớn và đây chỉ là hai vấn đề “đơn giản/cơ bản”, đây chỉ là phần nổi của tảng băng chìm. Tôi đã lập trình C/C++ hơn một thập kỷ và chưa bao giờ cảm thấy cần một trình thông dịch C/C++.

Trích dẫn:

Tuy nhiên, có các trình phân tích cú pháp C++ hiện có như một phần của trình biên dịch, một số trong đó là nguồn mở. Tôi chợt nhận ra rằng có thể diễn giải mã lắp ráp được trình phân tích cú pháp phát ra khi đang di chuyển. Điều này sẽ giống như một trình biên dịch JIT phát ra mã byte để máy ảo giải thích. Một vấn đề nảy sinh là việc sử dụng các tệp nguồn khác nhau, nếu không sẽ dẫn đến một số tệp đối tượng cần được liên kết. Đây thực sự là một hạn chế, nhưng không phải là một hạn chế nghiêm trọng nếu bạn hỏi tôi.

Tôi bắt đầu viết câu trả lời nhưng nó trở nên quá dài và phức tạp vì nó phân tích vấn đề của bạn theo nhiều mặt cắt khác nhau. Thay vào đó tôi chỉ viết ở đây một số kết luận của tôi.

Bạn nên trả lời các câu hỏi tôi đã đăng ở đoạn trước. Từ câu hỏi của bạn, tôi nghĩ có lẽ mục tiêu của bạn chỉ đơn giản là tạo ra MỘT Trình thông dịch C++ với số lượng công việc được đầu tư ít nhất – Tôi cho rằng điều này là do bạn muốn sử dụng lại nội dung (đơn vị biên dịch, tệp đối tượng) từ trình biên dịch hiện có. Vấn đề của tôi với điều này là mọi người làm điều gì đó với “đầu tư công sức ít nhất” khi họ phải làm điều gì đó mà họ không thích. Mặt khác, nếu họ làm điều gì đó chỉ để giải trí như một sở thích hoặc với một mục đích cụ thể thì họ thường không ngại làm nhiều việc. Trong trường hợp trình thông dịch C/C++, tất cả các giải pháp dường như đòi hỏi rất nhiều công việc.

Tùy thuộc vào trình biên dịch và cài đặt trình biên dịch, các tệp đối tượng có thể chứa nội dung khác ngoài những gì bạn cần. Chúng không được chuẩn hóa và thậm chí cùng một trình biên dịch có thể đưa rác hoàn toàn vô dụng vào chúng với một số cài đặt (như LTCG). IMO sẽ thực tế hơn nếu viết một chương trình phụ trợ để phát ra những gì bạn cần thay vì cố gắng phân tích nó từ các tệp đối tượng.

Giải pháp 4

Lý do suy đoán của tôi: Có vẻ như chưa có ai có nhu cầu so với sức lực để làm việc đó. Tức là bạn có thể xây một Tháp Eiffel trong khu vườn của mình, giả sử bạn có không gian, vật liệu, con người, mặt bằng đủ tốt, v.v. và bạn có thể làm điều đó vì niềm vui của riêng mình. 😉

Sự khác biệt từ C đến C++ như đã nêu trong tiêu chuẩn C++:

Ngoài các tiện ích do C cung cấp, C++ còn cung cấp thêm các kiểu dữ liệu, lớp, mẫu, ngoại lệ, không gian tên, nạp chồng toán tử, nạp chồng tên hàm, tham chiếu, toán tử quản lý cửa hàng miễn phí và các tiện ích thư viện bổ sung.

Nếu chuyển sang C++ 11, bạn có thể thêm các biểu thức lambda và một số phần khác, tất cả chủ yếu là đường cú pháp theo nghĩa là chúng trừu tượng hóa thứ gì đó chủ yếu liên quan đến trình phân tích cú pháp và cũng có thể được thực hiện (nếu không tẻ nhạt) bằng các phương tiện khác.

Kết quả là các mục thời gian chạy từ việc phân tích cú pháp các tính năng trên là
– các kiểu dữ liệu bổ sung: một số kiểu ký tự/số tích hợp khác
– lớp: các hàm phiên bản mở rộng với this tham số
– lớp: kế thừa với lớp cơ sở là đối tượng con của lớp dẫn xuất
– lớp: các lệnh gọi hàm ẩn đặc biệt (ctor, dtor, v.v.)
– class: vtable cho lệnh gọi hàm ảo
– lớp: thứ tự các định nghĩa (hầu hết) không quan trọng trong các lớp – chỉ việc tra cứu tên bị ảnh hưởng
– mẫu: các lớp hoặc hàm được tạo dựa trên loại hoặc giá trị tích phân không đổi
– ngoại lệ: luồng kiểm soát bổ sung và đặc biệt là mã dọn dẹp sổ sách kế toán
– không gian tên: “đường cú pháp” (các loại, đối tượng, chức năng duy nhất được xác định và gọi)
– nạp chồng: “cú pháp đường” (trình phân tích cú pháp tạo các cuộc gọi đến các hàm chính xác)
– tài liệu tham khảo: “cú pháp”, kết quả là con trỏ hoặc không có mã thời gian chạy nào cả
– mới/xóa: bộ nhớ mức thấp malloc/miễn phí cộng với các lệnh gọi ctor/dtor
– thư viện: tập hợp các mục dựa trên các tính năng ngôn ngữ
– biểu thức lambda: “cú pháp đường” (lớp functor ngầm)
– …

Có những vấn đề chi tiết khó khắc phục cần khắc phục, nhưng về mặt kỹ thuật, nó có thể được coi là một C mở rộng hơn nhiều.

Vì vậy, nếu bạn có giao diện người dùng C++ quản lý để dịch sang C có chức năng tương đương thì bạn đã đạt đến cấp độ CINT. Các vấn đề như nhiều tệp, thư viện tham chiếu và tệp đối tượng không chỉ xảy ra với C++ mà là một thực tế phổ biến với tất cả các ngôn ngữ C*. Vì vậy, bạn có thể sử dụng lại các khái niệm này của trình thông dịch các ngôn ngữ đó (CINT?).

Nhưng một lần nữa, việc biện minh cho nỗ lực đó phụ thuộc rất nhiều vào “lợi ích” tiềm năng.

Chúc mừng
Và tôi

Giải pháp 5

Bởi vì C++ là một ngôn ngữ lập trình lớn. Nó quá phức tạp. Trình thông dịch được tạo ra cho các ngôn ngữ như Python, JavaScript không chỉ vì chúng đơn giản mà còn nhằm mục đích diễn giải, chúng rất năng động. Việc triển khai Python đầu tiên là một trình thông dịch; không phải là một trình biên dịch. Đây không chỉ là lý do. Người ta đã biết rằng C++ nhanh hơn các ngôn ngữ thông dịch khi được “biên dịch”. Nhưng không phải lúc nào bạn cũng có thể mong đợi điều tương tự từ trình thông dịch C++. C++ nhạy cảm với ngữ cảnh; C++ rất lớn; C++ chứa thuốc generic. Do đó, sự phức tạp của ngôn ngữ góp phần làm chậm quá trình xử lý mã nguồn. Ví dụ: Xem tốc độ biên dịch của C++. Điều gì sẽ xảy ra nếu bạn giải thích nguồn? Nói như vậy, một chương trình “hello world” cổ điển có thể không mất nhiều thời gian. Nhưng hãy nghĩ đến một chương trình sử dụng nhiều kỹ thuật chung?

Nhưng vẫn còn một số phiên dịch viên như CINT, Ch. Xem trang sau:

[^]

Giải pháp 2

Thật khó để “giải quyết” câu hỏi này – có thể tốt hơn trên diễn đàn, nhưng đây là 2c của tôi.

Định nghĩa ngôn ngữ không thực sự ngăn cản việc tạo một trình thông dịch, nhưng C++ thực sự được thiết kế như một ngôn ngữ cấp thấp có thể được sử dụng để viết mã cực kỳ hiệu quả. Ngôn ngữ này cực kỳ phức tạp nhưng không thể phân tích được (AFAIK nó thực sự yêu cầu trình phân tích cú pháp GLR hoặc trình phân tích cú pháp viết tay). Điều đó nói lên rằng, phần lớn ưu điểm của C++ đến từ thực tế là nó có thể được sử dụng để tạo mã hiệu quả, chạy gần với máy. Trình thông dịch thường được sử dụng cho các tác vụ cấp cao, trong đó việc lặp lại nhanh trong quá trình phát triển quan trọng hơn tốc độ thực thi.

Nói tóm lại, đó sẽ là một công việc nặng nhọc và sẽ chạy như một con chó.

コメント

タイトルとURLをコピーしました