Tại sao không có người dịch tự động từ ngôn ngữ lập trình này sang ngôn ngữ khác? [đóng cửa]


37

Hầu hết các ngôn ngữ lập trình đều hoàn thành Turing, điều đó có nghĩa là bất kỳ tác vụ nào có thể được giải quyết bằng một ngôn ngữ đều có thể được giải quyết bằng ngôn ngữ khác hoặc thậm chí trên máy Turing. Vậy thì tại sao không có người dịch tự động có thể chuyển đổi chương trình từ bất kỳ ngôn ngữ nào sang ngôn ngữ khác? Tôi đã thấy một vài nỗ lực cho hai ngôn ngữ, nhưng chúng luôn chỉ hoạt động trên một tập hợp con giới hạn của ngôn ngữ và khó có thể được sử dụng để chuyển đổi các dự án thực.

Có thể, ít nhất là về lý thuyết, có thể viết người dịch chính xác 100% giữa tất cả các ngôn ngữ? Những thách thức trong thực tế là gì? Có bất kỳ dịch giả hiện có làm việc?


5
Hãy nhớ rằng, tất cả các ngôn ngữ, bao gồm cả những ngôn ngữ ngu ngốc như Oook! (Sự hoàn chỉnh của Turing không phải là toàn bộ câu chuyện; bạn cũng cần các tòa nhà chọc trời trong thực tế.)
Donal Fellows

Có vài. Các dịch giả từ C sang Pascal và Pascal sang C khá phổ biến tại một thời điểm. Như các câu trả lời dưới đây cho thấy, đầu ra thường không thể đọc được mà ít nhất là làm sạch thủ công. Và đây là những ngôn ngữ tương đối đơn giản với các thư viện tương đối đơn giản - thực hiện công việc tốt, ví dụ như C ++ đến Haskell hoặc ngược lại có lẽ là không thể.
Steve314

Hãy xem Roslyn trình biên dịch .net như một dịch vụ có khả năng dịch C # sang VB và ngược lại.
Daniel Little

2
Tất cả các trình biên dịch dịch một PL sang một PL khác, chúng không đảm bảo rằng mã trong PL đích dễ đọc mặc dù
jk.

Sau khi thấy tính chính xác của Google dịch, tôi tin chắc rằng tôi sẽ thấy một dịch giả phổ quát trong thời gian sống của tôi. Vâng, nó sẽ là một nỗ lực đầy thách thức và có thể đòi hỏi hiệu quả rất lớn vì trong trường hợp phân tích cơ sở mã lớn như github hoặc stackoverflow, nhưng điều này sẽ xảy ra và nhu cầu về một công cụ như vậy cũng sẽ tăng lên trong thời đại sắp tới, đặc biệt là bây giờ có rất nhiều lập trình viên để nghiên cứu AI và ML. Có thể không có một người nào tự mình phát triển một công cụ như vậy. Tuy nhiên, người ta có thể phát triển một bot để phát triển các bot để giải quyết vấn đề này.
Ganesh Kamath - 'Code Frenzy'

Câu trả lời:


32

Vấn đề lớn nhất không phải là bản dịch mã chương trình thực tế, mà là việc chuyển API nền tảng.

Hãy xem xét một trình dịch PHP sang Java. Cách khả thi duy nhất để làm điều đó mà không nhúng một phần nhị phân PHP là thực hiện lại tất cả các mô-đun và API của PHP trong Java. Điều này liên quan đến việc thực hiện hơn 10.000 chức năng. So với công việc thực sự dịch cú pháp thì dễ như ăn bánh. Và thậm chí sau tất cả những công việc bạn không có mã Java, bạn sẽ có một số thứ quái dị xảy ra để chạy trên nền tảng Java, nhưng nó được cấu trúc như PHP ở bên trong.

Đây là lý do tại sao các công cụ như vậy xuất hiện trong tâm trí là tất cả về dịch mã để triển khai nó, không phải để duy trì nó sau đó. GWT của Google "biên dịch" Java thành JavaScript. Hiphop của Facebook biên dịch PHP thành C.



