Có chương trình nào có thể "dịch" mã nguồn giữa hai ngôn ngữ không?


28

Có chương trình nào có thể 'dịch' mã nguồn giữa hai ngôn ngữ bất kỳ (giả sử người dịch có quyền truy cập vào các thư viện cần thiết) không?

Nếu có, làm thế nào để họ làm việc (kỹ thuật được sử dụng, kiến ​​thức cần thiết, vv)? Làm thế nào họ có thể được xây dựng khả thi?

Nếu họ không, những hạn chế ngăn cản sự phát triển của họ là gì? Đây có phải là một vấn đề hoàn chỉnh về AI (bản dịch ngôn ngữ tự nhiên được liệt kê là một)?

Chuyển đổi EDIT chỉ được mong đợi, khi ngôn ngữ có cùng sức mạnh biểu hiện, có thể giải quyết cùng loại vấn đề và mã được chuyển đổi có thể được thể hiện bằng ngôn ngữ đích. (Ví dụ: chuyển đổi từ tập lệnh shell sang MATLAB không được mong đợi).



14
Bạn có ý nghĩa gì bởi "bất kỳ hai ngôn ngữ"? Chắc chắn có những chương trình có thể dịch từ ngôn ngữ này sang ngôn ngữ khác. Chúng được gọi là "trình biên dịch". Đó đúng là định nghĩa của trình biên dịch: một chương trình dịch các chương trình từ ngôn ngữ này sang ngôn ngữ khác. Nhưng "bất kỳ hai ngôn ngữ"? Tôi không nghĩ điều đó là có thể. Người dịch phải biết cả nguồn và ngôn ngữ đích, và nó thường dành riêng cho một cặp ngôn ngữ cụ thể.
Jörg W Mittag

Chương trình được cung cấp các ngôn ngữ nguồn và đích. Tôi đang nghĩ đến việc viết một chương trình bằng C ++, dịch nó sang Java, python, Perl, Ruby, Go, v.v. Có thể có một số hạn chế (tôi không mong đợi nó chuyển đổi tập lệnh shell của bạn sang MATLAB chẳng hạn).
Tobi Alafin

4
Vâng, chúng được gọi là trình biên dịch, chúng hoạt động như trình biên dịch và chúng có thể được xây dựng giống như trình biên dịch.
dùng253751

1
Nếu theo "bất kỳ hai ngôn ngữ" nào, bạn có nghĩa là chương trình (hữu hạn) có thể đọc và hiểu vô số ngôn ngữ đầu vào, thì câu trả lời là không có . Tuy nhiên, hãy tập hợp các ngôn ngữ đầu vào hữu hạn và bạn có thể tìm thấy trình biên dịch cho tất cả các ngôn ngữ đó ..
Bakuriu

Câu trả lời:


57

TLDR; Điều này là có thể nhưng không thực tế.

(giả sử người dịch có quyền truy cập vào các thư viện cần thiết)?

