Dlaczego pierwszy kompilator został napisany przed pierwszym tłumaczem?

72

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?

anguyen
źródło
67
ponieważ wtedy było więcej potrzeby użycia kompilatora niż tłumacza
maniak zapadkowy
23
Aby skompilować pierwszego tłumacza? : P (tylko częściowo przymrużeniem oka, tłumacza jest złożona (bardziej niż prosty kompilator) i byłoby paskudne napisać efektywne jeden w kodzie maszynowym)
Vality
4
Jeśli weźmiesz swój procesor jako instrukcje interpretujące je, tak ja to widzę (jakkolwiek zaimplementowane sprzętowo), wtedy twierdzenie, że pierwszy interpreter został napisany po tym, jak pierwszy kompilator się nie potwierdzi. Przy okazji wiem, że to nie pomaga w pytaniu / odpowiedzi. To ma być ciekawy komentarz z innego punktu widzenia.
Pedro Henrique A. Oliveira
11
McCarthy nie napisał tłumacza LISP. McCarthy wynalazł formalizm matematyczny. Steve Russell, jeden z ówczesnych studentów MIT AI Lab, zdał sobie sprawę, że może napisać tłumacza wykonującego loty McCarthy'ego, a reszta to już historia.
John R. Strohm,
5
W rzeczywistości słyszałem, że McCarthy wierzył, że LISP jest niemożliwy do wdrożenia. To Russell zdał sobie sprawę, że uniwersalna funkcja McCarthy'ego z podręcznika LISP a) była tłumaczem ustnym i b) można ją wdrożyć.
Jörg W Mittag

Odpowiedzi:

97

Pisanie kompilatora wydaje się o wiele trudniejszym problemem niż tłumacz.

To może być prawda dzisiaj, ale twierdzę, że tak nie było 60 lat temu. Kilka powodów, dla których:

  • Z tłumaczem musisz zachować zarówno to, jak i program w pamięci. W czasach, w których 1kb pamięci był ogromnym luksusem, kluczem było utrzymanie niskiego poziomu pamięci. Tłumaczenie ustne wymaga nieco więcej pamięci niż uruchomienie skompilowanego programu.
  • Nowoczesne procesory są niezwykle złożone z ogromnymi katalogami instrukcji. Więc napisanie dobrego kompilatora jest prawdziwym wyzwaniem. Stare procesory były znacznie prostsze, więc nawet kompilacja była prostsza.
  • Współczesne języki są znacznie bardziej złożone niż stare języki, więc nawet kompilatory są znacznie bardziej złożone. Stare języki miałyby zatem prostsze kompilatory.
Euforyk
źródło
65
i bez kompilatora musiałbyś napisać interpretera w asemblerze
maniak zapadkowy
34
Pierwsze kompilatory, w których ludzie. (Kiedy ludzie są tłumaczami, nie potrzebujemy komputerów). Wtedy ktoś musiał pomyśleć o napisaniu kompilatora w skompilowanym języku (jedynym, który mieli, ale z czasem skompilowali moi ludzie).
ctrl-alt-delor
1
Właściwie… Niedawno przeczytałem, że Komputer Apollo Guidance używany w lotach z Księżyca w latach 60. miał tłumacza: wpis wiki : … tłumacz zapewnił o wiele więcej instrukcji niż natywnie obsługiwany przez AGC… „Przypuszczam, że ten„ tłumacz ”był bardziej jak „Sweet 16” tłumacza osadzonym w starych komputerach Apple II niż coś jak LISP.
Calphool
6
@ratchetfreak I tak było. Podobnie jak pierwsze kompilatory.
RBarryYoung
3
@richard: Kiedy ludzie byli tłumaczami ustnymi / kalkulatorami, ich stanowisko nazywało się „komputer”. Więc kiedy ludzie byli tłumaczami, byli komputerami, dosłownie. W projekcie Manhattan wykorzystano tysiące „komputerów” (faktyczne stanowisko, poważnie), do których fizycy nuklearni wysłali swoje obliczenia pocztą w celu ich wykonania. W rzeczywistości w projekcie zatrudniono także matematyków, którzy złamali obliczenia od inżynierów, którzy sformułowali obliczenia na podstawie teorii fizyków, aby wysłać „komputery”.
slebetman
42

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.

