BASIC interpreter -BASIC interpreter

Przykład wpisania popularnego programu do interpretera języka BASIC (w tym przypadku HAMURABI )

Interpreter języka BASIC to tłumacz , który umożliwia użytkownikom wprowadzanie i uruchamianie programów w języku BASIC i był przez pierwszą część ery mikrokomputerów domyślną aplikacją uruchamianą przez komputery. Oczekiwano, że użytkownicy będą używać interpretera języka BASIC do wpisywania programów lub ładowania programów z pamięci (początkowo kasety magnetofonowe, a następnie dyskietki ).

Interpretatory języka BASIC mają znaczenie historyczne. Pierwszym wystawionym na sprzedaż produktem Microsoftu był interpreter języka BASIC ( Altair BASIC ), który utorował firmie drogę do sukcesu. Przed Altair BASIC mikrokomputery były sprzedawane jako zestawy, które wymagały programowania w kodzie maszynowym (na przykład Apple I ). W okresie Altair interpretery języka BASIC były sprzedawane oddzielnie, stając się pierwszym oprogramowaniem sprzedawanym osobom fizycznym, a nie organizacjom; Apple BASIC był pierwszym oprogramowaniem firmy Apple. Po MITS Altair 8800 oczekiwano, że mikrokomputery będą dostarczane w pakiecie z własnymi interpreterami języka BASIC (np. Apple II , który miał wiele implementacji języka BASIC). Sprzeciw wobec ceny Altair BASIC firmy Microsoft doprowadził również do wczesnego wspólnego tworzenia oprogramowania, ogólnie dla implementacji Tiny BASIC , a konkretnie dla Palo Alto Tiny BASIC.

Tłumacze języka BASIC przestały być używane, gdy komputery rosły w siłę, a związane z nimi programy stały się zbyt długie, aby można je było wpisać jako rozsądny format dystrybucji. Oprogramowanie coraz częściej było prekompilowane i przesyłane na dyskietkach lub za pośrednictwem systemów tablic ogłoszeniowych , przez co potrzeba wykazów źródeł była mniej ważna. Dodatkowo, coraz bardziej wyrafinowane powłoki poleceń, takie jak MS-DOS i GUI Apple Macintosh , stały się głównym interfejsem użytkownika , a potrzeba działania BASIC-a jako powłoki zniknęła. Używanie tłumaczy języka BASIC jako podstawowego języka i interfejsu do systemów w dużej mierze zniknęło do połowy lat osiemdziesiątych.

Historia

BASIC pomógł rozpocząć erę podziału czasu, stał się głównym nurtem w erze mikrokomputerów, a następnie wyblakł, stając się kolejną aplikacją w erze DOS i GUI, a dziś przetrwał w kilku niszach związanych z tworzeniem gier, retrokomputerami i nauczaniem.

Era podziału czasu

Po raz pierwszy zaimplementowany jako system kompilacji i pracy, a nie interpreter, BASIC pojawił się jako część szerszego ruchu w kierunku systemów z podziałem czasu . General Electric , który pracował nad Dartmouth Time Sharing System i powiązanym z nim Dartmouth BASIC , napisał swój własny bazowy system operacyjny i uruchomił internetowy system podziału czasu znany jako Mark I, zawierający kompilator języka BASIC (nie tłumacza) jako jeden z głównych elementów sprzedaży zwrotnica. Inne firmy z rozwijającej się branży szybko poszły w ich ślady. We wczesnych latach siedemdziesiątych BASIC był w dużej mierze uniwersalny na komputerach mainframe ogólnego przeznaczenia.

Podstawowym zadaniem systemu HP 2000 było uruchamianie języka BASIC z podziałem czasu .

BASIC, jako usprawniony język zaprojektowany z myślą o zintegrowanej edycji linii, naturalnie nadawał się do przeniesienia na rynek minikomputerów , który pojawiał się w tym samym czasie, co usługi z podziałem czasu. Maszyny te miały bardzo małą pamięć główną , być może zaledwie 4 KB we współczesnej terminologii, i brakowało im pamięci masowej o wysokiej wydajności, takiej jak dyski twarde , dzięki którym kompilatory są praktyczne. Z kolei tłumacz wymagałby mniej zasobów obliczeniowych kosztem wydajności. W 1968 roku firma Hewlett Packard wprowadziła HP 2000 , system oparty na interpreterze HP Time-Shared BASIC . W 1969 roku Dan Paymar i Ira Baxter napisali kolejny wczesny interpreter języka BASIC dla firmy Data General Nova .

Jedną z przeszkód była firma Digital Equipment Corporation (DEC), wiodący dostawca minikomputerów. Wydali nowy język znany jako FOCAL , oparty na wcześniejszym JOSS opracowanym na maszynie DEC w Stanford Research Institute na początku lat 60. JOSS był pod wieloma względami podobny do BASICa, a FOCAL był wersją przeznaczoną do pracy w bardzo małych systemach pamięciowych, zwłaszcza PDP -8 , który często był dostarczany z 4 KB pamięci głównej . Pod koniec lat 60. sprzedawcy DEC, zwłaszcza w dziale sprzedaży edukacyjnej, stwierdzili, że ich potencjalni klienci nie byli zainteresowani FOCAL i szukali swoich systemów gdzie indziej. To skłoniło Davida H. Ahla do zatrudnienia programisty do stworzenia języka BASIC dla PDP-8 i innych maszyn DEC. W ciągu roku zniknęło całe zainteresowanie alternatywami, takimi jak JOSS i FOCAL.

Era mikrokomputerów

Wprowadzenie pierwszych mikrokomputerów w połowie lat siedemdziesiątych XX wieku było kontynuacją gwałtownego rozwoju BASIC-a, który miał tę zaletę, że był dość dobrze znany młodym projektantom i hobbystom komputerowym, którzy interesowali się mikrokomputerami, z których wielu widziało BASIC na minis lub komputery mainframe. BASIC był jednym z niewielu języków, który był zarówno wystarczająco wysoki, aby mógł być używany przez osoby bez przeszkolenia, jak i wystarczająco mały, aby zmieścił się w ówczesnych mikrokomputerach. W 1972 roku firma HP wprowadziła programowalny kalkulator biurkowy HP 9830A z interpreterem BASIC Plus w pamięci tylko do odczytu (ROM).

W czerwcu 1974 roku Alfred Weaver, Michael Tindall i Ronald Danielson z University of Illinois w Urbana-Champaign udowodnili, że możliwe jest stworzenie „A BASIC Language Interpreter for the Intel 8008 Microprocessor” w artykule o tym samym tytule, chociaż ich aplikacja została wdrożona w symulatorze 8008 dla IBM 360/75 i wymagała 16 KB.

Altair 8K BASIC na taśmie papierowej

W styczniu 1975 roku ogłoszono Altair 8800 , który zapoczątkował rewolucję mikrokomputerową . Jedna z pierwszych mikrokomputerowych wersji języka BASIC została napisana wspólnie przez Gatesa, Allena i Monte Davidoffa dla ich nowo utworzonej firmy Micro-Soft. Zostało to wydane przez MITS w formacie taśmy perforowanej dla Altair 8800 wkrótce po samej maszynie, pokazując BASIC jako podstawowy język wczesnych mikrokomputerów.

W marcu 1975 roku Steve Wozniak wziął udział w pierwszym spotkaniu Homebrew Computer Club i zaczął opracowywać projekt własnego komputera. Członkowie klubu byli zachwyceni Altair BASIC. Woźniak doszedł do wniosku, że jego maszyna musiałaby mieć własny BASIC. W tym czasie pracował w Hewlett Packard i użył ich dialektu minikomputerów, HP Time-Shared BASIC , jako podstawy dla swojej własnej wersji. Integer BASIC został wydany na kasecie dla Apple I i był dostarczany w pamięci ROM , gdy Apple II trafił do sprzedaży latem 1977 roku.

Inni członkowie Homebrew Computer Club zaczęli rozpowszechniać kopie Altair BASIC na taśmie papierowej, co skłoniło Gatesa do napisania Listu otwartego do hobbystów , w którym narzekał na ten wczesny przykład piractwa komputerowego . Częściowo w odpowiedzi na list Gate'a, a częściowo w celu stworzenia jeszcze mniejszego języka BASIC, który działałby z pożytkiem na maszynach 4 KB, Bob Albrecht namówił Dennisa Allisona do napisania własnej odmiany tego języka. Jak zaprojektować i wdrożyć okrojoną wersję interpretera języka BASIC, omówiono w artykułach Allison w pierwszych trzech kwartalnikach biuletynu People's Computer Company opublikowanego w 1975 r. Oraz implementacjach z kodem źródłowym opublikowanych w Dr. Dobb's Journal of Tiny BASIC Kalistenika i ortodoncja: światło do biegania bez overbyte'a . Doprowadziło to do powstania szerokiej gamy Tiny BASIC z dodatkowymi funkcjami lub innymi ulepszeniami, z dobrze znanymi wersjami autorstwa Toma Pittmana i Li-Chen Wanga , członków Homebrew Computer Club. Tiny BASIC został opublikowany otwarcie, a Wang ukuł termin „copyleft”, aby zachęcić innych do kopiowania jego kodu źródłowego. Hobbyści i profesjonaliści stworzyli własne implementacje, czyniąc Tiny BASIC przykładem projektu wolnego oprogramowania , który istniał przed ruchem wolnego oprogramowania .

Wiele firm opracowało interpretery języka BASIC. W 1976 roku SCELBI wprowadził SCELBAL dla 8008 , a University of Idaho i Lawrence Livermore Laboratory ogłosiły, że będą publikować w domenie publicznej LLL BASIC, która obejmowała obsługę zmiennoprzecinkową. W 1977 roku Apple II i TRS-80 Model I miały po dwie wersje języka BASIC, mniejszą wersję wprowadzoną wraz z pierwszymi wydaniami maszyn oraz licencjonowaną wersję Microsoft wprowadzoną później, gdy zainteresowanie platformami wzrosło.

Hello World , z odwrotnym wideo i znakiem dzwonka , uruchamia się następnie w Applesoft BASIC

Microsoft przeportował swój interpreter do MOS 6502 , który szybko stał się jednym z najpopularniejszych mikroprocesorów ery 8-bitowej. Kiedy zaczęły pojawiać się nowe mikrokomputery, takie jak Commodore PET , ich producenci licencjonowali Microsoft BASIC, dostosowany do możliwości sprzętowych. Do 1978 roku MS BASIC był de facto standardem i praktycznie każdy komputer domowy lat 80. zawierał go w pamięci ROM . W 1980 roku, w ramach większej umowy licencyjnej, która obejmowała inne języki i PC DOS , IBM odrzucił uwerturę Atari i zamiast tego licencjonował MS-BASIC na własną implementację, ostatecznie wypuszczając cztery wersje IBM BASIC , każda znacznie większa niż wcześniejsze interpretery ( na przykład Cartridge BASIC zajmował 40 KB). Don Estridge , lider zespołu IBM PC , powiedział: „IBM ma doskonały język BASIC — jest dobrze przyjęty, działa szybko na komputerach typu mainframe i jest o wiele bardziej funkcjonalny niż BASIC mikrokomputerów… liczba użytkowników była nieskończenie mała w porównaniu z liczbą użytkowników Microsoft BASIC. Microsoft BASIC miał setki tysięcy użytkowników na całym świecie. Jak zamierzasz się z tym kłócić?” (Zobacz Microsoft BASIC , aby zapoznać się z późniejszą historią tych różnych implementacji).

