Сайт о телевидении

Сайт о телевидении

» » Встраиваемые интерпретируемые языки программирования

Встраиваемые интерпретируемые языки программирования

В общем случае, любой язык может быть компилируемым и интерпретируемым, так что данное разделение относится к практике применения языка, а не является его свойством. При этом для многих языков существует различие в производительности между компилируемой и интерпретируемой реализацией.

Большое количество языков, включая BASIC , , Lisp , Pascal и Python , имеют обе реализации. В Java используется JIT-компиляция для генерации машинного кода, хотя изначально он переводится в интерпретируемую форму. Языки Microsoft .NET Framework компилируются в Common Intermediate Language (CIL) , который во время выполнения компилируется в нативный код. Большинство реализаций Lisp позволяют смешивать оба вида кода.

История

В ранние годы развития программирования на языки сильно влиял выбор способа выполнения. Например, компилируемые языки требовали задания типа данных переменной в момент ее описания или первого использования. В то время как интерпретируемые языки в силу своей динамической природы позволяли отказаться от этого требования, что давало больше гибкости и ускоряло разработку.

Изначально интерпретируемые языки преобразовывались в машинный код построчно, то есть каждая логическая строка компилировалась непосредственно перед выполнением. В результате каждая инструкция, заключенная в тело цикла и исполняемая несколько раз, столько же раз обрабатывалась транслятором. В настоящее время такие эффекты редки. Большинство интерпретируемых языков предварительно транслируются в промежуточное представление. Оно представляет собой байт-код или шитый код (threaded code) . Это набор инструкций по вызову небольших фрагментов более низкоуровнего кода, эквивалентный нескольким командам ассемблера или командам виртуальной машины соответственно. Уже этот код испольняется интерпретатором или виртуальной машиной.

Например, такую схему используют следующие языки:

  • Ruby (использует представление кода в виде абстрактного синтаксического дерева)

Промежуточный код может создаваться как явной процедурой компиляции всего проекта (Java), так и скрытой трансляцией каждый раз перед началом выполнения программы (Perl, Ruby) и при изменении исходного кода (Python).

Преимущества

Есть ряд возможностей, которые значительно легче реализовать в интерпретаторе, чем в компиляторе:

  • использование динамической области видимости и замыканий

Кроме того, принципы и стиль программирования часто не требуют создания и описания специальных конструкций, оформляющих программу (манифестов, классов, типов данных). Это позволяет разрабатывать и тестировать код постепенно, что удобно как для написания небольших программ, так и для изолированной разработки модулей для сложных систем. В силу своей универсальности их удобно применять в качестве скриптовых языков .

Недостатки

Основным недостатком является меньшая производительность по сравнению с компилируемыми языками, преобразуемыми в машинный код . Трансляция в байт-код и JIT-компиляция не решают этой проблемы полностью. Дополнительный слой интерпретатора или виртуальной машины замедляет выполнение программы и может требовать больше ресурсов.

Из-за отсутствия компиляции всего проекта большинство ошибок можно поймать только во время выполнения. В результате в среднем интерпретируемый код следует тестировать тщательнее компилируемого, строже придерживаться соглашений по оформлению программ и использовать дополнительные анализаторы качества кода. Последний недостаток выражен несильно, так как при серьезной разработке на компилируемых языках также необходимо применение этих средств.

Области использования

Исключение этапа компиляции позволяет производить более быструю разработку программ, поэтому интерпретируемые языки используются при написании сложных одноразовых программ (например, для проведения однократного вычисления).

Пример


Wikimedia Foundation . 2010 .

