Описание Глагола
Главная     Глагол-2008 ►   Азбука ►   Задачи на Глаголе ►   Примеры приложений ►   ООП по Вирту ►   Среда разработки ►   Отладка программ ►   Отличия от Оберона ►   Отличия от Паскаля ►   Ассемблер ARM ►   Глагол для ARM ►   ? и Ответы
 
 glagol.png Программируем по-русски
 

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

Издатель Глагола
 

 

Руководство по языку программирования Глагол

Август 2014 г.

 
 
Пока глагол в сердцах людских,
Ниспосланный для битв и пира,
Не содрогнёт страстей мирских,
Певец — твоя ничтожна лира!
Леонид Ивáнов, 1999

ПЕВЕЦ, из сб. "Времени капели".

  Что на уме, то и на языке.




 
 

Оглавление

Объектно-ориентированное программирование по Вирту (из WiKi) ►
 
 


Введение

Коротко да ясно, оттого прекрасно.

Этот справочник содержит полное описание Глагола – языка программирования общего назначения, родственного языкам Паскаль и Оберон. Основное отличие Глагола от Паскаля и от Оберона-2 состоит в том, что в нём используются только русские служебные слова. Имена постоянных, переменных и задач могут записываться с использованием 4-х алфавитов в уникоде: Латинский, Русский, Украинский, Белорусский и доРеформенных букв /Ѣ – ять). Перечислим некоторые характерные черты этого языка.

Все данные имеют определённый ВИД. Существуют как простые ВИДы (5.1) – числовые (ШИРВЕЩ, ВЕЩ, ШИРЦЕЛ, ЦЕЛ, УЗКЦЕЛ, ЯЧЦЕЛ), знаковый (ЗНАК), логический (КЛЮЧ), множество (МНОЖ), так и составные ВИДы данныхРЯД (5.2) и НАБОР (5.3). Кроме составных, ещё имеются дополнительные ВИДы данных: ДОСТУП (5.4), БЕГУНОК (5.5) и ЗАДАЧА (5.6) (также см. 15). Вид НАБОР можно расширять новыми свойствами (т.е. полями данных и задач). Данные могут быть ПОСТоянными и ПЕРеменными.

Простейшие преобразования данных выполняются так называемыми действиями, которые, в основном, имеют соответствующие машинные команды. Действия можно объединять в выражения. В выражениях всегда должно соблюдаться соответствие ВИДов. Более сложный порядок для преобразования данных задаётся УКАЗаниями. Данные и последовательности УКАЗаний можно объединять в задачи и отделы.

Обычно приложение строится из нескольких отделов. Каждый отдел существует в двух представлениях: текстовом, с которым работает человек, и машинном, которое получается из соответствующего текстового представления с помощью преобразователя языка. Преобразватель Глагола (ПГ.exe) – это не компилятор. ПГ переводит тексты на Глаголе в файлы на языке Ассемблера и вызывает бесплатный компилятор NASMW.EXE (вер.0.98.36 от 13.03.2003), который переводит их в .obj файлы. Затем вызывается бесплатный EXE-сборщик ALink.exe или Link.exe из MS Visual Studio/1998, который и собирает исполняемое приложение Windows. При использовании Link.exe от Microsoft возможна отладка приложения Windows в среде Visual Studio 2003..2015. Это всё 32-х разрядные приложения Windows, но без многопоточности.

Таким понятиям языка, как ВИД, ПОСТоянная, ПЕРеменная, ЗАДАЧА и ОТДЕЛ ставятся в соответствие некоторые названия. Область действия этих названий ограничивается с помощью участков, которые могут быть вложенными. В роли таких участков выступают отделы, задачи и наборы.


1. Условные обозначения

Горе в чужой земле безъязыкому.

Язык описывается с помощью расширенных формул Бэкуса-Наура (РБНФ) (см. 15). Разновидности выражений отделяются знаком | (или). Квадратные скобки [] обозначают необязательность записанного в них выражения, а фигурные скобки {} обозначают его повторение (возможно 0 раз). Понятия языка (см. 3) начинаются с заглавной буквы (например, Указание), а слова языка или начинаются со строчной буквы (например, название), или записываются целиком заглавными буквами (например, ЗАДАЧА), или берутся в кавычки (например, ":=").

Когда в тексте приводится определение, то его главные слова подчёркиваются и выделяются цветом (например, вид данных). Так, глава 14 содержит определения понятий, которые используются при описании правил соответствия ВИДов. В тексте эти понятия выделены курсивом (например, одинаковый вид, равный вид).

Ниже в тексте, в примерах и в таблицах используются такие цветовые обозначения:

  • собственно текст программы на Глаголе;
  • простые виды ПЕРеменной [ЗНАК / МНОЖ / КЛЮЧ / ЦЕЛ, ШИРЦЕЛ, УЗКЦЕЛ, ЯЧЦЕЛ / ВЕЩ, ШИРВЕЩ];
  • составные виды ПЕРеменной [РЯД / НАБОР / ЦЕПЬ];
  • дополнительные виды ПЕРеменной [ДОСТУП / БЕГУНОК / ЗАДАЧА];
  • Логическая ПОСТоянная [ВКЛ / ОТКЛ] и [ПУСТО];
  • Логическое действие [И / ИЛИ / НЕ] или отношение [В / ЯВЛЯЕТСЯ (проверка вида переменной)];
  • Служебные слова в Предметно Описательном (объектно-ориентированном) Подходе: [ДЛЯ…ВИДА…КОН (локальная охрана/привратник вида)];
  • Служебные слова Глагола: указания [ОТДЕЛ / УКАЗ / КОН / …] или словесные действия [ДЕЛИТЬ, ОСТАТОК];
  • Особые служебные слова-выходы Глагола [ВОЗВРАТ / ВЫЗОВ / ВЫХОД / СТОП];
  • Встроенные задачи в Глаголе [МАКС / МИН / МОДУЛЬ / ЧЕТ / ДЛИНА/ РАЗМЕР / УЗК / ВЦЕЛ / ВЗНАК / ОБНУЛИТЬ / …];
  • Виды и задачи отдела ОБХОД: Ячейка / Цел8 / … / Цел64 / Вещ64 / Адрес / ПолучитьАдрес / Узк / … ;
  • Знак одиночный (не число), например 00X,…,0FX,…,FFX;
  • Знак – арифметического действия [*+-/], отношения [=#><], разделитель [:.;,:=.. | ^ ];
  • Скобки: () / [] / {};
  • Число или цифра;
  • "Цепочка знаков" или "строковая ПОСТоянная";
  • (* Пояснение в Глаголе *).

Ниже в тексте и в примерах могут встретиться такие обозначения:

           п, п1, п2 – переменная;
           Вп, Вп1, Вп2Вид переменной п, п1, п2;
           ДкВпВид ДОСТУП К виду Вп переменной п;
           ВвВид выражения в;
           ВдВид данных (например, в выражении в);

           ОпорВпОпорный Вид переменной-потомка п;
           ОпорВрОпорный Вид ряда р;
           ОписВОписатель Вида переменной;
           ОписОпорВОписатель Опорных Видов переменной-потомка;
           О или ВоВид НАБОР переменной о или Опорный Вид;
           Р или ВрВид НАБОР переменной р или расширение Опорного Вида, т.е. Р(О) или Вр(Во);
           ДкО или ДкВоВид ДОСТУП К О или Во;
           ДкР или ДкВрВид ДОСТУП К Р или Вр, т.е. ДкР(ДкО) или ДкВр(ДкВо);

           з – переменная вида ЗАДАЧА;
           мн – переменная вида МНОЖество (32 разряда);
           зн, зн1, зн2 – знаковая/символьная/текстовая переменная вида ЗНАК (8 разрядов);
           k, i, j, M, N – целые переменные вида ЦЕЛ (32 разряда);
           x, y – вещественные переменные вида ШИРВЕЩ (64 разряда);
           к, к1, к2 – логические переменные вида КЛЮЧЬ (32 разряда);

           ВпрВид формального параметра-приёмника в описании задачи;
           ВисВид фактического параметра-источника при вызове задачи;
           в – выражение-источник любого вида при вызове задачи;
           цепь – переменная-источник вида ЦЕПЬ при вызове задачи;
           ц – целое-источник при вызове задачи (32 разряда);
           шц – широкое целое-источник при вызове задачи (64 разряда);
           уц – узкое целое-источник при вызове задачи (16 разрядов);
           яц – ячейка целое-источник при вызове задачи (8 разрядов);
           шв – широкое вещественное-источник при вызове задачи (64 разряда);
           вещ – вещественное-источник при вызове задачи (широкое в 64 или обычное в 32 разряда);
           знак – знак-источник при вызове задачи;
           б – бегунок-источник при вызове задачи;
           р – ряд-источник при вызове задачи;
           н – набор-источник при вызове задачи;
           пД – доступ к переменной-источнику п вида НАБОР, РЯД или ЦЕПЬ при вызове задачи;
           рД – доступ к ряду-источнику р вида РЯД при вызове задачи;
           нД – доступ к набору-источнику н вида НАБОР при вызове задачи;
           цепьД – доступ к цепочке-источнику цепь вида ЦЕПЬ при вызове задачи;
см. также параграфы: 7.1. Данные , 9.2. Встроенные задачи.

 
 


2. Слова языка

Живое слово дороже мёртвой буквы.

Каждый язык строится из простейших выражений – слов. Слова неделимы и сами по себе обозначают некоторое содержание. В языке Глагол присутствует семь разновидностей слов: названия(1), числа(2), одиночные знаки(3), цепочки знаков(4), действия(5), указания(6) и разделители(7).

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

б) Заглавные и строчные буквы считаются различными (см. отличия от Паскаля).

в) Пробелы и концы строк, которые не разделяют смежные слова, не учитываются.

г) Между любыми двумя словами могут располагаться пояснения и указания для текстореза. Они не влияют на машинное представление приложения.

Пояснение – это произвольная последовательность знаков, начинающаяся с (* и оканчивающаяся *). Пояснения могут быть вложенными. Указания для текстореза начинаются с <* и оканчиваются *>.

Примеры:

(* Пояснение в Глаголе *)

Названия(1) – это последовательности букв и цифр, которые начинаются с буквы. Знак подчёркивания "_" считается буквой.

название

 =  буква {буква | цифра}

Примеры:

Слово1
ПолПи
i
знак
ДкЗолотоеЯйцо

Числа(2) используются для представления целых и вещественных чисел без знака. Целое число имеет ВИД данных, который является наименьшим целым ВИДом, способным хранить его значение (см. 5.1). Если запись целого числа оканчивается буквой H, то оно представлено в шестнадцатеричном виде, иначе оно представлено в десятичном виде (т.е. в десятичной системе счисления).

Примеры:

ПОСТ
  яц8 = -128;  (*  8-ми разрядное МИН(ЯЧЦЕЛ) *)
  уц16 = -129; (* 16-ти разрядное УЗКЦЕЛ *)
  и8 = 127;    (*  8-ми разрядное МАКС(ЯЧЦЕЛ) *)
  и16 = 128;   (* 16-ти разрядное УЗКЦЕЛ *)
  вещПи = 3.1416;     (* 32-х разрядное ВЕЩ *)
  швПи = 3.141592654; (* 64-х разрядное ШИРВЕЩ *)
  ПолПи = швПи/2;    (* 64-х разрядное ШИРВЕЩ *)

Вещественное число всегда содержит десятичную точку. Оно может также содержать десятичный порядок. Буква E (или D) означает "умножить на десять в степени". Если у вещественного числа порядок содержит букву D, то у него вид ШИРВЕЩ, иначе у него вид ВЕЩ.

число

 =  целое | вещественное

целое

 =  цифра {цифра} | цифра {цифра16} "H"

вещественное

 =  цифра {цифра} "." {цифра} [порядок]

порядок

 =  ("E" | "D") ["+" | "-"] цифра {цифра}

цифра16

 =  цифра | "A" | "B" | "C" | "D" | "E" | "F"

цифра

 =  "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"

Примеры:

Запись числа Вид данных Значение

123

ЯЧЦЕЛ

123

0FFFFFH

ЦЕЛ