Điều này cuối cùng là một chút khó khăn và là một phần lý do tại sao những thứ như thế này không được sử dụng trong thực tế.

  1. Tất cả các trình biên dịch là dịch giả. Dịch từ ngôn ngữ này sang ngôn ngữ khác là hoàn toàn có thể, và đây thực sự là tất cả các trình biên dịch đang làm. Ngôn ngữ mà trình biên dịch phun ra như đầu ra thường là mã máy hoặc lắp ráp, nhưng đây chỉ là ngôn ngữ khác và có các trình biên dịch (đôi khi được gọi là transpilers hoặc transcompilers) dịch giữa hai ngôn ngữ . Ví dụ: có một loạt các ngôn ngữ biên dịch sang Javascript như PureScript, Elm, ClojureScript, v.v.

  2. Dịch giữa hai ngôn ngữ Turing Complete luôn luôn có thể. Bỏ qua những thứ như các cuộc gọi thư viện và FFI và các bit thực tế khó chịu khác cản trở, đó là. Nếu một ngôn ngữ là Turing Complete, thì bạn có:

    • Bản dịch chuyển đổi Máy Turing thành mã bằng ngôn ngữ này
    • Bản dịch từ ngôn ngữ này sang Turing Machine

    Vì vậy, để dịch từ ngôn ngữ A sang ngôn ngữ B, bạn chuyển đổi mã A thành Máy Turing, sau đó chuyển đổi máy đó thành mã B.

    Tất nhiên, trong thực tế, các bit thực tế cản trở và điều này cũng đòi hỏi bạn phải có các bản dịch có thể truy cập được cho bạn. Chúng tồn tại về cơ bản cho mọi ngôn ngữ, nhưng điều đó không có nghĩa là ai đó đã dành thời gian để viết chúng ra.

  3. Làm bản dịch này hiệu quả là khó . Ngôn ngữ khác nhau ưu tiên những thứ khác nhau. Ví dụ: nếu bạn dịch từ C sang Python, có lẽ bạn sẽ phải kết thúc việc mô phỏng bộ nhớ của C dưới dạng từ điển Python, để bạn có thể thực hiện số học con trỏ. Sẽ có chi phí liên quan đến việc này, vì hiện tại bạn không truy cập vào các hướng dẫn bộ nhớ kim loại trần.

    Các ngôn ngữ khác nhau có các ưu tiên về hiệu suất khác nhau, do đó, một ngôn ngữ tối ưu hóa (hay đúng hơn là việc thực hiện một ngôn ngữ tối ưu hóa) có thể không thể thực hiện nhanh chóng bằng ngôn ngữ khác. Dịch một ngôn ngữ chức năng với các cuộc gọi đuôi thích hợp sẽ bị chậm lại nếu bạn dịch nó sang ngôn ngữ mà không có các cuộc gọi đuôi thích hợp.

  4. Làm bản dịch này không làm cho mã có thể đọc được . Thật dễ dàng để có được một đoạn mã trong ngôn ngữ B hoạt động giống như mã từ ngôn ngữ A. Thật khó để làm cho nó trông giống như mã mà con người sẽ viết bằng B, vì một số lý do. A và B có thể có các công cụ trừu tượng khác nhau và máy tính không biết điều gì làm cho mã có thể đọc được. Điều này sẽ đặc biệt đúng nếu bạn kết thúc sử dụng bản dịch Turing Machine mà tôi đã mô tả trước đó.

    Điều này đặt ra câu hỏi: ý nghĩa của bản dịch như vậy là gì? Nếu tất cả những gì bạn nhận được ở cuối chúng tôi là một khối mã chậm, không thể đọc được, tại sao bạn không biên dịch nó thành mã máy và sử dụng một số loại FFI hoặc liên lạc giữa các quá trình để liên kết các phần lại với nhau?

    Có một số trường hợp ngoại lệ cho điều này. Đôi khi bạn cần những thứ trong một ngôn ngữ nhất định (như JavaScript). Đôi khi ngôn ngữ là tương tự, và một bản dịch hợp lý là dễ dàng. Đôi khi một ngôn ngữ không có nghĩa là được chạy, nhưng để mã của nó được trích xuất sang ngôn ngữ khác (chẳng hạn như Coq).

    Nhưng nói chung, nó không phải là một điều rất thực tế.


5
Một ví dụ cho điểm 4 là asm.js . Hôm nay, nó có thể làm cho nó sorta có thể đọc được, sử dụng Javascript Nguồn Maps và Element Inspector, nhưng không ai sẽ muốn làm điều đó ...
Ismael Miguel

1
Modelica là một ví dụ khác về ngôn ngữ được thiết kế để biên dịch sang ngôn ngữ khác (trong trường hợp này là C).
Phục hồi lại

Webassugging dịch từ C ++ sang javascript.
Surt

Có rất nhiều ví dụ về các bộ chuyển đổi từ X sang Y, nhưng nó khác với mọi thứ phổ biến cho bất kỳ trình biên dịch nào. Rõ ràng có những trường hợp mà transpiling có ý nghĩa.
jmite

Một ngoại lệ quan trọng bị thiếu IMO: biên dịch sang C. Lý do là nhiều hệ thống không phổ biến có trình biên dịch C hiện có, thường có thể phát ra mã máy khá hợp lý. Do đó, bằng cách biên dịch một ngôn ngữ thành C, bạn không cần phải có phần phụ trợ cho những kiến ​​trúc hiếm có đó.
MSalters

2

Có những chương trình như vậy. Ví dụ, các dịch giả Lisp-to-Fortran, được sử dụng rộng rãi vào thời điểm đó. Trình biên dịch Lisp duy nhất không biên dịch trực tiếp Lisp mà tạo mã C thay vào đó được biên dịch bởi trình biên dịch C thông thường. Một ví dụ khác là Vala không được biên dịch trực tiếp nhưng trước tiên được dịch sang C ++ trước khi mã C ++ được biên dịch. Qt được viết bằng MOC, một ngôn ngữ được dịch sang C ++ để biên dịch nó (nhưng vì MOC chỉ là C ++ với một vài lệnh bổ sung nên người ta có thể tranh luận nếu nó thực sự được đặt tên là "ngôn ngữ mới") - và trước đó là trình biên dịch C ++ có C ++ - to-C-translators. Và một số dự án đã được viết bằng Pascal và sau đó được dịch sang C. Ngoài ra clang và Java có xu hướng giống như một thứ khi chúng dịch mã C ++ và Java sang một số ngôn ngữ trung gian mà sau đó có thể được xử lý thêm.