Wielu dostawców „kłóciło się z tym” i korzystało z usług innych firm lub pisało własnych tłumaczy. We wrześniu 1978 roku Shepardson Microsystems kończył Cromemco 16K Structured BASIC dla maszyn autobusowych Cromemco S-100 opartych na Z80 . Paul Laughton i Kathleen O'Brien stworzyli następnie Atari BASIC jako zasadniczo okrojoną wersję Cromemco BASIC przeniesioną na 6502. W 1979 roku Warren Robinett opracował kasetę programistyczną BASIC dla Atari, Inc. , mimo że obsługiwała tylko programy z 9 linii kodu (łącznie 64 znaki). Również w 1979 roku firma Texas Instruments wypuściła TI BASIC (TI 99/4A) ze swoim TI-99/4 , który po przebudowie na TI-99/4A sprzedałby prawie 3 miliony systemów. Sinclair BASIC został opracowany dla ZX-80 przez Johna Granta i Steve'a Vickersa z Nine Tiles. W 1980 roku Sophie Wilson z Acorn Computers opracowała Atom BASIC , który później przekształciła w BBC BASIC , jeden z pierwszych tłumaczy oferujących ustrukturyzowane programowanie BASIC, z nazwanymi / procedurami i funkcjami, pętlami i strukturami inspirowanymi przez COMAL . Jan Jones opracował SuperBASIC , kolejny brytyjski BASIC wspierający programowanie strukturalne, dla Sinclair QL . W 1983 Randall Hyde opracował SmartBASIC dla Coleco Adam . Richard Clayton, Chris Hall i Paul Overell opracowali Mallard BASIC dla BBC Micro i Locomotive BASIC dla Amstrad CPC , oba obsługujące polecenia dla indeksowanego systemu plików ISAM . W 1985 roku MetaComCo wydało ABasiC dla Amigi i ST BASIC dla Atari ST . DEF PROCDEF FNREPEAT UNTILIF THEN ELSE

W 1978 roku David Lien opublikował pierwsze wydanie The BASIC Handbook: An Encyclopedia of the BASIC Computer Language , dokumentujące słowa kluczowe na ponad 78 różnych komputerach. Do 1981 roku druga edycja udokumentowała słowa kluczowe z ponad 250 różnych komputerów, ukazując gwałtowny rozwój ery mikrokomputerów.

Tłumacze jako aplikacje

Wraz z pojawieniem się dyskowych systemów operacyjnych i późniejszych graficznych interfejsów użytkownika interpretery języka BASIC stały się tylko jedną z wielu aplikacji, zamiast zapewniać pierwszy monit, jaki użytkownik może zobaczyć podczas włączania komputera.

W 1983 roku zadebiutował komputer przenośny TRS-80 Model 100 , którego implementacja Microsoft BASIC była godna uwagi z dwóch powodów. Po pierwsze, programy były edytowane przy użyciu prostego edytora tekstu TEKST, a nie wpisywane wiersz po wierszu (ale nadal wymagane były numery wierszy). Po drugie, był to ostatni produkt firmy Microsoft opracowany osobiście przez Billa Gatesa .

Również w 1983 roku Microsoft zaczął łączyć GW-BASIC z DOS-em. Funkcjonalnie identyczny z IBM BASICA , jego interpreter języka BASIC był w pełni samodzielnym plikiem wykonywalnym i nie wymagał kasetowej pamięci ROM BASIC znajdującej się w oryginalnym komputerze IBM PC . Według Marka Jonesa Lorenzo, biorąc pod uwagę zakres tego języka, „GW-BASIC jest prawdopodobnie ne plus ultra rodziny BASIC-ów z numerami wierszy firmy Microsoft, sięgających wstecz do Altaira - a być może nawet BASIC-a z numerami wierszy w ogóle”. Wraz z wydaniem MS-DOS 5.0 miejsce GW-BASIC-a zajął QBasic .

MacBASIC zawierał w pełni interaktywne środowisko programistyczne dla oryginalnego komputera Macintosh i został opracowany przez Donna Denmana, Marianne Hsiung, Larry'ego Kenyona i Bryana Stearnsa. MacBASIC został wydany jako oprogramowanie beta w 1985 roku i został przyjęty do użytku w miejscach takich jak wydział informatyki Dartmouth College , do użytku na wstępnym kursie programowania. Był skazany na to, że będzie drugim BASIC-em opracowanym przez Apple, który został zabity na rzecz BASIC-a Microsoftu. W listopadzie 1985 roku Apple nagle zakończyło projekt w ramach umowy z Microsoftem dotyczącej przedłużenia licencji na BASIC na Apple II .

BASIC pojawił się w niektórych systemach gier wideo, takich jak Nintendo Famicom .

Tłumacze języka BASIC nie były tylko wynalazkiem amerykańsko-brytyjskim. W 1984 roku firma Hudson Soft wypuściła Family BASIC na rynek japoński dla konsoli do gier wideo Nintendo Family Computer , implementację zawierającą wyłącznie liczby całkowite przeznaczoną do programowania gier, opartą na Hudson Soft BASIC dla Sharp MZ80 (z angielskimi słowami kluczowymi). Turbo-Basic XL to kompatybilny nadzbiór Atari BASIC, opracowany przez Franka Ostrowskiego i opublikowany w numerze niemieckiego magazynu komputerowego Happy Computer z grudnia 1985 roku , co czyni go jednym z ostatnich tłumaczy opublikowanych jako program do wpisywania . Oprócz tłumacza język zawierał kompilator i zawierał polecenia programowania strukturalnego. Inni autorzy wydali kilka zmodyfikowanych wersji działających z różnymi systemami DOS. We Francji François Lionet i Constantin Sotiropoulos opracowali dwa interpretery języka BASIC z naciskiem na multimedia: STOS BASIC dla Atari ST w 1988 r. i AMOS BASIC dla Amigi w 1990 r.

W maju 1991 r. Microsoft wypuścił Visual Basic , trzecia generacja języka programowania sterowanego zdarzeniami, znanego z modelu programowania Component Object Model (COM). Visual Basic wspierał szybkie tworzenie aplikacji (RAD) aplikacji z graficznym interfejsem użytkownika (GUI) , dostęp do baz danych za pomocą obiektów dostępu do danych , obiektów zdalnych obiektów danych lub obiektów danych ActiveX oraz tworzenie formantów i obiektów ActiveX . Visual Basic był używany do tworzenia zastrzeżonych aplikacji wewnętrznych, a także opublikowanych aplikacji.

Niszowe PODSTAWY

W 1993 roku Microsoft wydał Visual Basic for Applications , język skryptowy dla aplikacji pakietu Microsoft Office , który zastępuje i rozszerza możliwości wcześniejszych języków programowania makr specyficznych dla aplikacji , takich jak WordBASIC (który został wprowadzony w 1989).

W 1996 roku firma Microsoft wydała VBScript jako alternatywę dla JavaScript w celu dodawania interaktywnych funkcji po stronie klienta do stron internetowych przeglądanych w przeglądarce Internet Explorer .

W 1999 roku Benoît Minisini wypuścił Gambas jako alternatywę dla programistów Visual Basic, którzy zdecydowali się na migrację do Linuksa .

W 2000 roku Lee Bamber i Richard Vanner wydali DarkBASIC , system do tworzenia gier dla Microsoft Windows , wraz z towarzyszącym IDE i narzędziami programistycznymi.

W 2001 SmallBASIC został wydany dla Palm PDA . Innym interpreterem BASIC-a dla Palm był HotPaw BASIC, pochodna Chipmunk Basic .

W 2002 roku Emmanuel Chailloux, Pascal Manoury i Bruno Pagano opublikowali Tiny BASIC jako przykład tworzenia aplikacji z Objective Caml .

W 2011 roku Microsoft wydał Small Basic (w odróżnieniu od SmallBASIC), wraz z programem nauczania i przewodnikiem wprowadzającym, zaprojektowanym, aby pomóc uczniom, którzy nauczyli się wizualnych języków programowania, takich jak Scratch , w nauce programowania tekstowego. Powiązane IDE zapewnia uproszczone środowisko programistyczne z takimi funkcjami, jak podświetlanie składni , inteligentne uzupełnianie kodu i dostęp do dokumentacji w edytorze. Język ma tylko 14 słów kluczowych. W 2019 roku Microsoft ogłosił Small Basic Online (SBO), umożliwiając studentom uruchamianie programów z poziomu przeglądarki internetowej .

W 2014 roku Robin H. Edwards wypuścił Arduino BASIC dla Arduino , a teraz szeroko rozwidloną implementację. Inna implementacja o tej samej nazwie została zaadaptowana z Palo Alto Tiny BASIC w 1984 roku przez Gordona Brandly'ego dla jego 68000 Tiny BASIC, później przeniesiona do C przez Mike'a Fielda.

Mobilny BASIC dla Androida

Wiele interpreterów języka BASIC jest teraz dostępnych na smartfony i tablety za pośrednictwem sklepu Apple App Store lub sklepu Google Play dla systemu Android.

Dzisiaj kodowanie interpreterów języka BASIC stało się częścią retrokomputerowego hobby. Języki programowania wyższego poziomu w systemach z rozbudowaną pamięcią RAM uprościły implementację interpreterów języka BASIC. Na przykład zarządzanie wierszami jest proste, jeśli język implementacji obsługuje rzadkie macierze , zarządzanie zmiennymi jest proste w przypadku tablic asocjacyjnych , a wykonywanie programu jest łatwe dzięki funkcjom eval . Jako przykłady zobacz projekt open-source Vintage BASIC, napisany w Haskell lub OCaml Tiny BASIC .

Sprzedaż i dystrybucja

Początkowo tłumacze byli dołączani do sprzętu komputerowego lub opracowywani jako usługa niestandardowa, zanim pod koniec lat 60. pojawił się przemysł produkujący niezależnie pakietowane oprogramowanie dla organizacji. Interpretery języka BASIC były najpierw sprzedawane oddzielnie od mikrokomputerów, a następnie wbudowane, zanim ponownie zostały sprzedane jako aplikacje w erze DOS.

Tekst podpisu
Rok Głoska bezdźwięczna Przykład
1975 Taśma papierowa Altair BASIC
1975 Program do wpisywania Rozszerzony mały BASIC
1976 Kaseta Apple I BASIC
1977 Dyskietka ROM MIKRO PODSTAWOWE
1977 ROM PODSTAWOWE liczby całkowite
1983 Dyskietka GW-BASIC
1995 CD-ROM VisualBasic 4.0
2008 Sklep z aplikacjami Różny

Gdy rynek przestawił się na ROM, rozmiar ROM zaczął dominować przy podejmowaniu decyzji o tym, jak duży może być interpreter języka BASIC. Ponieważ pamięć RAM była sprzedawana jako chipy 4 KB, Altair BASIC był początkowo pakowany w osobne wydania dla 4K, 8K i 12K; przeniosło się to na chipy ROM, ponieważ producenci decydowali, ile chipów ROM mogliby zmieścić w swoim projekcie, biorąc pod uwagę cele cenowe i inne ograniczenia.

Kompilatory a interpretery

Kompilatory a interpretery
Aspekt Kompilator Interpretator
Zoptymalizowany dla Wydajność Zużycie pamięci
Szybkość wykonania Szybciej Wolniej
Zużycie pamięci Wyższy Niżej
Drugi magazyn Wymagany Opcjonalny
Sprawdzanie błędów Przed egzekucją Podczas egzekucji
Kod źródłowy Nie osadzony w pliku wykonywalnym Wymagane do wykonania

Pierwsza implementacja języka BASIC, Dartmouth BASIC , była kompilatorem. Ogólnie rzecz biorąc, kompilatory sprawdzają cały program w wieloetapowym procesie i tworzą drugi plik, który można bezpośrednio wykonać w podstawowym języku maszynowym komputera hosta bez odniesienia do kodu źródłowego. Kod ten często składa się z wywołań wstępnie napisanych procedur w systemie wykonawczym języka . Plik wykonywalny będzie zwykle mniejszy niż kod źródłowy, który go utworzył.

Główną wadą kompilatorów, przynajmniej w kontekście historycznym, jest to, że wymagają one dużej ilości pamięci tymczasowej. Podczas pracy kompilator generuje stale rosnący plik wyjściowy, który jest przechowywany w pamięci wraz z oryginalnym kodem źródłowym. Dodatkowa pamięć do tymczasowych wyszukiwań, zwłaszcza numerów linii w przypadku języka BASIC, zwiększa zapotrzebowanie na pamięć. Komputery tamtej epoki miały bardzo małą ilość pamięci; w nowoczesnych terminach typowy komputer mainframe może mieć około 64 KB. W systemie z podziałem czasu, jak w przypadku większości BASIC-ów z lat 60., ta pamięć była współdzielona przez wielu użytkowników.

