Czy istnieją programy, które potrafią „tłumaczyć” kod źródłowy między dowolnymi dwoma językami (zakładając, że tłumacz ma dostęp do wymaganych bibliotek)?
Jeśli tak, to w jaki sposób działają (zastosowane techniki, wymagana wiedza itp.)? Jak można by je wykonalnie skonstruować?
Jeśli nie są, jakie są ograniczenia uniemożliwiające ich rozwój? Czy jest to kompletny problem sztucznej inteligencji (tłumaczenie na język naturalny jest wymienione jako jeden)?
EDIT Konwersja jest oczekiwana tylko wtedy, gdy język ma tę samą moc wyrażania, może rozwiązać ten sam rodzaj problemów, a kod do konwersji może być wyrażony w języku docelowym. (Np. Konwersja ze skryptu powłoki do MATLAB nie jest oczekiwana).
computability
programming-languages
compilers
Tobi Alafin
źródło
źródło
Odpowiedzi:
TLDR; jest to możliwe, ale niepraktyczne.
To jest trudna sprawa i jest częścią tego, dlaczego takie rzeczy nie są używane w praktyce.
Wszystkie kompilatory są tłumaczami. Tłumaczenie z jednego języka na drugi jest zdecydowanie możliwe, i to dosłownie wszystko, co robi kompilator. Językiem, który kompilator wyrzuca jako dane wyjściowe, jest na ogół kod maszynowy lub asembler, ale jest to po prostu inny język i istnieją kompilatory (czasami nazywane transpilatorami lub transkompilatorami), które tłumaczą między dwoma językami . Na przykład istnieje cała gama języków kompilacji do Javascript, takich jak PureScript, Elm, ClojureScript itp.
Tłumaczenie między dwoma dowolnymi językami Turing Complete jest zawsze możliwe. Ignorowanie takich rzeczy jak wywołania biblioteczne, FFI i inne nieprzyjemne praktyczne bity, które przeszkadzają. Jeśli język jest ukończony przez Turinga, masz:
Aby przetłumaczyć z języka A na język B, konwertujesz kod A na maszynę Turinga, a następnie konwertujesz tę maszynę na kod B.
Oczywiście w praktyce przeszkadzają w tym praktyczne elementy, a to wymaga również posiadania dostępnych tłumaczeń. Istnieją w zasadzie dla każdego języka, ale to nie znaczy, że ktoś poświęcił czas na ich napisanie.
Skuteczne wykonanie tego tłumaczenia jest trudne . Inny język nadaje priorytet różnym rzeczom. Na przykład, jeśli tłumaczysz z C na Python, prawdopodobnie będziesz musiał skończyć z symulacją pamięci C jako słownika Pythona, abyś mógł wykonywać arytmetykę wskaźników. Będzie się to wiązało z narzutem, ponieważ nie masz teraz dostępu do instrukcji pamięci od zera.
Różne języki mają różne priorytety wydajności, więc coś, co optymalizuje jeden język (a raczej implementacja jednego języka optymalizuje), może być niemożliwe do zrobienia szybko w innym języku. Tłumaczenie funkcjonalnego języka z odpowiednimi wywołaniami ogona ulegnie spowolnieniu, jeśli przetłumaczysz go na język bez odpowiednich wywołań ogona.
Wykonanie tego tłumaczenia nie powoduje, że kod jest czytelny . Łatwo jest uzyskać fragment kodu w języku B, który zachowuje się tak samo jak kod z języka A. Trudno jest sprawić, aby wyglądał tak, jakby kod napisany przez człowieka był napisany w języku B z wielu powodów. A i B mogą mieć różne narzędzia abstrakcyjne, a komputer nie ma pojęcia, co czyni kod możliwym do odczytania. Będzie to szczególnie prawdziwe, jeśli skończysz na tłumaczeniu Turinga, które opisałem wcześniej.
Rodzi to pytanie: jaki jest sens takiego tłumaczenia? Jeśli na końcu otrzymujesz blok wolnego, nieczytelnego kodu, to dlaczego nie po prostu skompilować go do kodu maszynowego i użyć jakiegoś FFI lub komunikacji między procesami, aby połączyć elementy ze sobą?
Istnieją pewne wyjątki od tego. Czasami potrzebujesz rzeczy w określonym języku (np. JavaScript). Czasami język jest podobny, a rozsądne tłumaczenie jest łatwe. Czasami język nie jest przeznaczony do uruchamiania, ale do wyodrębnienia kodu w innym języku (np. Coq).
Ale ogólnie rzecz biorąc, nie jest to bardzo praktyczna rzecz.
źródło
Istnieją takie programy. Na przykład tłumacze Lisp-for-Fortran, którzy byli wówczas powszechnie używani. Kompilatory Sole Lisp nie kompilują bezpośrednio Lisp, ale zamiast tego generują kod C, który następnie jest kompilowany przez zwykły kompilator C. Innym przykładem może być Vala, która nie jest skompilowana bezpośrednio, ale najpierw przetłumaczona na C ++ przed skompilowaniem kodu C ++. Qt jest napisany w MOC, języku, który jest tłumaczony na C ++ w celu jego skompilowania (ale ponieważ MOC to po prostu C ++ z kilkoma dodatkowymi poleceniami, można się spierać, czy naprawdę należy go nazwać „nowym językiem”) - i wcześniej były kompilatory C ++, były C ++ - na C-translatory. Niektóre projekty zostały napisane w języku Pascal, a następnie przetłumaczone na C. Także clang i Java są czymś w rodzaju, ponieważ tłumaczą kod C ++ i Java na jakiś język pośredni, który następnie może być dalej przetwarzany.
To, czego nie można oczekiwać po wynikach tłumacza języka, to fakt, że wynik ma sens dla ludzkiego czytelnika: zadaniem programu jest napisanie kodu, w wyniku którego program będzie działał tak samo jak kod oryginalny (co z mojego doświadczenia może lub może nie działa, w zależności od funkcji języka i używanych bibliotek zewnętrznych). Ponieważ jednak nie wie on, jaki jest cel tego zadania, reszta znaczenia programu może zostać w dużym stopniu utracona.
źródło
Nie jest to bezpośrednia odpowiedź, ale istnieje wywołanie narzędzia ILSpy , które zostało napisane dla .NET Framework i pozwala na dekompilację zestawu .Net do C # lub VB.Net.
Jeśli nie znasz natury .Net, możesz pisać .Net kod w wielu językach, ale przede wszystkim w C # lub VB.Net. Gdy kompilator kompiluje aplikację, tłumaczy kod na „język pośredni” (lub w skrócie IL). Ten kod jest następnie kompilowany do plików binarnych .Net.
Ponieważ aplikacje .Net to pliki binarne skompilowane z kodu IL, ILSpy może przenieść aplikację .Net, odwrócić ją z powrotem do kodu IL, a następnie pójść o krok dalej i odwrócić z powrotem do C # lub VB.Net.
Za pomocą tego narzędzia wystarczy skompilować aplikację, a następnie przeglądać skompilowane pliki jako kod IL, C # lub VB.Net. Żeby było jasne, nie ma znaczenia, w jakim języku kod został początkowo napisany. Tak długo, jak plik binarny jest zestawem .Net, może dokonywać inżynierii wstecznej skompilowanych plików i wyświetlać zawartość w dowolnym z tych trzech języków.
Wiem, że to nie jest dokładnie kompilator, ale jest to narzędzie, które oferuje efekt końcowy podobny do tego, czego szukasz, i w rzeczywistości użyłem go do „przetłumaczenia” projektów VB.Net na coś trochę bardziej mi znany - C #.
źródło
W twoim przypadku użycia (na podstawie komentarzy) wygląda na to, że SWIG może być przydatny.
źródło
Przypominam sobie czcigodnego f2c , który dokonuje tłumaczenia między źródłami z Fortran 77 do C.
Był (czasem jest ...) używany głównie do tłumaczenia kodu numerycznego sprzed kilkudziesięciu lat bez konieczności integracji kompilatora fortran z łańcuchem narzędzi.
źródło
Teoria, która mówi, że takie programy istnieją, nazywa się w zasadzie dopuszczalnymi numeracjami . Możemy udowodnić, że istnieją kompilatory obliczalne między dowolnymi dwoma takimi numeracjami, a każdy formalizm Turinga (lub język programowania) jest w istocie jednym.
źródło