Смотреть что такое "Интерпретируемый язык программирования" в других словарях:

    Разработанный корпорацией Sun Microsistems межплатформенный, интерпретируемый, объектно ориентированный язык программирования, используемый для создания приложений, работающих в под управлением веб браузера и характеризующихся высоким уровнем… … Финансовый словарь

    Ruby Семантика: мультипарадигмальный Тип исполнения: интерпретатор Появился в: 1995 г. Автор(ы): Юкихиро Мацумото Последняя версия: 1.9.1 … Википедия

    Язык программирования формальная знаковая система, предназначенная для записи компьютерных программ. Язык программирования определяет набор лексических, синтаксических и семантических правил, задающих внешний вид программы и действия,… … Википедия

    У этого термина существуют и другие значения, см. B. У этого термина существуют и другие значения, см. БИ (значения). B Класс языка: процедурная Тип исполнения: интерпретируемый Появился в: 1969 А … Википедия

    У этого термина существуют и другие значения, см. Диалект (значения). Диалект Тип исполнения: интерпретируемый Автор(ы): Джордж Харт Диалект интерпретируемый язык программирования, созданный Джорджем Хартом в рамках институтского проекта по … Википедия Википедия

    ABC Класс языка: императивный, процедурный, структурный Тип исполнения: интерпретируемый, компилируемый Появился в: 1987 Автор(ы): Leo Geurts, Lambert Meertens (… Википедия

Лекция 1 – Языки программирования. Visual Basic

{Материал из Википедии - свободной энциклопедии}Язы́к программи́рования - формальнаязнаковая система, предназначенная для описанияалгоритмов в форме, которая удобна для исполнителя (например,компьютера ). Язык программирования определяет наборлексических ,синтаксических исемантических правил, используемых при составлениикомпьютерной программы . Он позволяетпрограммисту точно определить то, на какие события будет реагировать компьютер, как будут храниться и передаватьсяданные , а также какие именно действия следует выполнять над этими данными при различных обстоятельствах. Со времени создания первых программируемых машин человечество придумало уже более двух с половиной тысяч языков программирования (См.Список языков программирования (англ.)). Каждый год их число пополняется новыми. Некоторыми языками умеет пользоваться только небольшое число их собственных разработчиков, другие становятся известны миллионам людей. Профессиональные программисты иногда применяют в своей работе более десятка разнообразных языков программирования.Cоздатели языков по-разному толкуют понятиеязык программирования . Среди общих мест, признаваемых большинством разработчиков, находятся следующие:

    Функция: язык программирования предназначен для написания компьютерных программ, которые применяются для передачи компьютеруинструкций по выполнению того или иноговычислительного процесса и организации управления отдельнымиустройствами .

    Задача: язык программирования отличается отестественных языков тем, что предназначен для передачикоманд и данных от человека компьютеру, в то время, как естественные языки используются для общениялюдей между собой. В принципе, можно обобщить определение "языков программирования" - это способ передачи команд, приказов, четкого руководства к действию; тогда как человеческие языки служат также для обмена информацией.

    Исполнение: язык программирования может использовать специальные конструкции для определения и манипулированияструктурами данных и управления процессом вычислений.

Особенности языков программирования

Каждый язык программирования может быть представлен в виде набора формальных спецификаций, определяющих его синтаксис исемантику Эти спецификации обычно включают в себя описание:

    Типов и структур данных

    Операционную семантику (алгоритм вычисления конструкций языка)

    Семантические конструкции языка

    Библиотеки примитивов (например, инструкции ввода-вывода)

    Философии назначения и возможностей языка

Для многих широко распространённых языков программирования созданы международные комитеты по стандартизации, которые выполняют регулярное обновление и публикацию спецификаций и формальных определений соответствующего языка. В рамках таких комитетов продолжается разработка и модернизация языков программирования и решаются вопросы о расширении или поддержке уже существующих и новых языковых конструкций.

Типы данных

Во внутреннем представлении все данные в современных цифровых компьютерах сохраняются просто как нули и единицы (в двоичном виде ). Данные, которые представляют информацию из реального мира (имена, банковские счета, измерения и др.) - это низкоуровневые двоичные данные, которые преобразуются языками программирования в эти высокоуровневые концепции.

Особая система, по которой данные организуются в программе, - это система типов языка программирования; разработка и изучение систем типов известна под названиемтеория типов . Языки могут быть классифицированы как системысо статической типизацией и языки сдинамической типизацией . Статически-типизированные языки могут быть в дальнейшем подразделены на языки собязательной декларацией , где каждая переменная и объявление функции имеет обязательное объявление типа, и языки свыводимыми типами . Иногда динамически-типизированные языки называютсялатентно типизированными .

Структуры данных

Системы типов в языках высокого уровня позволяют определять сложные, составные типы, так называемые структуры данных . Как правило, структурные типы данных образуются какдекартово произведение базовых (атомарных) типов и ранее определённых составных типов. Основные структуры данных (списки, очереди, хэш-таблицы, двоичные деревья и пары) часто представлены особыми синтаксическими конструкциями в языках высокого уровня. Такие данные структурируются автоматически.

Компилируемые и интерпретируемые языки

Языки программирования делятся на два класса - компилируемые иинтерпретируемые . Программа на компилируемом языке при помощи специальной программыкомпилятора преобразуется (компилируется ) в набор инструкций для данного типа процессора (машинный код) и далее записывается висполняемый файл , который может быть запущен на выполнение как отдельная программа. Другими словами, компилятор переводит программу с языка высокого уровня на низкоуровневый язык, понятный процессору. Если программа написана на интерпретируемом языке, тоинтерпретатор непосредственно выполняет (интерпретирует ) ее текст без предварительного перевода. При этом программа остается на исходном языке и не может быть запущена без интерпретатора. Можно сказать, что процессор компьютера - это интерпретатор машинного кода. Кратко говоря, компилятор переводит программу на машинный язык сразу и целиком, создавая при этом отдельную программу, а интерпретатор переводит на машинный язык прямо во время исполнения программы. Разделение на компилируемые и интерпретируемые языки является несколько условным. Так, для любого традиционно компилируемого языка, как, например,Паскаль , можно написать интерпретатор. Кроме того, большинство современных «чистых» интерпретаторов не исполняют конструкции языка непосредственно, а компилируют их в некоторое высокоуровневое промежуточное представление (например, с разыменованием переменных и раскрытием макросов). Для любого интерпретируемого языка можно создать компилятор - например, язык Лисп, изначально интерпретируемый, может компилироваться без каких бы то ни было ограничений. Создаваемый во время исполнения программы код может так же динамически компилироваться во время исполнения. Как правило, скомпилированные программы выполняются быстрее и не требуют для выполнения дополнительных программ, так как уже переведены на машинный язык. Вместе с тем при каждом изменении текста программы требуется ее перекомпиляция, что создает трудности при разработке. Кроме того, скомпилированная программа может выполняться только на том же типе компьютеров и, как правило, под той же операционной системой, на которую был рассчитан компилятор. Чтобы создать исполняемый файл для машины другого типа, требуется новая компиляция. Интерпретируемые языки обладают некоторыми специфическими дополнительными возможностями (см. выше), кроме того, программы на них можно запускать сразу же после изменения, что облегчает разработку. Программа на интерпретируемом языке может быть зачастую запущена на разных типах машин и операционных систем без дополнительных усилий. Однако интерпретируемые программы выполняются заметно медленнее, чем компилируемые, кроме того, они не могут выполняться без дополнительной программы-интерпретатора. Некоторые языки, например,Java иC# , находятся между компилируемыми и интерпретируемыми. А именно, программа компилируется не в машинный язык, а в машинно-независимый код низкого уровня,байт-код . Далее байт-код выполняетсявиртуальной машиной . Для выполнения байт-кода обычно используется интерпретация, хотя отдельные его части для ускорения работы программы могут быть транслированы в машинный код непосредственно во время выполнения программы по технологии компиляции «на лету» (Just-in-time compilation,JIT ). Для Java байт-код исполняется виртуальной машиной Java (Java Virtual Machine,JVM ), для C# -Common Language Runtime . Подобный подход в некотором смысле позволяет использовать плюсы как интерпретаторов, так и компиляторов. Следует упомянуть также оригинальный языкФорт(Forth) , который является как бы одновременно интерпретируемым и компилируемым.

От Ali Çehreli . Большая часть материала ориентирована на начинающих, но так как большая часть аудитории уже имеет базовые знания в программировании, то этот материал убран под хабракаты. В данной части рассматриваются фундаментальные типы, свойства типов, основы компиляции и императивного программирования.

Базовый материал

Компилятор

Ранее мы увидели, что наиболее часто используемые инструменты в D - текстовый редактор и компилятор . Программы на D пишутся в текстовых редакторах (прим. ваш КО).

При использовании компилируемых языков , таких как D, необходимо понимать концепцию компиляции и функцию компилятора.

Машинные коды

Мозгом компьютера является микропроцессор (или ЦПУ, сокращение от центрального процессорного устройства ). Кодированием называется указывание, что именно должен делать ЦПУ, и инструкции, которые используются при этом, называются машинными кодами .

Большинство архитектур ЦПУ используют специфичные для них машинные коды. Эти машинные инструкции определяются с учетом ограничений аппаратных средств во время проектирования архитектуры. На самом низком уровне эти инструкции реализованы как электические сигналы. Так как простота программирования на этом уровне не является главной целью, написание программ напрямую в машиннах кодах ЦПУ является очень сложной задачей.

Эти машинные инструкции представляют собой специальные числа, которые представляют различные операции, поддерживаемые конкретным ЦПУ. Например, для воображаемого 8-битного ЦПУ, число 4 может представлять операцию загрузки, число 5 - операцию сохранения, и число 6 - операцию увеличения значения на единицу. Предполагая, что первые 3 бита слева - номер операции и 5 последующих бита - значение, которое используется в этой операции, программа-пример в машинных кодах этого ЦПУ может выглядеть следующим образом:
Operation Value Meaning 100 11110 LOAD 11110 101 10100 STORE 10100 110 10100 INCREMENT 10100 000 00000 PAUSE

Находясь настолько близко к железу, машинные коды не подходят для представления высокоуровневых понятий таких как: игральная карта или запись о студенте .

Языки программирования

Языки программирования разработаны быть эффективным способом программирования ЦПУ с возможностью представления высокоуровневых концепций. Языкам программирования не приходится иметь дело с ограничениями аппаратуры; их главная задача - простота использования и выразительность. Языки программирования легче понимаются людьми, они ближе к естественным языкам:
if (a_card_has_been_played()) { display_the_card(); }

Однако языки программирования придерживаются гораздо более строгих и формальных правил, чем любой язык, на котором говорят.

Компилируемые языки

В некоторых языках программирования инструкции должны быть скомпилированы прежде, чем стать исполняемой программой. Такие языки создают быстро выполняющиеся программы, но процесс разработки включает в себя два основных шага: написание программы и ее компиляцию.

В общем случае компилируемые языки помогают в обнаружении ошибок даже до того, как программа начинает выполняться.

D - компилируемый язык.

Интерпретируемые языки

Некоторые языки программирования не требует компиляции. Такие языки называются интерпретируемыми . Программа может запущена прямо из свеженапечатанного исходного кода. Некоторые примеры интерпретируемых языков: Python, Ruby и Perl. Так как этап компиляции отсутствует, для таких языков разработка программы может быть проще. С другой стороны, так как инструкции программы должны быть разобраны для интерпретации каждый раз, когда программа запускается, программа на таких языках медленнее, чем их эквиваленты, написанные на компилируемых языках.

В общем случае для интерпретируемых языков, многие типы ошибок в программе не могут быть обнаружены до момента начала выполнения.

Компилятор

Назначение компилятора - трансляция: он транслирует программы, написанные на языке программирования, в машинный код. Это перевод из языка программиста на язык ЦПУ. Такая трансляция называется компиляцией . Каждый компилятор понимает какой-то конкретный язык программирования и описывается, как компилятор для этого языка, например «компилятор для D».

Ошибки компиляции

Так как компилятор компилирует программу согласно правилам языка, он останавливает компиляцию как только достигает некорректных инструкций. Некорректные инструкции - те, которые выбиваются из спецификаций языка. Проблемы, такие как: несоответсвующие скобки, отсутствующая точка с запятой, ключевое слово с опечаткой и т.д. - все вызывают ошибки компиляции.

Также компилятор генерирует предупреждения компиляции , когда он видит подозрительный кусок кода, который может вызывать беспокойство, но не обязательно является ошибкой. Однако, предупреждения практически всегда указывают на настоящую ошибку или плохой стиль, поэтому самая распространенная практика - рассматривать большинство или все предупреждения как ошибки.

Фундаментальные типы

Ранее мы выяснили, что мозгом компьютера является ЦПУ. Большинство задач программы выполняются на ЦПУ, и остальные распределены по другим частям компьютера.

Наименьшая единица данных в компьтере называется битом , которая может принимать значения 0 или 1.

Так как тип данных, который может содержать только значения 0 или 1 имел бы очень ограниченное применение, ЦПУ определяет бОльшие типы данных, которые являются комбинациями из более одного бита. Например, байт содержит 8 битов. Наиболее производительный тип данных определяет битность ЦПУ: 32-битный ЦПУ, 64-битный ЦПУ и т.п.

Типов, определенных ЦПУ, все еще недостаточно: они не могут описать высокоуровневые понятия, как имя студента или игральная карта . D предоставляет множество полезных типов данных, но даже этих типов не хватает для описания многих высокоуровневых концепций. Такие концепции должны быть определены программистом как структуры (struct) или классы (class), которые мы увидим в следующих главах.

Фундаментальные типы D очень похожи на фундаментальные типы многих других языков, как показано в следующей таблице. Термины, появляющиеся в этой таблице, объяснены ниже:

Тип Определение Начальное значение
bool Логическое значение Истина/Ложь false
byte 8 битное число со знаком 0
ubyte 8 битное число без знака 0
short 16 битное число со знаком 0
ushort 16 битное число без знака 0
int 32 битное число соз знаком 0
uint 32 битное число без знака 0
long 64 битное число со знаком 0
ulong 64 битное число без знака 0
float 32 битное действительное число с плавающей точкой float.nan
double 64 битное действительное число с плавающей точкой double.nan
real наибольшое число с плавающей точкой, которое поддерживается оборудованием real.nan
ifloat мнимая часть комплексного числа для float float.nan * 1.0i
idouble мнимая часть комплексного числа для double double.nan * 1.0i
ireal мнимая часть комплексного числа для real real.nan * 1.0i
cfloat комплексный вариант float float.nan + float.nan * 1.0i
cdouble комплексный вариант double double.nan + double.nan * 1.0i
creal комплексный вариант real real.nan + real.nan * 1.0i
char символ UTF-8 (code point) 0xFF
wchar символ UTF-16 (code point) 0xFFFF
dchar символ UTF-32 (code point) 0x0000FFFF

В довесок к вышеперечисленным, ключевое слово void описывает сущности не имеющие типа . Ключевые слова cent и ucent зарезервированы для будущего использования для представления знаковых и безнаковых 128-битных значений.

Вы можете использовать int для большинства значений, до тех пор пока нет особых причин не делать это. Рассмотрите double для представления понятий, которые имеют дробную часть.

Разъяснения понятий, представленных в таблице

Логическое значение : тип логического выражения, имеющий значения true для истины и false для лжи.

Тип со знаком: Тип, который может принимать отрицательные и положительные значения. Например, byte может иметь значения от 0 до 255. Буква u в начале названия этих типов взята от слова unsigned .

Число с плавающей точкой: Тип может представлять значения с десятичной дробной частью, как у 1.25. Точность вычислений с плавающей точкой напрямую зависит от числа битов в типе: больше число битов, получаем более точные результаты.

Только числа с плавающей точкой могут представлять десятичные дроби; целочисленные типы (например, int ) могут держать только такие значения, как 1 и 2.

Комлексные типы чисел: Эти типы могут представлять комплексные числа из математики.

Мнимые типы чисел: Эти типы могут представлять только мнимую часть комплексных чисел. Буква i , которая находится в колонке начальных значений, в математике является квадратным корнем из -1.

nan: Сокращение от «not a number», представляющее некорректное значение с плавающей точкой .

Комментарии переводчика

Может показаться странным, что для чисел с плавающей точкой используются NaN значения как инициализаторы. Оффициальное объяснение от разработчиков (хотя я не согласен с этой позицией):

NaN"ы обладают интересным свойством, что в какой бы операции они не использовались, то в результате получается снова NaN. Поэтому NaN будет распространяться и будет результатом любых вычислений, где он был использован. Это означает, что внезапно появляющийся NaN является недвусмысленным индикатором того, что была использована непроиницилизированная переменная.

Если бы 0.0 использовался как начальное значение, его последствия легко было бы не заметить на выходе, поэтому если инициализация по умолчанию была непреднамеренная, баг мог бы остаться незамеченным.

Не подразумевается, что инициализатор по умолчанию должен быть полезным значением, его цель - вскрытие багов. NaN хорошо подходит под эту роль.

Но, конечно, компилятор может обнаружить и сгенерировать ошибку о переменных, которые не были проинициализированы? В большинстве случаев он может, но не всегда, и то, что он может, зависит от сложности внутреннего анализа потоков данных. Поэтому надежда на этот механизм - непереносимое и ненадежное решение.

Из-за особенностей реализации ЦПУ, NaN отсутствует для целочисленных, поэтому вместо этого D использует 0. Нулевое значение не имеет таких преимуществ для обнаружения ошибок, какими обладает NaN, но, по крайней мере, ошибки от непреднамеренной инициализации будут повторимы и поэтому более отлаживаемыми.

Свойства типов

В D у типов есть свойства . Чтобы получить значение свойства, нужно написать имя свойства после типа через точку. Например, sizeof свойство int вызывается так: int.sizeof . В этой главе рассматриваются только следующие четыре атрибута:
  • stringof: имя типа
  • sizeof: размер типа в байтах (для кол-ва битов умножьте на 8)
  • min: минимальное значение, которое может принимать тип
  • max: максимальное значение, которое может принимать тип

Программа, которая печатает эти свойства для int

import std.stdio ;

void main()
{
writeln("Тип: " , int .stringof ) ;
writeln("Длина в байтах: " , int .sizeof ) ;
writeln("Минимальное значение: " , int .min ) ;
writeln("Максимальное значение: " , int .max ) ;
}


Примечания переводчика

Некоторые типы имеют другие свойства, например float и double не имеют свойства min , вместо него используется -float.max и -double.max , .

size_t

Вы также встретитесь с типом size_t , имя которого расшифровывается как «size type». Он не является самостоятельным типом, а псевдонимом безнакового типа, которого хватит для представления всех возможных адресов в памяти. Поэтому этот тип зависит от системы: uint на 32-х битных, ulong для 64-х битных системах и т.д.

Можно использовать свойство .stringof , чтобы увидеть на какой тип ссылается size_t на вашей системе:

Код

import std.stdio ;

void main()
{
writeln(size_t .stringof ) ;
}

Вывод на моей системе:
ulong

Упражнения

Распечатайте свойства других типов.

Примечание :Нельзя использовать зарезервированные типы cent и ucent в любой программе; как исключение, void не имеет свойств .min и .max .

Решение

import std.stdio ;

void main()
{
writeln("Тип: " , short .stringof ) ;
writeln("Размер в байтах: " , short .sizeof ) ;
writeln("Минимальное значение: " , short .min ) ;
writeln("Максимальное занчение: " , short .max ) ;

Writeln() ;

Writeln("Тип: " , ulong .stringof ) ;
writeln("Размер в байтах: " , ulong .sizeof ) ;
writeln("Минимальное значение: " , ulong .min ) ;
writeln("Максимальное занчение: " , ulong .max ) ;
}



Базовый материал

Оператор присваивания и порядок вычислений

Первые два камня преткновения, которые ждут изучающих программирование, это - оператор присваивания и порядок вычислений.

Оператор присваивания
Вы будете встречать подобные строчки практически во всех программах, практически во всех языках программирования:
a = 10;

Значение этой строчки - «сделай значение a равным 10». Аналогично следующая строчка обозначает «сделай значение b равным 20»:
b = 20;

На основе вышеизложенной информации что можно сказать о следущей строчке?
a = b;

К сожалению, эта строчка не содержит оператор сравнения из математики, который, я предполагаю, все знают. Выражение выше не означает «a равно b»! Когда мы используем ту же логику, что и в предыдущих двух строчках, выражение выше должно означать «сделай значение a равным значению b ».

Хорошо известный символ = в математике имеет совершенно другой смысл в программировании: «сделать значение слева равным значению с правой стороны».

Порядок вычислений
Операции программы выполняются шаг за шагом в определенном порядке. Предыдущие три выражения в программе можно увидеть в следующем порядке:
a = 10; b = 20; a = b;

Смысл этих строк вместе: «сделай значение a равным 10, затем сделай значение b равным 20, затем сделай значение a равным значению b ». Соответственно, после выполнения этих трех операций оба значения a и b будут равны 20.

Упражнение

Изучите, как следующие три операции меняют местами значения a и b . Если в начале их значения были равны 1 и 2 соответственно, то после выполнения операций значения становятся равны 2 и 1:
c = a; a = b; b = c;

Решение

Значения a , b и c напечатаны справой стороны каждой операции:
в начале → a 1, b 2, c неважно c = a → a 1, b 2, c 1 a = b → a 2, b 2, c 1 b = c → a 2, b 1, c 1
В конце значения a и b меняются местами.


Теги:

  • dlang
  • tutorials
  • tutorials d
Добавить метки

Существует несколько подходов к определению семантики языков программирования.

Наиболее широко распространены разновидности следующих трёх: операционного, денотационного (математического) и деривационного (аксиоматического).

При описании семантики в рамках операционного подхода обычно исполнение конструкций языка программирования интерпретируется с помощью некоторой воображаемой (абстрактной) ЭВМ.

Деривационная семантика описывает последствия выполнения конструкций языка с помощью языка логики и задания пред- и постусловий. Денотационная семантика оперирует понятиями, типичными для математики -- множества, соответствия, а также суждения, утверждения и др.

Язык программирования строится в соответствии с той или иной базовой моделью вычислений и парадигмой программирования.

Несмотря на то, что большинство языков ориентировано на императивную модель вычислений, задаваемую фоннеймановской архитектурой ЭВМ, существуют и другие подходы. Можно упомянуть языки со стековой вычислительной моделью (Forth, Factor, Postscript и др.), а также функциональное (Лисп, Haskell, ML и др.) и логическое программирование (Пролог) и язык Рефал, основанный на модели вычислений, введённой советским математиком А.А. Марковым-младшим.

В настоящее время также активно развиваются проблемно-ориентированные, декларативные и визуальные языки программирования.

Компилируемые и интерпретируемые языки

Языки программирования могут быть разделены на компилируемые и интерпретируемые.

Программа на компилируемом языке при помощи специальной программы компилятора преобразуется (компилируется) в набор инструкций для данного типа процессора (машинный код) и далее записывается в исполнимый модуль, который может быть запущен на выполнение как отдельная программа. Другими словами, компилятор переводит исходный текст программы с языка программирования высокого уровня в двоичные коды инструкций процессора.

Если программа написана на интерпретируемом языке, то интерпретатор непосредственно выполняет (интерпретирует) исходный текст без предварительного перевода. При этом программа остаётся на исходном языке и не может быть запущена без интерпретатора. Можно сказать, что процессор компьютера -- это интерпретатор машинного кода.

Кратко говоря, компилятор переводит исходный текст программы на машинный язык сразу и целиком, создавая при этом отдельную исполняемую программу, а интерпретатор выполняет исходный текст прямо во время исполнения программы.

Разделение на компилируемые и интерпретируемые языки является несколько условным. Так, для любого традиционно компилируемого языка, как, например, Паскаль, можно написать интерпретатор. Кроме того, большинство современных «чистых» интерпретаторов не исполняют конструкции языка непосредственно, а компилируют их в некоторое высокоуровневое промежуточное представление (например, с разыменованием переменных и раскрытием макросов).

Для любого интерпретируемого языка можно создать компилятор -- например, язык Лисп, изначально интерпретируемый, может компилироваться без каких бы то ни было ограничений. Создаваемый во время исполнения программы код может так же динамически компилироваться во время исполнения.

Как правило, скомпилированные программы выполняются быстрее и не требуют для выполнения дополнительных программ, так как уже переведены на машинный язык. Вместе с тем, при каждом изменении текста программы требуется её перекомпиляция, что создаёт трудности при разработке. Кроме того, скомпилированная программа может выполняться только на том же типе компьютеров и, как правило, под той же операционной системой, на которую был рассчитан компилятор. Чтобы создать исполняемый файл для машины другого типа, требуется новая компиляция.

Интерпретируемые языки обладают некоторыми специфическими дополнительными возможностями (см. выше), кроме того, программы на них можно запускать сразу же после изменения, что облегчает разработку. Программа на интерпретируемом языке может быть зачастую запущена на разных типах машин и операционных систем без дополнительных усилий.

Однако интерпретируемые программы выполняются заметно медленнее, чем компилируемые, кроме того, они не могут выполняться без дополнительной программы-интерпретатора.

Некоторые языки, например, Java и C#, находятся между компилируемыми и интерпретируемыми. А именно, программа компилируется не в машинный язык, а в машинно-независимый код низкого уровня, байт-код. Далее байт-код выполняется виртуальной машиной. Для выполнения байт-кода обычно используется интерпретация, хотя отдельные его части для ускорения работы программы могут быть транслированы в машинный код непосредственно во время выполнения программы по технологии компиляции «на лету» (Just-in-time compilation, JIT). Для Java байт-код исполняется виртуальной машиной Java (Java Virtual Machine, JVM), для C# -- Common Language Runtime.

Подобный подход в некотором смысле позволяет использовать плюсы как интерпретаторов, так и компиляторов. Следует упомянуть также оригинальный язык Форт(Forth) имеющий и интерпретатор и компилятор.

Современные языки программирования рассчитаны на использование ASCII, то есть доступность всех графических символов ASCII является необходимым и достаточным условием для записи любых конструкций языка. Управляющие символы ASCII используются ограниченно: допускаются только возврат каретки CR, перевод строки LF и горизонтальная табуляция HT (иногда также вертикальная табуляция VT и переход к следующей странице FF).

Подробнее по этой теме см.: Переносимый набор символов.

Ранние языки, возникшие в эпоху 6-битных символов, использовали более ограниченный набор. Например, алфавит Фортрана включает 49 символов (включая пробел): A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 = + - * / () . , $ " :

Заметным исключением является язык APL, в котором используется очень много специальных символов.

Использование символов за пределами ASCII (например, символов KOI8-R или символов Юникода) зависит от реализации: иногда они разрешаются только в комментариях и символьных/строковых константах, а иногда и в идентификаторах. В СССР существовали языки, где все ключевые слова писались русскими буквами, но большую популярность подобные языки не завоевали (исключение составляет. Встроенный язык программирования 1С: Предприятие).

Подробнее по этой теме см.: Русские языки программирования.

Расширение набора используемых символов сдерживается тем, что многие проекты по разработке программного обеспечения являются международными. Очень сложно было бы работать с кодом, где имена одних переменных записаны русскими буквами, других -- арабскими, а третьих -- китайскими иероглифами. Вместе с тем, для работы с текстовыми данными языки программирования нового поколения (Delphi 2006, C#, Java) поддерживают Unicode.

Языки программирования могут быть разделены на компилируемые и интерпретируемые.

Программа на компилируемом языке при помощи специальной программы компилятора преобразуется в набор инструкций для данного типа процессора и далее записывается в исполнимый модуль, который может быть запущен на выполнение как отдельная программа.

Интерпретируемые языки обладают некоторыми специфическими дополнительными возможностями, кроме того, программы на них можно запускать сразу же после изменения, что облегчает разработку. Программа на интерпретируемом языке может быть зачастую запущена на разных типах машин и операционных систем без дополнительных усилий.

Некоторые языки, например, Java и C#, находятся между компилируемыми и интерпретируемыми. А именно, программа компилируется не в машинный язык, а в машинно-независимый код низкого уровня, байт-код. Далее байт-код выполняется виртуальной машиной.

Язык программирования служит двум связанным между собой целям: он дает программисту аппарат для задания действий, которые должны быть выполнены, и формирует концепции, которыми пользуется программист, размышляя о том, что делать.

Первой цели идеально отвечает язык, который настолько "близок к машине", что всеми основными машинными аспектами можно легко и просто оперировать достаточно очевидным для программиста образом.

Второй цели идеально отвечает язык, который настолько "близок к решаемой задаче", чтобы концепции ее решения можно было выражать прямо и коротко.

Классификация языков программирования

Машинно – ориентированные языки

Машинно – ориентированные языки – это языки, наборы операторов и изобразительные средства которых существенно зависят от особенностей ЭВМ (внутреннего языка, структуры памяти и т.д.).

Машинно-ориентированные языки по степени автоматического программирования подразделяются на классы:

1. Машинный язык

2. Языки Символического Кодирования

3. Автокоды

Машинно – независимые языки

Машинно – независимые языки – это средство описания алгоритмов решения задач и информации, подлежащей обработке. Они удобны в использовании для широкого круга пользователей и не требуют от них знания особенностей организации функционирования ЭВМ и ВС.

Подобные языки получили название высокоуровневых языков программирования. Программы, составляемые на таких языках, представляют собой последовательности операторов, структурированные согласно правилам рассматривания языка(задачи, сегменты, блоки и т.д.). Операторы языка описывают действия, которые должна выполнять система после трансляции программы на машинном языке.

Машинно-независимые языки подразделяются на классы:

1. Проблемно-ориентированные языки

2. Универсальные языки

3. Диалоговые языки

4. Непроцедурные языки

18.Обзор языков программирования

Языки программирования компьютеров делятся на 2 основные группы:

1) языки низкого уровня;

2) языки высокого уровня.

