Файл: Системы программирования как неотъемлемая часть ЭВМ.pdf

ВУЗ: Не указан

Категория: Курсовая работа

Дисциплина: Не указана

Добавлен: 06.04.2023

Просмотров: 125

Скачиваний: 2

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

В этом случае переменные могут получать только значения составных типов, причем фактический тип переменной формируется динамически при вычислении выражений. В то же время существует возможность объявлять типы переменных статически путем указания имени нужного типа (int, double, list, tuple, …) после ключевых слов var или def. Это позволит транслятору создавать эффективный код обработки данных примитивных типов, что может быть особенно важно для обработки векторов, содержащих элементы таких типов.

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

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

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

Достижению этой же цели служат разнообразные способы записи индексных выражений для векторов, близкие к математическим обозначениям и позволяющие организовывать неявную циклическую обработку нужных подмассивов любого вектора. В индексных выражениях можно использовать мнемонические обозначения нижней и верхней границ вектора, диапазоны и шаг изменения индексов. Например, следующий оператор умножает все элементы i-й строки матрицы на коэффициент k: matrix[ i ] [ _ .. ^ ] *= k;

Обозначение «..» в индексном выражении фактически организует неявный цикл перебора всех элементов вектора, находящихся в указанном диапазоне.

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

arr[2 * i + 1] = alpha[2 * i + 1] – beta[2 * i + 1]; то все, кроме первого, могут быть заменены ссылкой на него: arr[2 * i + 1] = alpha[#] – beta[#].

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


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

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

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

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

Модули могут включать в себя произвольное количество функций. Доступность функций для других модулей регулируется ключевыми словами public и private. Модули могут просто импортироваться, либо могут использоваться для создания одного или нескольких экземпляров, различающихся значениями константных полей и становящихся значениями переменных, через которые осуществляется доступ к их функциям.

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

Таким образом, в языке реализована возможность создавать и использовать объекты, но нет ни интерфейсов, ни наследования.

В языке имеется единственная управляющая конструкция by, позволяющая определять разветвления вычислений на две и большее количество ветвей (аналоги условных операторов и переключателей) и циклы. Имеются две разные формы этого оператора, отличающиеся способами формирования проверяемого условие и сопоставления его с образцами. Первая форма предполагает вычисление (впоследствии возможно перевычисление) одного значения, которое далее последовательно сопоставляется с несколькими образцами и, при совпадении, приводит к выполнению соответствующей ветки. Пример оператора ветвления в первой форме, вычисляющий очередное значение Сиракузской последовательности по значению очередного члена x: by x % 2 {of 0 : x \= 2; of 1 : x = 3 * x + 1;}


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

Сиракузской последовательности могут быть записаны так:

by { when x % 2 == 0 : x \= 2; else x = 3 * x + 1; }

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

by { when x == 1 : break; when x % 2 == 0 : x \= 2; again; else x = 3 * x + 1; again; }

Здесь: ‒ обе ветки, модифицирующие значения x, дополнены оператором again, осуществляющим возврат на начало выполнения оператора by; ‒ добавлена ветка с условием x == 1, обеспечивающая выход из цикла.

Кроме операторов break и again можно использовать оператор next, приводящий к выполнению следующей по тексту ветки без обработки условия ее выполнения. В форме break <label>; и again <label>; эти операторы могут быть использоваться для выхода или возврата на начало охватывающего оператора by, имеющего метку <label>. Отметим, что явное задание циклических вычислений в императивном стиле может использоваться вместо более дорогостоящих рекурсивных вызовов в функциональном стиле, которые, впрочем, тоже доступны.

Ожидается, что тестирование и отладка программ на языке El будут проще, чем в чисто императивных языках. Как обычно для языков функциональной парадигмы, это обусловлено тем, что в языке El нет ни глобальных переменных, ни указателей, нет побочного эффекта у функций (за исключением некоторых встроенных методов и ряда функций стандартных модулей, осуществляющих ввод-вывод), все функции чистые. Любое значение любой переменной формируется только внутри данной функции. Если функция полностью отлажена, то на ее работоспособность ничто извне повлиять не может. За это, конечно, тоже есть плата – необходимость копирования значений при передаче любых аргументов в функции и при возврате результатов.

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

Существование многих различных платформ (Linux, Windows, MacOS, …) приводит либо к необходимости реализации нескольких различных компиляторов для каждой из них, либо к решению создавать кроссплатформенный компилятор. Второй путь, очевидно, более предпочтителен, поэтому в качестве решения рассматривается двухэтапная компиляция: на первом этапе выполняется трансляция программы с языка El в платформно-независимое промежуточное представление, которое на втором этапе преобразуется в объектный код для целевой платформы с использованием специально предназначенного для этого средства.


В качестве такого инструмента из двух основных известных средств GCC и LLVM выбрана инфраструктура проектирования компиляторов LLVM. Эта инфраструктура реализует регистровую виртуальную машину и имеет собственный входной язык, называемый языком ассемблера. Разрабатываемый для языка El компилятор будет транслировать программы на язык ассемблера LLVM.

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

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

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

- процедурно-ориентированные;

- проблемно-ориентированные;

- объектно-ориентированные.

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

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

а) язык Фортран (Fortran). Является одним из первых языков программирования высокого уровня. К его основным достоинствам относится наличие огромного числа математических библиотек, поддержка работы с целыми, вещественными и комплексными числами высокой точности, встроенных средств обработки массивов.

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

б) язык Бейсик (Basic). Был разработан в 1964 г. в качестве языка для обучения программированию.

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

Одним из основных недостатков языка является то, что он поддерживает только операционные системы семейства Windows, DOS и Mac OS X, что значительно сужает сферы его применения. Также к недостаткам можно отнести низкую скорость работы и отсутствие механизма наследования реализации объектов.

в) язык Си (С) был создан в 1969-1973 годах в качестве языка системного программирования и первоначально предназначался для написания ОС UNIX. В 1980-е гг. язык С был дополнен инструментами объектно-ориентированного программирования и на основе него был создан язык C++.


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

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

г) язык Паскаль (Pascal). Был создан математиком Н. Виртом специально для обучения программированию. Однако со временем стал широко применяться для разработки программных средств в профессиональном программировании.

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

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

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

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

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

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