Aby kompilator działał, systemy musiały być wyposażone w dodatkową pamięć masową o wysokiej wydajności , zazwyczaj w dysk twardy . Edycja programu odbywała się w dedykowanym środowisku, które zapisywało kod źródłowy użytkownika do pliku tymczasowego. Kiedy użytkownik uruchomił program, edytor wychodził i uruchamiał kompilator, który odczytywał ten plik i tworzył kod wykonywalny, a następnie kompilator wychodził i uruchamiał wynikowy program. Podział zadania w ten sposób zmniejszył ilość pamięci potrzebnej dowolnej części całego systemu BASIC; w dowolnym momencie trzeba było załadować tylko edytor, kompilator lub środowisko wykonawcze, reszta znajdowała się w pamięci.

Podczas gdy komputery typu mainframe miały niewielkie ilości pamięci, minikomputery miały jeszcze mniejsze ilości: systemy 4 i 8 KB były typowe w latach sześćdziesiątych. Ale co znacznie ważniejsze, minikomputery zwykle nie miały żadnej formy pamięci masowej o wysokiej wydajności; większość wczesnych projektów wykorzystywała taśmę perforowaną jako podstawowy system przechowywania, a systemy z taśmą magnetyczną były przeznaczone dla wyższej półki na rynku. W tym środowisku system, który napisałby źródło, skompilował je, a następnie uruchomił wynik, zająłby kilka minut. Z powodu tych ograniczeń mnożyły się tłumacze.

Tłumacze ostatecznie wykonują te same podstawowe zadania, co kompilatory, odczytując kod źródłowy i konwertując go na wykonywalne instrukcje wywołujące funkcje wykonawcze. Podstawowa różnica polega na tym, kiedy wykonują różne zadania. W przypadku kompilatora cały kod źródłowy jest konwertowany podczas czegoś, co wydaje się użytkownikowi jako pojedyncza operacja, podczas gdy interpreter konwertuje i uruchamia instrukcję źródłową pojedynczo. Wynikowy kod maszynowy jest wykonywany, a nie wyprowadzany, a następnie ten kod jest odrzucany, a proces powtarza się z następną instrukcją. Eliminuje to potrzebę jakiejś formy dodatkowej pamięci masowej podczas tworzenia pliku wykonywalnego. Podstawową wadą jest to, że nie można już rozdzielić różnych części całego procesu — kod potrzebny do przekształcenia źródła w operacje maszynowe musi zostać załadowany do pamięci wraz ze środowiskiem wykonawczym potrzebnym do jego wykonania, a w większości przypadków również edytor kodu źródłowego.

Stworzenie języka zawierającego wszystkie te komponenty, który mieści się w niewielkiej ilości pamięci i nadal ma miejsce na kod źródłowy użytkownika, jest dużym wyzwaniem, ale eliminuje potrzebę dodatkowej pamięci masowej i było jedynym praktycznym rozwiązaniem dla wczesnych minikomputerów i większości historia rewolucji komputerów domowych .

Rozwój

Projektowanie języka

Projektowanie języka dla pierwszych tłumaczy często polegało po prostu na odwoływaniu się do innych implementacji. Na przykład odniesienia Wozniaka do BASIC-a to podręcznik HP BASIC i kopia 101 BASIC Computer Games . Na podstawie tych źródeł Woźniak zaczął szkicować schemat składni języka. Nie wiedział, że BASIC HP bardzo różni się od odmiany DEC BASIC używanej w 101 grach . Te dwa języki różniły się głównie pod względem obsługi ciągów znaków i struktur kontrolnych. Data General Business Basic , implementacja zawierająca tylko liczby całkowite, była inspiracją dla Atari BASIC.

Z kolei Dennis Allison , członek wydziału informatyki na Uniwersytecie Stanforda , napisał specyfikację prostej wersji tego języka. Allison została zachęcona do stworzenia standardu przez Boba Albrechta z Homebrew Computer Club , który widział BASIC na minikomputerach i uznał, że będzie on idealnie pasował do nowych maszyn, takich jak Altair. Proponowany projekt Allison wykorzystywał tylko arytmetykę liczb całkowitych i nie obsługiwał tablic ani manipulacji łańcuchami. Celem było, aby program mieścił się w 2 do 3 kilobajtach pamięci. Ogólny projekt Tiny BASIC został opublikowany we wrześniowym numerze biuletynu People's Computer Company (PCC) z września 1975 roku.

Gramatyka jest wymieniona poniżej w formie Backusa – Naura . Na liście gwiazdka („ *”) oznacza zero lub więcej obiektu po lewej stronie — z wyjątkiem pierwszej gwiazdki w definicji „ term”, która jest operatorem mnożenia; obiekty grupowe nawiasów; a epsilon („ ε”) oznacza zbiór pusty. Jak zwykle w notacji gramatyki języka komputerowego, pionowa kreska („ |”) rozróżnia alternatywy, podobnie jak wypisanie w osobnych wierszach. Symbol " CR" oznacza powrót karetki .

    line ::= number statement CR | statement CR
 
    statement ::= PRINT expr-list
                  IF expression relop expression THEN statement
                  GOTO expression
                  INPUT var-list
                  LET var = expression
                  GOSUB expression
                  RETURN
                  CLEAR
                  LIST
                  RUN
                  END
 
    expr-list ::= (string|expression) (, (string|expression) )*
 
    var-list ::= var (, var)*
 
    expression ::= (+|-|ε) term ((+|-) term)*
 
    term ::= factor ((*|/) factor)*
 
    factor ::= var | number | (expression)
 
    var ::= A | B | C ... | Y | Z
 
    number ::= digit digit*
 
    digit ::= 0 | 1 | 2 | 3 | ... | 8 | 9
 
    relop ::= < (>|=) | > (<|=) | =

Ta składnia, chociaż była prosta, dodała jedną innowację: GOTOmogła GOSUBprzyjąć wyrażenie zamiast numeru linii, dostarczając przypisane GOTO zamiast instrukcji switch struktury ON-GOTO/GOSUBbardziej typowej dla języka BASIC.

Sinclair BASIC użył jako definicji języka minimalnego standardu BASIC American National Standards Institute (ANSI) z 1978 r., Ale sam był niekompletną implementacją tylko z arytmetyką liczb całkowitych. Standard ANSI został opublikowany po zaprojektowaniu pierwszej generacji tłumaczy dla mikrokomputerów.

Architektura

Wspólne komponenty interpretera języka BASIC:

  • Obsługa wejść/wyjść i przerwań
    • Klawiatura i ekran
    • Wejście/wyjście pliku (jeśli istnieje)
  • Procedury edycji
    • Wiersz poleceń
    • Edycja i przechowywanie programów
  • Procedury wykonawcze
    • Analiza i interpretacja
    • Pakiet arytmetyczny
    • Zarządzanie pamięcią
      • Tabela symboli (jeśli istnieje)
      • Wywóz śmieci (jeśli istnieje)

Kodowanie