К языкам низкого уровня относятся языки Ассемблера. Свое название они получили от имени системной программы Ассемблер, которая преобразует исходные программы, написанные на таких языках, непосредственно в коды машинных команд.

Частями здесь служат операторы, а результатом сборки последовательность машинных команд. Язык Ассемблера объединяет в себе достоинства языка машинных команд и некоторые черты языков высокого уровня.

Ассемблер позволяет также гибко и полно использовать технические возможности компьютера, как и язык машинных команд. Транслятор исходных программ в Ассемблере проще транслятора, требующегося для языка программирования высокого уровня. На Ассемблере можно написать столь же эффективную по размеру и времени выполнения программу, как и программу на языке машинных команд.

Фортран

Фортран самый первый из языков высокого уровня (разработан Бэкусом в начале 1950-х годов) и широко распространенный язык, особенно среди пользователей, которые занимаются численным моделированием. Это объясняется несколькими причинами:

1. существованием огромных фондов прикладных программ на Фортране, накопленных за эти годы, а также наличием огромного количества программистов, эффективно использующих этот язык;

2. наличием эффективных трансляторов Фортрана на всех типах ЭВМ, причем версии для различных машин достаточно стандартизированы и перенос программ с машины на машину обычно не составляет больших трудностей;

3. изначальной направленностью Фортрана на физико-математические и технические приложения; в частности, это проявилось в том, что в течение долгого времени он оставался единственным языком со встроенным комплексным типом переменных и большим набором встроенных функций для работы с такими переменными.

