Учебное пособие по дисциплине Разработка языков программирования высокого уровня
Скачать 1.74 Mb.
|
2.2 Сущность концепции связыванияРеализация языка программирования основывается на концепции связывания. Связывание - это процесс установления связи между объектом и его атрибутом (свойством). Эффективность столь сложного процесса, как обработка программного кода в ЭВМ, которая состоит их 3-х основных этапов - компиляция кода. его редактирование и выполнение - напрямую зависит от того. как организован процесс связывания переменной и ее характеристик . Рассмотрим простой пример из двух операторов, демонстрирующий всю сложность и многоаспектность реализации концепции связывания. int i; i = i + 5; где при компиляции переменная i должна быть связана с типом int; при разработке языка программирования должно быть связано множество возможных числовых значений с типом int, а также определено множество возможных смыслов символа «+». включая операцию сложения; во время выполнения операторов числовая константа 5 должна быть связана с некоторой ячейкой ОП; при разработке компилятора должно быть определено внутреннее представление целого числа, в соответствии с которым константа 5 окажется содержимым ячейки ОП. Связывание может происходить: _ на этапе компиляции - статическое связывание, при этом оно более надежное, т.к. не изменяется в ходе обработки и выполнения программы, занимает меньше времени, не требует дополнительных ресурсов; _ на этапе выполнения программы -динамическое связывание, является более затратным по времени и по ресурсам, менее надежно с точки зрения организации процесса обработки. Далее будут рассмотрены вопросы организации связывания переменной с ее основными характеристиками - типом данных, временем жизни, областью видимости, т.к. именно с ними связано выполнение многих важных и сложных механизмов. 2.3 Тип переменнойПрежде чем рассматривать способы связывания переменной с ее типом, необходимо поговорить о самом понятии «тип данных», поэтому в данном разделе дается определение типа данных, описываются механизмы контроля типа и уровни типизации языка. Эти вопросы имеют особую значимость, т.к. определяют надежность ЯП. Определение. Тип переменной (данных) определяет (специфицирует): множество значений, которые может принимать переменная данного типа; множество операций, определенных над объектами данного типа; внутреннее представление данных и способ доступа к ним. Следствие 1. Если дан новый тип, то можно описать и инициировать, т.е. определить значение объекта этого типа. Следствие 2. Если даны две переменные некоторого типа, то их можно сравнить, по крайней мере, на равенство или неравенство. Следствие 3. Если два типа отличаются с точки зрения указанных свойств, то они считаются различными. Это определение говорит о том, что основа надежности ЯП заключается в возможности проверить, что любая операция, выполняемая над объектом данных соответствует специфицируемому типу этого объекта. Если два типа отличаются с точки зрения перечисленных свойств, то они считаются различными. Например, типы Array [l ..10] of real ; и Array [ l ..11] of real; различны. Контрольтипов Определенuе. Проверка, обеспечивающая анализ совместимости типов операндов оператора, называется контролем типов. Она заключается в определении типов выражений и их согласованности с правилами типизации языка программирования. Согласованность типов операндов может быть обеспечена: вручную (программист следит сам, чтобы типы были согласованы); - автоматически (с помощью функций преобразования типов или операций приведения типа). Операции приведения типа могут быть: суживающие -более широкий тип преобразуется к более узкому (float к типу integer); расширяющие. Расширяющее преобразование почти всегда безопасно. Проблема здесь может возникнуть только в следующем. В некоторых реализациях целые числа имеют размер 32 бита, что позволяет хранить 9 значащих десятичных цифр. Если значения с плавающей точкой также имеют размер 32 бита, то это 7 десятичных цифр. Поэтому точность в 2 цифры потеряется . Операции приведения могут быть реализованы двумя способами: явно, с помощью специальных функций (int(x), float(x), str(x) и т.д.); неявно, реализуется по правилам, заложенным при разработке ЯП. В теории языков нет единого мнения об использовании приведения типов арифметических выражений. С одной стороны, повышается гибкость программ от введения всевозможных приведений, с другой - приведение аннулирует выгоды от проверки типов и тем самым уменьшает надежность. Пример 1. void main() { int а,b,с ; float d; а = b* d; } Язык С допускает смешанные выражения, поэтому компилятор приведет Ь к типу float, произведет умножение и результат преобразует к типу int. Хотя возможен и другой порядок действий: вначале преобразовать d к типу int, а потом совершать арифметику. Выбор варианта производится при разработке компилятора, но ни тот, ни другой не гарантирует правильность результата из за использования суживающего приведения . В связи с этим в некоторых ЯП (АДА и Модула2) введено ограничение на смешения операндов. В большинстве же языков ограничений нет. Хотя наблюдение за приведением очень затратный процесс, т.к. и поверка, и преобразование происходит при выполнении программы. Контроль типов может выполняться: только при компиляции и, если все ошибки типов выявляются при компиляции, то такой язык называется с полнымстатическимконтролемтипов; только при выполнении -если все ошибки выявлены при выполнении, то такой язык называется с полнымдинамическимконтролемтипов; и при компиляции, и при выполнении (язык со смешаннымконтролемтипов). 2.4 Эквивалентность типов Если реализуется оператор х := <выражение>, то он реализуется только в том случае, когда типы операторов справа и слева эквивалентны, т.е. необходимо определить правила вычисления эквивалентности типов данных. Существуют два способа определения эквивалентности типов, которые принято использовать для структурных типов данных: Эквивалентность (совместимость) по структуре или структурнаяэквивалентность- две переменные имеют совместимые типы в том случае, если у их типов одинаковые структуры. Эквивалентность типов по имени или именнаяэквивалентность- две переменные имеют совместимые типы в том случае, если имена их типов одинаковы (в независимости от того, какова их структура и множество значений). Пример 2. Program А; type Т1 = array (1. . 10) of integer; type Т2 = array (1. . 10) of integer; var Х : array (1. . 1О) of integer; Y:T1, Z: Т2; begin Х:=У; X:=Z; Z:=Y end. Здесь, в случае эквивалентности по структуре типы переменных Х, У, Z будут считаться одинаковыми, а в случае эквивалентности по имени - различными. С точки зрения удовлетворения правилам эквивалентности, в языках вводится понятие производных типов и подтипов. Производный тип строится на основе базового типа путем определения именного, включающего логически связанные объекты, задачи. Производный тип наследует значения и операции базового типа. Пример 3. Туре Возраст = integer end; var begin end. этот_возвраст, общий_возраст :Возраст; i :integer; общий_возраст:=0; while (i<= 10) do readln (этот_возраст); общий_возраст:=общий_возраст+этот_возраст; Подтипы позволяют ограничивать множество значений и множество операций базового типа: subtype возраст range [15...30]:int; рост range [150...210]:int; индекс range [1...100]:int; .Уровни типизацииЯП Правила типизации языка предполагают: наличие объявления типов данных; реализация связывания типов с переменной; определение типов смешанных арифметических выражений; наличие правил преобразования типов. Определение. Если для языка определены правила типизации, то язык считается типизированным, если эти правила для языка не определены - язык не типизирован. При этом языки имеют несколько уровней типизации: Слабая типизация - язык, в котором информация о типе используется только для обеспечения корректности представления данных в ячейке. Например, для языка со слабой типизацией в операторах с char; с = 4; контроль типов ошибок не выявит. 2.Сильная типизация - язык, в котором осуществляется полный контроль типов (статический, динамический или смешанный), в таком языке ошибки типов выявляются все и всегда. З. Защитно-типизированный язык - язык, в котором операторы с возможными ошибками недопустимы . Сильная типизация обеспечивает высокую надежность. Pascal - сильноипизированный (за исключением вариантных записей) с элементами защитной типизации; Fortran - слаботипизированный, т.к. в языке нет проверки соответствия типов формальных и фактических параметров подпрограмм, а также переменных операторов EQUIVALENCE. Ada - почти сильнотипизированный , но позволяет программистам отключать проверку типов; С - слаботипизированный, имеются некоторые функции, параметры которых не подвергаются проверке, кроме того, для типа данных Union проверка не осуществляется, по крайней мере, в статике. |