1048575

0.031416E2

ВЕЩ

3.1416

1.23456789D-10

ШИРВЕЩ  

0.000000000123456789

Одиночные знаки(3) обозначаются порядковым номером знака в шестнадцатеричном виде с приписанной в конце буквой X.

одинзнак

 =  цифра {цифра16} "X"

Примеры:

00X0FXFFX

Цепочки знаков(4) – это последовательности печатных знаков, взятые в одиночные (') или двойные (") кавычки. Открывающая кавычка должна быть такой же, как и закрывающая, и не должна встречаться внутри цепочки знаков. Последовательность из знаков #nnnn, где nnnn – четырёхзначное шестнадцатеричное число, обозначает знак с кодом nnnn. Для знака # используется последовательность из ##. Количество знаков в цепочке называется её длиной. Цепочка из одного знака может использоваться везде, где допустим одиночный знак, и наоборот.

цепочка

 =  """ {знак} """ | "'" {знак} "'

знак

 =  печзнак
| "#" цифра16 цифра16
| "##"

Примеры:

'Сама (мышь) залезла в кувшин, а кричит: "Пусти!"'
"Зацепился за пень, #0D#0A да и стоит день."
"#0D"
"_1"
"1"
"##"
"Если А #23 Б, то"

Действия(5), указания(6) и разделители(7), перечисленные ниже – это знаки (арифметических действий [*+-/], отношений [=#><], разделители [:.;,:= | ]), пары знаков (скобки ()/[]/{}) и служебные слова (логическое действие [И / ИЛИ / НЕ], отношение [В (принадлежности к множеству) / ЯВЛЯЕТСЯ (проверка вида переменной)], вид [ЦЕПЬ / РЯД / НАБОР / ДОСТУП / БЕГУНОК / ЗАДАЧА], указание [ОТДЕЛ / ВИД / ПОСТ / ПЕР / УКАЗ / КОН /…], [ВОЗВРАТ / ВЫЗОВ / ВЫХОД] и [ДЛЯ…ВИДА ]). См. таблицу:

+

=

 В ЗАДАЧА ОТДЕЛ

-

#

ВИД И ПЕР[ЕМЕННЫЕ]

*

<

ВИДА ИЗ ПО

/

>

ВОЗВРАТ ИЛИ ПОВТОРЯТЬ

.

<=

ВЫБРАТЬ ИНАЧЕ ПОКА

,

>=

ВЫЗОВ ИСПОЛЬЗУЕТ ПОСТ[ОЯННЫЕ]

;

..

ВЫП[ОЛНЯТЬ] К ПУСТО

|

:

ВЫХОД КОЛЬЦО РЯД

(

)

ДЕЛИТЬ КОН[ЕЦ] ТО

[

]

ДЛЯ НАБОР УКАЗ[АНИЯ]

{

}

ДО НЕ ЦЕПЬ

:=

АЕСЛИ ДОСТУП ОСТАТОК ЯВЛЯЕТСЯ

^

БЕГУНОК ЕСЛИ ОТ  

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


 
 


3. Объявления и области действия понятий

С именем Иван, без имени болван.

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

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

Правила для области действия названия:

а) название не может обозначать больше, чем одно понятие внутри данной области действия;

б) разрешено объявлять вид ДкВп, как ДОСТУП К Вп (см. 5.4) в точке, где вид Вп ещё не объявлен; объявление вида Вп должно следовать на том же уровне участка, на котором происходит и объявление ДкВп;

в) названия свойств (полей), упоминаемые в объявлении НАБОРа (см. 5.3), используются только для обозначения свойств (полей) переменных этого вида НАБОР.

Понятие, объявленное на уровне отдела (см. 10), можно использовать и в других отделах, если при своём объявлении название этого понятия сопровождается меткой общедоступности (знак "-" или "+"). Такое понятие обозначается полным названием, состоящим из названия отдела, точки и названия понятия. Например, если в отделе-пользователе Пл необходимо обратиться к понятию с названием н, объявленному в отделе-владельце Вл, то полное название н в тексте отдела Пл будет записываться как Вл.н. Допустимо обращение к понятиям своего отдела по их полному названию, например Вл.н (после их объявления) в отделе Вл. В отделах-пользователях возможно изменение значений только тех переменных, которые были объявлены в отделе-владельце с меткой общедоступности "+", а переменные, объявленные в отделе-владельце с меткой общедоступности "-" доступны только для чтения.

ПолноеНазвание

 =  [название "."] название (* ВИДа, ПОСТоянной, ПЕРеменной *)

Следующие названия являются встроенными в язык (это: простые виды данных, логические постоянные, встроенные задачи), т.е. соответствующие понятия считаются уже объявленными на уровне каждого отдела. Применение этих названий см. в 5.1 и 9.2.

ВЕЩ

ЗНАК ОБНУЛИТЬ УВЕЛИЧИТЬ целое ШИРВЕЩ

ВКЛ

КЛЮЧ ПОСТАВИТЬ бегунок УЗК ШИРЦЕЛ

ВЗНАК целое

МАКС числ.вида ПРОВЕРИТЬ УЗКЦЕЛ ЯЧЦЕЛ

ВЦЕЛ знак

МИН числ.вида РАЗМЕР ряда УМЕНЬШИТЬ целое  

ВШИРЦЕЛ вещ

МНОЖ[ЕСТВО] СМЕСТИТЬ бегунок ЦЕЛ[ОЕ]  

ДЛИНА цепь

МОДУЛЬ абс.вел. СОЗДАТЬ ЦЕЛЧАСТЬ  

ЗАДАНО цепь

ОТКЛ СПИСАТЬ сост.вид ЧЕТ целого  

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


 
 


4. Объявление постоянной


Объявление постоянной связывает название со значением.

ОбъявлениеПостоянной

 =  название ["-"] "=" ПостоянноеВыражение

ПостоянноеВыражение

 =  Выражение

Постоянное выражение – это выражение, которое может быть вычислено Преобразователем Глагола (ПГ) по его тексту без выполнения приложения. Его данные (см. 7.1) – другие постоянные, различные действия и встроенные задачи (см. 9.2), которые могут быть выполнены преобразователем Глагола.

Примеры объявления постоянной:

ПОСТ
  Слагаемых = 100;
  Пи- = 3.141592654;
  ПолПи- = Пи/2;
  Замечание1 = "Деление на ноль.";
  ПолноеМножество = {МИН(МНОЖ)..МАКС(МНОЖ)};

 
 


5. Объявление вида


Вид данных определяет значения, которые могут принимать переменные этого вида, и действия, которые можно применять к этим переменным. При объявлении вида происходит связывание названия с видом данных. При объявлении составного вида (РЯД или НАБОР) обязательно задаётся и внутреннее строение переменных этого вида. Составной вид не может строиться из самого себя.

ОбъявлениеВида

 =  название ["-"] "=" Вид

Вид

 =  ПолноеНазвание | ВидРяд | ВидНабор | ВидДоступ | ВидЗадача
| ВидБегунок

Примеры:

ВИД
  Таблица = РЯД Слагаемых ИЗ ВЕЩ;
  Функция = ЗАДАЧА(x:ЦЕЛ):ЦЕЛ;

  ДкЯйцо- = ДОСТУП К ОписаниеЯйца;
                       ОписаниеЯйца- = НАБОР
    твёрдость-:ЦЕЛ;
    положение+:Место
                                         КОН;

  ДкЗолотоеЯйцо = ДОСТУП К ОписаниеЗолотогоЯйца;
                              ОписаниеЗолотогоЯйца = НАБОР(ОписаниеЯйца)
    богатство:ВЕЩ
                                                        КОН;

  Столбец = БЕГУНОК 3 ПО ЦЕЛ;





5.1. Простые виды

Аз да буки, да и конец науки.

Простые виды обозначены встроенными названиями. Соответствующие действия определены в 7.2, а встроенные задачи – в 9.2. Предусмотрены следующие простые виды:

Название Принимаемые значения

КЛЮЧ

логические ВКЛ и ОТКЛ

ЗНАК

знаки с порядковыми номерами от 0X до 0FFX

ЯЧЦЕЛ

наименьшее представление целого числа

УЗКЦЕЛ  

целые числа от МИН(УЗКЦЕЛ) до МАКС(УЗКЦЕЛ)

ЦЕЛ

целые числа от МИН(ЦЕЛ) до МАКС(ЦЕЛ)

ШИРЦЕЛ  

целые числа от МИН(ШИРЦЕЛ) до МАКС(ШИРЦЕЛ)

ВЕЩ

вещественные числа от МИН(ВЕЩ) до МАКС(ВЕЩ)

ШИРВЕЩ  

вещественные числа от МИН(ШИРВЕЩ) до МАКС(ШИРВЕЩ)

МНОЖ

множество из целых чисел от 0 до МАКС(МНОЖ)

ЗНАКзнаковый вид.

КЛЮЧлогический вид.

МНОЖвид множество.

ЯЧЦЕЛ, УЗКЦЕЛ, ЦЕЛ и ШИРЦЕЛцелые виды, ВЕЩ и ШИРВЕЩвещественные виды, а вместе они образуют числовые виды.

Считается, что ШИРВЕЩ >= ВЕЩ >= ШИРЦЕЛ >= ЦЕЛ >= УЗКЦЕЛ >= ЯЧЦЕЛ, причём больший вид поглощает меньший вид.


5.2. Вид РЯД

Одна головня и в печи не горит, а две и в поле курятся.

Переменные вида РЯД состоят из совокупности переменных одного вида, называемого опорным видом ряда. Число переменных, составляющих ряд, называют его размером. Целое число от 0 и до РАЗМЕР ряда минус 1 выделяет соответствующую переменную из ряда.

ВидРяд

 =       РЯД [Размер {"," Размер}] ИЗ Вид
| ЦЕПЬ ["[" Размер "]"]

Размер

 =  ПостоянноеВыражение

Объявление ряда

РЯД размер0,размер1,,размерn ИЗ Вп;

понимается как сокращение

РЯД размер0 ИЗ
  РЯД размер1 ИЗРЯД размерn ИЗ Вп

Объявление РЯД размер ИЗ ЗНАК можно записывать как ЦЕПЬ[размер].

Вид РЯД, объявленный без указания размера, называется открытым рядом. Такой вид используется только:
а) в приёмнике задачи (см. 9.1);
б) как опорный вид для вида ДОСТУП (см. 5.4);
в) как опорный вид другого открытого ряда.

Объявление ОБХОД.Ячейки равнозначно объявлению РЯД ИЗ ОБХОД.Ячейка (см. 11).

Примеры вида РЯД:

РЯД 10,N ИЗ ЦЕЛ; (* матрица 10xN *)
РЯД ИЗ ЗНАК;     (* открытый ряд из ЗНАК *)
ЦЕПЬ;           (* тоже что и РЯД ИЗ ЗНАК *)
ОБХОД.Ячейки;   (* открытый ряд из ОБХОД.Ячейка *)


5.3. Вид НАБОР

Из многих малых выходит одно большое.

Переменные вида НАБОР могут состоять из совокупности переменных различного вида. Переменные, составляющие этот набор, называются свойствами набора. Объявление вида НАБОР определяет название и вид каждого свойства. Область действия названий свойств простирается от точки их объявления до конца объявления вида НАБОР, а также захватывает обозначения свойств переменных вида НАБОР (см. 7.1). Если вид НАБОР объявлен с меткой общедоступности (см. 3), то свойства, которые должны быть доступны в отделах-пользователях, также объявляются с метками общедоступности. Такие свойства называются общедоступными свойствами, а неотмеченные свойства называются скрытыми свойствами (внутри отдела).

ВидНабор

 =  НАБОР ["(" ПолноеНазвание ")"]
  [ОбъявлениеПеременных]
КОН

Примеры вида НАБОР:

НАБОР
  день,месяц,год:ЦЕЛ
КОН;
НАБОР
  имя-,фамилия-,отчество-:ЦЕПЬ[32];
  возраст+:ЦЕЛ
КОН;

Вид НАБОР может быть объявлен как расширение другого вида НАБОР. В следующем примере