We wczesnych mikrokomputerach brakowało narzędzi programistycznych, a programiści opracowywali swój kod na minikomputerach lub ręcznie. Na przykład Dick Whipple i John Arnold napisali Tiny BASIC Extended bezpośrednio w kodzie maszynowym, używając ósemkowych plików . Robert Uiterwyk napisał odręcznie MICRO BASIC dla SWTPC ( system 6800 ) na notatniku. Steve Wozniak ręcznie napisał kod do Integer BASIC , tłumacząc instrukcje kodu asemblera na ich odpowiedniki w kodzie maszynowym , a następnie przesyłając wynik do swojego komputera. (Z tego powodu program był bardzo trudny do zmiany, a Wozniak nie był w stanie zmodyfikować go wystarczająco szybko dla Steve'a Jobsa , który następnie licencjonował BASIC od Microsoft.)

Gates i Allen nie mieli systemu Altair, na którym mogliby opracować i przetestować swojego tłumacza. Jednak Allen napisał emulator Intel 8008 dla swojego poprzedniego przedsięwzięcia, Traf-O-Data , który działał na komputerze z podziałem czasu PDP-10 . Allen zaadaptował ten emulator w oparciu o przewodnik programisty Altair, a także opracowali i przetestowali interpreter na PDP-10 firmy Harvard. Kiedy Harvard zaprzestał korzystania z tego systemu, Gates i Allen kupili czas komputerowy od usługi współdzielenia czasu w Bostonie, aby dokończyć debugowanie programu BASIC. Gates twierdził w swoim liście otwartym do hobbystów z 1976 roku, że wartość czasu komputerowego w pierwszym roku tworzenia oprogramowania wynosiła 40 000 dolarów.

Nie żeby Allen nie potrafił ręcznie kodować w języku maszynowym. Podczas ostatniego podejścia do lotniska Albuquerque w celu zademonstrowania tłumacza, Allen zdał sobie sprawę, że zapomniał napisać programu ładującego , który wczytałby taśmę do pamięci. Pisząc w języku maszynowym 8080, Allen zakończył program przed lądowaniem samolotu. Dopiero gdy załadował program na Altaira i zobaczył monit z pytaniem o rozmiar pamięci systemowej, wiedział, że interpreter pracował na sprzęcie Altaira.

Jedną z najpopularniejszych wersji Tiny BASIC był Palo Alto Tiny BASIC, w skrócie PATB. PATB po raz pierwszy pojawił się w wydaniu Dr. Dobbs z maja 1976 roku , napisanym w niestandardowym języku asemblera z niestandardowymi mnemonikami. Li-Chen Wang zakodował swojego tłumacza w systemie podziału czasu z ogólnym asemblerem.

Jedynym wyjątkiem od użycia asemblera było użycie ALGOL 60 dla interpretera Paisley XBASIC dla dużych systemów Burroughsa . Innym wyjątkiem i programem do wpisywania był Classic BASIC, napisany przez Lennarta Benschopa w Forth i opublikowany w holenderskim czasopiśmie Forth Vijgeblad (nr 42, 1993).

Kod źródłowy interpreterów był często open source (jak w przypadku Tiny BASIC) lub publikowany później przez autorów. Kompletny kod źródłowy z adnotacjami i specyfikacje projektowe Atari BASIC zostały opublikowane jako The Atari BASIC Source Book w 1983 roku.

Wirtualne maszyny

Niektóre interpretery języka BASIC zostały zakodowane w pośredniej reprezentacji maszyny wirtualnej , aby dodać warstwę abstrakcji i zwięzłości ponad natywny język maszynowy .

Maszyny wirtualne w wybitnych interpretatorach języka BASIC
Dialekt języka BASIC Język maszyny wirtualnej Natywna maszyna
Mały PODSTAWOWY Tiny BASIC Intermediate Language (TBIL) 6800
NIBL Język średniozaawansowany (IL) SC/MP
TI PODSTAWOWE Język programowania grafiki (GPL) TMS9900

Podczas gdy maszyny wirtualne były używane w systemach kompilacji i go, takich jak BASIC-PLUS , służyły one tylko do wykonywania kodu BASIC, a nie do jego analizowania. Z kolei Tiny BASIC został zaprojektowany do implementacji jako maszyna wirtualna, która analizowała i wykonywała (interpretowała) instrukcje BASIC; w takiej implementacji interpreter Tiny BASIC sam działa na interpreterze maszyny wirtualnej. Długość całego programu interpretera wynosiła zaledwie 120 operacji maszyny wirtualnej, składających się z 32 poleceń. W ten sposób wybór podejścia do maszyny wirtualnej pozwolił oszczędzić miejsce w pamięci i nakład pracy na implementację, chociaż uruchamiane na niej programy BASIC były wykonywane nieco wolno. (Zobacz Tiny BASIC: Implementacja na maszynie wirtualnej, aby zapoznać się z fragmentem i przykładowymi poleceniami). Chociaż intencją projektową było, aby Tiny BASIC korzystał z maszyny wirtualnej, nie każda implementacja to robiła; te, które to zrobiły, obejmowały Tiny BASIC Extended, 6800 Tiny BASIC i NIBL.

Dla swojego TI-99 firma Texas Instruments zaprojektowała maszynę wirtualną z językiem o nazwie GPL dla „Graphic Programming Language”. (Chociaż powszechnie obwiniano go za niską wydajność TI-BASIC-a , część problemu polegała na tym, że maszyna wirtualna była przechowywana w graficznej pamięci ROM, która miała powolny 8-bitowy interfejs).

Niezrozumienie ROMów Apple II doprowadziło niektórych do przekonania, że ​​Integer BASIC używa maszyny wirtualnej, niestandardowego języka asemblera zawartego w ROMach Apple i znanego jako SWEET16 . SWEET16 jest oparty na kodach bajtowych , które działają w prostej 16-bitowej maszynie wirtualnej, więc pamięć może być adresowana za pomocą pośrednich 16-bitowych wskaźników i 16-bitowych funkcji matematycznych obliczanych bez konieczności tłumaczenia ich na podstawową wieloinstrukcyjną 8-bitową 6502 kod. Jednak SWEET16 nie był używany przez podstawowy kod BASIC, chociaż był później używany do implementacji kilku narzędzi, takich jak procedura zmiany numeracji linii.

Edycja i przechowywanie programów

Edycja programu

Większość implementacji języka BASIC tamtej epoki działała zarówno jako tłumacz języka, jak i edytor liniowy . Gdy BASIC był uruchomiony, wyświetlał się > wiersz polecenia , w którym użytkownik mógł wprowadzać instrukcje. Było to znane jako „ tryb bezpośredni ”. Po uruchomieniu interpreter języka BASIC domyślnie przełączał się w tryb bezpośredni.

Instrukcje, które zostały wprowadzone z numerami wiodącymi, są wprowadzane do pamięci programu w celu „odroczonego wykonania”, albo jako nowe wiersze, albo zastępując te, które mogły mieć ten sam numer poprzednio. Instrukcje wprowadzone bez numeru wiersza były nazywane poleceniami i były uruchamiane natychmiast. Numery wierszy bez instrukcji (tj. po których następuje powrót karetki ) usuwają poprzednio zachowaną linię.

Gdy program był obecny w pamięci i użytkownik wpisze polecenie RUN, system przechodzi w „tryb pośredni”. W tym trybie wskaźnik jest ustawiony tak, aby wskazywał pierwszą linię programu, na przykład linię 10. Oryginalny tekst dla tej linii jest następnie pobierany z magazynu i uruchamiany tak, jakby użytkownik właśnie wpisał go w trybie bezpośrednim. Następnie wskaźnik przechodzi do następnej linii i proces jest kontynuowany.

Różne implementacje oferowały inne możliwości edycji programów. Altair BASIC 8K miał EDITpolecenie przejścia w tryb edycji dla jednej linii. Integer BASIC zawierał również AUTOpolecenie automatycznego wprowadzania numerów linii przy danym numerze początkowym, np AUTO 100. , dodając 10 do ostatniej liczby z każdą nową linią. AUTO 300,5zacząłby numerację w wierszu 300 od piątek; 300, 305 itd. Automatyczne numerowanie zostało wyłączone przez wprowadzenie MAN. Niektórzy tłumacze oferowali polecenia lub narzędzia do zmiany numeracji linii.

Tokenizacja i kodowanie linii

Aby zaoszczędzić pamięć RAM i przyspieszyć wykonywanie, wszystkie interpretery języka BASIC kodowałyby niektóre znaki ASCII linii w inne reprezentacje. Na przykład numery wierszy zostały przekonwertowane na liczby całkowite przechowywane jako bajty lub słowa , a słowom kluczowym można przypisać tokeny jednobajtowe (na przykład przechowywanie PRINTjako wartość bajtu 145 w MS-BASIC). Te reprezentacje byłyby następnie konwertowane z powrotem na czytelny tekst podczas LISTuruchamiania programu.

Kodowanie i tokenizacja w wybitnych interpretatorach języka BASIC
Dialekt języka BASIC Numery linii Słowa kluczowe Stałe numeryczne Nazwy zmiennych
Mały PODSTAWOWY Tak NIE NIE NIE
Altair BASIC Tak Tak NIE NIE
PODSTAWOWE liczby całkowite Tak Tak Tak NIE
Atari BASIC Tak Tak Tak Tak

Skróty

Jako alternatywę dla tokenizacji, aby zaoszczędzić pamięć RAM, wczesne implementacje Tiny BASIC, takie jak Extended Tiny BASIC, Denver Tiny BASIC i MINOL, obcięły słowa kluczowe: PRfor PRINT, INfor INPUT, RETfor RETURN. Pełne, tradycyjne słowa kluczowe nie zostały zaakceptowane.

W przeciwieństwie do tego Palo Alto Tiny BASIC akceptował tradycyjne słowa kluczowe, ale pozwalał na skracanie dowolnego słowa kluczowego do minimalnego unikalnego ciągu z kropką końcową. Na przykład PRINTmożna wpisać P., chociaż PR.i inne odmiany również działały. Ten system został zachowany w Level I BASIC dla TRS-80 , który używał PATB, a także został znaleziony w Atari BASIC i BASIC różnych komputerów kieszonkowych Sharp .

Aby rozwinąć skrót, tokenizer Atari BASIC przeszukuje swoją listę zarezerwowanych słów, aby znaleźć pierwsze, które pasuje do dostarczonej części. Częściej używane polecenia pojawiają się na początku listy słów zastrzeżonych, z REMpoczątkiem (można je wpisać jako .). Kiedy program jest później LISTedytowany, zwykle wypisze pełne słowa. MS BASIC dopuszczał również ?jako skrót dla PRINT, ale rozszerzał go podczas wyświetlania, traktując go jako skrót, a nie synonim.

Tokenizacja

Większość interpreterów BASIC-a wykonuje przynajmniej część konwersji z oryginalnej formy tekstowej na różne formaty specyficzne dla platformy. Tiny BASIC był prosty: konwertował tylko numer linii z formatu dziesiętnego na binarny. Na przykład numer wiersza „100” stał się wartością jednobajtową, 64 USD, dzięki czemu jest mniejszy do przechowywania w pamięci, a także łatwiejszy do wyszukiwania w kodzie maszynowym ( kilka projektów Tiny BASIC dozwolonych numerów linii tylko od 1 do 254 lub 255, chociaż większość używa wartości dwubajtowych i numerów linii co najmniej od 1 do 999). Resztę wiersza pozostawiono w oryginalnym formacie tekstowym. W rzeczywistości Dennis Allison argumentował, że biorąc pod uwagę ograniczenia pamięci, implementacja tokenizacji wymagałaby więcej kodu niż zaoszczędziłaby.

MS-BASIC poszedł nieco dalej, konwertując numer linii na wartość dwubajtową, a także konwertując słowa kluczowe, takie jak FORlub PRINT, na wartość jednobajtową, „token”. Wartość tokena miała ustawiony wysoki bit, aby umożliwić ich łatwe rozróżnienie w czasie wykonywania. Wszystko inne w wierszu pozostawiono w oryginalnym formacie, więc na przykład wiersz:

 10 FOR I=1 TO 10

byłby tokenizowany jako:

 $64$81 I$B211$A410

Zauważ, że spacja pomiędzy FORi Ipozostaje w tokenizowanym wierszu, a nazwy zmiennych i stałe nie są tokenizowane. Kod, który wykonał tę tokenizację, znany jako „chunker”, po prostu skopiował wszystko, czego nie rozpoznał jako token z powrotem do wyjścia, zachowując spacje bez zmian. Oznaczało to, że PRINTAbył przechowywany w dwóch bajtach, podczas gdy PRINT Abył przechowywany w trzech bajtach, a usuwanie spacji było powszechnym sposobem poprawy wykorzystania pamięci. Sinclair BASIC nieznacznie to zmodyfikował, usuwając spacje z przechowywanego kodu i wstawiając je do kodu podczas LIST, tak aby PRINTAnie PRINT Azajmował jeszcze dodatkowego bajtu w pamięci.

W przeciwieństwie do Integer BASIC przekształciłby linię 10 GOTO 100całkowicie w tokeny, które można by natychmiast odczytać i wykonać. W MS-BASIC linia generowałaby $64 $89 100, aw czasie wykonywania „100” musiałoby zostać przekonwertowane na format 16-bitowy za każdym razem, gdy zostało napotkane. W przeciwieństwie do Integer BASIC również tokenizował zmienne numeryczne, unikając tej konwersji i przyspieszając wykonanie. Wynikowa wartość dwubajtowa została wstawiona do tokenizowanego kodu wraz z bajtem prefiksu wskazującym następującą liczbę. Prefiks był wartością z zakresu od $B0 do $B9 , przy czym ostatni półbajt wartości był pierwszą cyfrą dziesiętną oryginalnej wartości. Literały łańcuchowe, takie jak „HELLO WORLD”, zostały zamiast tego zakodowane przez ustawienie wysokiego bitu każdego znaku, tak aby Abył przechowywany jako $C1 . Nazwy zmiennych zostały przekonwertowane w ten sam sposób, z zakodowanymi literami w celu włączenia ich wysokiego bitu i wszystkimi cyframi w nazwie reprezentowanymi przez odpowiednie $ B0 do $B9 , tak aby zmienna A5została zakodowana jako $C1B5 (nie zredukowany do tokena). Było wiele innych optymalizacji; gdzie Microsoft BASIC miał jeden token dla słowa kluczowego PRINT, Integer BASIC miał trzy tokeny: jeden, jeśli po słowie kluczowym nie występowały żadne argumenty, jeden, jeśli po nim następowało wyrażenie arytmetyczne, i jeden, jeśli po nim następował literał łańcuchowy.

Idąc jeszcze dalej, tokenizer Atari BASIC analizuje całą linię, gdy jest wprowadzana lub modyfikowana. Stałe numeryczne są analizowane do ich 48-bitowej postaci wewnętrznej, a następnie umieszczane w wierszu w tym formacie, podczas gdy ciągi znaków pozostawia się w ich oryginalnym formacie, ale poprzedzone bajtem opisującym ich długość. Pamięć dla zmiennych jest odkładana w miarę ich napotykania, a nie w czasie wykonywania, a ich nazwa jest zastępowana wskaźnikiem do miejsca ich przechowywania w pamięci. Shepardson odniósł się do tej wczesnej koncepcji tokenizacji jako „tłumacza prekompilującego”; instrukcje z błędami składniowymi nie mogły być faktycznie przechowywane, a użytkownik był natychmiast proszony o ich poprawienie.

Tokenizacja przy klawiaturze

Klawiatura Sinclair ZX Spectrum
Kombinacje klawiszy służą do wprowadzania słów kluczowych w języku BASIC.

Niektóre interpretery, takie jak systemy Sinclair, zasadniczo kazały użytkownikowi wykonać tokenizację, zapewniając specjalne naciśnięcia klawiszy w celu wprowadzenia zastrzeżonych słów. Najpopularniejsze polecenia wymagają tylko jednego naciśnięcia klawisza; na przykład naciśnięcie tylko Pna początku linii w Spectrum daje pełne polecenie PRINT. Rzadsze polecenia wymagają bardziej złożonych sekwencji klawiszy. Ponieważ każdy wiersz zaczyna się od słowa kluczowego, LETnie jest opcjonalny, po wpisaniu słowa kluczowego system powraca do akceptowania tekstu znak po znaku. Jedną z zalet tego podejścia jest to, że tokenizer nie może mylić ciągów znaków ze słowami kluczowymi. Na przykład pozwala nazwać zmienną PRINTi wyprowadzić jej wartość za pomocą PRINT PRINT.

Wiele „ komputerów kieszonkowych ” podobnie używa jednego naciśnięcia klawisza (czasami poprzedzonego różnymi rodzajami klawiszy Shift) do wytworzenia jednego bajtu (token słowa kluczowego), który reprezentuje całe słowo kluczowe BASIC, takie jak EXP, SQR, IF lub PEEK , takie jak Sharp pocket komputerowe zestawy znaków i TI-BASIC . Rozszerzenie BASIC dla Bally Astrocade również tego używa.

Zarządzanie linią

Prawidłowe numery linii we wczesnych implementacjach języka BASIC
Zakres Dialekt
od 1 do 254 MINOL
od 1 do 255 Mała uwaga projektowa BASIC
od 2 do 255 Denver Tiny BASIC
od 0 do 999 UIUC PODSTAWOWE
1 do 2045 DEC BASIC-8
od 0 do 32767 LLL BASIC, NIBL
1 do 32767 Apple I BASIC , Level I BASIC , Palo Alto Tiny BASIC
1 do 65535 Altair 4K BASIC , MICRO BASIC 1.3, 6800 Tiny BASIC, Tiny BASIC rozszerzony
od 1 do 99999 Dartmouth BASIC
od 1 do 999999 SCELBAL

Prawidłowe numery wierszy różniły się w zależności od implementacji, ale zazwyczaj wynosiły od 1 do 32767.

Większość pamięci używanej przez interpretery języka BASIC służyła do przechowywania samej listy programów. Instrukcje numerowane były przechowywane w porządku sekwencyjnym w rzadkiej tablicy zaimplementowanej jako zbiór liniowy (technicznie nie jest to lista , ponieważ żaden numer wiersza nie mógł wystąpić więcej niż raz).

Wiele implementacji Tiny BASIC zawierało wiersze w następujący sposób:

  • Binarny odpowiednik numeru linii (jeden lub dwa bajty, w zależności od obsługiwanego zakresu prawidłowych numerów linii)
  • Instrukcja źródłowa ASCII (zmienna długość)
  • Powrót karetki (jeden bajt, ustawiony na 13)

Microsoft BASIC, począwszy od Altair BASIC, przechowywał wiersze w następujący sposób:

  • Wskaźnik do następnej linii (dwa bajty)
  • Binarny odpowiednik numeru linii (dwa bajty, bez znaku)
  • Tokenizowana instrukcja źródłowa (zmienna długość)
  • Null (jeden bajt, ustawiony na 0)

LLL PODSTAWOWE:

  • Binarny odpowiednik numeru linii (dwa bajty)
  • Wskaźnik do przodu do następnej linii w sekwencji (dwa bajty)
  • Długość instrukcji źródłowej ASCII (jeden bajt)
  • Instrukcja źródłowa ASCII (zmienna długość)

Maksymalna długość linii była zróżnicowana: 64 znaki w Palo Alto Tiny BASIC, w tym dziesiętna reprezentacja numeru linii; 120 znaków w Atari BASIC; 128 znaków w Integer BASIC; i 255 znaków w MS-BASIC (nie licząc numeru linii).

Tłumacze przeszukiwali program wiersz po wierszu, patrząc na każdy numer wiersza. Gdyby był niższy niż numer nowej linii, późniejsze linie zostałyby przeniesione do pamięci, aby zrobić miejsce na miejsce wymagane dla nowej linii. Gdyby był to ten sam numer linii, a nie dokładnie taka sama długość, kolejne linie musiałyby zostać przesunięte do przodu lub do tyłu. (Ponieważ kolejność sekwencyjna była zawsze zachowywana w pamięci, nie były to listy połączone ).

W Tiny BASIC te wyszukiwania wymagały sprawdzania każdego bajtu w wierszu: wskaźnik był zwiększany raz po raz, aż do napotkania powrotu karetki, aby znaleźć bajt przed następnym wierszem. Z drugiej strony w Altair BASIC i LLL BASIC wskaźnik byłby zamiast tego ustawiony na początek następnej linii sekwencyjnej; było to znacznie szybsze, ale wymagało dwóch bajtów na linię. Biorąc pod uwagę, że zakładano, że programy Tiny BASIC mają rozmiar 4 KB lub mniejszy, było to zgodne z ogólną filozofią projektowania Tiny BASIC polegającą na kompromisie wydajności na rzecz minimalizacji zużycia pamięci.

Gdy użytkownik wpisał LISTw wierszu poleceń, system zapętlił tablicę wierszy, używając jednej z tych metod, przekonwertował numer wiersza z powrotem na format dziesiętny, a następnie wydrukował resztę tekstu w wierszu, dekodując wszelkie tokeny lub inne zakodowane reprezentacje.

Gdy programiści dodawali strukturalne konstrukcje programistyczne do BASIC-a, często całkowicie eliminowali potrzebę numerowania linii i dodawali edytory tekstu , a później zintegrowane środowiska programistyczne .

Zmienne i typy danych

Nazwy zmiennych

Dartmouth BASIC i HP-BASIC ograniczały nazwy zmiennych do maksymalnie dwóch znaków (albo pojedyncza litera, albo litera, po której następuje jedna cyfra, np. od A do Z9). MS-BASIC zezwalał na nazwy zmiennych składające się z litery, po której następuje opcjonalna litera lub cyfra (np. A do ZZ), ale ignorował kolejne znaki: w ten sposób można było przypadkowo napisać program ze zmiennymi „STRATA” i „LOAN”, który byłby traktowane jako to samo; przypisanie wartości do „LOAN” po cichu nadpisałoby wartość zamierzoną jako „STRATA”.

Integer BASIC był niezwykły w obsłudze nazw zmiennych o dowolnej długości (np. SUM, GAMEPOINTS, PLAYER2), pod warunkiem, że nie zawierał zarezerwowanego słowa. Słowa kluczowe nie mogły być używane w zmiennych w wielu wczesnych językach BASIC; „SCORE” będzie interpretowane jako „SC” LUB „E”, gdzie OR jest słowem kluczowym.

Zmienne łańcuchowe są zwykle rozróżniane w wielu mikrokomputerowych dialektach BASIC-a przez dodanie do ich nazwy sufiksu $ , a wartości są często identyfikowane jako ciągi znaków przez oddzielenie „podwójnych cudzysłowów”. Późniejsze implementacje użyłyby innych znaków interpunkcyjnych do określenia typu zmiennej: A% dla liczby całkowitej, A! dla pojedynczej precyzji i A# dla podwójnej precyzji .

Z wyjątkiem tablic i (w niektórych implementacjach) ciągów znaków, w przeciwieństwie do Pascala i innych bardziej strukturalnych języków programowania, BASIC nie wymaga deklarowania zmiennej przed odwołaniem. Wartości będą zazwyczaj domyślnie ustawione na 0 (z odpowiednią precyzją) lub ciąg pusty.

Tabela symboli

Ponieważ Tiny BASIC używał tylko 26 jednoliterowych zmiennych, zmienne można było przechowywać jako tablicę bez przechowywania odpowiadających im nazw, używając formuły opartej na wartości ASCII litery jako indeksu. Palo Alto Tiny BASIC poszedł o krok dalej: zmienne „wartości dwubajtowe były umieszczane w pamięci RAM w programie, od bajtów 130 (ASCII 65, „A”, razy dwa) do 181 (ASCII 90, „Z”, razy dwa , plus jeden dla drugiego bajtu).

Większość języków BASIC zapewniała możliwość posiadania znacznie więcej niż 26 zmiennych i tak potrzebnych tablic symboli , które zarezerwowałyby miejsce na przechowywanie tylko tych używanych zmiennych.

W LLL BASIC każdy wpis w tablicy symboli był przechowywany w następujący sposób:

  • Nazwa zmiennej (bajt 1: litera ASCII; bajt 2: 0-9 ASCII lub binarne 0)
  • Wskaźnik do przodu (2 bajty)
  • Wartość (4 bajty na element, 1 element w przypadku zmiennej skalarnej, w przeciwnym razie tyle elementów, ile wynosi DIMensioned dla tablicy)

W przeciwieństwie do większości interpreterów BASIC-a, UIUC BASIC miał funkcję haszującą , haszującą według litery nazwy zmiennej/funkcji/tablicy, a następnie przeprowadzającą stamtąd wyszukiwanie liniowe. W UIUC BASIC wpis w tablicy symboli wyglądał następująco:

  • Flaga (bit 0: pozycja w użyciu; bit 6: funkcja zdefiniowana przez użytkownika; bit 7: tablica}
  • Nazwa zmiennej (bajt 1: litera ASCII; bajt: 0-9 ASCII, " " lub "(") lub nazwa funkcji (bajt 1: litera ASCII lub token 154 dla ; FNlitera ASCII)
  • Wartość (5 bajtów):
    • Wartość zmiennoprzecinkowa dla skalara
    • Definicja tablicy (ostatnie 3 bajty: górny wymiar pierwszego, drugiego, trzeciego wymiaru, zakłada się, że wszystkie zaczynają się od 0)
    • Funkcja użytkownika (pierwsze 2 bajty z adresem funkcji; bajt 3 to przesunięcie tablicy symboli do parametru zmiennej fikcyjnej w definicji funkcji).

W Atari BASIC zestaw wskaźników (adresów) wskazywał różne dane: nazwy zmiennych były przechowywane w tablicy nazw zmiennych (VNTP – 82, 83 16 ), a ich wartości w tablicy wartości zmiennych (wskazywane na VVTP – 86, 87 16 ). Pośrednicząc w nazwach zmiennych w ten sposób, odwołanie do zmiennej wymagało tylko jednego bajtu, aby zaadresować jego wpis do odpowiedniej tabeli. Zmienne łańcuchowe miały swój własny obszar.

Jedna optymalizacja wydajności BBC BASIC obejmowała użycie wielu połączonych list do wyszukiwania zmiennych zamiast jednej długiej listy, jak w Microsoft BASIC .

Zarządzanie pamięcią

Ze względu na małą pojemność pamięci RAM większości systemów pierwotnie używanych do uruchamiania interpreterów języka BASIC, konieczne było zastosowanie sprytnych technik zarządzania pamięcią. Altair BASIC pozwolił użytkownikom odzyskać miejsce na funkcje trygonometrii, jeśli nie były one używane podczas sesji. PATB umieścił początek najpopularniejszych podprogramów na początku programu do użytku przez 1-bajtowy RSTkod operacji 8080 zamiast 3-bajtowego CALLkodu operacji. W LLL BASIC niektóre zmienne zajmowały te same lokalizacje pamięci, w przypadkach, gdy różne zmienne były używane tylko w trybie poleceń lub tylko w czasie wykonywania.

Wideo było często adresowalne w pamięci, a niektóre ezoteryczne funkcje były dostępne poprzez manipulowanie wartościami przy określonych wartościach pamięci. Na przykład adresy od 32 do 35 zawierały wymiary okna tekstowego (w przeciwieństwie do okna graficznego) w Applesoft BASIC. Polecenie POKEi PEEKfunkcja (zaadaptowane z monitorów kodu maszynowego, takich jak monitor DECsystem-10 ) zapewniały bezpośredni dostęp do pamięci do różnych celów, zwłaszcza do modyfikowania specjalnych rejestrów sprzętowych mapowanych w pamięci w celu sterowania określonymi funkcjami komputera, takimi jak wejście /wyjściowe urządzenia peryferyjne. „Mapy pamięci” (w archaicznym sensie list adresów pamięci i ich funkcji) były popularne w PEEK i POKE , a jedną z najbardziej znanych map pamięci była książka Mapping the Atari , napisana przez Iana Chadwicka.

Niektóre implementacje interpretera firmy Microsoft, na przykład te działające na TRS-80 Modele I/III, wymagały od użytkownika określenia ilości pamięci używanej przez tłumacza. Miało to pozwolić na zarezerwowanie obszaru pamięci na instalację podprogramów języka maszynowego, które mogłyby być wywoływane przez interpretowany program, w celu zwiększenia szybkości wykonywania. Gdy modele I/III są włączone, użytkownik jest witany komunikatem „Rozmiar pamięci?” w tym celu.

Matematyka

Integer BASIC, jak sama nazwa wskazuje, używa liczb całkowitych jako podstawy swojego pakietu matematycznego. Były one przechowywane wewnętrznie jako liczba 16-bitowa, little-endian (podobnie jak 6502). Pozwoliło to na uzyskanie maksymalnej wartości dla dowolnego obliczenia z zakresu od -32767 do 32767. Obliczenia, które dały wartości spoza tego zakresu, spowodowały błąd.

Większość interpreterów Tiny BASIC (a także Sinclair BASIC 4K) obsługiwała matematykę tylko przy użyciu liczb całkowitych, bez obsługi zmiennoprzecinkowej . Używanie liczb całkowitych umożliwiło przechowywanie liczb w znacznie bardziej zwartym formacie 16-bitowym, który można było szybciej odczytywać i przetwarzać niż 32- lub 40-bitowe formaty zmiennoprzecinkowe, które można było znaleźć w większości języków BASIC tamtej epoki. Ograniczało to jednak jego zastosowanie jako języka ogólnego przeznaczenia.

Implementacje Business BASIC , takie jak Data General Business Basic , były również oparte wyłącznie na liczbach całkowitych, ale zazwyczaj miały wyższą precyzję: „podwójnej precyzji”, tj . ^ 14).