Mctylr
źródło
Czy komputery korzystały z teletypów przed nadejściem dzielenia czasu? Spodziewałbym się, że albo skorzystają z drukarek liniowych, albo ze szpuli na taśmę. W przeciwnym razie 1-8 sekund, które komputer musiałby czekać po każdym wierszu tekstu, oznaczałoby 1-8 sekund, że komputer mógł - ale nie zrobił - zrobić coś pożytecznego.
supercat
2
@ superupat - tak, użyto teletypów, ale dalekie były od „interaktywnych”. Pierwszy komputer, który zaprogramowałem, miał pamięć składającą się z 18 bitowych słów - z czego 1K. Sama pamięć była obrotowym bębnem , więc kiedy włączyłeś komputer, musiałeś poczekać, aż pamięć przyspieszy. Miał dołączony teletyp i można A) odczytać znak wpisany z klawiatury lub odczytać z czytnika taśmy papierowej (z punktu widzenia komputera oba są takie same), B) napisać znak na „drukarce ”typu teletekstu. Ach, wspaniałe dni - WIELKIE dni ..! CZY MOJA GRUEL CIEPŁA JESZCZE?!?!? :-)
Bob Jarvis
@BobJarvis: Jaki to byłby rok?
supercat
1
@ supercat - 1973 - ale komputer, o którym mowa (EDP-18, według Educational Data Products), był jeszcze stosunkowo starszy. Mimo to mieliśmy to do czynienia (i posiadanie dowolnego komputera, z którym mogliśmy sobie poradzić w szkole średniej we wczesnych latach 70-tych było czymś niezwykłym), dlatego uważaliśmy, że jest niesamowity. :-)
Bob Jarvis
2
To jest znacznie lepsza i pełna odpowiedź niż zaakceptowana.
Jim Garrison
12

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).

Babou
źródło
3
Mój, jak śmiały .
Pharap
@Pharap Czy to niewłaściwy styl? Moim celem jest ułatwienie znalezienia kluczowych informacji, przy jednoczesnym zapewnieniu bardziej swobodnego stylu niż proste wyliczanie faktów. Muszę wyznać, że tak naprawdę nie wygląda to zbyt skutecznie na tej stronie SE.
babou
@ anonimowy-downvoter Downvoting bez komentarza pokazuje, że ktoś może być głupi. Jednak nie mówi kto.
babou
4

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 .

Mark E. Haase
źródło
3

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.

Bill Brothers
źródło
2

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.

Gangnus
źródło
1

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?

gnasher729
źródło
Nie znam się zbytnio na komputerach z lat 50., ale przynajmniej dla prostych maszyn von Neumanna z późniejszych dekad narzut tłumacza wynosiłby od dwóch do pięciu instrukcji (może łącznie od czterech do dziesięciu cykli) na interpretowaną instrukcję: dekodowanie, skok pośredni, może dekodowanie dodatkowe argumenty. Jeśli ustawisz interpretowany zestaw instrukcji na wystarczająco wysokim poziomie (abyś wykonał kilka instrukcji maszynowych na instrukcję interpretera), będzie to mniej niż 90%, a być może nawet akceptowalne. Zobacz także: Naprzód.
3
Przed napisaniem pierwszego kompilatora większość programów była napisana w rzeczywistym kodzie maszynowym, a nie w asemblerze (mnemoniki kodów operacyjnych).
mctylr
2
@delnan Systemy te działały z zegarami w kiloHertzach, więc marnowanie 3-5-krotnego zmniejszenia wydajności prawdopodobnie będzie różnicą między pomyślnym zakończeniem programu przed awarią systemu z powodu awarii sprzętu (tj. pęknięcia lampy próżniowej), czy nie. Awarie sprzętowe zdarzały się codziennie w latach 50., jeśli dobrze pamiętam.
mctylr
delnan: Pokaż mi tłumacza, który potrafi tłumaczyć z pięcioma instrukcjami. A Forth nie jest językiem interpretowanym, to obrzydliwość :-). Przepraszam, mam na myśli język wątkowy. Coś w rodzaju BASIC wymaga miliardów instrukcji interpretacji jednego stwierdzenia.
gnasher729
@gnasher: W 1974 roku zbudowałem wysokowydajny interpreter BASIC dla Keronix (ahem, klony Data General Nova), który używał zorientowanego na bajty kodu P do kodowania instrukcji BASIC. Potrzeba było około 25-50 instrukcji maszynowych, aby „zinterpretować” kod pC, 10 z nich dla samego pobierania bajtów. (Zrobiłem ten oparty na tokenie w 1969 r., Który wymagał więcej, ponieważ musiał w rezultacie ponownie przeanalizować wyrażenia). Ale to nie było i nie jest „gazillionami”.
Ira Baxter
1

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].gotoetykieta, która nie została jeszcze zdefiniowana, ponieważ wie, kiedy gotokompiluje 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.