БЕЙСИК

Бейсик (BASIC - Beginner’s All-Purpose Symbolic Instruction Code – “универсальный символический код инструкций для начинающих”). Прямой потомок Фортрана и до сих пор самый популярный язык программирования для персональных компьютеров.

Появился Бейсик в 1963 году. Как и любые преимущества, простота Бейсика оборачивалась, особенно в ранних версиях трудностями структурирования; кроме того, Бейсик не допускал рекурсию – интересный прием, позволяющий составлять эффективные и в то же время короткие программы.

Кобол

Кобол - это один из первых языков программирования, появившийся в 1959, разработанный прежде всего для исследований в экономической сфере.

Язык позволяет эффективно работать с большим количеством данных, он насыщен разнообразными возможностями поиска, сортировки и распределения.

О программах на Коболе, основанных на широком использовании английского языка, говорят, что они понятны даже тем, кто не владеет Коболом, поскольку тексты на этом языке программирования не нуждаются в каких-либо специальных комментариях. Подобные программы принято называть самодокументирующимися.

Паскаль

Язык программирования Паскаль был разработан профессором кафедры вычислительной техники Швейцарского Федерального института технологии Николасом Виртом в 1968 году как альтернатива существующим и все усложняющимся языкам программирования, таким, как PL/1, Algol, Fortran.