ВИД
  О = НАБОР
    ц:ЦЕЛ
  КОН;
  Р = НАБОР(О)
    в:ВЕЩ
  КОН;

Р – непосредственное расширение вида О, а О – непосредственный Опорный Вид (ОпорВ) вида Р (см. 14). Переменные расширенного вида Р состоят из свойств, объявленных в ОпорВ (опорном виде), и новых свойств, которые объявлены в самом Р. Все названия, объявленные в расширенном наборе, должны быть отличны от названий, объявленных в его опорном виде (видах).


5.4. Вид ДОСТУП

Отойдём да поглядим, хорошо ли мы сидим.

Переменные вида ДОСТУП принимают значения, которые обеспечивают доступ к переменным некоторого вида Вп.

ВидДоступ

 =  ДОСТУП К Вид

Вид Вп называется Опорным Видом Доступа (ОпорВД) и может быть только видом РЯД или видом НАБОР. Вид ДОСТУП заимствует отношение расширений своего ОпорВД (Опорного Вида Доступ). Так, если вид Р является расширением вида О, то и вид

ДкР = ДОСТУП К Р

также является расширением вида

ДкО = ДОСТУП К О.

Если ДкВп – переменная вида ДОСТУП К Вп, то вызов встроенной задачи СОЗДАТЬ(ДкВп) (см. 9.2) размещает новую переменную вида Вп в свободной памяти (если вид Вп – n-мерный открытый ряд, то размещение должно быть выполнено вызовом

СОЗДАТЬ(ДкВп,размер0,,размерn-1),

где размер0,,размерn-1 – это выражения, которые задают размеры соответствующим измерениям ряда). После вызова встроенной задачи СОЗДАТЬ(ДкВп) переменная ДкВп будет хранить значение, которое обеспечивает доступ к этой новой уже размещённой переменной вида Вп.

Любая переменная вида ДОСТУП может принимать значение ПУСТО, при котором нет доступа к её не размещённой переменной.

Примеры вида ДОСТУП:

ВИД
  ДкЯйцо- = ДОСТУП К ОписаниеЯйца;
                       ОписаниеЯйца- = НАБОР
    твёрдость-:ЦЕЛ;
    положение+:Место
                                         КОН;

  ДкЗолотоеЯйцо = ДОСТУП К ОписаниеЗолотогоЯйца;
                              ОписаниеЗолотогоЯйца = НАБОР(ОписаниеЯйца)
    богатство:ВЕЩ
                                                        КОН;


5.5. Вид БЕГУНОК

Тише едешь – дальше будешь.

Обычное обращение к элементу ряда р осуществляется по его номеру ц: р[ц]. При этом полный адрес элемента ц вычисляется так:

"адрес 0-го элемента" + "номер элемента ц" * "размер элемента".

При последовательном обращении к элементам ряда р можно ускорить процесс вычислений за счёт сокращения числа вычислений полных адресов очередных элементов, если определять адрес следующего элемента через адрес предыдущего. Для этого в языке применяется вид данных БЕГУНОК. Вид элементов ряда, к которым будет осуществляться последовательное обращение, называется Опорным Видом Бегунка (ОпорВБ), а число элементов, на которое будет перемещаться бегунок после каждого к нему обращения, называется шагом бегунка. Шаг бегунка задаётся как целая ПОСТоянная. Если при объявлении вида БЕГУНОК шаг бегунка не указан, то считается, что шаг равен 1.

ВидБегунок

 =  БЕГУНОК [ШагБегунка] ПО Вид (* РЯД *)

ШагБегунка

 =  ПостоянноеВыражение

До первого обращения к элементам ряда бегунок б должен быть установлен на нужный элемент ряда встроенной задачей ПОСТАВИТЬ(б,p,цНач). Здесь р – переменная вида РЯД, а цНач – произвольное целое выражение. При этом Опорный Вид Бегунка б должен совпадать с Опорным Видом ряда р. После такого вызова бегунок б будет установлен на адрес элемента р[цНач], вычисленный без учёта границ ряда р.

Для перемещения бегунка б на цШаг элементов ряда (без обращения к этим элементам) используется встроенная задача СМЕСТИТЬ(б,цШаг), где цШаг – целая ПОСТоянная.

Переменные вида БЕГУНОК с одинаковыми ОпорВБ (Опорными Видами Бегунка) можно сравнивать друг с другом и со значением ПУСТО.

При обращении через бегунки к переменным ВИДа многомерный ряд, последний рассматривается как развёрнутый в одномерный.

Переменные вида БЕГУНОК могут быть определены только в оконечных задачах (т.е. таких, из которых не вызываются другие задачи). Каждая переменная вида БЕГУНОК занимает один регистр. Рассмотрим на двух примерах преимущества бегунков (по количеству вычислений полных адресов элементов ряда) по сравнению с обычным обращением к элементам ряда.

Пример 1. Вычисление скалярного произведения двух векторов.

В обычной задаче приходится вычислять полные адреса элементов вектора v1 и вектора v2 для каждой координаты н (итого: 2*РАЗМЕР(v1) раз):

ЗАДАЧА* ВекторНаВектор(v1-,v2-:Вектор):ЦЕЛ;
ПЕР
  с,н:ЦЕЛ;
УКАЗ
  с:=0;
  ОТ н:=0 ДО РАЗМЕР(v1)-1 ВЫП
    с:=с + v1[н]*v2[н]
  КОН;
  ВОЗВРАТ с
КОН ВекторНаВектор;

Та же задача с использованием бегунков вычисляет полные адреса элементов вектора v1 и вектора v2 всего лишь 3 раза при вызове встроенной задачи ПОСТАВИТЬ(,,) перед циклом расчёта:

ЗАДАЧА* ВекторНаВектор(v1-,v2-:Вектор):ЦЕЛ;
ПЕР
  с:ЦЕЛ;
  б1,б2,барьер:БЕГУНОК ПО ЦЕЛ;
УКАЗ
  с:=0;
  ПОСТАВИТЬ(б1,v1,0);               (*     б1:=v1[0] с шагом 1 *)
  ПОСТАВИТЬ(б2,v2,0);               (*     б2:=v2[0] с шагом 1 *)
  ПОСТАВИТЬ(барьер,v1,РАЗМЕР(v1)); (* барьер:=v1[РАЗМЕР(v1)] уже за границей вектора v1[] *)
  ПОКА б1 < барьер ВЫП
    с:=с + б1^*б2^
  КОН;
  ВОЗВРАТ с
КОН ВекторНаВектор;

Пример 2. Вычисление произведения двух входных матриц: м1 размером 4х3 и м2 размером 3х4 в выходную матрицу м3 размером 4х4.

Обычная задача аж 2*РАЗМЕР(м2,0)=2*3=6 раз вычисляет полные адреса элементов входных матриц для каждого элемента выходной матрицы м3[i,j] да ещё 4*4=16 раз вычисляет полные адреса всех элементов выходной матрицы м3:

ЗАДАЧА* МатрицаНаМатрицу(м1-,м2-,м3+:Матрица);
ПЕР
  i,j:ЦЕЛ;
УКАЗ
  ОТ i:=0 ДО 3 ВЫП   (* по строкам матрицы м1 *)
    ОТ j:=0 ДО 3 ВЫП   (* по столбцам матрицы м2 *)
      м3[i,j]:=м1[i,0]*м2[0,j] + м1[i,1]*м2[1,j] + м1[i,2]*м2[2,j]
    КОН
  КОН
КОН МатрицаНаМатрицу;

Та же задача с использованием бегунков использует только 2 (вместо 6) вычисления полного адреса элементов входных матриц в 2-х вызовах встроенной задачи ПОСТАВИТЬ(,,) на каждый элемент выходной матрицы м3[i,j] да всего 1 раз (вместо 16) устанавливает бегунок б3 на 0-й элемент выходной матрицы м3[0,0] перед циклом расчёта:

ЗАДАЧА* МатрицаНаМатрицу(м1-,м2-,м3+:Матрица);
ПЕР
  i,j:ЦЕЛ;
  б1,б3:БЕГУНОК ПО ЦЕЛ;        (* шаг бегунка: БЕГУНОК 1 ПО ЦЕЛ; *)
  б2:БЕГУНОК 4 ПО ЦЕЛ;         (* шаг бегунка б2 равен 4 *)
УКАЗ
  ПОСТАВИТЬ(б3,м3,0);           (* установить бегунок б3 на м3[0,0] с шагом 1 приращения *)
  ОТ i:=0 ДО 3 ВЫП   (* по строкам матрицы м1 *)
    ОТ j:=0 ДО 3 ВЫП   (* по столбцам матрицы м2 *)
      ПОСТАВИТЬ(б1,м1[i],0);(* переустановить бегунок б1 на м1[i,0] с шагом 1 приращения *)
      ПОСТАВИТЬ(б2,м2,j);       (* установить бегунок б2 на м2[0,j] с шагом 4=РАЗМЕР(м2,1),
                                                  измерения в м2[i,j] идут от 01 *)
      б3^:=б1^*б2^ + б1^*б2^ + б1^*б2^;
    КОН
  КОН
КОН МатрицаНаМатрицу;


5.6. Вид ЗАДАЧА

Переменные вида ЗАДАЧА принимают значения, которые обеспечивают доступ к вызову задач. Эти переменные могут принимать и значение ПУСТО. Если задача з присваивается переменной вида Вп, то заголовки (см. 9.1) у з и у Вп должны совпадать (см. 14). При этом задача з не может быть ни встроенной задачей, ни вложенной в другую задачу.

ВидЗадача

 =  ЗАДАЧА [Приёмники [":" ВидОтвета]]

Пример:

ВИД
  Функция = ЗАДАЧА(x:ВЕЩ):ВЕЩ;

 
 


6. Объявление переменных


Объявление переменных определяет названия и вид их данных.

ОбъявлениеПеременных

 =  название ["-" | "+"] {"," название ["-" | "+"]} ":" Вид

Переменные вида НАБОР и вида ДОСТУП имеют как объявленный вид (или просто их вид), так и размещённый вид (вид их данных во время выполнения приложения). Объявленный вид определяет, какие свойства набора доступны. Для переменных вида ДОСТУП и приёмников ссылок вида НАБОР размещённый вид может быть расширением их объявленного вида. (Это аналог позднего связывания при ООП в ЯП C++/Turbo Pascal.)

Примеры объявлений переменных (см. примеры Объявления вида ДкЯйцо из 5):

ВИД
         ДкЯйцо- = ДОСТУП К ОписаниеЯйца;
  ДкЗолотоеЯйцо = ДОСТУП К ОписаниеЗолотогоЯйца;
ПЕР
  ц,i,j,M,N:ЦЕЛ;
  год,возраст:ЦЕЛ;
  x,y:ВЕЩ;
  к1,к2:КЛЮЧ;
  мн:МНОЖ;
  f:Функция;
  р:РЯД 100 ИЗ ВЕЩ;

  город:РЯД 16 ИЗ
    НАБОР
      название:ЦЕПЬ[32];
      жителей:ЦЕЛ
    КОН;

  яйцо:ДкЯйцо;
  золотоеяйцо:ДкЗолотоеЯйцо;
УКАЗ
  ...

 
 


7. Выражения

Струны готовы, недалеко и до песен.

Выражения задают правила вычисления других значений по велечинам ПОСТоянных и текущим значениям ПЕРеменных, входящих в выражение, путём применения действий и вызова задач, возвращающих ответ. Выражения состоят из данных и действий. Круглые скобки могут использоваться для объединения данных и действий, входящих в выражение.


7.1. Данные

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

Обозначение

 =  ПолноеНазвание {"." название | "["Выражения"]"
| "^" | "("ПолноеНазвание")"}

Выражения

 =  Выражение {"," Выражение}

Если р обозначает переменную вида РЯД, то р[в] обозначает элемент из ряда р, чей номер – текущее значение выражения в. Выражение в должно быть целого вида. Обозначение р[в0,в1,,вn] применимо вместо обозначения р[в0][в1][вn].

Если н обозначает переменную вида НАБОР, то н.с обозначает свойство с набора н.

Если р или н доступны только для чтения, то р[в] и н.с также доступны только для чтения.