supercat
źródło
1
Dysk? Ummmm ... nie. Taśma. Duże, wolne taśmy szpulowe. I wiele z nich. Pamiętam, jak poszedłem na wykład Grace Murray Hopper (podwójnie interesujący dla mnie, ponieważ byłem specjalistą ds. Analizy systemów ORAZ pomocnikiem w oddziale Marynarki Wojennej ROTC na terenie kampusu, a CAPT Hopper był oficerem marynarki wojennej). Opowiedziała historię, w której, jak powiedziała, wpadła na pomysł napisania niewykorzystanych części programu na taśmę - nazwała to „korzystaniem z pamięci dyskowej”. „Ale”, powiedziała, „pomysł nie przyjął się, dopóki IBM nie zrobił tego samego i nie nazwał go„ pamięcią wirtualną ”. CAPT Hopper naprawdę nie lubił IBM ... :-)
Bob Jarvis
@BobJarvis: Nie zastanawiałem się nad tym aspektem, ale ten sam ogólny jednoprzebiegowy projekt, który zostałby użyty do kompilacji gotowego do uruchomienia kodu do pamięci RAM, mógłby dobrze współpracować z napędem taśmowym; dane wyjściowe kompilatora przechodziłyby na taśmę, a następnie taśma była przewijana i wczytywana do kolejnych adresów pamięci i uruchamiana bezpośrednio, bez potrzeby posiadania jakiejkolwiek części kompilatora w pamięci w tym samym czasie.
supercat
0

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.

The Spooniest
źródło
Oryginalny interpreter podstawowy dla Apple] [z tego, co rozumiem, został ręcznie przetłumaczony na kod maszynowy i nigdy nie istniał w formacie kodu źródłowego do odczytu maszynowego. Nie jestem pewien, jakiego „kompilatora” użyłbyś do jego wytworzenia.
supercat
@ supercat: Nie wiem, jak powstał wspomniany interpreter podstawowy, ale nie mówię o kompilatorach używanych do tworzenia tłumaczy. Mówię o kompilatorach będących częścią tłumaczy. W ramach swojego kodu interpreter języka Apple] [BASIC potrzebuje sposobu na odczytanie plików tekstowych zawierających kod BASIC i utworzenie drzewa składni na podstawie tego tekstu, który następnie wykonuje. Kod, który to robi, jest kompilatorem; nie generuje kodu maszynowego, ale nadal wykonuje zadania odczytu kodu i tłumaczenia go na inny formularz.
Spooniest
Typowe interpretery BASIC mikrokomputera nie wytwarzają niczego, nawet zdalnie przypominającego drzewo składniowe. Nie znam oryginalnego interpretera języka BASIC (zwanego „liczbą całkowitą BASIC”), ale interpretera języka BASIC zaimplementowanego przez Microsoft dla Apple („Applesoft BASIC”), Commodore i różnych innych firm zapisywał tekst programu w niezmienionej postaci, z wyjątkiem dwóch rzeczy : (1) każda linia była poprzedzona 16-bitowym numerem linii i 16-bitowym adresem następnej linii, a po niej bajt zerowy; (2) każde słowo kluczowe zostało zastąpione jednym bajtem z ustawionym wysokim bitem. Poza tym wyrażenia zostały przeanalizowane ...
supercat
... znak po znaku, od lewej do prawej; wyrażenie takie jak A = 1234 "zamienia cyfry 1, 2, 3 i 4 na liczbę zmiennoprzecinkową w czasie wykonywania.
supercat
@ superupat: Brzmi to bliżej kodu bajtowego niż drzewa składniowego, więc mam błąd w tej kwestii. Ale główny punkt nadal istnieje: pseudobajtkod musi nadal być zbudowany z tekstu, a kod, który to robi, jest kompilatorem.
Spooniest
-1

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.

Loren Pechtel
źródło