Основные причины популярности Паскаля заключаются в следующем:

1. простота языка позволяет быстро его освоить и создавать алгоритмически сложные программы

2. развитые средства представления структур данных обеспечивают удобство работы как с числовой, так и с символьной и битовой информацией

3. наличие специальных методик создания трансляторов с Паскаля упростило их разработку и способствовало широкому распространению языка

4. оптимизирующие свойства трансляторов с Паскаля позволяют создавать эффективные программы. Это послужило одной из причин использования Паскаля в качестве языка системного программирования

5. в языке Паскаль реализуются идеи структурного программирования, что делает программу наглядной и дает хорошие возможности для разработки и отладки

Сотрудник фирмы Bell Labs Денис Ритчи создал язык Си в 1972 году во время совместной работы с Кеном Томпсоном, как инструментальное средство для реализации операционной системы Unix, однако популярность этого языка быстро переросла рамки конкретной операционной системы и конкретных задач системного программирования.

В настоящее время любая инструментальная и операционная система не может считаться полной если в ее состав не входит компилятор языка Си.

Си является орудием системного программиста и позволяет глубоко влезать в самые тонкие механизмы обработки информации на ЭВМ. Хотя язык требует от программиста высокой дисциплины, он не строг в формальных претензиях и допускает краткие формулировки.