Điều bạn không thể mong đợi về đầu ra của một dịch giả ngôn ngữ là kết quả có ý nghĩa đối với người đọc con người: Nhiệm vụ của chương trình là viết mã dẫn đến một chương trình hoạt động giống như mã gốc (theo kinh nghiệm của tôi có thể hoặc có thể không hoạt động, tùy thuộc vào tính năng nào của ngôn ngữ và thư viện bên ngoài nào bạn đang sử dụng). Nhưng vì nó không biết mục đích nhiệm vụ này được thực hiện trong phần còn lại của ý nghĩa của chương trình có thể bị mất ở mức độ lớn.


0

Không phải là câu trả lời trực tiếp, nhưng trong đó có một công cụ gọi ILSpy , được viết cho .Net Framework và cho phép bạn dịch ngược một tập hợp .Net thành C # hoặc VB.Net.

Nếu bạn không quen với bản chất của .Net, bạn có thể viết mã .Net bằng nhiều ngôn ngữ nhưng chủ yếu là C # hoặc VB.Net. Khi trình biên dịch biên dịch ứng dụng, nó sẽ dịch mã thành mã "Ngôn ngữ trung gian" (viết tắt là IL). Mã này sau đó được biên dịch thành nhị phân .Net.

Vì các ứng dụng .Net là các nhị phân được biên dịch từ mã IL, ILSpy có thể lấy ứng dụng .Net, đảo ngược lại mã IL và sau đó, tiến thêm một bước và đảo ngược nó trở lại C # hoặc VB.Net.

Sử dụng công cụ này, tất cả những gì bạn phải làm là biên dịch một ứng dụng và sau đó bạn có thể duyệt các tệp được biên dịch dưới dạng mã IL, C # hoặc VB.Net. Để rõ ràng, không quan trọng mã ngôn ngữ ban đầu được viết bằng ngôn ngữ nào. Miễn là nhị phân là một tập hợp .Net, nó có thể đảo ngược các tệp được biên dịch và xuất nội dung như bất kỳ ngôn ngữ nào trong ba ngôn ngữ này.

Tôi biết đây không chính xác là một trình biên dịch, nhưng nó là một công cụ cung cấp kết quả cuối cùng tương tự như những gì bạn đang tìm kiếm và trên thực tế, tôi đã sử dụng nó để "dịch" các dự án VB.Net thành một cái gì đó một chút quen thuộc hơn với tôi-- C #.


0

Đối với trường hợp sử dụng của bạn (dựa trên nhận xét), có vẻ như SWIG có thể hữu ích.

SWIG là một công cụ phát triển phần mềm kết nối các chương trình được viết bằng C và C ++ với nhiều ngôn ngữ lập trình cấp cao. SWIG được sử dụng với các loại ngôn ngữ đích khác nhau, bao gồm các ngôn ngữ script phổ biến như Javascript, Perl, PHP, Python, Tcl và Ruby. Danh sách các ngôn ngữ được hỗ trợ cũng bao gồm các ngôn ngữ không phải là tập lệnh như C #, Common Lisp (CLISP, Allegro CL, CFFI, UFFI), ngôn ngữ D, Go, Java bao gồm Android, Lua, Modula-3, OCAML, Octave, Scilab và R Ngoài ra, một số triển khai Đề án được biên dịch và biên dịch (Guile, MzScheme / Vợt, Gà) được hỗ trợ.


0

Tôi nhớ lại f2c đáng kính , dịch thuật từ nguồn sang nguồn từ Fortran 77 sang C.

Nó (đôi khi là ...) được sử dụng chủ yếu để dịch mã số từ nhiều thập kỷ trước mà không phải tích hợp trình biên dịch fortran vào chuỗi công cụ của bạn.


0

Phần lý thuyết cho bạn biết rằng các chương trình như vậy tồn tại, về nguyên tắc, được gọi là đánh số chấp nhận được . Chúng tôi có thể chứng minh rằng có các trình biên dịch có thể tính toán giữa bất kỳ hai số nào như vậy và mọi chủ nghĩa hình thức hoàn chỉnh Turing (hoặc ngôn ngữ lập trình) về bản chất là một.

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.