Если пД обозначает переменную вида ДОСТУП, то пД^ обозначает переменную, к которой в пД хранится доступ. Обозначения пД^ и пД^[в] могут быть сокращены до пД.с и пД[в].

Если б обозначает переменную вида БЕГУНОК, то б^ обозначает элемент ряда, соответствующий текущему значению бегунка б. После обращения к элементу ряда, обозначенного таким способом, текущее значение б смещяется на шаг по элементам ряда. Где шаг был указан при объявлении вида переменной б (см. 5.5).

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

а) пприёмник ссылок вида НАБОР, или п – переменная вида ДОСТУП, и если

б) Вп – расширение объявленного вида п.

Если обозначенное понятиеПОСТоянная или ПЕРеменная, то обозначение ссылается на их текущее значение. Если же понятие является задачей (имеет вид ЗАДАЧА) и обозначение сопровождается (возможно, пустым) списком источников, то в этом случае подразумевается вызов задачи и подстановка значения ответа, полученного при её исполнении. Источники должны соответствовать приёмникам, как и при вызовах собственно задач (см. 9.1).

Примеры обозначений (см. примеры из 6):

Обозначение Вид данных

ц

ЦЕЛ

р[ц]

ВЕЩ

город[3].название[ц]

ЗНАК

яйцо.твёрдость

ЦЕЛ

яйцо(ДкЗолотоеЯйцо).богатство

ВЕЩ


7.2. Действия

Язык придерживается принятых в математике соглашений о порядке выполнения действий в выражениях. Существует четыре разряда действий с различными преимуществами порядка выполнения. У отрицания НЕ самое высокое преимущество, далее следуют действия типа умножения, действия типа сложения и отношения. Действия с одинаковым преимуществом выполняются слева направо. Например, x-y-z означает (x-y)-z.

Выражение

 =  ПростоеВыражение [Отношение ПростоеВыражение]

ПростоеВыражение

 =  ["*" | "-"] Слагаемое {Сложение Слагаемое}

Слагаемое

 =  Множитель {Умножение Множитель}

Множитель

 =  Обозначение [Источники] | число | одинзнак
| цепочка | ПУСТО | Множество | "(" Выражение ")"
| НЕ Множитель

Множество

 =  "{"[Элемент {"," Элемент}]"}

Элемент

 =  Выражение [".." Выражение]

Источники

 =  "(" [Выражения] ")"

Отношение

 =  "=" | "#" | "<" | "<=" | ">" | ">=" | В | ЯВЛЯЕТСЯ

Сложение

 =  "+" | "-" | ИЛИ

Умножение

 =  "*" | "/" | ДЕЛИТЬ | ОСТАТОК | И

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

Логические действия

а ИЛИ б  

если а, то ВКЛ, иначе б

а И б

если а, то б, иначе ОТКЛ

НЕ а

не а

Эти действия применимы к данным вида КЛЮЧ и дают ответ вида КЛЮЧ.

Арифметические действия

+

сложение

-

вычитание

*

произведение

/

вещественное деление

ДЕЛИТЬ

деление нацело

ОСТАТОК  

остаток от деления

Действия "+", "-", "*" и "/" применимы к данным числовых видов. Вид ответа "+", "-" и "*" есть вид того данного, который поглощает вид другого данного. У "/" ответ – наименьший вещественный вид, который поглощает виды обоих данных. Одноместный "-" обозначает перемену знака, а одноместный "+" – тождественное действие. Действия ДЕЛИТЬ и ОСТАТОК применимы только к данным целого вида. Они связаны следующими формулами, определёнными для любого x и положительного делителя y:

x = (x ДЕЛИТЬ y) * y + (x ОСТАТОК y)

0 <= (x ОСТАТОК y) < y

Примеры:

    x      y   x ДЕЛИТЬ y x ОСТАТОК y

10    

3    

3

1

-10    

3    

-4

2

11    

3    

3

2

-11    

3    

-4

1

Действия над множествами

x+y  

объединение

x*y  

пересечение

x-y  

разность

x*(-y)

x/y  

симметрическая разность

(x-y)+(y-x)

Действия над множествами применимы к данным вида МНОЖ и дают ответ вида МНОЖ. Одноместный знак минус "-" обозначает дополнение множества x, то есть -x – это множество целых чисел от 0 до МАКС(МНОЖ), которые не являются элементами множества x. На действия с множествами не распространяется сочетательный закон, т.е. (a+b)-c # a+(b-c). Построитель множества задаёт значение (величину) множества в виде списка элементов (через запятую), который взят в фигурные скобки {}. Элементы должны быть целого вида и иметь значения от 0 до МАКС(МНОЖ). Диапазон a..b в фигурных скобках построителя множества обозначает все целые числа на отрезке [a,b].

Отношения

 = 

равно

#

не равно

<

меньше

<=

меньше или равно

>

больше

>=

больше или равно

В

принадлежность множеству

ЯВЛЯЕТСЯ  

проверка вида

Все отношения дают ответ вида КЛЮЧ. Отношения "=", "#", "<", "<=", ">" и ">=" применимы к числовым видам, виду ЗНАК, цепочкам знаков и рядам из знаков, содержащим в конце 0X. Отношения "=" и "#", кроме того, применимы и к видам КЛЮЧ, МНОЖ, ДОСТУП, ЗАДАЧА и к значению ПУСТО.

Отношение (в В мн) выясняет, не входит ли значение выражения в в множество значений выражения мн, где в должно быть целого вида, а мнвида МНОЖ.

Отношение (п ЯВЛЯЕТСЯ Вп) называется проверкой вида и выясняет, является ли размещённый вид переменной п видом Вп или же является его расширением. Проверка вида применима, если

а) пприёмник ссылок вида НАБОР, или п – переменная вида ДОСТУП, и если

б) Вп – расширение объявленного вида п.

Примеры выражений (см. примеры 6):

Выражение Вид ответа

2003

ЦЕЛ

ц ДЕЛИТЬ 5

ЦЕЛ

НЕ к1 ИЛИ к2

КЛЮЧ

(ц+i)*(ц-i)

ЦЕЛ

мн-{7,i,12}

МНОЖ

ц+x

ВЕЩ

р[ц+i]*р[ц-i]

ВЕЩ

(0<=ц) ИЛИ (ц<100)

КЛЮЧ

ц В {i..j-1}

КЛЮЧ

город[ц].название<="Москва"  

КЛЮЧ

яйцо ЯВЛЯЕТСЯ ДкЗолотоеЯйцо  

КЛЮЧ



 
 


8. Указания


Указания определяют ход выполнения приложения. В языке существуют простые и составные указания.

Простые указания – это присваивание ":=", вызов задачи, ВОЗВРАТ из задачи или ВЫХОД из цикла КОЛЬЦО (лучше бы из КРУГа).

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

Указание

 =  [Присваивание | ВызовЗадачи | ЕслиТо | ВыбратьИз | Пока
| ПовторятьДо | ОтДо | Кольцо | Для | ВЫХОД | ВОЗВРАТ [Выражение]]

Последовательность указаний, разделённых точкой с запятой, означает поочерёдное выполнение составляющих её указаний.

Указания

 =  Указание {";" Указание}


8.1. Присваивание

Присваивание заменяет текущее значение переменной новым значением, которое определяется результатом выражения. Выражение должно быть совместимо по присваиванию с переменной (см. 14). Символом присваивания является ":=".

Присваивание

 =  Обозначение ":=" Выражение

Если выражение в вида Вв присваивается переменной п вида Вп (т.е. п:=в;), то имеет место следующее:

а) если Вп и Вввида НАБОР, то в присваивании участвуют только те свойства набора Вв, которые также имеются в наборе Вп; размещённый вид п и объявленный вид п должны быть одинаковыми, после присваивания они не изменяются;

б) если Вп и Вввида ДОСТУП, то размещённым видом п становится размещённый вид в;

в) если Вп – это РЯД N ИЗ ЗНАК, а в – цепочка длины M<N, то i-му элементу п[i] присваивается значение в[i], где i=0..M-1, а в конце цепочки п[M] получает значение 0X.

Примеры присваиваний (см. примеры 6):

ц:=0;
к1:= ц=i;
x:=ц+1;
j:=log2(ц+i); (* см. 9.1 *)
f:=log2;
мн:={2,3,5,7,11};
р[ц]:=(x+y)*(x-y);
город[ц+1].название:="Тверь";
город[i]:=город[j]


8.2. Вызов задачи

Вызов задачи определяет выполнение последовательности УКАЗаний, объявленных в этой задаче. В нём (вызове) может быть список источников данных (фактических параметров). Каждому источнику всегда соответствует приёмник (формальный параметр), определённый в объявлении задачи (см. 9). Соответствие устанавливается в порядке следования в списках источников и приёмников.

Если источник обозначает часть составной переменной, то эта часть выделяется перед выполнением задачи. Если приёмник является приёмником ссылок, то соответствующий источник может быть только обозначением переменной (вида ДОСТУП К). Примечание: если приёмник ссылок объявлен с меткой общедоступности "-" (см. 9.1), то источник также может быть и цепочкой знаков, т.е. вида ЦЕПЬ.

Если приёмник является приёмником значений, то соответствующий источник может быть выражением. Это выражение вычисляется перед выполнением задачи, а полученное значение присваивается приёмнику (см. также 9.1).

ВызовЗадачи

 =  Обозначение [Источники]

Примеры:

ПисатьЦел(ц*2+1);             (* см. 9.1 *)
УВЕЛИЧИТЬ(город[j].жителей)   (* см. 9.2 *)


8.3. Указание ЕСЛИ…ТО

ЕслиТо

 =    ЕСЛИ Выражение ТО
   Указания
{АЕСЛИ Выражение ТО
   Указания}
[ИНАЧЕ
   Указания]
 КОН

Указание ЕСЛИ…ТО задаёт условное выполнение входящих в него последовательностей указаний. Логические выражения, предшествующие последовательности указаний, будем называть условиями. Условия проверяются последовательно одно за другим, пока очередное не окажется равным ВКЛ, после чего выполняется связанная с этим условием последовательность указаний. Если ни одно условие не удовлетворено и имеется служебное слово ИНАЧЕ, то выполняется последовательность указаний, записанная после этого слова.

Пример:

ЕСЛИ (знак>="A") И (знак<="Z") ТО
  Название()
АЕСЛИ (знак>="0") И (знак<="9") ТО
  Число()
АЕСЛИ (знак="'") ИЛИ (знак='"') ТО
  Цепочка()
ИНАЧЕ
  Ошибка()
КОН;


8.4. Указание ВЫБРАТЬ…ИЗ

Указание ВЫБРАТЬ…ИЗ определяет выбор и выполнение последовательности указаний по значению выражения. Прежде всего вычисляется значение выбирающего выражения, а затем выполняется та последовательность указаний, чей список меток варианта содержит полученное значение. Выбирающее выражение должно быть такого целого вида, который поглощает виды всех меток вариантов, или же – и выбирающее выражение, и метки вариантов должны иметь вид ЗНАК. Метки варианта состоят из постоянных выражений, и ни одно из их значений не должно употребляться больше одного раза. Если значение выражения не совпадает с меткой ни одного из вариантов, выбирается последовательность указаний после слова ИНАЧЕ, если оно есть, иначе выполнение приложения прерывается.

ВыбратьИз

 =      ВЫБРАТЬ Выражение ИЗ
["|"] Вариант  (* первое "|" не обязательно *)
{"|"  Вариант} (* повтор от 0 раз *)
 [ИНАЧЕ
    Указания]
  КОН

Вариант

 =  [СписокМеток ":" Указания]

СписокМеток

 =  Метки {"," Метки}

Метки

 =  ПостоянноеВыражение [".." ПостоянноеВыражение]

Пример:

ВЫБРАТЬ год-годРождения ИЗ
|   0..7*1-1: возраст:=дитя
| 7*1..7*2-1: возраст:=отрок
| 7*2..7*3-1: возраст:=юноша
| 7*3..7*8-1: возраст:=муж
| 60,70,80:   возраст:=юбиляр
ИНАЧЕ
  возраст:=старец
КОН;