Си – современный язык. Он включает в себя те управляющие конструкции, которые рекомендованы теорией и практикой программирования. Его структура побуждает программиста использовать в своей работе нисходящее проектирование, структурное программирование и пошаговую разработку модулей.

Си – мощный и гибкий язык. Большая часть операционной системы Unix, компиляторы и интерпретаторы языков Фортран, Паскаль, Лисп, и Бейсик написаны именно с его помощью.

Язык C++ появился в начале 80-х годов. Созданный Бьерном Страуструпом с первоначальной целью избавить себя и своих друзей от программирования на ассемблере, Си или различных других языках высокого уровня.

По мнению автора языка, различие между идеологией Си и C++ заключается примерно в следующем: программа на Си отражает “способ мышления” процессора, а C++ - способ мышления программиста. Отвечая требованиям современного программирования, C++ делает акцент на разработке новых типов данных наиболее полно соответствующих концепциям выбранной области знаний и задачам приложения. Класс является ключевым понятием C++.

Язык С++ является средством объектного программирования, новейшей методики проектирования и реализации программ, которая в текущем десятилетии, скорее всего, заменит традиционное процедурное программирование.

Язык создан в основном в 1975 - 1980 годах в результате грандиозного проекта, предпринятого Министерством Обороны США с целью разработать единый язык программирования для так называемых встроенных систем (т. е. систем управления автоматизированными комплексами, работающими в реальном времени).

