Pierwszy kompilator został napisany przez Grace Hopper w 1952 roku, podczas gdy tłumacz Lisp został napisany w 1958 roku przez studenta Johna McCarthy'ego, Steve'a Russella. Pisanie kompilatora wydaje się o wiele trudniejszym problemem niż tłumacz. Jeśli tak, to dlaczego pierwszy kompilator napisano sześć lat przed pierwszym tłumaczem?
history
compiler
interpreters
anguyen
źródło
źródło
Odpowiedzi:
To może być prawda dzisiaj, ale twierdzę, że tak nie było 60 lat temu. Kilka powodów, dla których:
źródło
Podstawową kwestią jest to, że środowisko sprzętowe komputerów z lat 50. XX wieku sprawiło, że tylko kompilator był wykonalny, biorąc pod uwagę przetwarzanie wsadowe komputerów w tamtych czasach.
W tym czasie lepsze interfejsy użytkownika ograniczały się głównie do kart dziurkowanych i drukarek teletekstowych . W 1961 r. System SAGE stał się pierwszym wyświetlaczem kineskopu (CRT) na komputerze. Interaktywny charakter tłumacza był więc preferowany i naturalny dopiero znacznie później.
Liczne komputery w latach 50. XX wieku używały przełączników na panelu przednim, aby załadować instrukcje, a wynikiem były po prostu rzędy lamp / diod LED, a hobbystowie stosowali nawet przełączniki na panelu przednim i diody LED w latach 70. Może znasz osławiony Altair 8800 .
Inne ograniczenia sprzętowe również uniemożliwiały tłumaczy. W latach 50. XX wieku w komputerach była bardzo ograniczona dostępność pamięci podstawowej (np. RAM). Przed półprzewodnikowym układem scalonym (który pojawił się dopiero w 1958 r.) Pamięć była ograniczona do pamięci z rdzeniem magnetycznym lub pamięci linii opóźniającej, mierzonej w bitach lub słowach , bez prefiksu. W połączeniu ze spowolnieniem dodatkowej pamięci (np. Dysku lub taśmy) byłoby uważane za marnotrawstwo, jeśli nie niewykonalne, aby większość pamięci była używana przez interpretera, nawet przed załadowaniem interpretowanego programu.
Ograniczenia pamięci były nadal głównym czynnikiem, gdy zespół kierowany przez Johna Backusa z IBM stworzył kompilator FORTRAN w latach 1954-57. Ten innowacyjny kompilator odniósł sukces tylko dlatego, że był kompilatorem optymalizującym .
Większość komputerów w 1950 roku ledwie dowolny system operacyjny, nie mówiąc już o nowoczesnych funkcji, takich jak dynamiczne łączenie i zarządzania pamięcią wirtualną, więc pomysł tłumacza był zbyt radykalny i niepraktyczne w tym czasie.
Uzupełnienie
Języki lat 50. były prymitywne. Obejmowały tylko niewielką garść operacji, na które często miały wpływ instrukcje sprzętu lub definicja problemu ich docelowego użycia.
W tamtym czasie komputery rzadko były komputerami ogólnego przeznaczenia w takim znaczeniu, w jakim myślimy o komputerach dzisiaj. To, że można je przeprogramować bez konieczności przebudowy, uznano za rewolucyjną koncepcję - wcześniej ludzie używali maszyn elektromechanicznych (zwykle kalkulatorów) do obliczania lub obliczania odpowiedzi (większość aplikacji w latach 50. miała charakter numeryczny).
Z punktu widzenia informatyki, zarówno kompilatory, jak i tłumacze są tłumaczami i mają mniej więcej taką samą złożoność do wdrożenia.
źródło
Pierwsze języki programowania były dość proste (na przykład bez rekurencji) i zbliżone do architektury maszyn, która sama w sobie była prosta. Tłumaczenie był wtedy prosty proces .
Kompilator był prostszy jako program niż interpreter, który musiałby przechowywać zarówno dane do wykonania programu, jak i tabele do interpretacji kodu źródłowego. A tłumacz zajmowałby więcej miejsca dla kodu źródłowego programu i tabel symbolicznych.
Pamięć może być tak rzadka (zarówno ze względu na koszty, jak i architekturę), że kompilatory mogą być samodzielnymi programami, które nadpisują system operacyjny (użyłem jednego z nich). System operacyjny musiał zostać ponownie załadowany po kompilacji, aby uruchomić skompilowany program. ... co wyjaśnia, że uruchomienie tłumacza w prawdziwej pracy po prostu nie było opcją .
Prawdą jest, że prostota wymagana od kompilatorów była taka, że kompilatory nie były bardzo dobre (optymalizacja kodu była jeszcze w powijakach, jeśli w ogóle była brana pod uwagę). Ręcznie napisany kod maszynowy miał, przynajmniej do późnych lat sześćdziesiątych, reputację bycia znacznie bardziej wydajnym niż kod generowany przez kompilator. Istniała nawet koncepcja współczynnika rozszerzania kodu , który porównywał rozmiar skompilowanego kodu z pracą bardzo dobrego programisty. Zazwyczaj był większy niż 1 dla większości (wszystkich?) Kompilatorów, co oznaczało wolniejsze programy i, co ważniejsze, większe programy wymagające więcej pamięci. To był wciąż problem w latach sześćdziesiątych.
Zainteresowanie kompilatora polegało na łatwości programowania, szczególnie dla użytkowników, którzy nie byli specjalistami od komputerów, takich jak naukowcy z różnych dziedzin. To zainteresowanie nie było wydajnością kodu. Nadal jednak czas programisty uznano za tani zasób. Kosztem był czas komputerowy, do 1975–1980, kiedy to koszt przeszedł ze sprzętu na oprogramowanie. Co oznacza, że niektórzy profesjonaliści nawet nie traktowali poważnie kompilatora .
Bardzo wysoki koszt czasu komputerowego był kolejnym powodem dyskwalifikacji tłumaczy , do tego stopnia, że sam pomysł byłby śmieszny dla większości ludzi.
Przypadek Lispa jest wyjątkowy, ponieważ był to niezwykle prosty język, który sprawił, że był on wykonalny (a komputer stał się nieco większy w 58). Co ważniejsze, interpreter Lisp był dowodem koncepcji dotyczącej samookreślalności Lisp ( meta-okrężność ), niezależnie od jakiejkolwiek kwestii użyteczności.
Sukces Lisp wynika w dużej mierze z faktu, że ta samookreślalność uczyniła go doskonałym narzędziem do testowania struktur programowania i projektowania nowych języków (a także ze względu na wygodę obliczeń symbolicznych).
źródło
Nie zgadzam się z założeniem pytania.
Adm. Pierwszy kompilator Hoppera (A-0) bardziej przypominał linker lub język makr. Przechowywała podprogramy na taśmie (każdemu z nich przypisano numer), a jej programy byłyby zapisywane jako lista podprogramów i argumentów. Kompilator skopiuje żądane podprogramy z taśmy i ponownie zamieni je w kompletny program.
Użyła słowa „kompiluj” w tym samym sensie, w jakim kompiluje się antologię wierszy: gromadząc różne przedmioty w jednym tomie.
O ile mi wiadomo, ten pierwszy kompilator nie miał leksemu ani parsera, co czyni go odległym przodkiem współczesnego kompilatora. Później stworzyła inny kompilator (B-0, znany również jako FLOW-MATIC), którego celem jest bardziej angielska składnia, ale został ukończony dopiero w 1958 lub 1959 r. - mniej więcej w tym samym czasie co tłumacz Lisp.
Dlatego myślę, że samo pytanie jest nieco błędne. Wygląda na to, że kompilatorzy i tłumacze ewoluowali prawie dokładnie w tym samym czasie, bez wątpienia dzięki dzieleniu się pomysłami, które wielu naukowców myślałoby w tym samym czasie.
Lepsza odpowiedź z cytatami tutaj: https://stackoverflow.com/a/7719098/122763 .
źródło
Inną częścią równania jest to, że kompilatory były abstrakcją stopniową powyżej asemblera. Najpierw mieliśmy zakodowany kod maszynowy. „My” byliśmy asemblerem. Każdy skok i przesunięcie itp. Obliczano ręcznie na heksadecymalny (lub ósemkowy), a następnie przebijano na papierową taśmę lub karty. Kiedy na scenie pojawili się asemblerzy, oszczędzało to dużo czasu. Kolejnym krokiem były asemblery makr. Dało to możliwość napisania makra, które rozwinąłoby się w zestaw instrukcji maszynowych. Fortran i Cobol byli więc wielkim krokiem naprzód. Brak zasobów (pamięci, pamięci i cykli procesora) oznaczał, że tłumacze ogólnego przeznaczenia musieli czekać na rozwój technologii. Większość wczesnych interpretatorów były silnikami bajtowymi (jak Java lub CLR dzisiaj, ale z dużo mniejszymi możliwościami). UCSD Pascal był bardzo popularnym (i szybkim) językiem. MS Basic był silnikiem z kodem bajtowym pod maską.
Jeśli chodzi o narzut instrukcji, to całkowicie zależało od tego, jaki procesor był uruchomiony. Przemysł przez jakiś czas przeżywał wielkie zamieszanie RISC kontra CISC. Osobiście napisałem asembler dla IBM, Data General, Motorola, Intel (kiedy się pojawili), TI i kilku innych. Istniała dość znacząca różnica w zestawach instrukcji, rejestrach itp., Które miałyby wpływ na to, co było wymagane do „interpretacji” kodu p.
Jako czas odniesienia zacząłem programować w firmie telefonicznej około 1972 roku.
źródło
Jeśli nie trzymasz wszystkiego w pamięci, skompilowany kod jest znacznie szybszy. Nie zapominaj, że w tych czasach funkcje zostały połączone ze skompilowanym kodem. Jeśli nie kompilujesz, nie wiesz, jakich funkcji będziesz potrzebować. Więc wywołujesz funkcje z ... Och, jeszcze nie z dysku, jesteśmy na początku lat 50., ale z kart! W czasie wykonywania!
Oczywiście można znaleźć obejścia, ale jeszcze ich nie znaleziono, ponieważ języki były bardzo proste i nie były tak dalekie od kodu maszynowego. A kompilacja była łatwa i wystarczająca.
źródło
Przed napisaniem pierwszego kompilatora ludzie pisali kod asemblera, co było ogromnym postępem w porównaniu do zwykłego kodu binarnego. W tym czasie istniał silny argument, że kod skompilowany przez kompilator byłby mniej wydajny niż kod asemblera - w tym czasie stosunek (koszt komputera) do (koszt programisty) był znacznie, znacznie inny niż obecnie. Z tego punktu widzenia istniała silna odporność na kompilatory.
Ale kompilatory są o wiele bardziej wydajne niż tłumacze. Gdybyś w tym momencie zasugerował Ci napisanie tłumacza, ludzie pomyśleliby, że zwariowałeś. Czy możesz sobie wyobrazić zakup komputera za milion dolarów, a następnie marnowanie 90% jego mocy na interpretację kodu?
źródło
Przed interpretacją programu zapętlającego należy go zapisać na nośniku, który może być wielokrotnie odczytywany. W większości przypadków jedynym odpowiednim nośnikiem byłaby pamięć RAM. Ponieważ kod będzie zwykle wprowadzany na kartach perforowanych, które - w przypadku języków czytelnych dla ludzi - prawdopodobnie będą w dużej mierze puste, kod musi zostać przetworzony przed zapisaniem w pamięci RAM. W wielu przypadkach przetwarzanie tekstu z dziurkowanej karty do postaci odpowiedniej do bezpośredniego wykonania przez procesor nie jest tak naprawdę trudniejsze niż przetwarzanie go do postaci, która mogłaby być skutecznie obsługiwana przez interpretera.
Zauważ, że celem wczesnych kompilatorów nie było tworzenie pliku asemblera lub pliku kodu obiektowego na dysku, ale raczej umieszczenie kodu w pamięci RAM, który był gotowy do uruchomienia. Jest to w rzeczywistości zaskakująco łatwe, gdy nie ma przeszkadzającego systemu operacyjnego. Kompilator może generować kod, zaczynając od jednego końca pamięci i przydzielać zmienne i obiekty docelowe, zaczynając od drugiego. Jeśli instrukcja jest oznaczona etykietą „1234”, kompilator zapisze w zmiennej o nazwie „1234” instrukcję przejścia do bieżącego adresu generowania kodu, tworząc tę zmienną, jeśli nie istnieje. Instrukcja „goto 1234” utworzy zmienną „1234”, jeśli nie istnieje, a następnie przeskoczy do tej zmiennej [która, mam nadzieję, przejdzie do odpowiedniej lokalizacji zapisanej w niej przed wykonaniem tej instrukcji].
goto
etykieta, która nie została jeszcze zdefiniowana, ponieważ wie, kiedygoto
kompiluje się, dokąd ma skoczyć - do zmiennej. Może to nie być najskuteczniejszy sposób generowania kodu, ale jest odpowiedni dla rozmiarów programów obsługiwanych przez komputery.źródło
Ponieważ tłumacze potrzebują kompilatorów do działania.
Powyższe stwierdzenie nie jest tak naprawdę prawdą. Ściśle mówiąc, to można zrobić bez tłumacza kiedykolwiek użyciem lub w inny sposób interakcji z kompilatora. Ale wyniki tego nie wyglądałyby bardzo podobnie do tego, co rozumiem przez te terminy.
W ścisłym tego słowa znaczeniu kompilatory i tłumacze robią zupełnie inne rzeczy. Kompilator odczytuje tekst z jakiegoś źródła i przekształca go w inny format: język asemblera, kod maszynowy, inny język wysokiego poziomu, struktura danych lub cokolwiek innego. Tymczasem tłumacz interpretuje strukturę danych i wykonuje na jej podstawie instrukcje.
To, co obecnie nazywamy „kompilatorem”, to tak naprawdę kompilator sparowany z generatorem kodu : program, który pobiera dane z jakiegoś źródła i generuje kod w jakimś formacie w oparciu o to, co widzi. Jest to dość intuicyjne zastosowanie dla kompilatorów i była to jedna z pierwszych rzeczy, dla których kompilatory zostały stworzone. Ale jeśli spojrzysz na to z innej strony, wydaje się to bardzo podobne do tego, co robi tłumacz. Zawsze wypisuje kod zamiast wykonywania bardziej ogólnych operacji, ale zasada jest taka sama.
Jeśli spojrzymy na to z drugiej strony, tłumacz musi dostać swoje dane skądś . To tylko dane, więc możesz je budować w taki sam sposób, jak inne dane. Ponieważ mówimy o interpretacji, wydaje się naturalne, że możesz budować swoje dane na podstawie instrukcji w pliku tekstowym. Ale aby to zrobić, musisz coś przeczytać w tekście i stworzyć strukturę danych, a to jest kompilator . Jest podłączony do interpretera zamiast do generatora kodu, ale mimo wszystko jest kompilatorem.
Dlatego kompilatory zostały napisane jako pierwsze. Pomysł interpretacji struktur danych nie był nowy, nawet gdy opracowano kompilatory, ale kompilatory były „brakującym ogniwem”, które pozwoliło programistom budować te struktury z tekstu.
źródło
Kolejny czynnik: kiedy napisano pierwsze kompilatory, koszt czasu pracy maszyny był znacznie wyższy niż obecnie. Tłumacze używają dużo więcej czasu na maszynie.
źródło