8.5. Указание ПОКА

Указание ПОКА задаёт повторное выполнение последовательности указаний, пока условие, заданное логическим выражением, остаётся равным ВКЛ. Условие проверяется перед каждым выполнением последовательности указаний.

Пока

 =  ПОКА Выражение ВЫП
  Указания
КОН


8.6. Указание ПОВТОРЯТЬ…ДО

Указание ПОВТОРЯТЬ…ДО определяет повторное выполнение последовательности указаний, пока условие, заданное логическим выражением, не удовлетворено. Последовательность указаний выполняется, по крайней мере, один раз.

ПовторятьДо

 =  ПОВТОРЯТЬ
  Указания
ДО Выражение


8.7. Указание КОЛЬЦО

Указание КОЛЬЦО определяет повторное выполнение последовательности указаний. Оно завершается после выполнения указания ВЫХОД внутри этой последовательности (см. 8.9).

Кольцо

 =  КОЛЬЦО
  Указания | ВЫХОД (* из цикла КОЛЬЦО *)
КОН

Указания КОЛЬЦО нужны для того, чтобы выразить (и использовать) повторения с несколькими точками выхода, или в случаях, когда условие выхода находится в середине повторяемой последовательности указаний.


8.8. Указание ОТ…ДО…ВЫП

Указание ОТ…ДО…ВЫП определяет повторное выполнение последовательности указаний для увеличивающихся (уменьшающихся) значений переменной целого вида, называемой управляющей переменной.

ОтДо

 =  ОТ ПолноеНазвание ":=" Выражение ДО Выражение [ПО ПостоянноеВыражение] ВЫП
  Указания
КОН

Указание

ОТ ц:=НачальноеВыражение ДО КонечноеВыражение ПО шаг ВЫП
  Указания
КОН;

равнозначно

конец :=КонечноеВыражение;
начало:=НачальноеВыражение;
ЕСЛИ шаг > 0 ТО
  ПОКА ц <= конец ВЫП
    Указания;
    УВЕЛИЧИТЬ(ц,шаг)
  КОН
АЕСЛИ шаг < 0 ТО
  ПОКА ц >= конец ВЫП
    Указания;
    УВЕЛИЧИТЬ(ц,шаг)
  КОН
КОН;

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

Пример:

ОТ i:=0 ДО 99 ВЫП
  x:=x+р[i]
КОН;


8.9. Указания ВОЗВРАТ из задачи и ВЫХОД из кольца

Указание ВОЗВРАТ определяет точку завершения выполнения задачи. Оно обозначается служебным словом ВОЗВРАТ.

Задачи, возвращающие ответ, завершаются указанием ВОЗВРАТ, задающим значение ответа. Ответ обозначается выражением, которое следует за словом ВОЗВРАТ. Вид выражения должен быть совместим по присваиванию (см. 14) с видом ответа, определённым в заголовке задачи (см. 9).

В собственно задачах (т.е. не возвращающих ответ) указание ВОЗВРАТ подразумевается в конце тела задачи. Любое явное указание ВОЗВРАТ служит дополнительной точкой завершения выполнения задачи.

Указание ВЫХОД определяет точку завершения охватывающего указания КОЛЬЦО. Оно обозначается служебным словом ВЫХОД.

Пример с указаниями ПОКА, ПОВТОРЯТЬ, КОЛЬЦО, ВЫХОД:

живёт(дед); живёт(баба);
КОЛЬЦО
  снесла(курочка,яйцо);
  ЕСЛИ НЕ (яйцо ЯВЛЯЕТСЯ ДкЗолотоеЯйцо) ТО
    ВЫХОД
  КОН;
  ПОКА НЕ устаёт(дед) ВЫП
    бьёт(дед,яйцо)
  КОН;
  ПОКА НЕ устаёт(баба)ВЫП
    бьёт(баба,яйцо)
  КОН;
  ПОВТОРЯТЬ
    бегает(мышь)
  ДО задела(мышь,яйцо) И разбито(яйцо);
  плачет(дед); плачет(баба);
  кудахчет(курочка)
КОН;


8.10. Указание ДЛЯ…ВИДА…КОН

Указание ДЛЯ определяет выполнение последовательности указаний при помощи проверки вида у заданной переменной и применяет охрану вида к каждому вхождению этой переменной внутри выполняемой последовательности указаний.

Для

 =      ДЛЯ ПолноеНазвание ВИДА
["|"] ОхранаУказаний   (* первое "|" не обязательно *)
{"|"  ОхранаУказаний } (* повтор от 0 раз *)
 [ИНАЧЕ
    Указания]
  КОН;

ОхранаУказаний

 =  [охраняемыйВид ":" Указания]

Если пприёмник ссылок вида НАБОР или переменная вида ДОСТУП, и её объявленный вид Вп0, то указание

ДЛЯ п ВИДА
| Вп1: ПослУказ1
| Вп2: ПослУказ2
ИНАЧЕ
       ПослУказ3
КОН;

имеет следующий смысл: если размещённый вид переменной п есть Вп1, то выполняется последовательность указаний ПослУказ1, в которой п воспринимается как имеющая объявленный вид Вп1, иначе если размещённый вид переменной п есть Вп2, то выполняется ПослУказ2, в которой п воспринимается как имеющая объявленный вид Вп2, ИНАЧЕ выполняется ПослУказ3. Здесь виды Вп1 и Вп2 должны быть расширениями вида Вп0. Если ни одна проверка вида не удовлетворена, а ИНАЧЕ отсутствует, то выполнение приложения прерывается.

Пример:

ДЛЯ яйцо ВИДА
(* доступ к виду ЗолотоеЯйцо *)
|  ДкЗолотоеЯйцо: УМЕНЬШИТЬ(яйцо.богатство)
КОН;

 
 


9. Объявление задачи


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

Имеются два рода задач: собственно задачи и задачи, возвращающие ответ. Последние вызываются обозначением задачи как части выражения и возвращают ответ, который является данным для выражения. Собственно задачи получают управление после вызова задачи. Задача является задачей, возвращающей ответ, если определён вид её ответа. Тело задачи, возвращающей ответ, должно содержать указание ВОЗВРАТ, которое и определяет ответ. Вид ответа задачи не может быть ни видом НАБОР, ни видом РЯД.

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

ОбъявлениеПеременных

 =  название ["-" | "+"] {"," название ["-" | "+"]} ":" Вид

ЗаготовкаЗадачи

 =  ЗАДАЧА ["*"] "^" название ["-"]
[ "(" [ОбъявленияПриёмников] ")" [":" ВидОтвета] ]

ОбъявлениеЗадачи

 =      ЗаголовокЗадачи ";" ТелоЗадачи название
| ЗаголовокЗадачи ";" ВЫЗОВ цепочка ИЗ цепочка

ЗаголовокЗадачи

 =  ЗАДАЧА ["*"] название ["-"]
[ "(" [ОбъявленияПриёмников] ")" [":" ВидОтвета] ]

ТелоЗадачи

 =     Объявления
[УКАЗ
   Указания | ВОЗВРАТ [Выражение]  (* из ЗАДАЧИ *)
] (* [не обязательно] *)
 КОН

ОбъявленияПриёмников

 =  ОбъявлениеПеременных {";" ОбъявлениеПеременных}

Заготовка задачи [т.е. это опережающее определение (см. отличия от Паскаля)] служит для того, чтобы разрешить вызов задачи до её объявления. Написание заготовки задачи отличается от написания заголовка задачи только разделителем "^" после слова ЗАДАЧА.

Пример заготовки задачи:

ЗАДАЧА^ ПисатьЦепь-(цепочкаЗнаков:ЦЕПЬ);

Символ "*" в описании заготовки ЗАДАЧА ["*"] поясняется в п. 13.3.


9.1. Приёмники

Приёмники – это переменные (формальные параметры), которым при вызове данной задачи должны соответствовать передаваемые источники (фактические параметры). Имеются два рода приёмников: приёмники значений и приёмники ссылок, отличающиеся при объявлении соответственно отсутствием или наличием метки общедоступности (см. 3). Приёмники значений – это внутренние переменные задачи, которым в качестве начального присваивается значение соответствующего источника. Приёмниками значений также являются и приёмники простых видов, объявленные с меткой общедоступности "-". Приёмники значений не могут быть составного вида. Приёмникам ссылок должны соответствовать источники, которые являются переменными, и означают эти переменные. Приёмнику ссылок с меткой "-" также может соответствовать и цепочка знаков. Область действия приёмника простирается от его объявления до конца задачи, в которой он объявлен. В этой области невозможно изменять значения у тех приёмников, которые объявлены с меткой "-". Задача, возвращающая ответ без приёмников, должна иметь пустой список приёмников. Она должна вызываться обозначением задачи, чей список источников также является пустым (т.е. п:=имя();).

ОбъявленияПриёмников

 =  ОбъявлениеПеременных {";" ОбъявлениеПеременных}

Пусть Впрвид приёмника пр (кроме открытого ряда) и Висвид соответствующего источника ис. Виды Вис и Впр для приёмников ссылок должны быть одинаковыми видами, или вид Впр должен быть видом НАБОР, а вид Вис – расширением вида Впр. Всегда ис должен быть совместим при вызове задачи с пр (см. 14).

Если вид источника Вис – открытый ряд, то размер пр становится равным размеру ис.

Примеры объявлений задач:

ЗАДАЧА^ ПисатьЦепь-(цепочкаЗнаков:ЦЕПЬ); (* опережающее определение задачи ПисатьЦепь() *)

ЗАДАЧА ПисатьЦел-(ц:ЦЕЛ); (* 0<=ц<100000 *)
ПЕР
  ц:ЦЕЛ;
  цифры:РЯД 6 ИЗ ЗНАК;
УКАЗ
  ц:=0;
  ПОВТОРЯТЬ
    цифры[ц]:=ВЗНАК(ц ОСТАТОК 10 + ВЦЕЛ("0"));
    ц:=ц ДЕЛИТЬ 10;
    УВЕЛИЧИТЬ(ц)
  ДО ц = 0;
    цифры[ц]:=0X;
    ПисатьЦепь(цифры)
КОН ПисЦел;
 
ЗАДАЧА^ ПисатьЗнак-(знак:ЗНАК); (* опережающее определение задачи ПисатьЗнак() *)

ЗАДАЧА ПисатьЦепь-(р:ЦЕПЬ);
ПЕР
  ц:ЦЕЛ;