PL/1 разработан в 1964-1965 годах фирмой IBM. PL/1 относится к числу универсальных языков, т. е. позволяет решать задачи из разных областей: численные расчеты, текстовая обработка, экономические задачи и т. д.

PL/1 содержит все основные конструкции, характерные для так называемых языков высокого уровня, а также ряд специфичных средств, удобных для практического программирования. Язык напоминает конструктор с большим числом деталей – пользователю достаточно освоить только те части языка, которые ему практически необходимы. Его операторы довольно емки, что часто позволяет получить запись программы более компактную, чем на других языках. Знающий PL/1 программист без труда осваивает любой другой язык того же или близкого класса.

Модула

Можно считать, что история языка Модула начинается в 1980 году, когда Никлаус Вирт, один из выдающихся специалистов по теории информации, известный большинству специалистов по вычислительной технике в основном как создатель языка Паскаль, опубликовал описание нового языка программирования, названного им Модула.

В отличие от Паскаля, который был по замыслу языком для обучения программирования, Модула с самого начала представлял собой язык для профессиональных системных программистов, продолжая лучшие традиции своего предшественника и обогащая их новыми идеями, соответствующих таким требованиям к языкам программирования, как структурность, модульность и способность к расширению.

Лисп

Язык Лисп был предложен Дж. Маккарти в работе в 1960 году и ориентирован на разработку программ для решения задач не численного характера. Английское название этого языка – LISP является аббревиатурой выражения LISt Processing (обработка списков) и хорошо подчеркивает основную область его применения. Понятие “список” оказалось очень емким. В виде списков удобно представлять алгебраические выражения, графы, элементы конечных групп, множества, правила вывода и многие другие сложные объекты.

