Język programowania wysokiego poziomu - High-level programming language

W informatyce , wykorzystując język wysokiego poziomu jest językiem programowania z silnym abstrakcji od szczegółów komputerze . W przeciwieństwie do języków programowania niskopoziomowego , może wykorzystywać elementy języka naturalnego , być łatwiejszy w obsłudze, czy też automatyzować (lub nawet całkowicie ukrywać) istotne obszary systemów obliczeniowych (np. zarządzanie pamięcią ), ułatwiając proces tworzenia programu i bardziej zrozumiałe niż przy użyciu języka niższego poziomu. Ilość dostarczonej abstrakcji określa, jak „wysoki poziom” jest język programowania.

W latach 60. języki programowania wysokiego poziomu wykorzystujące kompilator były powszechnie nazywane autokodami . Przykładami autokodów są COBOL i Fortran .

Pierwszym wysokopoziomowym językiem programowania przeznaczonym dla komputerów był Plankalkül , stworzony przez Konrada Zuse . Jednak nie został wdrożony w jego czasach, a jego oryginalny wkład był w dużej mierze odizolowany od innych wydarzeń z powodu II wojny światowej , poza wpływem języka na język „Superplan” Heinza Rutishausera, a także do pewnego stopnia Algola . Pierwszym szeroko rozpowszechnionym językiem wysokiego poziomu był Fortran , niezależny od maszyny rozwój wcześniejszych systemów Autocode IBM . Rodzina Algol , z Algolem 58 zdefiniowanym w 1958 i Algolem 60 zdefiniowanym w 1960 przez komitety europejskich i amerykańskich informatyków, wprowadziła rekurencję oraz funkcje zagnieżdżone w zakresie leksykalnym . Algol 60 był również pierwszym językiem z wyraźnym rozróżnieniem między wartością a parametrami nazwy i odpowiadającymi im semantyką . Algol wprowadził również kilka koncepcji programowania strukturalnego , takich jak konstrukcje while-do i if-then-else, a jego składnia jako pierwsza została opisana w notacji formalnej – „ forma Backus-Naur ” (BNF). Mniej więcej w tym samym okresie Cobol wprowadził rekordy (zwane również strukturami), a Lisp po raz pierwszy wprowadził w pełni ogólną abstrakcję lambda w języku programowania.

Cechy

„Język wysokiego poziomu” odnosi się do wyższego poziomu abstrakcji od języka maszynowego . Zamiast zajmować się rejestrami, adresami pamięci i stosami wywołań, języki wysokiego poziomu zajmują się zmiennymi, tablicami, obiektami , złożonymi wyrażeniami arytmetycznymi lub boolowskimi, podprogramami i funkcjami, pętlami, wątkami , blokadami i innymi abstrakcyjnymi koncepcjami informatyki, z skupić się na użyteczności nad optymalną wydajnością programu. W przeciwieństwie do języków asemblerowych niskiego poziomu , języki wysokiego poziomu mają niewiele, jeśli w ogóle, elementów językowych, które przekładają się bezpośrednio na natywne kody operacyjne maszyny . Mogą być również obecne inne funkcje, takie jak procedury obsługi ciągów znaków, funkcje języka obiektowego i wejścia/wyjścia plików. Jedną rzeczą, na którą należy zwrócić uwagę w przypadku języków programowania wysokiego poziomu, jest to, że te języki pozwalają programiście na odłączenie i oddzielenie od maszyny. Oznacza to, że w przeciwieństwie do języków niskiego poziomu, takich jak asembler lub język maszynowy, programowanie wysokiego poziomu może wzmacniać instrukcje programisty i wyzwalać wiele ruchów danych w tle bez jego wiedzy. Odpowiedzialność i uprawnienia do wykonywania instrukcji zostały przekazane maszynie od programisty.

Kara za abstrakcję