УКАЗ
  ц:=0;
  ПОКА (ц < РАЗМЕР(р)) И (р[ц] # 0X) ВЫП
    ПисатьЗнак(р[ц]);
    УВЕЛИЧИТЬ(ц)
  КОН
КОН ПисатьЦепь;
 
ЗАДАЧА^ ЧитатьЗнак-(знак:ЗНАК); (* опережающее определение задачи ЧитатьЗнак() *)

ЗАДАЧА ЧитатьЦел-(ц+:ЦЕЛ);
ПЕР
  знак:ЗНАК;
УКАЗ
  ц:=0;
  ЧитатьЗнак(знак);
  ПОКА ("0" <= знак) И (знак <= "9" ) ВЫП
    ц:=10*ц + (ВЦЕЛ(знак) - ВЦЕЛ("0"));
    ЧитатьЗнак(знак)
  КОН
КОН ЧитатьЦел;
 
ЗАДАЧА log2(x:ЦЕЛ):ЦЕЛ; (* x > 0 *)
ПЕР
  цЛогарифмПоОснованию2:ЦЕЛ;
УКАЗ
  цЛогарифмПоОснованию2:=0;
  ПОКА x > 1 ВЫП
    x:=x ДЕЛИТЬ 2;
    УВЕЛИЧИТЬ(цЛогарифмПоОснованию2)
  КОН;
  ВОЗВРАТ цЛогарифмПоОснованию2
КОН log2;


9.2. Встроенные задачи

Следующая таблица содержит список встроенных задач. Некоторые задачи – обобщённые, т.е. они применимы к данным нескольких видов. Обозначения названий: п – переменная, в – выражение, Вдвид данных. (см. также 1. Условные обозначения, 7.1. Данные).

Задачи, возвращающие ответ:

Вызов задачи Виды источников Вид ответа Значение ответа

ВЗНАК(ц)

целый

ЗНАК

знак с порядковым номером ц

ВЦЕЛ(знак)

ЗНАК

ЦЕЛ

порядковый номер (уникод) знака знак

 ВШИРЦЕЛ(вещ) вещественный

ШИРЦЕЛ

ближайшее к вещ целое двойной точности (64 разряда)

   ДЛИНА(цепь)

цепочка знаков

ЦЕЛ

длина цепочки знаков цепь

   ДЛИНА(цепь)  ЦЕПЬ[Размер]

ЦЕЛ

позиция первого 0X знака в цепочке цепь или РАЗМЕР(цепь),
если такого знака в цепочке цепь не существует

 ЗАДАНО(Цепь)

цепочка знаков

КЛЮЧ

возвращает ВКЛ, если при старте ПГ.exe среди параметров
задан ключ преобразования –кЦепь (используется в тексторезе)

МАКС(Вп)

числовой

Вп

наибольшее значение вида Вп

МАКС(МНОЖ)

МНОЖ

ЦЕЛ

наибольший элемент множества = 31

МИН(Вп)

числовой

Вп

наименьшее значение вида Вп

МИН(МНОЖ)

МНОЖ

ЦЕЛ

наименьший элемент множества = 0

МОДУЛЬ(в)

числовой

как и у в

модуль (абсолютная величина) выражения в

 РАЗМЕР(р)

РЯД

ЦЕЛ

равносильно РАЗМЕР(р,0)

 РАЗМЕР(р,ц)  р:РЯД;ц:целый

ЦЕЛ

размер ряда р в измерении ц (первым считается 0-е измерение)

УЗК(шц)

ШИРЦЕЛ

ЦЕЛ

тождество (сузить или укоротить в два раза: 64 => 32)

УЗК(ц)

ЦЕЛ

УЗКЦЕЛ

тождество (сузить или укоротить в два раза: 32 => 16)

УЗК(уц)

УЗКЦЕЛ

ЯЧЦЕЛ

тождество (сузить или укоротить в два раза: 16 => 8)

УЗК(шв)

ШИРВЕЩ

ВЕЩ

тождество (сузить или усечь в два раза: 64 => 32)

 ЦЕЛЧАСТЬ(вещ) вещественный вещественный

целая часть вещ

ЧЕТ(ц)

целый

КЛЮЧ

возвращает ВКЛ, если (ц ОСТАТОК 2 = 0) – проверка равенства

Собственно задачи:

Вызов задачи Виды источников Выполняемое действие

ОБНУЛИТЬ(п)

п:составной вид (НАБОР или РЯД)

заполнение нулями всех переменных,
входящих в состав п (вида НАБОР или РЯД)

ПОСТАВИТЬ(б,р,цНач)

б:БЕГУНОК ПО Вп;

р:РЯД ИЗ Вп;

цНач:целый

начальная выставка бегунка б
(по переменным вида Вп)
на элемент с номером цНач в ряду р,
т.е. на р[цНач]

ПРОВЕРИТЬ(к)

КЛЮЧ

прерывает выполнение приложения,
если НЕ к

СМЕСТИТЬ(б,цШаг)

б:БЕГУНОК ПО Вп;

цШаг:целая ПОСТоянная

смещение бегунка б
(по переменным вида Вп)
на цШаг элементов ряда р

СОЗДАТЬ(пД)

ДОСТУП К НАБОР или

ДОСТУП К РЯД

размещает в памяти переменную пД^
(вида НАБОР или РЯД)

СОЗДАТЬ(рД,в0,,вN)

рД:ДОСТУП К открытому ряду;

в0,,вN:целый

размещает в памяти открытый ряд рД^
с размерами в0,,вN

СОЗДАТЬ(цепьД,в)

цепьД:ДОСТУП К ЦЕПЬ;

в:ЦЕПЬ; (открытый ряд) или

в:ЦЕПЬ[Размер_в];

размещает в памяти цепьД^
с размером равным ДЛИНА(в)+1 и
переписывает значение в в цепьД^
(см. СПИСАТЬ)

СПИСАТЬ(в,цепь)

в:ЦЕПЬ; (открытый ряд) или

в:ЦЕПЬ[Размер_в];

цепь:ЦЕПЬ; (открытый ряд) или

цепь:ЦЕПЬ[Размер_цепь];

цепь:=в;

Размер_цепь <= Размер_в

СТОП(ц)

ц:целый

прерывает выполнение приложения и
передаёт окружению целое значение ц

УВЕЛИЧИТЬ(ц)

ц:целый

ц:=ц+1;

УВЕЛИЧИТЬ(ц,в)

ц,в:целый

ц:=ц+в;

УМЕНЬШИТЬ(ц)

ц:целый

ц:=ц-1;

УМЕНЬШИТЬ(ц,в)

ц,в:целый

ц:=ц-в;

Задача СПИСАТЬ(в,цепь) выполняет присваивание значения выражения в, являющегося цепочкой знаков (или рядом из знаков) и содержащего ограничитель 0X, другой переменной-источнику цепь (копирует значение в в цепь). При необходимости присвоенное значение усекается до размера РАЗМЕР(цепь)-1. Переменная-источник цепь вида ЦЕПЬ всегда будет содержать 0X как ограничитель.


 
 


10. Отделы


Отдел – это совокупность объявлений ПОСТоянных, ВИДов, ПЕРеменных и ЗАДАЧ с последовательностью УКАЗаний, предназначенных для задания переменным отдела их начальных значений.

Отдел

 =     ОТДЕЛ название ["-" | "+"] ";"
[ИСПОЛЬЗУЕТ
   название [ИЗ цепочка] {"," название [ИЗ цепочка]} ";"]
   Объявления
[УКАЗ
   Указания]
 КОН название "."

В отделе-владельце необходимо ставить метки общедоступности (оконечные -/+) в объявлениях названий тех понятий (см. 3), которые должны быть видимы в отделах-пользователях. Названия отделов-владельцев, понятия которых используются в отделе-пользователе, необходимо перечислить после служебного слова ИСПОЛЬЗУЕТ в начале отдела-пользователя, указывая при необходимости после служебного слова ИЗ путь к текстовому файлу отдела-владельца. Закольцовывание (отделов-владельцев и отдела-пользователя) при перечислении после служебного слова ИСПОЛЬЗУЕТ недопустимо. Путь к служебным отделам ОБХОД (см. 11) и СРЕДА (см. 12) указывать не нужно.

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

Запущенным считается отдел, у которого уже запущены все используемые в нём отделы и выполнена последовательность указаний после слова УКАЗ.

Запуск приложения осуществляется запуском головного отдела, т.е. отдела, у которого название отмечено оконечной меткой общедоступности "+".


 
 


11. Отдел ОБХОД


Отдел ОБХОД содержит средства, позволяющие обойти правила совместимости видов, наложенные определением языка. Рекомендуется ограничить использование этих средств отделами низкого уровня.

Виды Цел8, Цел16, Цел32, Цел64, Вещ32, Вещ64, определённые в этом отделе, являются вспомогательными числовыми видами. В названиях этих видов явно указывается число разрядов, занимаемых переменными этих видов. Вспомогательный числовой вид Адрес применяется в адресных задачах отдела ОБХОД.

В отделе ОБХОД определён также вид Доступ. Переменным вида Доступ могут быть присвоены значения переменных любого вида ДОСТУП. Соответственно, если приёмник ссылок имеет вид Доступ, то источник может иметь произвольный вид ДОСТУП.

Переменным вида Ячейка можно присваивать значения переменных вида ЯЧЦЕЛ. Если приёмник ссылок имеет вид РЯД ИЗ Ячейка (или, что тоже самое, ОБХОД.Ячейки), то соответствующий источник может иметь любой вид. [В Обероне-2 и Компонетном Паскале тоже есть подобная конструкция: ARRAY OF BYTE (см. также отличия Глагола от Оберона-2).]

Примеры объявления задач, позволяющих обойти правила совместимости видов:

ЗАДАЧА БайтИзРядаЯчеек-
     (
           регистр-:РЯД ИЗ ОБХОД.Ячейка;   (* РАЗМЕР(регистр)=4/ЦЕЛ или 8/ШИРЦЕЛ *)
         номерБайта:ЦЕЛ        (* номер извлекаемого байта: 0..3/ЦЕЛ или 0..7/ШИРЦЕЛ *)
     ):ЯЧЦЕЛ;
УКАЗ
  ВОЗВРАТ ОБХОД.Значение(ЯЧЦЕЛ,
               регистр[номерБайта]  (* преобразование элемента ряда в ЯЧЦЕЛ *)
                        )
КОН БайтИзРядаЯчеек;

ЗАДАЧА УзкИзРядаЯчеек-
     (
           регистр-:РЯД ИЗ ОБХОД.Ячейка;   (* РАЗМЕР(регистр)=4/ЦЕЛ или 8/ШИРЦЕЛ *)
           номерУзк:ЦЕЛ;         (* номер извлекаемого узк: 0..1/ЦЕЛ или 0..3/ШИРЦЕЛ *)
               узк+:УЗКЦЕЛ
     );
УКАЗ                         (* Адрес элемента ряда  узк, 2=SIZE(УЗКЦЕЛ) *)
  ОБХОД.ИзПамяти(ОБХОД.ПолучитьАдрес(регистр)+номерУзк*2,
               узк)
КОН УзкИзРядаЯчеек;

Задачи, которые содержатся в отделе ОБХОД, перечислены в таблицах приведенных ниже. Обозначения: п – переменная, в и ав – выражения, Вдвид данных.

Задачи, возвращающие ответ:

Вызов задачи Виды источников Вид ответа Выполняемое действие

ПолучитьАдрес(п)

любой

Адрес

возвращает адрес п

Значение(Вд,в)

размеры данных Вд и в
должны совпадать (см. 13.2)

Вд

  в воспринимается как значение вида Вд, т.е. это
 преобразование переменной в к виду Вд

Узк(в)

числовой

меньший вид

тождество

Собственно задачи:

Вызов задачи Виды источников Выполняемое действие

ИзПамяти(ав,п)

ав - Адрес; п - любого основного вида,

вид ДОСТУП, вид ЗАДАЧА

п:=Память[ав]

ВПамять(ав,п)

ав - Адрес; п - любого основного вида,

вид ДОСТУП, вид ЗАДАЧА

Память[ав]:=п

Образ(ав0,ав1,ц)

ав0,ав1:Адрес; ц:целый

Память[ав1..ав1+ц-1]:=

Память[ав0..ав0+ц-1]



 
 


12. Среда выполнения


12.1. Уборка памяти

Нет молочка, так сливок дай.

В языке существует встроенная задача СОЗДАТЬ, которая выделяет (новые) участки в свободной динамической памяти, т.е. в "куче" (heap/хип), для данных (переменных). Однако, нет никакого способа явно освободить уже распределённый участок в "куче". Взамен этого среда выполнения Глагол-приложений сама производит уборку памяти или сборку "мусора" (garbage collection/гербег коллэкшин), после которой встроенная задача СОЗДАТЬ сможет снова распределять неиспользуемые участки памяти под новые данные. Участок считается используемым, если он доступен по цепочке переменных вида ДОСТУП. Эта цепочка может начинаться или от переменных уровня отдела (приложения), или от переменных в задачах, вызванных на данный момент. Разрыв этой цепочки (например, присваиванием переменной вида ДОСТУП значения ПУСТО) переводит все последующие по цепочке участки в разряд неиспользуемых.

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


12.2. Описатели ВИДа

При верном псе и сторож спит.

Во время выполнения (run time/ран тайм) приложения для проверки и охраны вида необходимы знания о виде размещённых переменных. Также и для уборки динамической памяти (т.е. автоматической сборки "мусора" или пустот — участков памяти, на которые уже нет ссылок) нужны знания о расположении полей (свойств) вида ДОСТУП, входящих в переменные вида НАБОР, которые размещяются в памяти во время выполнения приложения. Эти сведения хранятся в так называемом Описателе Вида (ОписВ). Каждый вид НАБОР и каждое его расширение имеют свой собственный ОписВ (Описатель Вида). Таким образом, во время выполнения приложения для каждой размещённой переменной вида НАБОР в её скрытом свойстве <.ОписВ>, т.е. в невидимом для программиста поле (tag/тег), предшествующем обычным свойствам этого набора, хранится ДОСТУП к Описателю Вида (ОписВ).

Каждый Описатель Вида (ОписВ, по анг. tag) обязательно хранит растущий ряд доступов ко всем Описателям Опорных Видов (ОписОпорВ, по анг. BaseTypes), начиная с родоначальника (предка, опоры) и заканчивая доступом к самому себе. Этот ряд (см. ниже на рисунках в двух таблицах столбцы с .ОписОпорВ, т.е. столбцы с Дк* ... ПУСТО) необходим для охраны и проверки вида.

Вернёмся к примеру из параграфа 5 c видом НАБОР ОписаниеЯйца и его расширением ОписаниеЗолотогоЯйца = НАБОР(ОписаниеЯйца):


ВИД
  ДкЯйцо- = ДОСТУП К ОписаниеЯйца;
                       ОписаниеЯйца- = НАБОР
    твёрдость-:ЦЕЛ;
    положение+:Место
                                         КОН;

  ДкЗолотоеЯйцо = ДОСТУП К ОписаниеЗолотогоЯйца;
                              ОписаниеЗолотогоЯйца = НАБОР(ОписаниеЯйца)
    богатство:ВЕЩ
                                                        КОН;

Для (размещённой в памяти) переменной п вида ДкЗолотоеЯйцо (доступ к набору ОписаниеЗолотогоЯйца, являющемуся расширением набора ОписаниеЯйца) рисунок ниже показывает устройство (размещение) данных во время работы приложения.

п

п

п^

<.ОписВ> скрытый

ДкЗолотоеЯйцо  

.твёрдость

10

.положение

Стол

.богатство

1.0E-10

ДкЗолотоеЯйцо^                                     УРВ

.ОписОпорВ  

ДкЯйцо  

0 

ДкЗолотоеЯйцо  

1 

ПУСТО

Тоже самое, для (размещённой в памяти) переменной п вида ДкЯйцо рисунок ниже показывает устройство (размещение) данных во время работы приложения.

п

п

п^

<.ОписВ> скрытый

ДкЯйцо  

.твёрдость

10

.положение

Стол

ДкЯйцо^                                     УРВ

.ОписОпорВ  

ДкЯйцо  

0 

ПУСТО

Проверка вида: п ЯВЛЯЕТСЯ ДкВп (т.е. имеет ли размещённая переменная п вид ДОСТУП К Вп или же к его расширению) преобразуется в выражение сравнения:

п^.ОписВ^.ОписОпорВ[УРВ] = ОписВ .                       

Уровень Расширения Вида (УРВ, по анг. ExtensionLevelType), Описатель Вида Вп переменной п (ОписВ) и ряд доступов ко всем Описателям Опорных Видов (ОписОпорВ) известны во время преобразования (см. выше на рисунках в двух таблицах столбцы с .ОписОпорВ — это скрытые от программиста ряды из доступов к наборам и их раширениям, т.е. столбцы с Дк* ... ПУСТО). Например, для вида ДкЯйцо УРВ у ОписОпорВ равен 0 (этот вид не имеет опорных), а для вида ДкЗолотоеЯйцо УРВ (Уровень Расширения Вида) у ОписОпорВ равен 1, т.е.

п^.ОписВ^.ОписОпорВ[0] = ДкЯйцо ,                    
п^.ОписВ^.ОписОпорВ[1] = ДкЗолотоеЯйцо .    

NB! Из выше приведенных таблиц можно сделать такие выводы. В языках Оберон-семейства (а также в Java) представление комплексных чисел в виде набора из двух свойств (мнимое и реальное) для задач вычислительной математики может быть менее эффективным, чем их представелние в виде числового вектора (т.е. ряда из двух чисел, в котором нет дополнительного ОписВ, по анг. tag). Например, доступ к элементам вектора комплексных чисел, представленых набором, может быть медленнее, чем при организации такого же вектора в виде ряда из рядов из двух чисел (т.е. матрицы 2хN) или же из 2-х отдельных векторов для мнимой и реальной составляющих комплексного числа. Однако, эксперименты это предположение не подтверждают, т.е. наборы в Глаголе не замедляют численные алгоритмы! Однако, при обращении к вектору (ряду) в ЯП Оберон-семейства делается проверка выхода индекса за пределы ряда (0<=k<=N-1), что повышает надёжность и правильность работы приложений, хотя и немного их замеджляет (на 3%-5%). Но Глагол (и другие ЯП Оберон-семейства, и даже "Си") не могут оптимизировать использование регистров с плавающей точкой у математического сопроцессора (iFPU387) и поэтому скорость таких алгоритмов (например, БПФ2), написанных на Глаголе, будет заметно отставать от тех, что написаны на Ассемблере (в 2 раза).


 
 


13. Перевод в машинное представление


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


13.1. Тексторез

Тексторез даёт возможность выборочного перевода текста отдела в машинный код. Области перевода задаются указаниями ЕСЛИ ТО (см. 8.3), которые ограничены скобками текстореза <* и *> (см. 2). В качестве условий для этих указаний могут использоваться только ПОСТоянные выражения. Области перевода могут быть вложенными.

Пример выборочного перевода:

ОТДЕЛ Отдел;
ИСПОЛЬЗУЕТ
  Настрой;   (* отдел настройки точности вычислений и другое *)
ПОСТ
  вещ = ВКЛ;  (* работа с вещественной или целой арифметикой *)
ПЕР
  длина,
  ширина:
       <* ЕСЛИ Настрой.точность = 2 ТО *>
         <* ЕСЛИ вещ ТО *>
             ШИРВЕЩ;
         <* ИНАЧЕ *>
             ШИРЦЕЛ;
         <* КОН *>
       <* ИНАЧЕ *>
         <* ЕСЛИ вещ ТО *>
             ВЕЩ;
         <* ИНАЧЕ *>
             ЦЕЛ;
         <* КОН *>
       <* КОН *>


13.2. Преобразователь Глагола

С помощью Преобразователя Глагола (ПГ.exe) можно переводить исходные тексты приложений в машинный код формата COFF (как это делают компиляторы из MS Visual Studio). В полученном коде переменные простых видов занимают следующее число разрядов:

Вид

Разрядов

Вид Разрядов

КЛЮЧ

  8

ОБХОД.Ячейка

  8

ЗНАК

16

ОБХОД.Адрес

32

ЯЧЦЕЛ

  8

ОБХОД.Цел8

  8

УЗКЦЕЛ  

16

ОБХОД.Цел16

16

ЦЕЛ

32

ОБХОД.Цел32

32

ШИРЦЕЛ  

64

ОБХОД.Цел64

64

ВЕЩ

32

ОБХОД.Вещ32

32

ШИРВЕЩ  

64

ОБХОД.Вещ64

64

МНОЖ

32

ОБХОД.Доступ

32


13.2a. Отладка

ПГ можно настроить для создания кода, содержащего данные для внешнего отладчика, на самопроверку работы приложения, на отработку встроенной задачи ПРОВЕРИТЬ (см. 9.2), установку в ПУСТО переменных доступа при каждом вызове задач, в которых определены эти переменные. Также можно настроить ключи для взаимодействия со встроенной задачей ЗАДАНО (см. 9.2).

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

ПГ -п- %tekput%\%1 %2 %3 %4

Ключи ПГ.exe



13.3. Расширения языка для взаимодействия с иноязычными приложениями

По умолчанию, для ускорения доступа к свойствам (полям) набора производится выравнивание их положения по границе слова [4 ячейки=32 бита] или двойного слова [8 ячеек=64 бита]. Такое выравнивание данных не будет производиться, если при определении вида (см. 5.3) перед словом НАБОР добавить слово СЖАТЫЙ.

ВидНабор

 =  [СЖАТЫЙ] НАБОР ["(" ПолноеНазвание (* переменной *) ")"]
   [ОбъявлениеПеременных]
 КОН
(* [не обязательно] *)

В данном примере

ВИД 
  Набор = СЖАТЫЙ НАБОР 
    зн1:ЗНАК;  (* 1 вместо  2-х ячеек *)
    уц:УЗКЦЕЛ;(* 2 также   2 ячейки  *)
    зн2:ЗНАК;  (* 1 вместо  4-х ячеек, т.к. следующее поле выравнивается по 4-м ячейкам *)
    ц :ЦЕЛ;   (* 4 также   4 ячейки  *)
  КОН;  (* всего: 8 вместо 12 ячеек *)
ПЕР
  набор:Набор;

переменная набор будет занимать не 12, а 8 ячеек. Использование сжатых наборов понижает скорость доступа к свойствам (полям) набора, но позволяет достичь совместимости с внешними источниками данных.

Для того чтобы задачи, написанные на Глаголе, правильно принимали источники из иноязычных приложений, необходимо при объявлении задачи (см. 9) или объявлении вида ЗАДАЧА (см. 5.6) после слова ЗАДАЧА поставить знак "*".

ЗаголовокЗадачи

 =  ЗАДАЧА ["*"] название ["-"] [Приёмники [":" ВидОтвета]]

ВидЗадача

 =  ЗАДАЧА ["*"] [Приёмники [":" ВидОтвета]]

Пример:

ПЕР
  Proc:ЗАДАЧА*();
ЗАДАЧА* WinProc();
...
  Proc:=WinProc;

Задачи, объявленные таким образом, недопустимо вызывать из приложений, написанных на Глаголе (см. в КОС.отд ЗАДАЧА* Часы(uID,uMsg,dwUser,dw1,dw2:ЦЕЛ);). Иноязычное приложение сможет само связаться с такой задачей во время загрузки, если она объявлена в головном отделе, имеющем метку "+" (см. 10), и сопровождается меткой общедоступности "-" (см. 3).

Пример:

ОТДЕЛ ДПБ+;
  ЗАДАЧА* DllEntryPoint-():ЦЕЛ;
...

Для вызова внешних иноязычных задач применяются особым образом объявленные задачи. В таких объявлениях за обычным заголовком задачи после слова ВЫЗОВ записываются цепочка знаков с названием требуемой иноязычной задачи, слово ИЗ и цепочка знаков с названием места хранения этой задачи (см. в ГОС.отд пояснение Задачи ОС).

ОбъявлениеЗадачи

 =  ЗаголовокЗадачи ";" ВЫЗОВ цепочка ИЗ цепочка

Пример:

ЗАДАЧА CreateFile():ЦЕЛ; ВЫЗОВ "CreateFileW" ИЗ "Kernel32.dll";
 
 


14. Соответствие видов

Не дочитав сказки, не бросай указки.


Целые виды

ЯЧЦЕЛ, УЗКЦЕЛ, ЦЕЛ, ШИРЦЕЛ

Вещественные виды

ВЕЩ, ШИРВЕЩ

Числовые виды

целые виды, вещественные виды


Одинаковые виды

Две переменные п1 и п2 вида Вп1 и Вп2 соответственно имеют одинаковый вид, если

а) Вп1 и Вп2 оба обозначены одним и тем же названием, или