После появления Лиспа различными авторами был предложен целый ряд других алгоритмических языков ориентированных на решение задач в области искусственного интеллекта, среди которых можно отметить Плэнер, Снобол, Рефал, Пролог. Однако это не помешало Лиспу остаться наиболее популярным языком для решения таких задач. На протяжении почти сорокалетней истории его существования появился ряд диалектов этого языка: Common LISP, Mac LISP, Inter LISP, Standard LISP и др.

Язык программирования Лисп предназначен в первую очередь для обработки символьной информации. Поэтому естественно, что в мире Лиспа числа играют далеко не главную роль. Основные типы данных в Лиспе называются “атом” и “точечная пара”.

19.Описание линейного процесса обработки данных с помощью блок-схем

Схе́ма - графическое представление определения, анализа или метода решения задачи, в котором используются символы для отображения операций, данных, потока, оборудования и т. д.

Блок-схема - распространенный тип схем (графических моделей), описывающих алгоритмы или процессы, в которых отдельные шаги изображаются в виде блоков различной формы, соединенных между собой линиями, указывающими направление последовательности.

Основные элементы схем алгоритма:

Наименование Обозначение Функция
Блок начало-конец (пуск-остановка) Элемент отображает вход из внешней среды или выход из неё (наиболее частое применение − начало и конец программы). Внутри фигуры записывается соответствующее действие.
Блок вычислений (вычислительный блок) Выполнение одной или нескольких операций, обработка данных любого вида (изменение значения данных, формы представления, расположения). Внутри фигуры записывают непосредственно сами операции, например, операцию присваивания: a = 10*b + c.
Логический блок (блок условия) Отображает решение или функцию переключательного типа с одним входом и двумя или более альтернативными выходами, из которых только один может быть выбран после вычисления условий, определенных внутри этого элемента. Вход в элемент обозначается линией, входящей обычно в верхнюю вершину элемента. Если выходов два или три, то обычно каждый выход обозначается линией, выходящей из оставшихся вершин (боковых и нижней). Если выходов больше трех, то их следует показывать одной линией, выходящей из вершины (чаще нижней) элемента, которая затем разветвляется. Соответствующие результаты вычислений могут записываться рядом с линиями, отображающими эти пути. Примеры решения: в общем случае − сравнение (три выхода: >, <, =); в программировании − условные операторы if (два выхода: true, false) и case (множество выходов).
Предопределённый процесс Символ отображает выполнение процесса, состоящего из одной или нескольких операций, который определен в другом месте программы (в подпрограмме, модуле). Внутри символа записывается название процесса и передаваемые в него данные. Например, в программировании − вызов процедуры или функции.
Данные (ввод-вывод) Преобразование данных в форму, пригодную для обработки (ввод) или отображения результатов обработки (вывод). Данный символ не определяет носителя данных (для указания типа носителя данных используются специфические символы).
Граница цикла Символ состоит из двух частей − соответственно, начало и конец цикла − операции, выполняемые внутри цикла, размещаются между ними. Условия цикла и приращения записываются внутри символа начала или конца цикла − в зависимости от типа организации цикла. Часто для изображения на блок-схеме цикла вместо данного символа используют символ условия, указывая в нём решение, а одну из линий выхода замыкают выше в блок-схеме (перед операциями цикла).
Соединитель Символ отображает вход в часть схемы и выход из другой части этой схемы. Используется для обрыва линии и продолжения её в другом месте (для избежания излишних пересечений или слишком длинных линий, а также, если схема состоит из нескольких страниц). Соответствующие соединительные символы должны иметь одинаковое (при том уникальное) обозначение.