Czasami używano innych formatów liczb komputerowych . Na przykład MINOL Tiny BASIC obsługiwał tylko bajty bez znaku , a MICRO-BASIC Tiny BASIC używał kodu dziesiętnego binarnego . Ale zmiennoprzecinkowy zacząłby dominować.

Zmiennoprzecinkowy

Jedna historia podsumowuje, dlaczego zmiennoprzecinkowe uznano za tak ważne. Na oryginalnym prototypie modelu TRS-80 uruchomiłem wersję Tiny BASIC należącą do domeny publicznej autorstwa Li-Chen Wanga . Wymagało to tylko 2 KB pamięci dla interpretera , pozostawiając średnio kolejne 2 KB wolnego miejsca dla programów użytkownika w typowych układach pamięci 4 KB wczesnych maszyn. Podczas demonstracji dla kadry kierowniczej ówczesny prezes Tandy Corporation , Charles Tandy, próbował wprowadzić swoją pensję, ale nie był w stanie tego zrobić. Stało się tak, ponieważ Tiny BASIC używał 2-bajtowych liczb całkowitych ze znakiem o maksymalnej wartości 32 767. Rezultatem była prośba o matematykę zmiennoprzecinkową dla wersji produkcyjnej. Doprowadziło to do zastąpienia istniejącego 16-bitowego kodu liczb całkowitych wersją wykorzystującą 32-bitowe liczby zmiennoprzecinkowe o pojedynczej precyzji przez pracownika Tandy, Steve'a Leiningera.