Có vẻ như ai đó đã tạo một trình dịch php sang java và thực sự đã nhúng tệp nhị phân PHP. Đồng ý mặc dù nó không thay đổi quan điểm của bạn. runtimeconverter.com/single-post/2017/09/15/...
user1122069

20

Nếu bạn có định dạng trung gian, thì bạn có thể triển khai thứ gì đó dịch chương trình trong Ngôn ngữ X sang định dạng đó và từ định dạng đó sang Ngôn ngữ Y. Thực hiện các chuyển đổi đó cho tất cả các ngôn ngữ bạn quan tâm và bạn đã hoàn thành, phải không?

Vâng bạn biết gì không? Một định dạng như vậy đã tồn tại: lắp ráp. Trình biên dịch đã thực hiện chuyển đổi "Ngôn ngữ X để lắp ráp" và phân tách thành chuyển đổi "lắp ráp thành Ngôn ngữ Y".

Bây giờ, lắp ráp không phải là một ngôn ngữ tuyệt vời để thực hiện chuyển đổi ngược lại, nhưng MSIL thực sự không phải là xấu. Tải xuống Reflector và bạn sẽ thấy có các tùy chọn để tháo rời một cụm .NET thành một loạt các ngôn ngữ khác nhau (và các plugin cung cấp nhiều hơn nữa). Vì vậy, hoàn toàn có thể lấy một chương trình trong C #, biên dịch nó thành một DLL (nghĩa là MSIL), sau đó sử dụng bộ phản xạ để phân tách nó thành VB, C ++ / CLI, F # và một nhóm khác. Tất nhiên, tất cả các công việc chuyển đổi khác, quá. Lấy một tệp F #, biên dịch thành DLL, sử dụng Reflector để chuyển đổi nó thành C #.