б) Вп2 объявлен как Вп2=Вп1, или

в) п1 и п2 появляются в одном и том же списке названий переменных, свойств набора или в объявлении приёмников задач и не являются открытыми рядами.


Равные виды

Виды Вп1 и Вп2 называются равными видами, если

а) виды Вп1 и Вп2одинаковые виды, или

б) виды Вп1 и Вп2 – открытые ряды с равными Опорными Видами, или

в) виды Вп1 и Вп2виды задач, чьи заголовки совпадают.


Поглощение числовых видов

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

ШИРВЕЩ >= ВЕЩ >= ШИРЦЕЛ >= ЦЕЛ >= УЗКЦЕЛ >= ЯЧЦЕЛ.


Расширение видов (опорный вид)

В объявлении вида Р=НАБОР(О)КОН, вид Рнепосредственное расширение вида О, а Онепосредственный Опорный Вид вида Р.

Вид Р является расширением вида О (О является Опорным Видом Р), если

а) О и Родинаковые виды, или

б) Рнепосредственное расширение вида, являющегося расширением вида О.

Если вид ДкО=ДОСТУП К О и вид ДкР=ДОСТУП К Р, то вид ДкР является расширением вида ДкО (вид ДкО является Опорным Видом для ДкР), если вид Р является расширением вида О, т.е. из Р(О) следует ДкР(ДкО).