SCELBAL używał procedur zmiennoprzecinkowych opublikowanych przez Wadswortha w 1975 roku w Machine Language Programming dla 8008 w oparciu o format 32-bitowy (czterobajtowy) do obliczeń numerycznych, z 23-bitową mantysą , 1-bitowym znakiem mantysy, 7- wykładnik bitowy i znak 1-bitowy dla wykładnika. Zostały one zorganizowane w odwrotnej kolejności, z najmniej znaczącym bajtem mantysy w pierwszym bajcie, po którym następował środkowy, a następnie najbardziej znaczący bajt ze znakiem w górnym bicie. Wykładnik był ostatni, znowu ze znakiem w wysokim bicie. Podręcznik zawiera dobrze udokumentowany kod asemblera dla całego pakietu matematycznego, w tym punkty wejścia i uwagi dotyczące użytkowania.

Konsultanci byli zazwyczaj zatrudniani do obsługi arytmetyki zmiennoprzecinkowej , specjalistycznej dziedziny dobrze zbadanej i opracowanej dla zastosowań naukowych i komercyjnych, które charakteryzowały komputery typu mainframe. Kiedy Allen i Gates pracowali nad Altair BASIC, inny student Harvardu, Monte Davidoff, przekonał ich do przejścia z arytmetyki liczb całkowitych . Zatrudnili Davidoffa do napisania pakietu zmiennoprzecinkowego, który nadal mieściłby się w granicach 4 KB pamięci. Steve Wozniak zwrócił się do Roya Rankina z Uniwersytetu Stanforda o zaimplementowanie funkcji transcendentalnych LOG, LOG10 i EXP; jednak Woźniak nigdy nie skończył dodawać obsługi zmiennoprzecinkowej do Integer BASIC. LLL BASIC , opracowany na University of Idaho przez Johna Dickensona, Jerry'ego Barbera i Johna Teetera, zwrócił się do Davida Meada, Hala Branda i Franka Olkena o wsparcie zmiennoprzecinkowe. Dla UIUC BASIC licencjonowano pakiet zmiennoprzecinkowy Datapoint 2200 .

Z kolei systemy z podziałem czasu często opierały się na sprzęcie. Na przykład GE-235 został wybrany do wdrożenia pierwszej wersji Dartmouth BASIC, ponieważ zawierał „ pomocniczą jednostkę arytmetyczną ” do obliczeń zmiennoprzecinkowych i podwójnej precyzji.

Wczesne interpretery używały formatów 32-bitowych, podobnych do binarnego formatu zmiennoprzecinkowego pojedynczej precyzji IEEE 754 , który określa:

Oto wartość 0,15625 przechowywana w tym formacie: Pływający przykład.svg

Podczas gdy formaty 32-bitowe były powszechne w tamtej epoce, późniejsze wersje języka BASIC, począwszy od Microsoft BASIC dla MOS 6502 , generalnie przyjęły format 40-bitowy (pięciobajtowy) w celu zwiększenia precyzji.

Operatory i funkcje

Operatory infiksowe zazwyczaj obejmowały +(dodawanie), -(odejmowanie), *(mnożenie), /(dzielenie) i wykładnik przy użyciu ^znaku. Względne operacje obejmowały standardowy zestaw =, >, <, >=, <=i dla „nierówne” <>albo inspirowane HP-TSB# . Operatory binarne, takie jak AND, ORi NOT, nie występowały w każdej implementacji, a niektóre wykonywały algebrę Boole'a , a inne nie.

Początkowa edycja Dartmouth BASIC zawierała następujące funkcje: ABS( wartość bezwzględna ), ATN( arcus tangens ), COS( cosinus ), EXP( e podniesione do potęgi ), INT( obcięcie dowolnej wartości ułamkowej, zwrócenie liczby całkowitej ), LOG( logarytm ), RND( generator liczb pseudolosowych ) , SIN( sinus ), SQR( pierwiastek kwadratowy ) i TAN( tangens ). Zawierał również DEF FNinstrukcję deklarowania funkcji jednowierszowych, które następnie byłyby określane jako FNA(), FNB(), itd.

Ta RNDfunkcja była najbardziej rozpowszechnioną funkcją obsługiwaną we wczesnych językach BASIC, chociaż implementacje były różne:

  • Dartmouth RNDignorował ten parametr i zawsze zwracał nową liczbę pseudolosową z przedziału od 0 do 1.
  • Altair BASIC i późniejsze Microsoft BASIC używały znaku parametru: Dla RND (X), „X <0 rozpoczyna nową sekwencję liczb losowych za pomocą X. Wywołanie RND z tym samym X rozpoczyna tę samą sekwencję liczb losowych. X = 0 daje ostatnia wygenerowana liczba losowa”.
  • Nie mogąc zwrócić liczby dziesiętnej, języki BASIC zawierające tylko liczby całkowite zamiast tego używały wartości parametru, zwykle w celu określenia górnej granicy randomizacji; na przykład w samym Integer BASIC RND(6)+1symulowałby rzut kostką, zwracając wartości od 1 do 6.
  • W przeciwieństwie do tego, w niektórych TRS-80 BASIC parametrem była górna granica, którą można było zwrócić; na przykład RND(6)zwróci wartość od 1 do 6 i RND(1)zawsze zwróci 1.

Tablice

Druga wersja Dartmouth BASIC obsługiwała macierze i operacje na macierzach , przydatne do rozwiązywania zbiorów równoczesnych liniowych równań algebraicznych; MATobsługiwane były operacje macierzowe, takie jak przypisywanie, dodawanie, mnożenie (kompatybilnych typów macierzy) i ocena wyznacznika.

W przeciwieństwie do tego Tiny BASIC, zgodnie z pierwotnym projektem, nie miał nawet żadnych tablic, ze względu na ograniczoną pamięć główną dostępną we wczesnych mikrokomputerach , często 4 KB, która musiała zawierać zarówno interpreter, jak i program BASIC. Palo Alto Tiny BASIC dodał pojedynczą tablicę liczb całkowitych o zmiennej długości , której rozmiar nie musiał być wymiarowany, ale wykorzystywał pamięć RAM nieużywaną przez tłumacza ani listę programów, A().

SCELBAL obsługiwał wiele tablic, ale razem te tablice mogły zawierać nie więcej niż 64 elementy. Obsługiwane przez Integer BASIC tablice o jednym wymiarze, ograniczone jedynie dostępną pamięcią. Tiny BASIC Extended obsługiwał dwuwymiarowe tablice do 255 na 255. Altair BASIC 4K obsługiwał tylko tablice (jednowymiarowe), podczas gdy wersja 8K obsługiwała macierze do 34 wymiarów.

Wiele implementacji wspierało praktykę Dartmouth BASIC polegającą na tym, że nie wymagano wymiarowania tablicy, w którym to przypadku zakładano, że ma ona 11 elementów (od 0 do 10); np. {{{1}}}stworzy 11-elementową tablicę jako efekt uboczny.

Wektor narkotyku tablic różnił się w zależności od implementacji. Na przykład wektor narkotyku macierzy Altair BASIC 4K:

  • Nazwa zmiennej (2 bajty)
  • Rozmiar elementów tablicy w bajtach (2 bajty, czyli 4-krotność liczby elementów, czyli górna granica plus jeden)

Następnie same wartości tablicy:

  • Wartość elementu 0 (4 bajty)
  • Wartość elementu 1 (4 bajty)
  • ...
  • Wartość elementu N (4 bajty)

Implementacje obsługujące macierze musiały rejestrować liczbę wymiarów i górną granicę każdego wymiaru. Ponadto, ponieważ niektóre interpretery miały tylko jeden typ danych (albo zmiennoprzecinkowy, albo całkowity), wektor dope musiał jedynie rejestrować liczbę wymiarów i górną granicę każdego wymiaru. Interpretatory z wieloma typami danych musiały rejestrować typ danych tablicy.

Mimo że Microsoft i inne języki BASIC obsługiwały macierze, operacje na macierzach nie były wbudowane, ale musiały być jawnie programowane na elementach tablicy.

Smyczki

Oryginalny Dartmouth BASIC, niektóre z jego bezpośrednich potomków oraz implementacje Tiny BASIC nie miały obsługi łańcuchów. Wyewoluowały dwie konkurujące ze sobą szkoły posługiwania się strunami, zapoczątkowane przez HP i DEC, chociaż inne podejścia pojawiły się później. Wymagały one różnych strategii wdrażania.

Obsługa ciągów znaków w wybitnych interpreterach języka BASIC
Dialekt języka BASIC Typ Podciągi
HP Time-Shared BASIC Poprawiona długość Krajanie na plastry
DEC BASIC-PLUS Zmienna długość Funkcje
Czwarta edycja Dartmouth BASIC Zmienna długość Indeksowanie tablicy
Mały PODSTAWOWY Tablica liczb całkowitych Indeksowanie tablicy

Najprostsza obsługa ciągów skopiowała HP Time-Shared BASIC i zdefiniowała zmienne łańcuchowe jako tablice znaków, które musiały zostać DIMzaprojektowane przed użyciem. Ciągi znaków w HP TSB są traktowane jako tablica znaków, łącznie do 72 znaków, a nie pojedynczy obiekt wieloznakowy. Domyślnie mają one przydzielony jeden znak w pamięci, a jeśli potrzebny jest dłuższy ciąg znaków, należy je zadeklarować. Na przykład skonfiguruje ciąg, który może zawierać maksymalnie 10 znaków. DIM A$[10]

Dostęp do podłańcuchów w łańcuchach uzyskuje się za pomocą notacji „ przecinającej ”: lub , gdzie podłańcuch zaczyna się od skrajnego lewego znaku określonego przez indeks L i przechodzi do najbardziej wysuniętego na prawo znaku określonego przez indeks R, lub formy, w której podłańcuch zaczyna się od skrajnego lewego znaku określony przez indeks L i trwa do końca łańcucha. TSB akceptuje () lub [] zamiennie. Indeksy tablic i podłańcuchów zaczynają się od 1. A$(L,R)A$[L,R]A$[L]