Tất nhiên, hai vấn đề lớn mà bạn sẽ tìm thấy là:

  1. Mã về cơ bản là không thể đọc được. MSIL (ngay cả với thông tin gỡ lỗi) sẽ xóa rất nhiều thông tin khỏi nguồn ban đầu, vì vậy phiên bản dịch không có độ trung thực 100% (về mặt lý thuyết thực hiện chuyển đổi C # -> MSIL-> C # sẽ cung cấp cho bạn mã gốc, nhưng nó sẽ không).
  2. Nhiều ngôn ngữ .NET có thư viện tùy chỉnh riêng (ví dụ thư viện thời gian chạy VB, thư viện F #, v.v.). Chúng cần được đưa vào (hoặc chuyển đổi) khi bạn thực hiện chuyển đổi.

Thực sự không có gì để có được khoảng # 2, nhưng bạn có thể có được khoảng # 1 với một số chú thích bổ sung trong MSIL (có thể thông qua các thuộc tính). Đó sẽ là công việc bổ sung, tất nhiên.


Rất nhiều siêu dữ liệu từ nguồn ban đầu được bao gồm trong MSIL (bao gồm các nhận xét XML và phương thức ban đầu, tên thuộc tính và tên thành viên), vì vậy tôi không nghĩ việc chuyển đổi sang C # là không thể đọc được như bạn nói. Hãy thử tháo rời các phần của khung .NET; nó rất dễ đọc Tất nhiên, tình huống có thể khác đối với chuyển đổi F # sang C #.
Robert Harvey

@Robert: Nhận xét XML không được bao gồm trong MSIL. Nếu bạn nhìn vào Microsoft.NET\Framework\v2.0.50727\enví dụ, bạn có thể thấy tất cả tài liệu XML cho các thư viện hệ thống. Đây là những gì Reflector (et al) sử dụng để hiển thị các bình luận. Chuyển đổi không phải là không thể đọc được, tất cả những gì tôi đã nói là nó không trung thực 100% mà bạn có thể mong đợi từ một bản dịch cấp nguồn.
Dean Harding

2
Trình phân tách chuyển đổi trở lại nhị phân thực thi của máy thành trình biên dịch mã cho loại bộ xử lý cụ thể đó (Không phải tất cả thế giới đều là x86). Bạn thực sự có nghĩa là một trình dịch ngược để đưa mã được biên dịch trở lại nguồn. Đây là một nhiệm vụ khó khăn khủng khiếp vì mỗi trình biên dịch, từ mỗi nhà sản xuất, ở mỗi cấp độ tối ưu hóa sẽ chuyển đổi các dòng nguồn thành một dạng nhị phân đầu ra khác nhau.
uɐɪ

20

Có thể, ít nhất là về lý thuyết, có thể viết người dịch chính xác 100% giữa tất cả các ngôn ngữ? Những thách thức trong thực tế là gì?

  • Dịch từ một ngôn ngữ có cấu trúc nhiều hơn sang ngôn ngữ ít cấu trúc hơn mà vẫn hoàn chỉnh Turing, luôn luôn có thể.
    • Yêu cầu này nên được xem theo nghĩa kỹ thuật nghiêm ngặt: Điều đó có nghĩa là chương trình dịch sẽ tạo ra kết quả chính xác tương tự khi nó được thực thi.
    • Không có gì ngụ ý về khả năng đọc mã dịch hoặc bảo toàn cấu trúc chương trình gốc.
  • Có thể dịch từ ngôn ngữ ít cấu trúc sang ngôn ngữ có cấu trúc chặt chẽ hơn, nhưng mã dịch sẽ vẫn ở dạng ít cấu trúc hơn.

1
Anh nói trúng phóc. Hãy thử đọc mã phát ra từ phụ trợ C của LLVM. Đó là mã C hợp pháp về mặt kỹ thuật nhưng Nó không đẹp (TM).
dsimcha

1
@dsimcha: Khả năng đọc sang một bên mà C phụ trợ làm cho đầu ra dễ đọc hơn nhiều so với gỡ lỗi hoặc tháo gỡ. Tôi rất vui vì họ đã mang phần phụ trợ đó trở lại một lần nữa, sau khi nó được bảo trì trong một thời gian ngắn.
JM Becker

10

Tại sao bạn muốn chuyển đổi một chương trình?

Cả hai ngôn ngữ, nguồn và ngôn ngữ đích đều được biên dịch thành (dù sao) máy móc mã hóa *, vì vậy, vì lý do kỹ thuật, không cần phải có trình biên dịch sang ngôn ngữ cấp cao khác.

Ngôn ngữ là dành cho con người. Vì vậy, yêu cầu ngầm định cho câu hỏi của bạn là: 'tại sao không có người dịch tạo mã có thể đọc được ' và câu trả lời sẽ là (imho): bởi vì nếu có hai ngôn ngữ khác nhau một cách chính xác, thì cách viết 'mã có thể đọc được' là khác nhau theo cách không chỉ yêu cầu dịch thuật toán, mà lấy các thuật toán khác nhau.

Ví dụ, so sánh một lần lặp điển hình trong C và một lần lặp. Hoặc trăn 'một cách tốt nhất' với ruby ​​thành ngữ.

Ở đây, những vấn đề tương tự bắt đầu xuất hiện ở các ngôn ngữ thực, như bạn dịch 'Trời mưa mèo và chó' sang một thứ gì đó với ý nghĩa 'Nó đổ như xô từ' khi dịch từ tiếng Anh sang tiếng Đức, bạn không thể dịch từng chữ một, nhưng bạn phải tìm nghĩa.

Và "ý nghĩa" không phải là một khái niệm dễ dàng để làm việc.

*) tốt, có cà phê ...


1
Câu trả lời tốt. Người ta có thể nói thêm rằng nếu hai ngôn ngữ có chính xác cùng một tập hợp các tính năng và thành ngữ, nó sẽ có thể dịch một ngôn ngữ khác khá hiệu quả, nhưng hầu hết ngôn ngữ được thiết kế cho mục đích của tính năng và thành ngữ mà người sáng tạo của họ cảm thấy hỗ trợ không đầy đủ được hỗ trợ trong các ngôn ngữ khác . Bản dịch cơ học của mã có thể duy trì đôi khi có thể thực hiện được khi các tính năng và thành ngữ trong ngôn ngữ đích là siêu âm của những ngôn ngữ nguồn, nhưng những tình huống như vậy không phổ biến lắm.
supercat

6

Về mặt lý thuyết là có thể nhưng chủ yếu là vô dụng. Hầu như mọi sự kết hợp giữa ngôn ngữ nguồn và ngôn ngữ đích đều có thể, nhưng trong hầu hết các trường hợp, không ai muốn nhìn vào hoặc sử dụng kết quả.

Một số lượng lớn trình biên dịch thực hiện nhắm mục tiêu C, đơn giản vì trình biên dịch C có sẵn cho hầu hết mọi nền tảng tồn tại (và có các trình tạo trình biên dịch tự động sẽ cho phép bạn thiết kế bộ xử lý và tự động tạo trình biên dịch C nhắm vào bộ xử lý mới của bạn). Tất nhiên cũng có một số lượng triển khai hợp lý nhắm mục tiêu các ngôn ngữ được sử dụng bởi các máy ảo khác nhau như .NET, JVM, C-- và LLVM.

Tuy nhiên, điểm mấu chốt là nó thực sự chỉ hữu ích nếu bạn đối xử với mục tiêu về cơ bản là một ngôn ngữ lắp ráp chỉ được sử dụng như một bước trong quy trình biên dịch. Cụ thể, bạn thường không muốn một lập trình viên bình thường đọc hoặc làm việc với kết quả đó; nó thường sẽ không thể đọc được.


5

FWIW, có một dịch giả từ Java sang D. Nó được gọi là TioPort và được sử dụng trong một nỗ lực khá nghiêm trọng để chuyển SWT sang D. Vấn đề chính mà nó gặp phải là cần phải chuyển các phần lớn của thư viện chuẩn Java .


4

Mặc dù nó không phải là dịch mã theo từng se, khái niệm bàn làm việc ngôn ngữ cho thấy cách thức một cái gì đó giống với một dịch giả chính xác 100% giữa tất cả các ngôn ngữ có thể được thực hiện.

Theo cách tiếp cận hiện tại của chúng tôi, mã nguồn được lưu trữ ở định dạng văn bản. Trong quá trình biên dịch, các tệp văn bản có thể đọc được của con người được phân tích cú pháp thành một biểu diễn cây cú pháp trừu tượng, lần lượt được sử dụng để tạo mã byte hoặc mã máy. Đại diện trừu tượng này tuy nhiên là tạm thời và nội bộ cho trình biên dịch.

Trong cách tiếp cận bàn làm việc ngôn ngữ, một biểu diễn cây cú pháp trừu tượng tương tự là tạo phẩm được lưu trữ vĩnh viễn. Cả mã máy và mã 'nguồn' văn ​​bản đều được tạo dựa trên biểu diễn trừu tượng này. Một trong những hậu quả của một phương pháp như vậy là sự biểu diễn trừu tượng của chương trình thực sự không liên quan đến ngôn ngữ và có thể được sử dụng để tạo mã văn bản trong bất kỳ ngôn ngữ được triển khai nào. Có nghĩa là một người có thể tự do làm việc trên các khía cạnh khác nhau của hệ thống bằng cách sử dụng bất kỳ ngôn ngữ nào họ thấy là phù hợp nhất hoặc mỗi thành viên trong nhóm có thể làm việc với dự án được chia sẻ bằng ngôn ngữ mà họ quen thuộc nhất.

Theo như tôi biết, công nghệ vẫn còn lâu mới có thể sử dụng được trong phát triển chính thống, tuy nhiên có một số nhóm làm việc độc lập với nó. Thật khó để biết liệu bất kỳ ai trong số họ sẽ thực hiện theo lời hứa của họ, nhưng sẽ rất thú vị khi thấy điều đó xảy ra.


Bạn có thể kể tên một số nhóm này không?
Qwertie

4

Ở đó được một số dịch tự động. Nếu mục tiêu của bạn là sản xuất mã có thể biên dịch, thay vì mã có thể đọc được, nó hoàn toàn có thể và đôi khi hữu ích, chỉ là không thường xuyên. Nổi tiếng, trình biên dịch C ++ đầu tiên không thực sự là trình biên dịch, mà đã dịch C ++ thành nguồn C (thực sự phức tạp) sau đó được biên dịch bởi trình biên dịch C. Nhiều trình biên dịch có thể tạo mã lắp ráp theo yêu cầu - nhưng thay vì phun ra văn bản lắp ráp và sau đó dịch mã sang mã máy, thông thường họ có thể tạo mã máy trực tiếp.

Với một đặc điểm kỹ thuật hoàn chỉnh của ngôn ngữ A, về nguyên tắc không khó để viết một chương trình thể hiện các chỉ thị của nó bằng một số ngôn ngữ B. Nhưng thông thường, bất cứ ai gặp rắc rối sẽ chọn một thứ gì đó thực sự ở mức thấp cho "ngôn ngữ B": Mã máy hoặc ngày nay là mã byte: Jython là một triển khai của python tạo mã byte java, được Java VM diễn giải. Không cần phải bận tâm viết ra và biên dịch phân cấp lớp java!


3

Điều này được thực hiện tất cả các thời gian.

Mỗi trình biên dịch dịch "ngôn ngữ chính" như C ++ sang ngôn ngữ lắp ráp riêng của máy hoặc mã byte độc ​​lập với kiến ​​trúc trong trường hợp ngôn ngữ được dịch.

Tôi tưởng tượng đó không phải là những gì bạn đang nói về, mặc dù. Bạn có thể muốn một trình dịch chuyển đổi C ++ thành một cái gì đó như Java hoặc Python. Điểm của điều đó là gì? Tốt nhất, kết quả cuối cùng sẽ có hiệu quả chính xác như nguồn ban đầu. (Thực tế, nó sẽ tệ hơn nhiều.)

Nếu bạn chỉ muốn mã được dịch để bạn có thể đọc nó như một ngôn ngữ bạn hiểu, thì một dịch giả như vậy sẽ có tác dụng ngược lại với hiệu ứng mong muốn. Bạn sẽ bị bỏ lại với một loạt mã khó hiểu, không trực quan và không thể đọc được.

Điều này là do chỉ những điều tầm thường nhất dịch trực tiếp từ ngôn ngữ này sang ngôn ngữ khác. Thông thường, những gì đơn giản trong một ngôn ngữ đòi hỏi các thư viện lớn cho ngôn ngữ khác - hoặc có thể hoàn toàn không thể. Vì thế:

  1. Nếu chương trình là tầm thường, bạn có thể nhận được một kết quả tốt. Nhưng sau đó, nếu nó đơn giản, thì điều gì thậm chí là điều hành nó thông qua một dịch giả?
  2. Nếu chương trình không cần thiết, mã sẽ có chất lượng thấp.

Cuối cùng, cách duy nhất để viết mã tốt là thực sự viết nó. Máy tính đơn giản là không thể - ít nhất là chưa - phù hợp với con người về các vấn đề dễ đọc, thực hành tốt nhất và giải pháp thanh lịch.

Nói tóm lại, nó không đáng


sự tương tự của bạn sau đó cũng sẽ áp dụng cho việc biên dịch thông thường, và chúng tôi biết điều đó theo kinh nghiệm thì không! Máy tính làm 'tạo' (không ghi) mã chất lượng tốt. Những gì họ thường làm xấu là khả năng đọc / bảo trì. Nếu ai đó cần một quy trình như vậy, điều mà tôi tin rằng mọi người thỉnh thoảng vẫn làm, thì không có vấn đề nào là điểm dừng. Nếu họ là, tốt sau đó, rõ ràng bản dịch không bao giờ quan trọng ban đầu.
JM Becker

1

Không có người dịch ngôn ngữ cho các ngôn ngữ lập trình vì ngôn ngữ lập trình rất phức tạp. Trong khi nó là giả thuyết có thể, có nhiều thách thức.

Thách thức đầu tiên chỉ đơn thuần là trong thực tiễn ngôn ngữ được chấp nhận. Chuyển đổi giữa hai ngôn ngữ hướng đối tượng như Java và C ++ là vô cùng phức tạp và cả hai đều dựa trên C. Chương trình dịch thuật sẽ phải có kiến ​​thức hoàn hảo về các thư viện chuẩn cho cả hai ngôn ngữ và có thể biết được sự khác biệt trong hành vi. Bạn sẽ phải tạo một từ điển lớn và thậm chí sau đó, sự khác biệt trong phong cách lập trình từ lập trình viên đến lập trình viên có nghĩa là nó sẽ phải đoán về cách thực hiện một số thay đổi.

Khi bạn đã dịch được cú pháp xuống, sau đó bạn phải tìm ra cách chuyển đổi một cấu trúc trong ngôn ngữ đầu tiên sang một cấu trúc trong ngôn ngữ thứ hai. Điều này tốt nếu bạn chuyển một đối tượng trong C ++ sang một đối tượng trong Java (tương đối dễ dàng) nhưng bạn sẽ làm gì với các cấu trúc C ++ của mình? Hoặc các chức năng bên ngoài các lớp C ++? Quyết định làm thế nào để xử lý việc này có thể khó khăn vì nó có thể dẫn đến một vấn đề khác, cụ thể là việc tạo ra một đối tượng blob. Các blob là một antipotype là đủ phổ biến.

Đây không phải là một danh sách đầy đủ các vấn đề, nhưng đó chỉ là hai và chúng là những vấn đề lớn. Một trong những giáo sư của tôi đã đề cập rằng ai đó đã thuyết phục chủ nhân của mình rằng họ có thể tạo một từ mã máy đến C trong những năm 80, nhưng sau đó nó không hoạt động. Tôi nghi ngờ sẽ có một cái hoạt động đầy đủ.


Tôi nghĩ rằng không cần phải biết các thư viện hiện có, nó chỉ có thể dịch các thư viện khi nó đi (giả sử họ có sẵn nguồn).
serg

1
Điều đó thực sự làm tăng sự phức tạp của vấn đề thứ hai sau đó. Và đó là giả sử bạn có quyền truy cập vào mã nguồn để dịch nó. Dù bằng cách nào, nó vẫn không khả thi.
indyK1ng

+1 điểm về libs là hoàn toàn hợp lệ và có LUÔN LUÔN LUÔN.
Dan Rosenstark

1

Điểm biên dịch là để có được một cái gì đó hữu ích cho máy tính. tức là một cái gì đó có thể chạy. Tại sao biên dịch thành một cái gì đó thậm chí có thể cao hơn những gì bạn đã viết nó trong?

Tôi thích chiến lược của .NET hơn. Biên dịch mọi thứ thành một ngôn ngữ chung. Điều này mang lại lợi ích của các ngôn ngữ có thể giao tiếp mà không cần phải tạo (N ^ 2) -N trình biên dịch ngôn ngữ chéo.

Ví dụ: nếu bạn có 10 ngôn ngữ lập trình, bạn sẽ chỉ cần viết 10 trình biên dịch theo mô hình .NET và tất cả chúng có thể giao tiếp với nhau. Nếu bạn thực hiện tất cả các trình biên dịch ngôn ngữ chéo có thể, bạn sẽ cần phải viết 90 trình biên dịch. Đó là rất nhiều công việc làm thêm vì lợi ích nhỏ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.