Подобие опорных видов ряда

Опорный вид ОВп ряда п подобен опорному виду ОВр ряда р, если

а) Опорные Виды ОВп и ОВродинаковые виды, или

б) Опорные Виды ОВп и ОВр – оба вида ДОСТУП и ОВпрасширение вида ОВр, т.е. ОВп(ОВр), или

в) Опорный Вид ОВр – открытый ряд, Опорный Вид ОВп – произвольный ряд и Опорный Вид ОВп ряда п подобен Опорному Виду ОВр ряда р.


Совместимость по присваиванию

Выражение в вида Вв совместимо по присваиванию с переменной п вида Вп, если выполнено одно из следующих условий:

а) виды Вв и Вподинаковые виды;

б) виды Вв и Впчисловые виды и Вп поглощает Вв;

в) виды Вв и Вп – оба виды НАБОР, Вврасширение вида Вп, т.е. Вв(Вп), а переменная п имеет размещённый вид Вп;

г) виды Вв и Вп – оба виды ДОСТУП и Вврасширение вида Вп, т.е. Вв(Вп);

д) виды Вв и Вп – оба виды БЕГУНОК и Опорные Виды у Вв и Вп одинаковые;

е) вид Впвид ДОСТУП, БЕГУНОК, ЗАДАЧА, а выражение вПУСТО;

ж) вид ВпРЯД N ИЗ ЗНАК, выражение в – цепочка из M знаков и M<N;

з) вид Впвид ЗАДАЧА, а переменная п – название задачи, у которой заголовок совпадает с заголовком Вп;

и) вид Вп – доступ к открытому ряду, вид Вв – доступ к произвольному ряду, а Опорный Вид ряда по доступу Вв подобен Опорному Виду ряда по доступу Вп.


Совместимость при вызове задачи

Выражение источника ис вида Вис совместимо при вызове задачи с приёмником пр вида Впр, если выполнено одно из следующих условий:

а) вид Вис совместим по присваиванию с видом Впр;

б) вид ВпрЦЕПЬ или открытый РЯД ИЗ ЗНАК, источник ис – цепочка знаков (пр не может быть приёмником ссылок для записи, а только на чтение);

в) вид Впр – открытый ряд, вид Вис – произвольный ряд, а Опорный Вид ряда Вис подобен Опорному Виду ряда Впр.


Совместимость выражений

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

Действие Вид первого данного Вид второго данного Вид ответа

+ – *

числовой числовой

наименьший числовой вид,
поглощающий виды обоих данных

/

числовой числовой

наименьший вещественный вид,
поглощающий виды обоих данных

 ДЕЛИТЬ ОСТАТОК целый целый

наименьший целый вид,
поглощающий виды обоих данных

+ – * /

МНОЖ

МНОЖ

МНОЖ

И ИЛИ НЕ

КЛЮЧ

КЛЮЧ

КЛЮЧ

= # < <= >= >

числовой числовой

КЛЮЧ

= # < <= >= >

ЗНАК

ЗНАК

КЛЮЧ

< <= > >=

БЕГУНОК ПО Во

БЕГУНОК ПО Во

КЛЮЧ

= # < <= >= >

ЦЕПЬ,
цепочка знаков

ЦЕПЬ,
цепочка знаков

КЛЮЧ

= #

КЛЮЧ

КЛЮЧ

КЛЮЧ

= #

МНОЖ

МНОЖ

КЛЮЧ

= #

ЗАДАЧА,

ПУСТО

ЗАДАЧА,

ПУСТО

КЛЮЧ

= #

БЕГУНОК ПО Во,

ПУСТО

БЕГУНОК ПО Во,

ПУСТО

КЛЮЧ

= #

ДОСТУП К Во,

Вр,

ПУСТО

ДОСТУП К Во,

Вр,

ПУСТО

КЛЮЧ

В

целый

МНОЖ

КЛЮЧ

ЯВЛЯЕТСЯ

Во

Вр

КЛЮЧ


Совпадение заголовков задач

Два заголовка задач совпадают, если

а) они имеют одинаковое количество приёмников, и

б) они имеют или одинаковый вид ответа задачи, или не имеют никакого, и

в) приёмники в соответствующих позициях имеют равные виды, и

г) приёмники в соответствующих позициях оба – или приёмники значений, или приёмники ссылок.


 

 


15. Правила построения языка

Не дочитав сказки, не бросай указки.

Отдел

 =    ОТДЕЛ название ["-" | "+"] ";"(* + для главного отдела приложения *)
[ИСПОЛЬЗУЕТ название [ИЗ цепочка] { ","
           название [ИЗ цепочка] } ";" (* {повтор от 0 раз} *)
]
    Объявления
[УКАЗ
    Указания] (* [не обязательно] *)
 КОН название (* отдела *) "."

Объявления

 =  {ПОСТ
    {ОбъявлениеПостоянной ";"} (* {повтор от 0 раз} *)
|ВИД
    {ОбъявлениеВида ";"}       (* {повтор от 0 раз} *)
|ПЕР
    {ОбъявлениеПеременных ";"} (* {повтор от 0 раз} *)
}
{ ЗаготовкаЗадачи ";" | ОбъявлениеЗадачи ";" }

ОбъявлениеПостоянной

 =  название ["-"] "=" ПостоянноеВыражение

ОбъявлениеВида

 =  название ["-"] "=" Вид

ОбъявлениеПеременных

 =  название ["-" | "+"] {"," название ["-" | "+"]} ":" Вид

ЗаготовкаЗадачи

 =  ЗАДАЧА ["*"] "^" название ["-"]
[ "(" [ОбъявленияПриёмников] ")" [":" ВидОтвета] ]

ОбъявлениеЗадачи

 =      ЗаголовокЗадачи ";" ТелоЗадачи название
| ЗаголовокЗадачи ";" ВЫЗОВ цепочка ИЗ цепочка

ЗаголовокЗадачи

 =  ЗАДАЧА ["*"] название ["-"]
[ "(" [ОбъявленияПриёмников] ")" [":" ВидОтвета] ]

ТелоЗадачи

 =     Объявления
[УКАЗ
   Указания | ВОЗВРАТ [Выражение]  (* из ЗАДАЧИ *)
] (* [не обязательно] *)
 КОН

ОбъявленияПриёмников

 =  ОбъявлениеПеременных {";" ОбъявлениеПеременных}

Вид

 =  ПолноеНазвание (* Вида ПЕРеменной *)
| простойВид              (* ЗНАК, МНОЖ, КЛЮЧ, ВЕЩ и ЦЕЛ *)
| составнойВид            (* РЯД, ЦЕПЬ и НАБОР *)
| дополнительныйВид       (* ДОСТУП, БЕГУНОК и ЗАДАЧА *)

простойВид

 =  ПолноеНазвание (* простого Вида ПЕРеменной *)
| ЗНАК
| МНОЖ
| КЛЮЧ
| ВЕЩ
| ШИРВЕЩ
| ЦЕЛ
| ШИРЦЕЛ
| УЗКЦЕЛ
| ЯЧЦЕЛ

составнойВид

 =  ПолноеНазвание (* составного Вида ПЕРеменной *)
| РЯД [ПостоянноеВыражение {"," ПостоянноеВыражение}] ИЗ Вид
| ЦЕПЬ ["[" ПостоянноеВыражение "]"] (* РЯД из элементов ВИДа ЗНАК *)
| [СЖАТЫЙ] НАБОР ["(" ПолноеНазвание ")"] (* [не обязательно] *)
    [ОбъявлениеПеременных] (* [не обязательно] *)
  КОН (* ВИДа НАБОР *)

дополнительныйВид

 =  ПолноеНазвание (* дополнительного Вида ПЕРеменной *)
| ДОСТУП К составнойВид (* НАБОР или РЯД или ЦЕПЬ *)
| БЕГУНОК [ПостоянноеВыражение] ПО составнойВид (* только РЯД из чисел *)
| ЗАДАЧА ["*"] [ "(" [ОбъявлениеПеременных] ")" [":" ВидОтвета] ]

ВидОтвета

 =  ПолноеНазвание (* Вида ответа *)
| простойВид
| ДОСТУП К составнойВид

Указания

 =  Указание {";" Указание}

Указание

 =  [ Обозначение ":=" Выражение
| Обозначение ["(" [Выражения] ")"]
| ЕСЛИ  Выражение ТО Указания
 {АЕСЛИ Выражение ТО Указания} (* {повтор от 0 раз} *)
 [ИНАЧЕ
    Указания] (* [не обязательно] *)
  КОН (* указания ЕСЛИТО *)
| ВЫБРАТЬ Выражение ИЗ
 ["|"] Вариант  (* первое "|" не обязательно *)
 {"|"  Вариант} (* {повтор от 0 раз} *)
 [ИНАЧЕ
    Указания] (* [не обязательно] *)
  КОН (* указания ВЫБРАТЬИЗ *)
| ПОКА Выражение ВЫП
    Указания
  КОН (* цикла ПОКА *)
| ПОВТОРЯТЬ
    Указания
  ДО Выражение (* конец цикла ПОВТОРЯТЬ *)
| ОТ ПолноеНазвание":="Выражение ДО Выражение [ПО ПостоянноеВыражение]
  ВЫП
    Указания
  КОН (* цикла ОТДО *)
| КОЛЬЦО
    Указания | ВЫХОД (* из цикла КОЛЬЦО *)
  КОН (* цикла КОЛЬЦО *)
| ДЛЯ ПолноеНазвание (* переменной *) ВИДА
 ["|"] ОхранаУказаний  (* первое "|" не обязательно *)
 {"|"  ОхранаУказаний} (* {повтор от 0 раз} *)
 [ИНАЧЕ
    Указания] (* [не обязательно] *)
  КОН (* локальной охраны/привратника ВИДа *)
]

Вариант

 =  [Метки {"," Метки} ":" Указания]

Метки

 =  ПостоянноеВыражение [".." ПостоянноеВыражение]

ОхранаУказаний

 =  [охраняемыйВид ":" Указания]

охраняемыйВид

 =  ПолноеНазвание (* охраняемого ВИДа *)
| приёмник ссылок ВИДа НАБОР
| ДОСТУП К составнойВид

ПостоянноеВыражение

 =  Выражение

Выражения

 =  Выражение {"," Выражение}

Выражение

 =  ПростоеВыражение [Отношение ПростоеВыражение]

ПростоеВыражение

 =  ["+" | "-"] Слагаемое {Сложение Слагаемое}

Слагаемое

 =  Множитель {Умножение Множитель}

Множитель

 =  Обозначение ["(" [Выражения] ")"]
| число
| одинзнак
| цепочка
| ПУСТО
| Множество
| "(" Выражение ")"
| НЕ Множитель

Множество

 =  "{" [Элемент {"," Элемент}] "}"

Элемент

 =  Выражение [".." Выражение]

Отношение

 =  "=" | "#" | "<" | "<=" | ">" | ">=" | В | ЯВЛЯЕТСЯ

Сложение

 =  "+" | "-" | ИЛИ

Умножение

 =  "*" | "/" | ДЕЛИТЬ | ОСТАТОК | И

Обозначение

 =  ПолноеНазвание {"." название
| "[" Выражения "]"
| "^"
| "(" ПолноеНазвание ")"}

ПолноеНазвание

 =  [название "."] название (* ВИДа, ПОСТоянной, ПЕРеменной *)
 
 



Вопросы, замечания и предложения высылайте на atimopheyev@yahoo.com

 
Главная     Глагол-2006 ►   Азбука ►   Задачи на Глаголе ►   Примеры приложений ►   Среда разработки ►   Отладка программ ►   Отличия от Оберона ►   Отличия от Паскаля ►   ООП по Вирту ►   Ассемблер ARM ►   Глагол для ARM ►   ? и Ответы