Stoi to w ostrym kontraście do BASIC-ów zgodnych ze wzorcem DEC, które używają funkcji takich jak LEFT$(), MID$()i RIGHT$()do uzyskiwania dostępu do podłańcuchów. Notacja HP, przyjęta później przez ANSI BASIC, może być również używana po stronie docelowej instrukcji LETa lub INPUTw celu zmodyfikowania części istniejącej wartości ciągu, na przykład or , czego nie można zrobić we wczesnych implementacjach . 100 A$[3,5]="XYZ"120 B$[3]="CHANGE ALL BUT FIRST TWO CHARS"LEFT$/MID$/RIGHT$

Późniejsze wersje Dartmouth BASIC zawierały zmienne łańcuchowe. Jednak nie używali LEFT$/MID$/RIGHT$funkcji do manipulowania łańcuchami, ale zamiast tego używali CHANGEpolecenia, które konwertowało ciąg na iz równoważnych wartości ASCII. (Później przyjęty przez DEC i dostosowany przez HP, który zmienił słowo kluczowe na CONVERT.) Dodatkowo można użyć pojedynczego cudzysłowu, aby przekonwertować stałą numeryczną na znak ASCII, umożliwiając zbudowanie ciągu w częściach; A$='23 '64 '49 "DEF"wygenerował ciąg „ABCDEF” bez potrzeby stosowania funkcji CHR$(). Obsługiwany Dartmouth BASIC Sixth Edition SEG$(dla MID$) i POS(dla INSTR).

Integer BASIC, North Star BASIC i Atari BASIC naśladowały podejście HP, które ponownie kontrastowało ze stylem występującym w BASIC-ach wywodzących się z DEC , w tym Microsoft BASIC , gdzie ciągi znaków są wewnętrznym typem o zmiennej długości.

Niektóre implementacje Tiny BASIC obsługiwały jedną lub więcej predefiniowanych tablic liczb całkowitych, które mogły być używane do przechowywania kodów znaków, pod warunkiem, że język miał funkcjonalność wprowadzania i wyprowadzania kodów znaków (np. Astro BASIC miał KPi TVdo tego celu).

Zbieranie śmieci

Posiadanie łańcuchów wykorzystujących stałą ilość pamięci, niezależnie od liczby użytych w nich znaków, maksymalnie do 255 znaków, mogło powodować marnowanie pamięci, ale miało tę zaletę, że pozwalało uniknąć konieczności implementowania wyrzucania elementów bezużytecznych ze sterty , formy automatycznego zarządzanie pamięcią używane do odzyskiwania pamięci zajmowanej przez ciągi znaków, które nie są już używane. Krótkie ciągi, które zostały zwolnione, mogły być przechowywane w środku innych ciągów, uniemożliwiając użycie tej pamięci, gdy potrzebny był dłuższy ciąg.

We wczesnych mikrokomputerach, z ich ograniczoną pamięcią i wolnymi procesorami, wyrzucanie elementów bezużytecznych w BASIC-u mogło często powodować pozornie przypadkowe, niewytłumaczalne przerwy w działaniu programu. Niektóre interpretery języka BASIC, takie jak Applesoft BASIC w rodzinie Apple II , wielokrotnie skanowały deskryptory łańcuchów znaków w poszukiwaniu łańcucha o najwyższym adresie, aby upakować go w kierunku wysokiej pamięci, co skutkowało wydajnością O(n 2 ) , co mogło wprowadzić długie minuty wstrzymuje wykonywanie programów intensywnie korzystających z ciągów znaków. Wyrzucanie elementów bezużytecznych było notorycznie powolne lub nawet zepsute w innych wersjach Microsoft BASIC. Niektóre systemy operacyjne obsługujące zadania w tle sterowane przerwaniami, takie jak TRSDOS/LS-DOS 6.x na TRS-80 Model 4 , wykorzystywały okresy bezczynności użytkownika (takie jak milisekundowe okresy między naciśnięciami klawiszy i okresy po odświeżeniu ekranu wideo ) do przetwarzania wyrzucania elementów bezużytecznych podczas uruchamiania programu w języku BASIC.

Inne funkcje

Grafika i dźwięk

Większość interpreterów języka BASIC różniła się znacznie grafiką i dźwiękiem, które różniły się znacznie w zależności od mikrokomputera. Altair BASIC nie miał żadnych poleceń graficznych ani dźwiękowych, podobnie jak implementacje Tiny BASIC, podczas gdy Integer BASIC zapewniał bogaty zestaw.

Level I BASIC dla TRS-80 miał jak najmniejszy zestaw: CLS, dla CLear Screen; SET(X,Y), który oświetlił miejsce na wyświetlaczu; RESET(X,Y), który go wyłączył; i POINT(X,Y), która zwracała 1, jeśli miejsce było oświetlone, 0, jeśli nie było. Współrzędne mogą być dowolne i mieścić się w zakresie od 0 do 127 dla osi X i od 0 do 47 dla osi Y. Obsługiwany był tylko czarno-biały wyświetlacz.

Natomiast Integer BASIC obsługiwał kolorową grafikę, prosty dźwięk i kontrolery gier. Tryb graficzny włączano poleceniem, GRa wyłączano poleceniem TEXT. Rysowanie było modalne i zwykle rozpoczynało się od wydania polecenia zmiany koloru, co było realizowane przez ustawienie pseudozmiennej; COLOR=12ustawi kolor rysunku na 12, jasnozielony. Można by wtedy PLOT 10,10wytworzyć pojedynczą plamkę tego koloru, HLIN 0,39 AT 20narysować poziomą linię w rzędzie 20, która obejmowała ekran, lub VLIN 5,15 AT 7narysować krótszą pionową linię w dół kolumny 7. A=SCRN X,Yzwrócił kolor ekranu w X, Y.

zestaw graficzny bloków tekstowych ZX-81

Producenci sprzętu często dołączali zastrzeżone wsparcie dla półgrafiki , prostych kształtów i ikon traktowanych jako znaki specjalne . Przykłady obejmowały grafikę blokową ZX-81 oraz symbole kart ♠, ♣, ♥ i ♦ w zestawie znaków Commodore International PETSCII . BASIC może generować te symbole za pomocą PRINT CHR$();.

Microsoft dodał wiele poleceń graficznych do IBM BASIC : LINE, PSET​​(Pixel SET), PRESET(Pixel RESET), GET(przechowuje prostokąt ekranu w tablicy), ( PUTwyświetla zapisany segment prostokątny), LOCATE(aby przesunąć kursor tekstowy) i DRAW, który szkicuje kształty przy użyciu składni podobnej do LOGO . Bill Gates i Neil Konzen napisali DONKEY.BAS , dołączoną grę, aby zademonstrować kolorową grafikę i dźwięk tłumacza .

Wejście wyjście

Innym obszarem, w którym implementacje się różniły, były słowa kluczowe związane z mediami (kasety i dyskietki), wprowadzanie z klawiatury i kontrolery gier (jeśli istnieją).

Ponieważ interpretery języka BASIC oparte na pamięci ROM często działały jako powłoki do ładowania w innych aplikacjach, implementacje dodawały polecenia związane z kasetami (np. i CLOAD) CSAVE, binarnymi plikami dyskowymi ( np . i ). Implementacje Business BASIC dodały polecenia dotyczące plików o swobodnym dostępie. (Nawet interpretery języka BASIC oparte na pamięci ROM nie zostały zaprojektowane ani przeznaczone do użytku jako systemy operacyjne, a mniejsze mikrokomputery po prostu w ogóle nie miały żadnego systemu operacyjnego). BLOADBSAVEBRUNLOADSAVECATALOG

W Dartmouth BASIC brakowało polecenia umożliwiającego wprowadzanie danych z klawiatury bez zatrzymywania programu. Aby obsługiwać gry wideo , BASIC dodał w tym celu zastrzeżone polecenia: INKEY$była funkcją w Microsoft BASIC , która zwracała pusty ciąg, jeśli żaden klawisz nie został naciśnięty lub w inny sposób pojedynczy znak; KP(dla KeyPress ) zwrócił wartość ASCII wejścia w Astro BASIC .

Palo Alto Tiny BASIC nie miał ciągów znaków, ale pozwalał użytkownikom na wprowadzanie wyrażeń matematycznych jako odpowiedzi na INPUTstwierdzenia; ustawiając zmienne, takie jak Y=1; N=0, użytkownik może odpowiedzieć „Y” lub „1”, a nawet „3*2-5” w odpowiedzi tak/nie.

Niektóre systemy obsługiwały kontrolery gier. Obsługiwany Astro BASIC JX()(określona pozycja pozioma joysticka), JY()(pozycja pionowa joysticka), KN()(stan pokrętła) i TR()(stan wyzwalania). Integer BASIC obsługiwał kontroler do gier , paddle controller , który miał dwa kontrolery na jednym złączu. Pozycję kontrolera można odczytać za pomocą PDLfunkcji, przekazując numer kontrolera, 0 lub 1, na przykład A=PDL(0):PRINT A, zwracając wartość z zakresu od 0 do 255.

Integer BASIC nie miał żadnych niestandardowych poleceń wejścia/wyjścia, a także brakowało DATAinstrukcji i powiązanego pliku READ. Aby wprowadzać i wyprowadzać dane z programu, funkcja wejścia/wyjścia była przekierowywana do wybranego gniazda karty za pomocą przycisków PR#xi IN#x, które przekierowywały dane wyjściowe lub dane wejściowe (odpowiednio) do ponumerowanego gniazda. Odtąd dane można było przesyłać na kartę za pomocą konwencjonalnych PRINTpoleceń i odczytywać z niej za pomocą INPUT. Wytwarzanie dźwięków odbywało się poprzez PEEKmapowanie w pamięci lokalizacji prostego „sygnału dźwiękowego”, -16336.

Programowanie strukturalne

Podczas gdy programowanie strukturalne , z przykładów ALGOL 58 i ALGOL 60 , było znane Kemeny'emu i Kurtzowi, kiedy projektowali BASIC, zaadaptowali tylko pętlę for, ignorując instrukcję else, pętlę while, pętlę powtórzeń, nazwane procedury, parametry przekazywanie i zmienne lokalne. W rezultacie kolejne dialekty często różniły się dramatycznie sformułowaniami używanymi w technikach strukturalnych. Na przykład WHILE...WEND(w Microsoft BASIC ), WHILE...ENDWHILE(w Turbo-Basic XL ), DO...LOOP WHILEa nawet WHILEklauzule (oba w BASIC-PLUS ).

Spośród implementacji Tiny BASIC tylko National Industrial Basic Language (NIBL) oferował dowolne polecenie pętli, DO/UNTIL. Stało się tak pomimo tego, że wynalazca Tiny BASIC, Dennis Allison, publicznie lamentował nad stanem BASIC-a.

BBC BASIC był jednym z pierwszych interpreterów mikrokomputerów, który oferował strukturalne programowanie BASIC, z nazwanymi DEF PROC/ DEF FNprocedurami i funkcjami, REPEAT UNTILpętlami i IF THEN ELSEstrukturami inspirowanymi przez COMAL . Języki BASIC drugiej generacji — na przykład SBASIC (1976), BBC BASIC (1981), True BASIC (1983), Beta BASIC (1983), QuickBASIC (1985) i AmigaBASIC (1986) — wprowadziły szereg funkcji do język programowania, głównie związany z programowaniem strukturalnym i proceduralnym. Zwykle numeracja wierszy jest pomijana w języku i zastępowana etykietami (dla GOTO ) oraz procedurami zachęcającymi do łatwiejszego i bardziej elastycznego projektowania. Ponadto wprowadzono słowa kluczowe i struktury wspierające powtarzanie, selekcję i procedury ze zmiennymi lokalnymi.

Poniższy przykład dotyczy Microsoft QBASIC, trzeciej implementacji ustrukturyzowanego języka BASIC firmy Microsoft (po Macintosh BASIC w 1984 r. i Amiga BASIC w 1985 r.).

REM QBASIC example

REM Forward declaration - allows the main code to call a
REM    subroutine that is defined later in the source code
DECLARE SUB PrintSomeStars (StarCount!)

REM Main program follows
DO
   INPUT "How many stars do you want? (0 to quit) ", NumStars
   CALL PrintSomeStars(NumStars)