Języki wysokiego poziomu mają zapewnić funkcje, które standaryzują typowe zadania, umożliwiają rozbudowane debugowanie i zachowują agnostycyzm architektoniczny; podczas gdy języki niskiego poziomu często generują bardziej wydajny kod poprzez optymalizację pod kątem określonej architektury systemu. Kara za abstrakcję to koszt, który techniki programowania wysokiego poziomu płacą za niemożność zoptymalizowania wydajności lub użycia określonego sprzętu, ponieważ nie wykorzystują one niektórych zasobów architektury niskiego poziomu. Programowanie wysokiego poziomu zawiera funkcje, takie jak bardziej ogólne struktury danych i operacje, interpretacja w czasie wykonywania i pliki kodu pośredniego; co często skutkuje wykonaniem znacznie większej liczby operacji niż to konieczne, większym zużyciem pamięci i większym rozmiarem programu binarnego. Z tego powodu kod, który musi działać szczególnie szybko i wydajnie, może wymagać użycia języka niższego poziomu, nawet jeśli język wyższego poziomu ułatwiłby kodowanie. W wielu przypadkach krytyczne części programu, głównie w języku wysokiego poziomu, mogą być ręcznie napisane w języku asemblerowym , co prowadzi do znacznie szybszego, wydajniejszego lub po prostu niezawodnie działającego zoptymalizowanego programu .

Jednak wraz z rosnącą złożonością nowoczesnych architektur mikroprocesorowych , dobrze zaprojektowane kompilatory dla języków wysokiego poziomu często generują kod porównywalny pod względem wydajności do tego, który większość programistów niskiego poziomu jest w stanie stworzyć ręcznie, a wyższa abstrakcja może pozwolić na zastosowanie potężniejszych technik zapewniających lepsze ogólne wyniki niż ich odpowiedniki na niskim poziomie w określonych warunkach. Języki wysokiego poziomu są projektowane niezależnie od konkretnej architektury systemu komputerowego. Ułatwia to wykonanie programu napisanego w takim języku na dowolnym systemie obliczeniowym z kompatybilną obsługą programu Interpreted lub JIT . Języki wysokiego poziomu można ulepszać, gdy ich projektanci opracowują ulepszenia. W innych przypadkach nowe języki wysokiego poziomu ewoluują z jednego lub kilku innych w celu agregowania najpopularniejszych konstrukcji z nowymi lub ulepszonymi funkcjami. Przykładem tego jest Scala, która zachowuje wsteczną kompatybilność z Javą, co oznacza, że ​​programy i biblioteki napisane w Javie będą nadal używane, nawet jeśli sklep programistyczny przełączy się na Scala; to sprawia, że ​​przejście jest łatwiejsze, a żywotność takiego wysokopoziomowego kodowania jest nieskończona. W przeciwieństwie do tego, programy niskopoziomowe rzadko przetrwają poza architekturą systemu, dla której zostały napisane, bez większych zmian. To jest „kompromis” inżynieryjny za „karę za abstrakcję”.

Względne znaczenie

Przykłady aktywnych języków programowania wysokiego poziomu to Python , Visual Basic , Delphi , Perl , PHP , ECMAScript , Ruby , C# , Java i wiele innych.

Terminy wysoki i niski poziom są z natury względne. Kilkadziesiąt lat temu język C i podobne języki były najczęściej uważane za „wysoki poziom”, ponieważ obsługiwały koncepcje takie jak ocena wyrażeń, parametryzowane funkcje rekurencyjne oraz typy i struktury danych, podczas gdy język asembler był uważany za „niskopoziomowy”. ”. Obecnie wielu programistów może odnosić się do C jako niskopoziomowego, ponieważ brakuje mu dużego systemu wykonawczego (brak wyrzucania śmieci itp.), zasadniczo obsługuje tylko operacje skalarne i zapewnia bezpośrednie adresowanie pamięci. Dlatego łatwo łączy się z językiem asemblera i poziomem maszynowym procesorów i mikrokontrolerów .

Język asembler może sam w sobie być uważany za reprezentację kodu maszynowego na wyższym poziomie (ale często nadal jeden do jednego, jeśli jest używany bez makr ) , ponieważ obsługuje koncepcje takie jak stałe i (ograniczone) wyrażenia, czasami nawet zmienne, procedury i dane struktury . Kod maszynowy , z kolei, jest z natury na nieco wyższym poziomie niż microcode lub mikro-operacje używane wewnętrznie w wielu procesorów.

Tryby wykonania

Istnieją trzy ogólne tryby wykonywania dla nowoczesnych języków wysokiego poziomu:

Interpretowane
Gdy kod napisany w języku jest interpretowany , jego składnia jest odczytywana, a następnie wykonywana bezpośrednio, bez etapu kompilacji. Program zwany interpreterem odczytuje każdą instrukcję programu, podążając za przebiegiem programu, a następnie decyduje, co zrobić i robi to. Hybryda interpretera i kompilatora skompiluje instrukcję do kodu maszynowego i wykona go; kod maszynowy jest następnie odrzucany i interpretowany na nowo, jeśli wiersz zostanie wykonany ponownie. Interpretery są zwykle najprostszymi implementacjami zachowania języka w porównaniu z pozostałymi dwoma wymienionymi tutaj wariantami.
Skompilowany
Kiedy kod napisany w języku jest kompilowany , jego składnia jest przekształcana w formę wykonywalną przed uruchomieniem. Istnieją dwa rodzaje kompilacji:
Generowanie kodu maszynowego
Niektóre kompilatory kompilują kod źródłowy bezpośrednio do kodu maszynowego . Jest to oryginalny tryb kompilacji, a języki, które są w ten sposób bezpośrednio i całkowicie przekształcane w kod maszynowy, można nazwać prawdziwie skompilowanymi językami. Zobacz język asemblera .
Reprezentacje pośrednie
Gdy kod napisany w języku jest kompilowany do reprezentacji pośredniej , ta reprezentacja może zostać zoptymalizowana lub zapisana do późniejszego wykonania bez konieczności ponownego odczytywania pliku źródłowego. Gdy reprezentacja pośrednia jest zapisywana, może mieć postać taką jak kod bajtowy . Pośrednia reprezentacja musi być następnie zinterpretowana lub dalej skompilowana, aby ją wykonać. Maszyny wirtualne, które wykonują kod bajtowy bezpośrednio lub przekształcają go dalej w kod maszynowy, zatarły niegdyś wyraźną różnicę między reprezentacjami pośrednimi a prawdziwie skompilowanymi językami.
Tłumaczenie lub transkompilacja ze źródła do źródła
Kod napisany w języku może zostać przetłumaczony na warunki języka niższego poziomu, dla którego kompilatory kodu natywnego są już powszechne. JavaScript i język C są wspólnymi celami dla takich tłumaczy. Zobacz przykłady CoffeeScript , Chicken Scheme i Eiffel . W szczególności wygenerowany kod C i C++ można zobaczyć (jako wygenerowany z języka Eiffel podczas korzystania z IDE EiffelStudio ) w katalogu EIFGENs dowolnego skompilowanego projektu Eiffel. W systemie Eiffel przetłumaczony proces jest określany jako transkompilacja lub transkompilacja, a kompilator Eiffla jako transkompilator lub kompilator źródła do źródła .

Zauważ, że języki nie są ściśle interpretowanymi językami ani językami kompilowanymi . Implementacje zachowań językowych wykorzystują raczej interpretację lub kompilację. Na przykład ALGOL 60 i Fortran zostały zinterpretowane (chociaż były bardziej typowo skompilowane). Podobnie Java pokazuje trudności związane z próbą zastosowania tych etykiet do języków, a nie do implementacji; Java jest kompilowana do kodu bajtowego, który jest następnie wykonywany przez interpretację (w wirtualnej maszynie Java (JVM)) lub kompilację (zazwyczaj za pomocą kompilatora just-in-time, takiego jak HotSpot , ponownie w JVM). Co więcej, kompilowanie, transkompilowanie i interpretowanie nie ogranicza się wyłącznie do opisu artefaktu kompilatora (binarny plik wykonywalny lub zespół IL).

Architektura komputerowa języka wysokiego poziomu

Alternatywnie możliwe jest bezpośrednie zaimplementowanie języka wysokiego poziomu przez komputer – komputer bezpośrednio wykonuje kod HLL. Jest to znane jako architektura komputerowa języka wysokiego poziomu — sama architektura komputera jest zaprojektowana tak, aby była przeznaczona dla określonego języka wysokiego poziomu. Na przykład duże systemy Burroughs były maszynami docelowymi dla ALGOL 60 .

Zobacz też

Uwagi

Bibliografia

Zewnętrzne linki