LOOP WHILE NumStars>0
END

REM subroutine definition
SUB PrintSomeStars (StarCount)
   REM This procedure uses a local variable called Stars$
   Stars$ = STRING$(StarCount, "*")
   PRINT Stars$
END SUB

Zorientowany obiektowo

Początkowa obsługa programowania obiektowego zapewniała jedynie ponowne wykorzystanie obiektów utworzonych w innych językach, na przykład w jaki sposób Visual Basic i PowerBASIC obsługiwały Windows Component Object Model . W miarę ewolucji interpreterów języka BASIC dodano obsługę funkcji zorientowanych obiektowo, takich jak metody , konstruktory , dynamiczna alokacja pamięci , właściwości i alokacja tymczasowa.

W zestawie asembler

Pamięci ROM Integer BASIC zawierały również monitor kodu maszynowego , „mini asembler ” i deasembler do tworzenia i debugowania programów w języku asemblera .

Jedną z unikalnych cech BBC BASIC był wbudowany asembler , umożliwiający użytkownikom pisanie programów w języku asemblera dla 6502 , a później Zilog Z80 , NS32016 i ARM . Asembler został w pełni zintegrowany z interpreterem języka BASIC i współdzielił z nim zmienne, które można było umieszczać między znakami [ i ], zapisywać za pomocą * SAVE i * LOAD oraz wywoływać za pomocą poleceń CALL lub USR. Umożliwiło to programistom pisanie nie tylko kodu w języku asemblera, ale także kodu BASIC do emitowania języka asemblera, umożliwiając korzystanie z technik generowania kodu, a nawet pisanie prostych kompilatorów w języku BASIC.

Wykonanie

Debugowanie

Jak w większości języków BASIC, programy były uruchamiane za pomocą RUNpolecenia i, co było powszechne, można je było kierować do określonego numeru linii, na przykład RUN 300. Wykonywanie można zatrzymać w dowolnym momencie za pomocą Ctrl+ C(lub BREAK, jak na TRS-80), a następnie ponownie uruchomić za pomocą CONTinue ( CONw Integer BASIC). Korzystając z unikalnych możliwości programów interpretowanych (kod jest przetwarzany w czasie rzeczywistym po jednej instrukcji na raz, w przeciwieństwie do kompilatorów ), użytkownik przy konsoli mógł badać zmienne dane za pomocą instrukcji PRINT i zmieniać je w locie , a następnie wznów wykonywanie programu.

Aby wykonać krok po kroku, instrukcja TRONlub TRACEmoże być użyta w wierszu polecenia lub umieszczona w samym programie. Po włączeniu numery linii były drukowane dla każdej linii odwiedzanej przez program. Funkcję można ponownie wyłączyć za pomocą TROFFlub NOTRACE.

Niektóre implementacje, takie jak interpretery firmy Microsoft dla różnych znaków TRS-80, zawierały polecenie ON ERROR GOSUB. Spowodowałoby to przekierowanie wykonywania programu do określonego numeru wiersza w celu specjalnej obsługi błędów.

W przeciwieństwie do większości języków BASIC, Atari BASIC skanował właśnie wprowadzoną linię programu i natychmiast zgłaszał błędy składniowe. Jeśli został znaleziony błąd, edytor ponownie wyświetlał linię, podświetlając tekst w pobliżu błędu w odwróconym wideo .

W wielu interpreterach, w tym Atari BASIC, błędy są wyświetlane jako kody numeryczne, z opisami wydrukowanymi w instrukcji. Wiele MS-BASIC używało dwuznakowych skrótów (np. SN dla SYNTAX ERROR). Palo Alto Tiny BASIC i Level I BASIC używały trzech słów w komunikatach o błędach: „CO?” w przypadku błędów składniowych „JAK?” w przypadku błędów w czasie wykonywania, takich jak GOTO do linii, która nie istniała lub przepełnienia numeryczne, oraz „SORRY” w przypadku problemów z brakiem pamięci.

Rozbiór gramatyczny zdania

Podczas gdy język BASIC ma prostą składnię, wyrażenia matematyczne nie, obsługują różne reguły pierwszeństwa dla nawiasów i różnych operatorów matematycznych. Obsługa takich wyrażeń wymaga zaimplementowania parsera rekurencyjnego .

Ten parser można zaimplementować na kilka sposobów:

  • Jako maszyna wirtualna, jak omówiono powyżej dla wielu implementacji Tiny BASIC. Wartość inicjatywy Tiny BASIC polegała na określeniu implementacji parsera.
  • Jako maszyna skończona , podobnie jak w UIUC BASIC IUC, gdzie została zaimplementowana jako tablica sterująca .
  • Bezpośrednio w kodzie, jak w Palo Alto Tiny BASIC i Integer BASIC. W Integer BASIC interpreter środowiska wykonawczego używał do wykonania dwóch stosów: jeden dla słów kluczowych instrukcji, a drugi do oceny parametrów. Każdej instrukcji nadano dwa priorytety: jeden, który określał, gdzie powinna wystąpić w wieloetapowej operacji, jak ciąg operacji matematycznych w celu ustalenia kolejności operacji , oraz drugi, który sugerował, kiedy ocena powinna nastąpić, na przykład obliczanie wewnętrznych wartości formuła nawiasowa. Kiedy napotkano zmienne, ich nazwy były analizowane, a następnie wyszukiwane w tablicy symboli. Jeśli nie został znaleziony, został dodany na koniec listy. Adres przechowywania zmiennej, być może świeżo utworzony, został następnie umieszczony na stosie ewaluacyjnym.

Wydajność

Zakres decyzji projektowych, które podjęto przy programowaniu interpretera języka BASIC, często ujawniał się poprzez różnice w wydajności.

Implementacje zarządzania wierszami często wpływały na wydajność i zwykle stosowano wyszukiwanie liniowe . Ograniczenie każdej linii za pomocą CR spowodowałoby, że GOTO lub GOSUB do późniejszej linii zajęłoby więcej czasu, ponieważ program musiałby iterować po wszystkich liniach, aby znaleźć numer linii docelowej. W niektórych implementacjach, takich jak Atari BASIC, długość każdej linii była zapisywana i przechowywana po numerze linii, dzięki czemu program nie musiał skanować każdego znaku linii, aby znaleźć następny powrót karetki. Wiele implementacji zawsze szukałoby numeru linii do rozgałęzienia od początku programu; MS-BASIC szukałby od bieżącej linii, gdyby numer linii docelowej był większy. Pittman dodał łatkę do swojego 6800 Tiny BASIC, aby używać wyszukiwania binarnego.

Praca wyłącznie z matematyką liczb całkowitych zapewnia kolejny znaczący wzrost szybkości. Ponieważ wiele komputerowych testów porównawczych tamtej epoki było małych i często wykonywało prostą matematykę, która nie wymagała zmiennoprzecinkowych, Integer BASIC pokonał większość innych BASIC-ów. W jednym z najwcześniejszych znanych testów porównawczych mikrokomputerów, testach porównawczych Rugg/Feldman , Integer BASIC był ponad dwa razy szybszy niż Applesoft BASIC na tej samej maszynie. W Byte Sieve , gdzie matematyka była mniej ważna, ale dominował dostęp do tablicy i wydajność pętli, Integer BASIC zajmował 166 sekund, podczas gdy Applesoft 200. Nie pojawił się w Creative Computing Benchmark , który został po raz pierwszy opublikowany w 1983 roku, kiedy to Integer BASIC nie był już dostarczany domyślnie. Poniższa seria testów, zaczerpnięta z obu oryginalnych artykułów Rugga/Feldmana, pokazuje wydajność Integera w stosunku do BASIC-a pochodzącego z MS na tej samej platformie.

System procesor PODSTAWOWY Próba 1 Próba 2 Próba 3 Próba 4 Próba 5 Próba 6 Próba 7
Jabłko II 6502 przy 1 MHz PODSTAWOWE liczby całkowite 1.3 3.1 7.2 7.2 8.8 18,5 28.0
Jabłko II 6502 przy 1 MHz Applesoft BASIC 1.3 8.5 16.0 17.8 19.1 28.6 44,8

Teoretycznie Atari BASIC powinien działać szybciej niż współczesne BASIC-y oparte na wzorcu Microsoftu. Ponieważ kod źródłowy jest w pełni tokenizowany po wprowadzeniu, wszystkie etapy tokenizacji i analizy są już zakończone. Nawet złożone operacje matematyczne są gotowe do wykonania, a wszelkie stałe numeryczne są już przekonwertowane do wewnętrznego formatu 48-bitowego, a wartości zmiennych są wyszukiwane według adresu, zamiast konieczności ich wyszukiwania. Pomimo tych teoretycznych zalet, w praktyce Atari BASIC jest wolniejszy niż inne BASIC-y komputerów domowych , często o wiele. W praktyce nie znalazło to potwierdzenia. W dwóch powszechnie używanych testach porównawczych tamtej epoki, Sieve of Eratosthenes magazynu Byte i teście porównawczym Creative Computing napisanym przez Davida H. Ahla , Atari zakończyło się pod koniec listy pod względem wydajności i było znacznie wolniejsze niż współczesny Apple II lub Commodore PET , pomimo posiadania tego samego procesora, ale działającego z mniej więcej dwukrotnie większą szybkością. Skończył za stosunkowo wolnymi maszynami, takimi jak Sinclair ZX81 , a nawet za niektórymi programowalnymi kalkulatorami.

Większość powolności języka wynikała z trzech problemów. Po pierwsze, procedury matematyczne zmiennoprzecinkowe były słabo zoptymalizowane. W teście porównawczym Ahl operacja na pojedynczym wykładniku, która wewnętrznie zapętla funkcję powolnego mnożenia, była odpowiedzialna za większość słabych wyników maszyny. Po drugie, konwersja między wewnętrznym formatem zmiennoprzecinkowym a 16-bitowymi liczbami całkowitymi używanymi w niektórych częściach języka była stosunkowo powolna. Wewnętrznie te liczby całkowite były używane do numerowania wierszy i indeksowania tablic, wraz z kilkoma innymi zadaniami, ale liczby w tokenizowanym programie były zawsze przechowywane w formacie dziesiętnym kodowanym binarnie (BCD). Ilekroć jeden z nich zostanie napotkany, na przykład w numerze wiersza w GOTO 100, tokenizowana wartość BCD musi zostać przekonwertowana na liczbę całkowitą, co może zająć nawet 3500 mikrosekund. Inne języki BASIC uniknęły tego opóźnienia, dokonując specjalnej konwersji liczb, które mogą być tylko liczbami całkowitymi, na przykład numeru wiersza następującego po GOTO, przełączając się na specjalny kod ASCII na liczbę całkowitą w celu poprawy wydajności. Po trzecie, jak Atari BASIC zaimplementował rozgałęzienia i FORpętle. Aby wykonać rozgałęzienie w a GOTOlub GOSUB, interpreter przeszukuje cały program w poszukiwaniu pasującego numeru wiersza, którego potrzebuje. Jednym z drobnych ulepszeń, które można znaleźć w większości BASIC-ów pochodzących od Microsoftu, jest porównanie docelowego numeru linii z bieżącym numerem linii i wyszukiwanie do przodu od tego punktu, jeśli jest większy, lub rozpoczęcie od góry, jeśli jest mniejszy. Tego ulepszenia brakowało w Atari BASIC. W przeciwieństwie do prawie wszystkich innych BASIC-ów, które pchnęłyby wskaźnik do położenia na FORstosie, więc kiedy osiągnął on, NEXTmógł z łatwością powrócić do FORponownie w jednej operacji rozgałęzienia, Atari BASIC zamiast tego przesunął numer linii. Oznaczało to, że za każdym razem NEXT, gdy napotkano a, system musiał przeszukać cały program, aby znaleźć odpowiednią FORlinię. W rezultacie wszelkie pętle w programie Atari BASIC powodują dużą utratę wydajności w porównaniu z innymi BASIC-ami.

Zobacz też

Notatki

Bibliografia

Bibliografia

Dalsza lektura

Kod źródłowy i dokumenty projektowe, w porządku chronologicznym wydania implementacji języka BASIC: