Инструкции
Инструкция приказывает системе выполнить какое-либо действие. Инструкции могут содержать одно или несколько присваиваний, меток или команд и, как правило, начинаются с новой строки. Далее приводятся краткие описания и примеры общеупотребительных инструкций.
Инструкция SAY - Формат инструкции SAY следующий:
SAY выражение
Выражение представляет собой какое-либо сообщение, которое Вы хотите вывести на экран, либо арифметическое выражение, которое должно быть вычислено, как, например, в следующем уравнении:
SAY 5 + 6 "= одиннадцать"
На экран будет выведено
11 = одиннадцать
Все символы в инструкции SAY, не заключенные в кавычки, преобразуются в прописные буквы или обрабатываются. Поэтому, если нужно вывести сообщение именно так, как оно набрано, то заключите его в кавычки.
Инструкции PULL и PARSE PULL - Обычная последовательность инструкций в процедуре - SAY для задания вопроса, а затем PULL для получения ответа. Ответ, введенный пользователем, помещается в память системы. Процедура, текст которой приведен ниже, выполнится некорректно, если инструкция PULL будет предшествовать инструкции SAY.
Вопрос: Что произойдет, если выполнится процедура NAME.CMD, текст которой приведен ниже?
/* Использование инструкции PULL */ SAY "Введите Ваше имя" PULL name /* Помещает ответ пользователя в память */ SAY "Привет" name EXIT
Ответ: NAME.CMD помещает введенное имя в память, а затем выводит это имя без кавычек в любом месте файла, где появится слово name.
Если Вы выполните процедуру NAME, то, возможно, заметите, что все буквы имени преобразуются в прописные. Чтобы сохранить символы в том виде, в каком они были набраны, используйте инструкцию PARSE PULL. Ниже приведен пример процедуры CHITCHAT.CMD, которая использует эту инструкцию:
/* Использование инструкции PARSE PULL */ SAY "Привет! Вы все еще там?" SAY "Я забыл Ваше имя. Как Вас зовут?" PARSE PULL name SAY name "Вы собираетесь на семинар к Ричарду?" PULL answer IF answer = "YES" THEN SAY "Хорошо. Увидимся там!" IF answer = "NO" THEN SAY "Как жаль, мы пропустим Ваше сообщение." EXIT
Инструкция PARSE PULL считывает все символы, введенные с клавиатуры так, как они были набраны, строчными или прописными. В приведенной процедуре имя выводится так, как Вы его ввели. Однако символы, помещенные в поле answer, преобразуются в прописные, поскольку при этом используется инструкция PULL. Это гарантирует, что какой бы Вы ответ ни ввели, yes, Yes или YES, будет выполнено одно и то же действие.
Инструкция EXIT - Инструкция EXIT прекращает выполнение процедуры. Эта инструкция должна использоваться в процедурах, содержащих подпрограммы. Несмотря на то, что инструкция EXIT необязательна для некоторых процедур, использование ее в конце каждой процедуры - признак хорошего стиля программирования.
Использование основных элементов языка REXX
В этом разделе пользователю предоставляется возможность ознакомиться с некоторыми элементами, используемыми при написании процедур REXX. Не беспокойтесь том, что при программировании могут быть ошибки, так как в этом разделе информация излагается последовательно по шагам.
Прим. | При написании процедур REXX рекомендуется для каждого элемента использовать отдельную строку. Если Вы хотите расположить элемент в нескольких строках, то поставьте запятую (,) в конце строки. Это обозначает, что элемент продолжается на следующей строке. Если же нужно поместить несколько элементов в одной строке, то разделите их точкой с запятой (;). |
В процедурах REXX могут быть любые или все перечисленные ниже элементы:
в дальнейшем REXX) разработан как
Язык процедур 2/REXX для OS/2* (именуемый в дальнейшем REXX) разработан как язык процедур Systems Application Architecture* для семейства продуктов типа Office Vision и операционной системы OS/2. Он предназначен для того, чтобы облегчить программирование в стадии кодирования и отладки. Высокое качество программирования может быть достигнуто при использовании общепринятых слов английского языка в синтаксисе языка процедур, что одинаково понятно как начинающему, так и опытному программисту.
REXX использует ряд мощных программных функций общего назначения и стандартные арифметические возможности наряду с командами OS/2 в простой конструкции. Существующие пакетные файлы могут быть преобразованы в процедуры REXX, обладающие большими функциональными возможностями.
Процедуры REXX выполняются только в сеансах OS/2, они должны иметь расширение файла .CMD и начинаться со строки комментария (/*....*/). Также, как и для пакетных файлов, чтобы выполнить процедуру REXX, необязательно указывать расширение .CMD.
Приведенная информация:
Настоящая оперативная информация по REXX предназначена для ознакомления с языком, получения сведений об его основных особенностях и возможностях, а также для формирования представления о базовых принципах его работы. Разделы от "Приступая к работе .." до "PMREXX" представляют собой краткий обзор, основанный на информации об общих концепциях REXX, в то время как разделы "Инструкции" и "Функции" содержат конкретные сведения обо всех инструкциях и функциях, которые являются частью языка. Для получения более детальной информации по языку REXX обращайтесь к документу Язык процедур 2/REXX. Справочник или Руководство пользователя.
это слово, фраза или аббревиатура,
Команда - это слово, фраза или аббревиатура, которые приказывают системе выполнить определенные действия. В языке REXX все, что не является инструкцией REXX, оператором присваивания или меткой, рассматривается как команда. Например, в процедурах REXX можно использовать такие команды OS/2, как COPY, BACKUP, PRINT, TYPE и т.д.
Ниже приводится пример использования команды OS/2 TYPE в процедуре REXX:
/* Использование команд в процедуре REXX */ TYPE hello.cmd EXIT
Это означает, что REXX инициирует выполнение команды TYPE.
Все процедуры REXX должны начинаться
Все процедуры REXX должны начинаться комментарием, расположенным с первой позиции первой строки файла. Комментарий указывает процессору команд, что программа, которую нужно прочитать и выполнить, - это процедура REXX. Для обозначения комментария используются следующие символы:
/* Отмечает начало комментария
*/ Отмечает конец комментария
Когда интерпретатор команд находит символ /*, он прекращает интерпретацию; если же он встречает символ */, интерпретация начинается с информации, следующей за этим символом. Комментарий может содержать несколько слов, несколько строк или вообще не содержать информации, т.е. состоять из пустого элемента, как показано на следующих примерах:
/* Это комментарий. */ или
SAY "'Будьте готовы!'" /* Этот комментарий расположен в той же строке, что и инструкция, и продолжается на следующей строке */
В начале процедуры REXX можно использовать комментарий типа /* */, однако гораздо предпочтительнее помещать в качестве комментария краткое описание процедуры.
Комментарий может отражать назначение данной процедуры, способ ввода информации, вывода результатов работы и т.д. Комментарии помогают быстрее разобраться в процедуре, когда Вы будете читать ее спустя некоторое время. Комментарии можно добавлять, улучшать или использовать в разных частях этой или другой процедуры.
При написании процедуры не забывайте, что кто-то будет ее использовать и, возможно, ее потребуется модифицировать. Поэтому добавление комментариев к инструкциям помогает понять каждый шаг процедуры. Если к тому же процедура используется достаточно редко, то комментарии позволяют самому разработчику быстро освежить в памяти ее назначение. Вообще говоря, процедура должна быть прокомментирована достаточно хорошо, чтобы быть понятной всем, кто будет ею пользоваться.
Метки
В качестве метки может выступать любое слово, за которым следует двоеточие (между словом и двоеточием не должно быть пробелов) и которое не заключено в кавычки. Например:
MYNAME:
Метка отмечает начало подпрограммы. Ниже приведен пример использования метки error внутри процедуры:
. . . IF problem = 'yes' then SIGNAL error . . . error: SAY 'Ошибка в данных' EXIT
Написание процедур
Напишем следующую процедуру REXX с помощью текстового редактора. Чтобы написать процедуру REXX с именем HELLO.CMD, выполните следующие инструкции:
1. Создайте текстовый файл с именем HELLO.CMD.
2. Наберите текст процедуры HELLO.CMD, приведенной ниже:
/* Введение в REXX */ SAY "Привет! Я - REXX" SAY "Как Вас зовут?" PULL who IF who = "" THEN SAY "Привет, Незнакомец" ELSE SAY "Привет," who EXIT
3. Сохраните файл и выйдите из текстового редактора.
Теперь все готово для того, чтобы выполнить эту процедуру REXX. Наберите имя процедуры в командном режиме OS/2 и нажмите клавишу ENTER.
hello
Когда процедура сделает паузу, Вы можете либо ввести свое имя, либо просто нажать клавишу ENTER, чтобы увидеть второй вариант ответа.
Далее приведено краткое описание каждой части процедуры HELLO.CMD :
/* Введение в REXX */ В этом комментарии указывается, что данная процедура выполняет. Строка комментария начинается с символа /* и заканчивается символом */. Все процедуры REXX должны начинаться с комментария в первой позиции первой строки файла. Строка комментария указывает процессору команд, что процедура, которую нужно выполнить, - это процедура REXX. По этому признаку процессор команд отличает ее от обычных пакетных файлов.
SAY "Привет! Я - REXX." SAY "Как Вас зовут?" С помощью этих инструкций слова, заключенные в двойные кавычки, выводятся на экран.
PULL who С помощью инструкции PULL читается ответ, введенный с клавиатуры, и помещается в память операционной системы. Who - это имя, присвоенное области памяти, куда помещается введенный пользователем ответ. В инструкции PULL можно использовать любое имя.
IF who = " " Инструкция IF проверяет условие. В этом примере проверяется, пусто ли поле who. Оно будет пустым, если пользователь набрал пробел, а затем нажал клавишу ENTER, либо просто нажал клавишу ENTER.
THEN Определяет, что в случае истинности проверяемого условия, должна выполняться инструкция, следующая за данной.
SAY "Привет, Незнакомец" Выводит на экран слова Привет, Незнакомец.
ELSE Определяет, что в случае ложности проверяемого условия должна выполняться инструкция, следующая за данной.
SAY "Привет," who Выводит на экран слово Привет с последующим отображением содержимого поля who.
EXIT Эта инструкция прекращает выполнение процедуры.
Если пользователь с именем Сергей выполнит процедуру HELLO, то протокол его работы будет иметь следующий вид:
[C:\]hello Привет! Я - REXX. Как Вас зовут?
Сергей
Привет, Сергей
[C:\]
Если Сергей не введет свое имя, а наберет пробел, то протокол работы будет следующим:
[C:\]hello Привет! Я - REXX. Как Вас зовут?
Привет, Незнакомец
[C:\]
Операторы присваивания
Оператор присваивания сообщает системе, что цепочку символов нужно поместить в определенное поле в памяти операционной системы. Например:
Work = "Здание 021" строка Здание 021 запоминается как значение поля Work в памяти операционной системы. Так как поле Work может принимать различные значения (переопределяться по ходу выполнения) в различных частях процедуры, то его можно назвать переменной.
Приступая к работе с REXX
Процедура REXX представляет собой программу, состоящую из набора заданий, заключенных в один обрабатывающий или пакетный файл.
Для написания программ могут быть использованы многие языки программирования. BASIC, который широко используется для базовых вычислений, имеет очень ограниченный набор правил, однако при написании сложных программ требует многих строк кода. Такие языки, как PL/1, COBOL, C, APL и PASCAL имеют более обширный набор правил, но при этом позволяют в нескольких строках закодировать большее число функций.
REXX сочетает простоту такого языка программирования, как BASIC, с возможностями более мощных языков, перечисленных выше. REXX легок в изучении, так как использует знакомые слова и понятия. При этом REXX позволяет решать как простые задачи, так и более сложные комплексные проблемы.
Чтобы начать работу с языком REXX, необходимо иметь:
Персональный компьютер с инсталлированной на нем операционной системой OS/2 версии 2.0. Процедуры REXX выполняются только в сеансах OS/2. Сведения об использовании текстового редактора.
Многие изучают язык программирования, просматривая примеры, поэтому настоящий обзор сопровождается примерами процедур REXX. Сначала просмотрите процедуру, затем изучите разъяснение к примерам, чтобы понять, что содержится в процедуре. При желании можно выполнить процедуру, чтобы увидеть, как она работает.
Строки
Строка представляет собой цепочку символов, заключенных в апострофы или кавычки. Можно использовать любые из этих символов, но только парами. Когда интерпретатор команд встречает один из этих символов, он прекращает интерпретацию и последующие символы оставляет в таком виде, в каком они были набраны, включая строчные и прописные буквы. Когда интерпретатор команд опять встречает такой же символ, он возобновляет интерпретацию. Например:
'Грандиознейшее Шоу на Планете' "Президент правит своей страной"
Оба сообщения - строки.
Чтобы использовать апостроф или кавычки внутри строки, для обрамления полной строки выберите другой символ. Например:
"Don't count your chickens before they hatch." или
'Do not count your "chickens" before they hatch.'
Внутри строки можно также использовать удвоенный символ (такого же типа, как и для обрамления полной строки). Например:
SAY "Mary said ""He's here."""
Эту инструкцию REXX интерпретирует следующим образом:
Mary said "He's here."
Написание арифметических процедур REXX
Ниже дано упражнение, позволяющее повторить некоторые правила, используемые в предыдущих примерах. Вам нужно написать процедуру, выполняющую операцию сложения двух чисел. Имя процедуры - ADD.CMD.
В своей процедуре Вам придется выполнить следующие действия:
Идентифицировать и описать процедуру REXX. Предложить пользователю ввести числа. Прочитать введенные числа и поместить их в память системы. Сложить два числа и вывести результат на экран. Завершить выполнение процедуры.
Существует множество способов, позволяющих выполнить поставленную задачу. Чтобы облегчить ее выполнение в данной процедуре, предложим пользователю ввести каждое число отдельно, а затем сложим эти числа. Далее приведены размышления, которые помогут Вам при написании процедуры ADD.CMD.
Первым делом, что идентифицирует процедуру REXX? Если Вы считаете, что это комментарий, то Вы правы. Далее, нужно предложить пользователю ввести число. С помощью инструкции SAY можно вывести это предложение на экран. Когда число введено, его нужно поместить в память компьютера. Инструкция PULL получает ответ и помещает его в память. Инструкция, которая запрашивает ввод второго числа, может выглядеть подобно первой; второе число также должно быть помещено в память. Следующая инструкция похожа на инструкцию в процедуре MATH. В одном операторе языка REXX можно приказать интерпретатору сложить два значения в памяти и вывести результат на экран. Для этого используйте одну инструкцию, которая содержит строку и операцию сложения. В заключение, для завершения выполнения процедуры используйте инструкцию EXIT. Если Вы хотите проверить работу этой процедуры, то наберите и сохраните текст, приведенный ниже.
/* Эта процедура складывает два числа */ SAY "Введите первое число." PULL num1 SAY "Введите второе число." PULL num2 SAY "Сумма двух чисел равна" num1 + num2 EXIT
Чтобы выполнить процедуру ADD.CMD, введите ADD в командном режиме OS/2, а затем введите два любых числа. Ниже приведен протокол работы этой процедуры, если Вы ввели числа 3 и 12.
[C:\]ADD Введите первое число. 3 Введите второе число. 12 Сумма двух чисел равна 15 [C:\]
Переменные
Переменная представляет собой часть данных с изменяющимся значением. Каждой переменной внутри процедуры присваивается уникальное имя, по которому на нее ссылаются в дальнейшем.
При выборе имени переменной имейте в виду, что первым символом может быть один из следующих:
A B C...Z ! ? _
Первым символом имени может быть и строчная буква. Интерпретатор перекодирует ее в прописную.
Остальными символами могут быть все перечисленные символы, а также цифры от 0 до 9.
Работа с переменными и арифметическими выражениями
В этом разделе рассказывается о том, как использовать переменные и производить арифметические вычисления, а также как писать комментарии, поясняющие работу процедуры. Этот раздел содержит информацию по следующим темам:
Часть данных, которой присвоено уникальное имя | |
Содержание переменной | |
Символы, используемые для арифметических функций | |
+ оператор | |
- оператор | |
* оператор | |
/, //, % операторы |
Выполнение арифметических вычислений
Может возникнуть необходимость включить в процедуры REXX арифметические операции сложения, вычитания, умножения и деления. Например, Вам потребуется присвоить числовые значения двум переменным и затем сложить их.
Арифметические операции выполняются обычным образом. Вы можете использовать целые числа и десятичные дроби. Целое число - это любое натуральное число, положительное, отрицательное или ноль, которое не содержит десятичной части (например, 1, 25 или 50). Десятичная дробь содержит десятичную точку (например, 1.45 или 0.6).
Прежде чем продемонстрировать использование этих четырех операций в процедурах, мы приведем примеры написания арифметических выражений и символов, предназначенных для каждой операции. Это будут просто некоторые арифметические операции, используемые в REXX.
Прим. | Приведенные примеры содержат пробелы между числами и операторами для того, чтобы выражение смотрелось нагляднее, однако эти пробелы необязательны. |
Операторы - Символы, используемые для арифметических операций (+, -, *, /), называются операторами. Они производят действия над соседними элементами. В следующем примере операторы производят действия над числами (элементами) 4 и 2:
SAY 4 + 2 /* выводит "6" */ SAY 4 * 2 /* выводит "8" */ SAY 4 / 2 /* выводит "2" */
Сложение - Оператор сложения - это знак плюс (+). Инструкция сложения двух чисел выглядит следующим образом:
SAY 4 + 2
Результат выполнения инструкции Вы увидите на экране, это будет число 6.
Вычитание - Оператором вычитания - это знак минус (-). Инструкция вычитания двух чисел выглядит следующим образом:
SAY 8 - 3
Результатом выполнения инструкции будет число 5, которое выводится на экран.
Умножение - Оператор умножения - это звездочка (*). Инструкция умножения двух чисел выглядит следующим образом:
SAY 2 * 2
Результатом выполнения инструкции будет число 4, которое выводится на экран.
Деление - Для операции деления можно использовать несколько операторов в зависимости от того, каким Вы хотите видеть результат: в виде полного числа, либо в виде какой-то его части.
Значение переменной, в отличие от имени, может изменяться. Когда Вы именуете переменную (придаете ей некоторое значение), то тем самым выполняете присваивание. Например, любой оператор типа symbol = выражение является оператором присваивания. Таким образом, Вы приказываете интерпретатору вычислить значение выражения и поместить результат в поле переменной symbol. Это эквивалентно следующему: "Присвоить переменной symbol значение результата выражения" или каждый раз, когда переменная symbol появляется в тексте строки инструкции SAY без кавычек, выводить на ее месте значение выражения. Взаимосвязь между переменной и ее значением такая же, как и между почтовым ящиком и его содержимым. Номер почтового ящика всегда один и тот же, а его содержимое может поменяться в любое время. Ниже приведен пример еще одного оператора присваивания: num1 = 10 Здесь num1 имеет то же смысловое значение, что и слово symbol в предыдущем примере, а значение 10 соответствует слову выражение. Один из способов изменения значения переменной num1 - добавление некоторого числа или выражения к старому значению с помощью следующего оператора присваивания: num1 = num1 + 3 Значение num1 теперь изменилось с 10 на 13. Специальным соглашением в REXX является то, что в качестве первоначального значения переменной, которой не было присвоено значение, является ее имя, выводимое прописными буквами. Например, если Вы напишете в процедуре list = 2 20 40 SAY list то на экран выведется следующая информация: 2 20 40 Таким образом, переменная list принимает значения, которые были ей присвоены. Однако, если Вы не присвоите переменной list никакого значения и просто напишете: SAY list то на экран выведется: LIST Ниже приведен пример простой процедуры VARIABLE.CMD, которая присваивает значения переменным: /* Присваивание значений переменным */ a = 'abc' SAY a b = 'def' SAY a b EXIT Если Вы выполните процедуру VARIABLE, то протокол работы будет выглядеть следующим образом: [C:\]VARIABLE abc abc def [C:\] Процесс присваивания значений прост, однако убедитесь в том, что имя, выбранное для переменной, не будет использовано непредумышленно, как показано на примере процедуры MEETING.CMD: /* Непреднамеренная интерпретация переменной */ the='no' SAY Here is the person I want to meet EXIT Протокол выполнения процедуры: [C:\]MEETING HERE IS no PERSON I WANT TO MEET [C:\] Чтобы предотвратить непреднамеренное замещение слова переменной, заключите предложение в кавычки, как это сделано в процедуре MEETING.CMD, которая теперь уже правильно присваивает значение переменной: /* Правильная интерпретация переменной the*/ the= 'no' SAY "Here is the person I want to meet" EXIT SELECT приказывает интерпретатору выбрать одну инструкцию из перечня возможных. Она используется только вместе с WHEN, THEN, END и иногда с OTHERWISE. Инструкция END отмечает конец каждой группы SELECT. Инструкция SELECT выглядит следующим образом: SELECT WHEN выражение1 THEN инструкция1 WHEN выражение2 THEN инструкция2 WHEN выражение3 THEN инструкция3 ... OTHERWISE инструкция инструкция инструкция END
Например, для обычной операции деления используется символ наклонной черты (/). Инструкция деления двух чисел выглядит следующим образом:
SAY 7 / 2
Результатом выполнения инструкции будет число 3.5, которое выводится на экран.
Для того, чтобы получить только остаток от деления, в качестве оператора деления используйте символ, состоящий из двух наклонных черт (//). Чтобы получить только целую часть без остатка, используйте знак процента (%).
Для просмотра примеров, демонстрирующих выполнение описанных выше арифметических действий, выберите => .
Вычисляемые выражения - Обычно выражения вычисляются слева направо. Выражение, приведенное ниже, иллюстрирует это правило. До сих пор Вы имели дело с выражениями, содержащими один оператор и два элемента, например, 4 + 2. Предположим, что имеется следующее выражение:
9 - 5 + 4 =
Сначала вычисляется выражение 9 - 5. К значению выражения 4 добавляется 4 и в конечном итоге получится 8.
Однако некоторые операции имеют приоритет перед другими. В общем случае к выражениям применимы правила алгебры. Например, в выражении, приведенном ниже, операция деления выполняется раньше операции сложения:
10 + 8 / 2 =
Результатом этого выражения будет число 14.
Если в выражении Вы используете скобки, то интерпретатор сначала вычислит значение выражения в скобках. Например:
(10 + 8) / 2 =
Результатом данного выражения будет число 9.
Значение
Инструкции SELECT, AND, WHEN, OTHERWISE и NOP
Прим. | Инструкцию IF-THEN нельзя использовать с инструкцией SELECT, за исключением случаев, когда она следует за инструкциями WHEN или OTHERWISE. Формат инструкции SELECT, приведенный выше, можно интерпретировать следующим образом: Если выражение1 истинно, то выполняется инструкция1. После этого обработка продолжается с инструкции, следующей за END. Инструкция END отмечает конец инструкции SELECT. Если выражение1 ложно, проверяется выражение2. Если выражение2 истинно, то выполняется инструкция2 и обработка продолжается с инструкции, следующей за END. Тогда и только тогда, когда все указанные выражения ложны, обработка продолжается с инструкции, следующей за OTHERWISE. |
На диаграмме, приведенной ниже, представлена наглядная структура инструкции SELECT:
Инструкцию DO-END можно включить в инструкцию SELECT следующим образом:
SELECT WHEN выражение1 THEN DO инструкция1 инструкция2 инструкция3 END . . .
Инструкцию SELECT применяйте для использования одной переменной, которая может принимать несколько различных значений. С каждым из этих значений можно связать выполнение различных действий.
Допустим, Вы хотите составить памятку основных дел на неделю. Переменная day может принимать значения Понедельник - Пятница. В зависимости от дня недели (значение переменной), Вы можете вывести список дел на соответствующий день (с помощью инструкции). Процедура SELECT.CMD, приведенная ниже, решает поставленную задачу.
Прим. | Инструкция THEN или ELSE должна предшествовать инструкции, непосредственно выполняющей выбранное действие. |
/* Выбор дел на каждый день недели */ SAY 'Какой сегодня день?' Pull day SELECT WHEN day = 'ПОНЕДЕЛЬНИК' THEN SAY ' Знакомство с доской объявлений' WHEN day = 'ВТОРНИК' THEN SAY "Встреча с моей командой" WHEN day = 'СРЕДА' THEN NOP /* Нет операции */ WHEN day = 'ЧЕТВЕРГ' THEN SAY "Мой семинар" WHEN day = 'ПЯТНИЦА' THEN SAY "Рецензирование книги" OTHERWISE SAY "Выходной день, все может случиться!" END EXIT
Инструкция NOP: Если Вы не хотите предпринимать никаких действий для определенного выражения, то используйте инструкцию NOP (No Operation), как показано в предыдущем примере для значения СРЕДА.
Инструкция ELSE
ELSE определяет инструкцию, которая должна быть выполнена в случае, если выражение ложно. Чтобы приказать интерпретатору выбрать одну из двух возможных инструкций, используйте следующую конструкцию: IF выражение THEN инструкция1 ELSE инструкция2
Формат IF-THEN-ELSE можно включить и в следующую процедуру:
IF answer = 'ДА' THEN SAY 'ХОРОШО!' ELSE SAY 'почему нет?'
Выполните процедуру GOING.CMD, чтобы посмотреть, как на практике осуществляется выбор между двумя инструкциями:
/* Использование IF-THEN-ELSE */ SAY "Ты собираешься на заседание?" PULL answer IF answer = "ДА" THEN SAY "Я буду тебя ждать." ELSE SAY "Я сделаю для тебя заметки." EXIT
Ниже приведен протокол работы этой процедуры:
[C:\]GOING Ты собираешься на заседание?
да
Я буду тебя ждать.
[C:\]
Логические операторы NOT, AND, OR
Логические операторы могут возвращать только значения 1 или 0. Оператор NOT (¬ или \), указанный перед элементом, изменяет его значение либо с истинного на ложное, либо с ложного на истинное.
SAY \ 0 /* выведет '1' */ SAY \ 1 /* выведет '0' */ SAY \ (4 = 4) /* выведет '0' */ SAY \ 2 /* выведет ошибку синтаксиса */
Оператор AND (&), указанный между двумя элементами, принимает значение истина только в том случае, когда оба элемента истинны.
SAY ( 3 = 3 ) & ( 5 = 5 ) /* выведет '1' */ SAY ( 3 = 4 ) & ( 5 = 5 ) /* выведет '0' */ SAY ( 3 = 3 ) & ( 4 = 5 ) /* выведет '0' */ SAY ( 3 = 4 ) & ( 4 = 5 ) /* выведет '0' */
Оператор OR ( | ), указанный между двумя элементами, принимает значение истина, если хотя бы один элемент имеет значение истина.
Прим. | В зависимости от клавиатуры персонального компьютера и используемой кодовой страницы, Вы можете не найти сплошную вертикальную черту для оператора OR. Поэтому в качестве оператора OR REXX также распознает прерывистую вертикальную черту. Некоторые клавиатуры содержат оба этих символа. В этом случае для логического оператора OR будет использоваться только тот, который в коде ASCII имеет значение 124. Подобное несоответствие может быть причиной того, что символы на Вашей клавиатуре не идентичны символам, выводимым на экран. |
SAY ( 3 = 3 ) | ( 5 = 5 ) /* выведет '1' */ SAY ( 3 = 4 ) | ( 5 = 5 ) /* выведет '1' */ SAY ( 3 = 3 ) | ( 4 = 5 ) /* выведет '1' */ SAY ( 3 = 4 ) | ( 4 = 5 ) /* выведет '0' */
Если Вы хотите просмотреть еще некоторые примеры по использованию логических операторов, =>.
Операторы истинности и ложности
При написании процедур бывает полезно определить, истинно или ложно выражение. Если выражение истинно, то вычисленный результат будет равен 1, в противном случае - 0. Ниже предлагается несколько примеров, иллюстрирующих вычисление истинности или ложности выражений.
Операторы сравнения - Перечисленные далее операторы можно использовать для сравнений:
> | Больше чем |
< | Меньше чем |
= | Равно |
Сравнивать можно как числовые, так и символьные величины. Ниже приведены примеры сравнения чисел:
Значение выражения 5 > 3 равно 1. Результат - истина. Значение выражения 2.0 = 002 равно 1. Результат - истина. Значение выражения 332 < 299 равно 0. Результат - ложь. |
Если элементы, которые нужно сравнить, не числа, то интерпретатор сравнивает символы. Например, при сравнении двух слов (строк) airmail и airplane, символ за символом, три первых буквы у них совпадут. Далее, так как m < p, то и airmail < airplane.
Равенство - В языке REXX знак равенства (=) может иметь два значения в зависимости от его местоположения. Например,
amount = 5 /* Это оператор присваивания */ присваивает переменной amount значение 5. Если же знак равенства используется не в операторе присваивания, то в этом случае будет выполняться сравнение. Например,
SAY amount = 5 /* Это оператор сравнения */ сравнивает значение переменной amount с числом 5. Если они совпадают, то на экран выводится число 1, в противном случае - 0.
Если Вы хотите просмотреть еще некоторые примеры сравнений => .
Принятие решений (IF THEN)
В процедурах, примеры которых были приведены ранее, инструкции выполнялись последовательно одна за другой. В этом разделе описывается, как управлять порядком выполнения инструкций. В зависимости от диалога, который пользователь ведет с процедурой, некоторые строки ее кода могут быть опущены.
Существует две инструкции, IF и SELECT, которые позволяют принимать решения о порядке выполнения прочих инструкций в процедуре. Инструкция IF подобна команде OS/2 IF. Она определяет, выполнять ли следующую инструкцию или пропустить ее. Инструкция SELECT позволяет выбрать для выполнения одну инструкцию из группы.
Для принятия решения инструкция IF должна использоваться вместе с инструкцией THEN. Интерпретатор выполняет следующую за IF инструкцию в том случае, если выражение истинно, например:
IF answer = "ДА" THEN SAY "ХОРОШО!"
В предыдущем примере инструкция SAY выполняется только в том случае, если переменная answer имеет значение ДА.
Объединение инструкций с помощью DO и END - Для того, чтобы приказать интерпретатору выполнить некоторый перечень инструкций, следующих за инструкцией THEN, используйте конструкцию типа:
DO Инструкция1 Инструкция2 Инструкция3 END
Инструкция DO и завершающая ее инструкция END указывают интерпретатору рассматривать все инструкции, расположенные между ними, как одну инструкцию.
Средства языка REXX
В этом разделе описываются средства языка REXX, которые можно использовать для написания более сложных процедур. Вы увидите, как в процедуре можно сделать выбор, проверяя значение переменной с помощью инструкции IF. Вы также узнаете, как сравнивать величины и определять, является выражение истинным либо ложным. Ниже приведено краткое описание элементов, обсуждаемых в этом разделе.
Используется вместе с THEN. Проверяет истинность выражения. Принимает решение на основании одной инструкции. | |
Определяет инструкцию, которая должна быть выполнена, если выражение истинно. | |
Определяет инструкцию, которая должна быть выполнена, если выражение ложно. | |
Приказывает интерпретатору выбрать из нескольких инструкций одну. | |
Используется вместе с SELECT. Определяет выражение, которое должно проверяться. | |
Используется вместе с SELECT. Определяет инструкцию, которая должна быть выполнена, если проверяемое выражение ложно. | |
Указывает, что должна быть выполнена некоторая группа инструкций. | |
Указывает, что с данным выражением ничего не нужно делать. | |
> < = | Определяют, больше ли, меньше либо равно чему-либо данное выражение. |
¬ или \ | Изменяет значение элемента с истинного на ложное, либо с ложного на истинное. |
& | Присваивает значение истина, если оба элемента являются истинными. |
| | Присваивает значение истина, если хотя бы один элемент является истинным. |
Автоматизация повторяющихся задач - использование циклов
Если Вы хотите повторить выполнение нескольких инструкций в процедуре, можете использовать цикл. Циклы часто используются в программировании, так как они группируют некоторое множество инструкций, выполняемых несколько раз. Циклы делают Вашу процедуру более краткой, а также позволяют опрашивать пользователя до тех пор, пока он не введет правильный ответ.
С помощью циклов можно складывать или вычитать числа до тех пор, пока Вы не захотите остановиться. Вы можете определить, сколько раз процедура должна выполнить указанные инструкции. В этом разделе Вы познакомитесь с простейшими циклами, используемыми для выполнения в процедуре повторяющихся инструкций.
Существуют два типа циклов. Это и . Циклы начинаются с инструкции DO и завершаются инструкцией END. Ниже приведено краткое описание элементов, обсуждаемых в этом разделе:
Повторяет цикл фиксированное число раз. | |
Подсчитывает каждый проход по циклу. Устанавливает начальное и конечное значение переменной. | |
Проверяет истинность или ложность некоторого выражения в начале цикла. Повторяет цикл, если значение истинно. В противном случае выполнение процедуры продолжается с инструкции, следующей за END. | |
Проверяет истинность или ложность некоторого выражения в конце цикла. Повторяет цикл, если значение ложно. В противном случае выполнение процедуры продолжается с инструкции, следующей за END. | |
Приказывает интерпретатору выйти из цикла. | |
Повторяет выполнение инструкций до тех пор, пока пользователь не решит закончить. | |
Требует нажатия комбинации клавиш Ctrl+Break. | |
Закрепляет за каждым словом в группе различные переменные. |
Повторяющиеся циклы
Простые повторяющиеся циклы могут быть выполнены определенное количество раз. Вы можете указать число повторений цикла или использовать переменную, которая имеет изменяющееся значение.
Ниже приведен пример цикла, который повторяется фиксированное число раз.
DO num инструкция1 инструкция2 инструкция3 ... END
Num представляет собой целое число, указывающее количество повторений цикла.
Процедура LOOP.CMD является примером простого повторяющегося цикла.
/* Простой цикл */ DO 5 SAY 'Спасибо' END EXIT
Ниже приведен протокол работы процедуры LOOP.CMD:
[C:\]loop Спасибо Спасибо Спасибо Спасибо Спасибо
[C:\]
Инструкция DO может также иметь следующий вид:
DO XYZ = 1 to 10
Инструкция DO такого типа подсчитывает каждый проход по циклу, поэтому этот счетчик можно использовать как переменную. Значение XYZ изменяется (на 1) каждый раз, когда отрабатывает цикл. Значение 1 (или любое другое число) присваивается переменной, когда цикл выполняется первый раз. Значение 10 (или любое другое число) будет присвоено переменной при последнем проходе по циклу.
Процедура NEWLOOP.CMD является примером подобного цикла:
/* Цикл с инструкцией DO другого типа */ sum = 0 DO XYZ = 1 to 7 SAY 'Введите значение' XYZ PULL value sum = sum + value END SAY 'Общий итог равен' sum EXIT
Ниже приведен протокол работы процедуры NEWLOOP.CMD:
[C:\]newloop Введите значение 1 2 Введите значение 2 4 Введите значение 3 6 Введите значение 4 8 Введите значение 5 10 Введите значение 6 12 Введите значение 7 14 Общий итог равен 56
[C:\]
После завершения цикла выполнение процедуры продолжается с инструкции, следующей за инструкцией END (которая свидетельствует о конце цикла).
Разбор слов
Инструкция PULL получает ответ и помещает его в память некоторой переменной. PULL может также использоваться для помещения в память нескольких переменных каждого слова из группы слов. В языке REXX это называется разбором. В следующем примере используются переменные с именами: first, second, third и rest.
SAY 'Введите, пожалуйста, три слова или более' PULL first second third rest
Предположим, Вы ввели следующий ответ:
garbage in garbage out
После нажатия клавиши Enter выполнение процедуры продолжится. При этом указанные переменные получат следующие значения:
Переменной first присваивается значение GARBAGE. |
Переменной second присваивается значение IN. |
Переменной third присваивается значение GARBAGE. |
Переменной rest присваивается значение OUT. |
Каждая переменная в качестве своего значения получает слово без пробелов, а последняя переменная - остаток введенной строки, если он есть, вместе с пробелами. Если в процедуре указано больше переменных, чем введено слов, то лишние переменные получают нулевое или пустое значение.
Условные циклы
Условные циклы выполняются до тех пор, пока удовлетворяется условие истинности или ложности некоторого выражения. Рассмотрим несколько инструкций, которые используются для условных циклов:
DO WHILE и DO UNTIL - Инструкции DO WHILE и DO UNTIL выполняются, пока удовлетворяется некоторое условие или до тех пор, пока оно не удовлетворится. Инструкция DO WHILE имеет следующую структуру:
DO WHILE выражение инструкция1 инструкция2 инструкция3 END
Инструкция DO WHILE проверяет истинность или ложность некоторого выражения в начале цикла; т.е. перед выполнением последующих инструкций. Если выражение является истинным, то инструкции выполняются. Если выражение является ложным, то цикл завершается и управление передается инструкции, следующей за END.
На диаграмме, приведенной ниже, представлена наглядная структура инструкции DO WHILE:
Чтобы просмотреть примеры использования инструкции DO WHILE в процедурах, выберите =>.
DO UNTIL - Инструкция DO UNTIL отличается от DO WHILE тем, что она сначала выполняет инструкции, образующие тело цикла, а затем проверяет значение выражения. Если выражение ложно, то инструкции повторяются (в цикле). Если выражение истинно, то цикл завершается и управление передается инструкции, следующей за END.
Так как инструкция DO UNTIL проверяет значение выражения в конце цикла, инструкции внутри цикла DO выполняются по крайней мере один раз.
Инструкция DO UNTIL имеет следующую структуру:
DO UNTIL выражение инструкция1 инструкция2 инструкция3
END
На диаграмме, приведенной ниже, представлена наглядная структура инструкции DO UNTIL:
Чтобы просмотреть примеры использования инструкции DO UNTIL в процедурах, выберите =>.
LEAVE - Вам может понадобиться выйти из цикла до того, как он завершится естественным образом по удовлетворении некоторого условия. Вы можете сделать это с помощью инструкции LEAVE. Эта инструкция завершает цикл, и управление передается инструкции, следующей за END. Проиллюстрируем на примере процедуры LEAVE.CMD использование инструкции LEAVE.
/* Использование инструкции LEAVE в цикле */ SAY ' введите сумму наличных денег' PULL salary spent = 0 /* Присваивает spent значение 0 */ DO UNTIL spent > salary SAY 'Введите стоимость товара или END для завершения' PULL cost IF cost = 'END' THEN LEAVE spent = spent + cost END SAY 'Пустые карманы.' EXIT
DO FOREVER - Иногда Вы не можете определить, сколько раз нужно повторить цикл. Например, может потребоваться, чтобы пользователь вводил цифровые данные (числа, которые должны складываться), а процедура выполняла вычисления до тех пор, пока сложены), а процедура выполняла вычисления до тех пор, пока пользователь не прикажет остановиться. Для процедур подобного типа Вы можете использовать инструкцию DO FOREVER вместе с инструкцией LEAVE.
Проиллюстрируем на следующем примере использование инструкции DO FOREVER.
/* Использование цикла DO FOREVER для сложения чисел */ sum = 0 DO FOREVER SAY 'Введите число или END для завершения' PULL value IF value = 'END' THEN LEAVE /* процедура завершается при получении "end" */ sum = sum + value END SAY 'Сумма равна ' sum EXIT
Выход из циклов
Чтобы прекратить выполнение большинства процедур REXX, пользуйтесь комбинацией клавиш Ctrl+Break. REXX распознает комбинацию Ctrl+Break после окончания выполнения текущей инструкции. Бывают случаи (как, например, в приведенной ниже процедуре), когда для того, чтобы выйти из цикла, нужно нажать комбинацию клавиш Ctrl+Break, а затем Enter.
/* Угадайте пароль ! */ DO UNTIL answer = "Sesame" SAY "Введите, пожалуйста, пароль . . ." PULL answer END EXIT
Если Вы все-таки не смогли завершить процедуру, то нажмите комбинацию клавиш Alt+Esc, чтобы завершить сеанс OS/2 и остановить выполнение процедуры.
Расширенные функции REXX
По мере приобретения опыта в программировании Вы научитесь создавать процедуры, обладающие большими возможностями и работающие более эффективно. Иногда это означает добавление в процедуру специальных функций или вызов подпрограмм.
В этом разделе мы рассмотрим, как с помощью этих функций можно поставить написание процедур REXX на более профессиональную основу.
ADDRESS
Инструкция ADDRESS используется для того, чтобы послать на выполнение в указанную среду, представленную на диаграмме словом среда, одну команду. В качестве обозначения среды может выступать текстовая цепочка или символ, которые являются константами и позиционно предшествуют выражению. Выражение вычисляется и результирующая командная строка направляется в указанную среду. После того, как команда выполнится, среда устанавливается в то состояние, в котором она находилась до выполнения команды. Таким образом происходит временное изменение адресата для одной команды.
Пример: ADDRESS CMD "DIR C:\STARTUP.CMD" /* OS/2 */
Если указана только среда, то происходит постоянное изменение адресата: все последующие команды (предложения, которые не являются инструкциями REXX и операторами присваивания) будут направляться в указанную командную среду до тех пор, пока не будет введена следующая инструкция ADDRESS. Сохраняется среда, установленная ранее.
Пример:
Предположим, что в качестве среды для текстового редактора зарезервировано имя "EDIT": address CMD 'DIR C:\STARTUP.CMD' if rc=0 then 'COPY STARTUP.CMD *.TMP' address EDIT
Все последующие команды направляются на выполнение в среду текстового редактора до тех пор, пока не будет введена очередная инструкция ADDRESS.
Чтобы выполнить постоянное изменение среды, можно также использовать форму VALUE. В этом случае выражение1 (которое может быть просто именем переменной) вычисляется и результат формирует имя среды. Вложенное ключевое слово VALUE может быть опущено при условии, что выражение1 начинается со специального символа (для того, чтобы не ошибиться с символом или строкой).
Пример: ADDRESS ('ENVIR'number)
Если инструкция введена без аргументов, то команды направляются для выполнения в среду, которая была установлена до предыдущего постоянного изменения среды, и имя этой текущей среды сохраняется. Поэтому повторное выполнение инструкции ADDRESS без аргументов приводит к попеременному переключению командных сред с одной на другую. Пустая строка (" "), указанная для имени среды, означает то же самое, что и среда, принимаемая по умолчанию.
ARG
Инструкция ARG используется для восстановления строк аргументов, предоставляемых программе или внутренней подпрограмме, и присваивания их значений некоторым переменным. Представляет собой краткую форму следующей инструкции:
Шаблон представляет собой список символов, разделенных пробелами.
Если выполняется не подпрограмма или внутренняя функция, то интерпретатор считывает аргументы, указанные при вызове программы; встречающиеся буквы переводит в прописные (например, строчные a-z в прописные A-Z), а затем присваивает значения считанных аргументов некоторым переменным. Если Вы не хотите переводить строчные буквы в прописные, то используйте инструкцию PARSE ARG.
Если выполняется подпрограмма или внутренняя функция, то использованные данные будут строками аргументов, переданных программе.
Инструкции ARG и PARSE ARG могут выполняться как угодно часто (как правило, с различными шаблонами), при этом всегда разбирая по переменным одну и ту же текущую строку ввода. Не существует ограничений на длину или содержание разбираемых данных, кроме тех, которые налагаются вызывающей программой.
Пример: /* Переданная строка - "Easy Rider" */
Arg adjective noun
/* Теперь: "ADJECTIVE" содержит 'EASY' */ /* "NOUN" содержит 'RIDER' */
Если ожидается, что программе будут доступны несколько строк аргументов, то каждая из них может быть выбрана по очереди, ориентируясь на разделяющую запятую в разбираемом шаблоне.
Пример: /* функция вызывается следующим образом: FRED('data X',1,5) */
Fred: Arg string, num1, num2
/* Теперь: "STRING" содержит 'DATA X' */ /* "NUM1" содержит '1' */ /* "NUM2" содержит '5' */
Примечания: Строки аргументов для процедур REXX или внутренних программ можно восстановить или проверить и с помощью встроенной функции ARG.
Источник данных, которые будут обрабатываться, также предоставляется при входе в программу. Для получения более подробной информации обращайтесь к описанию инструкции PARSE (режим SOURCE).
CALL
Инструкция CALL используется для вызова программы (если Вы указали имя) или для управления отслеживанием некоторых условий (если Вы указали ON или OFF).
Для управления отслеживанием укажите OFF или ON и условие, которое Вы хотите отследить. OFF прекращает процесс отслеживания указанного условия. ON запускает процесс отслеживания указанного условия.
Для вызова программы укажите имя, являющееся символом или текстовой строкой, которые представляют собой константу. Имя должно быть действительным символом. Вызываемая программа может быть одной из следующих: Внутренняя программа Внешняя программа Встроенная функция.
Если для указания имени используется строка (т.е. имя заключено в кавычки), то поиск внутренних меток не производится и вызываются только встроенные функции или внешние программы. Следует отметить, что имена встроенных функций (и, как правило, имена внешних программ тоже) пишутся прописными буквами; поэтому и имя в текстовой строке должно быть указано прописными буквами.
В необязательном порядке программа может возвращать результат, который функционально идентичен следующему предложению:
Исключительная ситуация возникает тогда, когда переменная result инициализируется при отсутствии результата, возвращенного вызванной программой.
Имя, заданное в инструкции CALL, должно быть действительным символом.
Интерпретатор OS/2 допускает возможность указания до 20 выражений, разделенных запятыми. Выражения вычисляются слева направо и формируют строки аргументов в процессе выполнения программы. Любая инструкция ARG или PARSE ARG, а также встроенная функция ARG в вызванной программе получит доступ к этим строкам прежде, чем они станут активными в вызывающей программе. При необходимости Вы можете опустить некоторые выражения, вставляя на их место дополнительные запятые.
Инструкция CALL инициирует затем переход к программе с указанным именем, используя тот же механизм, что и при вызове функции. Порядок, в котором осуществляется поиск программ, описан в разделе, посвященном функциям.
Ниже приведена краткая информация:
Внутренние программы: | Представляют собой последовательность инструкций, расположенных внутри основной программы и начинающихся с метки, которая соответствует имени, указанному в инструкции CALL. Если имя программы указано в кавычках, то данная внутренняя программа не рассматривается как объект для поиска. |
Встроенные программы: | Представляют собой программы, встроенные в языковой процессор для обеспечения выполнения различных функций. Они всегда возвращают строку, содержащую результат выполнения функции. |
Внешние программы: | Пользователи могут написать сами или использовать программы, которые являются внешними для языкового процессора или вызывающей программы. Внешняя программа может быть написана на любом языке, включая REXX, который поддерживает системно-зависимые интерфейсы. Если внешняя программа, написанная на языке REXX, вызвана как подпрограмма с помощью инструкции CALL, Вы можете восстановить любую строку аргументов, используя инструкции ARG или PARSE ARG, а также встроенную функцию ARG. |
DO
повторитель:
условие:
DO используется для того, чтобы объединить некоторые инструкции и, необязательно, неоднократно их выполнить. В процессе неоднократного выполнения инструкций управляющая переменная (имя) может наращиваться, принимая различные значения из некоторого диапазона.
Примечания по синтаксису: Значения exprr, expri, exprb, exprt и exprf (если они указаны) представляют собой выражения, результат вычисления которых - число. Значения exprr и exprf представляют собой выражения, результат вычисления которых - целое неотрицательное число. При необходимости числа округляются в соответствии с установкой NUMERIC DIGITS. Значения exprw или expru (если они указаны) могут быть любым выражением, результат вычисления которого равен 1 или 0.
Фразы TO, BY и FOR могут указываться в любом порядке, если они используются.
Инструкции могут включать в себя операторы присваивания, команды и ключевые инструкции (которые сами могут включать любую из более сложных конструкций, таких, как IF, SELECT и инструкцию DO).
Вложенные ключевые слова TO, BY, FOR, WHILE и UNTIL зарезервированы внутри инструкции DO, в которой они не могут использоваться в качестве имен переменных в выражениях, но могут выступать в качестве имени управляющей переменной. Вложенное ключевое слово FOREVER также зарезервировано, но только в том случае, если оно непосредственно следует за ключевым словом DO.
Значение exprb по умолчанию принимается равным 1, если это имеет отношение к делу.
Простая группа DO:
Если не указан ни повторитель, ни условие, то конструкция DO просто группирует вместе некоторое число инструкций. Они выполняются один раз. В противном случае группа инструкций образует повторяющийся цикл DO, который выполняется несколько раз, в зависимости от заданного повторителя и условия, которое может его изменять.
В следующем примере инструкции выполняются один раз.
Пример: /* Две инструкции между DO и END будут */ /* выполнены в случае, если A = 3. */ If a=3 then Do a=a+2 Say 'Улыбнитесь!' End
Простые повторяющиеся циклы:
Если повторитель опущен, но указано условие, или если повторителем является FOREVER, то группа инструкций, вообще говоря, будет выполняться постоянно, т.е. до тех пор, пока не удовлетворится требуемое условие, или не выполнится инструкция REXX, которая осуществит выход из цикла (например, LEAVE).
В простой форме повторяющегося цикла выражение exprr вычисляется немедленно (результат должен быть целым неотрицательным числом), и цикл выполняется указанное число раз.
Пример: /* Выводит "Привет" пять раз */ Do 5 say 'Привет' end
Помните, чем отличается команда от оператора присваивания? Также и в инструкции DO: если первый знак exprr- символ, а второй - знак "=", то будет использоваться, скорее всего, управляемая форма повторителя.
Управляемые повторяющиеся циклы:
При использовании управляемой формы цикла указывается управляющая переменная имя, которой присваивается начальное значение (результат вычисления выражения expri, выполненного таким образом, как если бы был добавлен 0). Затем при каждом выполнении группы инструкций управляющая переменная наращивается (т.е. к ее значению в конце цикла добавляется результат вычисления exprb). Выполнение группы инструкций продолжается до тех пор, пока не встретится конечное условие (определенное как результат вычисления выражения exprt). Если значение exprb - положительное число или нуль, то цикл будет завершен, когда значение имени превысит значение exprt. В противном случае (если значение exprb - отрицательное число), цикл завершится, когда значение имени станет меньше значения exprt.
Результаты вычисления выражений expri, exprt и exprb должны быть числами. Они вычисляются только один раз, перед началом цикла и перед присваиванием управляющей переменной ее начального значения. По умолчанию значение выражения exprb равно 1. Если опущено выражение exprt, то цикл выполняется бесконечно, пока его не завершит какое-либо другое условие.
Пример: Do I=3 to -2 by -1 /* Выведет: */ say i /* 3 */ end /* 2 */ /* 1 */ /* 0 */ /* -1 */ /* -2 */
Числа не обязательно должны быть целыми.
Пример: X=0.3 /* Выведет: */ Do Y=X to X+4 by 0.7 /* 0.3 */ say Y /* 1.0 */ end /* 1.7 */ /* 2.4 */ /* 3.1 */ /* 3.8 */
Управляющую переменную можно изменить внутри цикла, но это может повлиять на количество повторений цикла. Изменение значения управляющей переменной считается дурным стилем программирования, хотя при некоторых обстоятельствах это может быть вполне приемлемо.
Следует отметить, что конечное условие проверяется в начале каждой итерации (повторения); а также после наращивания управляющей переменной, на второй и всех последующих итерациях. Поэтому группа инструкций может быть полностью пропущена, как только удовлетворится конечное условие. Отметим также, что на управляющую переменную ссылаются по ее имени. Если, например, для управляющей переменной используется составное имя A.I, то изменение I внутри цикла приведет к изменению управляющей переменной.
Количество итераций управляемого цикла может быть дополнительно ограничено с помощью фразы FOR. В этом случае должно быть указано выражение exprf, и результатом его вычисления должно быть целое неотрицательное число. Это число играет роль счетчика повторений в простом повторяющемся цикле, устанавливая предел количества итераций внутри цикла, если никакое другое условие не завершит его прежде. Подобно выражениям во фразах TO и BY, выражение во фразе FOR вычисляется только один раз: когда инструкция DO выполняется первый раз и управляющая переменная получает свое начальное значение. Аналогично условию TO, условие FOR проверяется в начале каждой итерации.
Пример: Do Y=0.3 to 4.3 by 0.7 for 3 /* Выведет: */ say Y /* 0.3 */ end /* 1.0 */ /* 1.7 */
В управляемых циклах имя, описывающее управляющую переменную, может быть указано в предложении END. Это имя должно совпадать с именем в предложении DO во всех отношениях, кроме регистра клавиатуры - строчные буквы или прописные - (отметим, что никакие подстановки для составных переменных не производятся); в противном случае выдается сообщение о синтаксической ошибке.
Данная возможность с минимальными издержками позволяет автоматически контролировать вложенность циклов.
Пример: Do K=1 to 10 ... ... End k /* Определяет конец цикла K */
Прим. Значения, которые принимает управляющая переменная, могут находиться под влиянием установок NUMERIC, так как вычисление приращения управляющей переменной выполняется по обычным арифметическим правилам, используемым REXX.
Условные фразы (WHILE и UNTIL):
Любой из типов повторителей (никакой, FOREVER, простой или управляемый) может предшествовать условной фразе, с помощью которой можно завершить цикл. Если Вы указали WHILE или UNTIL, то соответствующие выражения exprw или expru вычисляются при каждом проходе по циклу, используя при этом последние значения всех переменных (результатом вычисления должен быть либо 0, либо 1). При этом группа инструкций повторно выполняется, либо пока результат равен 1, либо до тех пор, пока результат не станет равным 1.
Для цикла WHILE проверяемое условие вычисляется в начале группы инструкций; для цикла UNTIL проверяемое условие вычисляется в конце, перед наращиванием управляющей переменной.
Пример: Do I=1 to 10 by 2 until i>6 say i end /* Выведет на экран: 1, 3, 5, 7 */
Прим. Способ выполнения повторяющихся циклов может быть изменен инструкцией LEAVE или ITERATE.
DROP
Каждое имя представляет собой имя действительной переменной, иногда заключенное в скобки (для обозначения дополнительного списка), и отделяется от любого другого имени одним или несколькими пробелами.
Инструкция DROP используется для отмены назначений переменных; т.е. для восстановления их в первоначальное непроинициализированное состояние.
Каждая указанная переменная удаляется из списка известных переменных. Если единственное указанное имя заключено в скобки, то его значение рассматривается как дополнительный список переменных, которые нужно освободить. Принцип расположения переменных в дополнительном списке должен подчиняться тем правилам, которые приняты и для основного списка (содержать действительные имена переменных, разделенные пробелами), но без пробелов в начале и конце списка. Переменные освобождаются последовательно слева направо. Не будет ошибкой указание одного и того же имени переменной несколько раз или попытка освободить переменную, имя которой неизвестно. Если указана проявляющаяся переменная (см. описание инструкции PROCEDURE), то эта переменная сама будет освобождена при последующей генерации.
Пример: j=4 Drop a x.3 x.j /* освободит переменные: A, X.3, and X.4, поэтому */ /* последующая ссылка на них выдаст их имена. */
В следующем примере имя переменной в скобках используется как дополнительный список.
Пример: x=4;y=5;z=6; a='x y z' DROP (a) /* освободит x,y и z */
Если указана основа (символ, содержащий только одну точку в качестве последнего знака), то освобождаются все переменные, начинающиеся с этой основы.
Пример: Drop x. /* освободит все переменные, чьи имена начинаются с X. */
EXIT
Инструкция EXIT используется для безусловного завершения программы. В некоторых случаях EXIT возвращает вызывающей программе строку данных. Программа завершается немедленно, даже если при этом выполняется внутренняя программа. При отсутствии активных внутренних программ инструкции RETURN и EXIT идентичны по их воздействию на выполняющуюся программу.
Если Вы указали выражение, то оно вычисляется и после завершения программы результирующая строка возвращается вызывающей программе.
Пример: j=3 Exit j*4 /* Завершится с результирующей строкой '12' */
Если Вы не указываете выражение, то вызывающей программе никакие данные не передаются. Если программа была вызвана как внешняя функция, то это воспринимается как ошибка, независимо от того, немедленно завершилась программа (при использовании EXIT) или по возврату в вызывающую программу (при использовании RETURN).
Выражение "достижение конца" программы всегда равнозначно инструкции EXIT в той ее форме, когда она завершает всю программу и не возвращает результирующей строки.
Прим. | Языковой процессор не делает различий между вызовом программы, с одной стороны, и вызовом подпрограммы или функции, с другой. Если программа была вызвана через командный интерфейс, то делается попытка преобразовать полученное значение в код возврата, приемлемый для вызывающей процедуры REXX. Возвращенная результирующая строка должна быть целым числом со знаком в диапазоне от -2**15 до 2**15-1. |
IF
Инструкция IF используется для условного выполнения инструкции или группы инструкций в зависимости от результата вычисления выражения. Результат вычисления выражения должен быть равен 0 или 1.
Инструкция, следующая за THEN, выполняется только в том случае, если результат вычисления равен 1. Если Вы указали предложение ELSE, то инструкция, следующая за ELSE, выполняется только в том случае, если результат вычисления равен 0.
Пример: if answer='ДА' then say 'Хорошо!' else say 'Почему нет?'
Не забывайте, что если предложение ELSE находится в той же строке, что и последняя часть предложения THEN, то их нужно разделить точкой с запятой.
Пример: if answer='ДА' then say 'Хорошо!'; else say 'Почему нет?'
Предложение ELSE связывается с ближайшей инструкцией соответствующего уровня. Чтобы исключить ошибки и возможную путаницу при написании вложенных конструкций IF, можно использовать инструкцию NOP, как показано в следующем примере.
Пример: If answer = 'ДА' Then If name = 'ФРЕД' Then say 'Хорошо, Фред.' Else nop Else say 'Почему нет?'
Примечания:
Инструкцией может быть любой оператор присваивания, команда или ключевая инструкция, включающая любую более сложную конструкцию, такую как DO, SELECT или саму инструкцию IF. Предложение, содержащее пустую строку, не является инструкцией; поэтому указание за THEN или ELSE дополнительной точки с запятой не равнозначно выполнению фиктивной инструкции (как это принято в языке С). Для этих целей предназначена инструкция NOP.
Слово THEN нельзя использовать внутри выражения (в котором оно не предназначается для начала предложения), так как ключевое слово THEN обрабатывается иначе. Если же оно используется, то это может привести к завершению выражения в предложении IF посредством символа THEN, указанного без требуемого разделителя (;). Если бы это было не так, то пользователи других компьютерных языков испытывали бы определенные затруднения.
INTERPRET
Инструкция INTERPRET используется для выполнения инструкций, построенных динамически в процессе вычисления выражения.
Выражение вычисляется, а затем обрабатывается (интерпретируется) так, как если бы результирующая цепочка символов была строкой, вставленной в исходный файл (и ограниченной DO; и END;).
Допустимы любые инструкции (включая инструкции INTERPRET), но конструкции типа DO ... END и SELECT ... END должны иметь завершенный вид. Например, строка инструкций, которая интерпретируется, не может содержать инструкции LEAVE или ITERATE (действительные только внутри повторяющегося цикла DO), если она при этом не содержит полную повторяющуюся конструкцию DO ... END.
Для удобства пользователя в конце выражения подразумевается точка с запятой.
Пример: data='FRED' interpret data '= 4' /* a) построит строку "FRED = 4" */ /* b) вычислит FRED = 4; */ /* Теперь переменной "FRED" будет присвоено значение "4" */
Пример: data='do 3; say "Привет!"; end' interpret data /* Выведет: */ /* Привет! */ /* Привет! */ /* Привет! */
Примечания:
1 | Метки внутри интерпретируемой строки не являются неизменными и поэтому игнорируются. Поэтому выполнение инструкции SIGNAL из интерпретируемой строки приведет к немедленному выходу из этой строки до того, как начнется поиск метки. |
2 | Если концепция инструкции INTERPRET для Вас нова и получаемые результаты непонятны, то полезно выполнить эту инструкцию, указывав в процедуре TRACE R или TRACE I.
Пример: /* Мы имеем небольшую программу. */ Trace Int name='Китти' indirect='name' interpret 'say "Привет"' indirect'"!"' При выполнении этой процедуры на экран выводится следующая информация: [C:\]kitty kitty 3 *-* name='Китти' >L> "Китти" 4 *-* indirect='name' >L> "name" 5 *-* interpret 'say "Привет"' indirect'"!"' >L> "say "Привет"" >V> "name" >O> "say "Привет" name" >L> ""!"" >O> "say "Привет" name"!"" *-* say "Привет" name"!" >L> "Привет" >V> "Китти" >O> "Привет Китти" >L> "!" >O> "Привет Китти!" Привет Китти! [C:\] Строки 3 и 4 устанавливают переменные, используемые в строке 5. Вычисление строки 5 происходит в два этапа. Сначала строится строка, которая будет интерпретироваться при помощи текстовой строки, переменной (INDIRECT) и еще одного литерала. Затем результирующая строка, состоящая только из символов, интерпретируется так, как если бы она была частью исходной программы. Так как полученная строка является новым предложением, то она трассируется следующим образом (второй трассировочный флаг *-* под строкой 5), а затем выполняется. После этого текстовая строка объединяется со значением переменной (NAME) и вторым литералом, и окончательный результат выводится на экран в следующем виде: Привет Китти! |
3 | Во многих случаях вместо инструкции INTERPRET можно использовать функцию VALUE. Например, строку 5 в последнем примере можно заменить следующей: say "Привет" value(indirect)"!" |
Использование инструкции INTERPRET обычно требуется лишь в специальных случаях, например, когда за один раз должно быть интерпретировано несколько операторов.
ITERATE
Инструкция ITERATE предназначена для изменения естественного потока инструкций внутри повторяющегося цикла DO (т.е. любой конструкции DO, кроме простых циклов DO).
Выполнение группы инструкций прекращается и управление передается инструкции DO, как если бы встретилось предложение END. Управляющая переменная (если она существует) наращивается и проверяется как обычно, и выполнение группы инструкций возобновляется, если только цикл не завершится по инициативе инструкции DO.
Если имя не указано, то инструкция ITERATE будет отноcиться к самому внутреннему активному повторяющемуся циклу. Если имя задано, то оно должно быть именем управляющей переменной текущего активного цикла, который может быть самым внутренним циклом; к этому циклу и будет применяться инструкция ITERATE. Любой активный цикл, вложенный в цикл, выбранный для итераций, завершается (как если бы встретилась инструкция LEAVE).
Пример: do i=1 to 4 if i=2 then iterate say i end /* Будут выведены числа: 1, 3, 4 */
Примечания:
Если указано имя, то оно должно совпадать с именем в инструкции DO во всех отношениях, кроме регистра клавиатуры (строчные или прописные буквы). При этом, когда выполняется сравнение имен, никакие подстановки для составных переменных не производятся.
Цикл считается активным, если он в настоящий момент обрабатывается. Если в процессе выполнения цикла была вызвана подпрограмма или началась обработка инструкции INTERPRET, то цикл становится неактивным до тех пор, пока не будет осуществлен возврат из подпрограммы или не завершится выполнение инструкции INTERPRET. Инструкцию ITERATE нельзя использовать в неактивных циклах.
Если одна и та же управляющая переменная используется в нескольких активных циклах, то инструкция ITERATE относится к самому внутреннему циклу.
Ключевые инструкции
Ключевая инструкция представляет собой одно или несколько предложений, первое из которых начинается ключевым словом, определяющим инструкцию. Если инструкция состоит из нескольких предложений, то они должны отделяться друг от друга точкой с запятой (;).
Некоторые ключевые инструкции, например, начинающиеся ключевым словом DO, могут включать в себя вложенные инструкции.
В синтаксических диаграммах символы (слова), изображенные прописными буквами, представляют ключевые слова; остальные слова (такие как выражение) являются набором символов. Ключевые слова не зависят от того, какими буквами они набраны (прописными или строчными), поэтому все нижеперечисленные слова: if, If и iF будут вызывать выполнение одной и той же инструкции IF. Вы можете также опускать большинство указанных разделителей (;), приведенных в синтаксисе для обозначения конца строки.
LEAVE
Инструкция LEAVE используется для немедленного выхода из одного или нескольких повторяющихся циклов DO (т.е. из любой конструкции DO, отличной от простого цикла DO).
Выполнение группы инструкций завершается, и управление передается инструкции, следующей за предложением END, как если бы цикл закончился естественным образом после обработки условия завершения. Однако при этом управляющая переменная, если она есть, на выходе будет иметь то значение, которое она имела перед выполнением инструкции LEAVE.
Если имя не указано, то инструкция LEAVE завершает самый внутренний активный повторяющийся цикл. Если имя указано, то оно должно быть именем управляющей переменной текущего активного цикла, который может быть самым внутренним циклом; этот цикл (как и все активные циклы, вложенные в него) будет завершен. Потом управление передается инструкции, следующей за предложением END, соответствующим предложению DO выбранного цикла.
Пример: do i=1 to 5 say i if i=3 then leave end /* Будут выведены числа: 1, 2, 3 */
Примечания: Если указано имя, то оно должно совпадать с именем в инструкции DO во всех отношениях, кроме регистра клавиатуры (строчные или прописные буквы). При этом, когда выполняется сравнение имен, никакие подстановки для составных переменных не производятся.
Цикл считается активным, если он в настоящий момент обрабатывается. Если в процессе выполнения цикла была вызвана подпрограмма или началась обработка инструкции INTERPRET, то цикл становится неактивным до тех пор, пока не выполнится возврат из подпрограммы или не завершится выполнение инструкции INTERPRET. Инструкцию LEAVE нельзя использовать для завершения неактивного цикла.
Если одна и та же управляющая переменная используется в нескольких активных циклах, то инструкция LEAVE завершит самый внутренний цикл.
NOP
NOP - это фиктивная инструкция, которая не выполняет никаких действий. Может использоваться в качестве инструкции в предложениях THEN или ELSE.
Пример: Select when a=b then nop /* Ничего не делать */ when a>b then say 'A > B' otherwise say 'A < B' end
Прим. | Если вместо инструкции NOP указать дополнительную точку с запятой, то будет вставлено пустое предложение, которое игнорируется. При этом второе предложение WHEN воспримется как первая инструкция, следующая за THEN, и поэтому будет истолковано как синтаксическая ошибка. Однако NOP является корректной инструкцией и действительным целевым назначением для предложения THEN. |
NUMERIC
Инструкция NUMERIC используется для изменения способа выполнения арифметических операций. Режимы данной инструкции подробно описаны в документе Язык процедур 2/REXX для OS/2. Справочник.
Инструкция NUMERIC с режимом DIGITS управляет точностью вычисления арифметических выражений и арифметических встроенных функций. Если выражение опущено, то по умолчанию используется значение 9. В противном случае результат выражения при необходимости округляется в соответствии с текущим назначением NUMERIC DIGITS. Используемое значение должно быть целым положительным числом, большим, чем текущее назначение NUMERIC FUZZ.
Не существует ограничений на значение DIGITS (кроме объема доступной памяти), но следует отметить, что высокая точность вычислений обычно требует много процессорного времени. Поэтому рекомендуется во всех возможных случаях использовать значение по умолчанию.
Текущее назначение NUMERIC DIGITS можно получить с помощью встроенной функции DIGITS.
Инструкция NUMERIC с режимом FORM управляет формой экспоненциального представления результатов выполнения арифметических операций и встроенных арифметических функций, используемой в языке REXX. Это может быть SCIENTIFIC (в этом случае перед десятичной точкой появляется только одна цифра, отличная от нуля) или ENGINEERING (в этом случае степень числа 10 всегда кратна трем). По умолчанию принимается значение SCIENTIFIC. Режим FORM устанавливается либо с помощью прямого указания вложенного ключевого слова (SCIENTIFIC или ENGINEERING), либо принимается как результат вычисления выражения, следующего за VALUE. Результат в этом случае может быть либо SCIENTIFIC, либо ENGINEERING. Вы можете опустить вложенное ключевое слово VALUE, если выражение начинается не с символа или текстовой строки (например, если оно начинается со специального знака: оператора или скобки).
Текущее значение NUMERIC FORM можно получить с помощью встроенной функции FORM.
Инструкция NUMERIC с режимом FUZZ указывает, сколько цифр результата, полученного с указанной точностью, можно отбросить при выполнении операции сравнения.
Если выражение опущено, то по умолчанию принимается значение 0. В противном случае результат вычисления выражения должен быть нулевым или целым положительным числом, которое перед использованием нужно округлить в соответствии с текущей установкой NUMERIC DIGITS. Используемое значение должно быть целым положительным числом, меньшим, чем текущее назначение NUMERIC DIGITS.
Режим FUZZ временно уменьшает значение DIGITS на величину FUZZ перед каждой операцией числового сравнения. Сравниваемые числа вычитаются одно из другого, используя точность (DIGITS - FUZZ), а потом результат сравнивается с нулем.
Текущее значение NUMERIC FUZZ можно получить с помощью встроенной функции FUZZ.
Прим. | Все три числовых назначения автоматически сохраняются при вызове подпрограммы или внутренней функции. Для получения более подробной информации смотрите описание инструкции CALL. |
OPTIONS
Инструкция OPTIONS используется для передачи специальных запросов или параметров языковому процессору. Например, это могут быть режимы языкового процессора или определения специального набора символов.
Результат вычисления выражения проверяется слово за словом. Если слова распознаются языковым процессором, то они принимаются. Нераспознанные слова игнорируются. Считается, что это инструкции другого процессора.
Языковый процессор распознает следующие слова:
ETMODE | Определяет, что в программе могут использоваться текстовые строки, содержащие наборы двухбайтовых символов (DBCS). |
NOETMODE | Определяет, что в программе не могут использоваться текстовые строки, содержащие символы DBCS. NOETMODE принимается по умолчанию. |
EXMODE | Определяет, что данные DBCS в смешанных строках обрабатываются инструкциями, операторами и функциями, основываясь на понятии логического элемента. При этом сохраняется целостность данных DBCS. |
NOEXMODE | Определяет, что любые данные в строках обрабатываются на основе байта. При этом целостность символов DBCS может быть нарушена. NOEXMODE принимается по умолчанию. |
Примечания: Из-за просмотра процедур языковым процессором в программах, содержащих текстовые строки DBCS, помещайте инструкцию OPTIONS ETMODE в качестве первой инструкции.
Чтобы не сомневаться в правильности просмотра программы, содержащей символы DBCS, вводите режимы ETMODE, NOETMODE, EXMODE и NOEXMODE инструкции OPTIONS как текстовые строки (в кавычках).
Назначения OPTIONS ETMODE и OPTIONS EXMODE сохраняются на время выполнения подпрограммы или функции, а затем восстанавливаются.
Слова ETMODE, EXMODE, NOEXMODE и NOETMODE могут встретиться несколько раз внутри результирующей строки. При этом режим, который будет принят к исполнению, определяется последним действительным словом, указанным между парами ETMODE/NOETMODE и EXMODE/NOEXMODE.
PARSE
Инструкция PARSE используется для присваивания данных из различных источников одной или нескольким переменным в соответствии с правилами и шаблонами, описанными в разделе по разбору слов документа Язык процедур 2/REXX для OS/2. Справочник.
Если указан шаблон, то он представляет собой список символов, разделенных пробелами.
Если шаблон не указан, то переменные не назначаются, но при необходимости выполняется подготовка данных к разбору. Например, для PARSE PULL строка данных перемещается из текущей очереди данных; для PARSE LINEIN (и PARSE PULL, если текущая очередь пуста) строка выбирается из входного потока значений по умолчанию; для PARSE VALUE вычисляется выражение. Для PARSE VAR выбирается указанная переменная. Если эта переменная не имеет никакого значения, то устанавливается условие NOVALUE, если оно разрешено.
Если указан режим UPPER, то буквы в строке, которую нужно разобрать, сначала переводятся в прописные (например, строчные a-z в прописные A-Z). В противном случае при разборе слов не производится перевод строчных букв в прописные.
Данные, используемые для каждого из вариантов инструкции PARSE, приведены ниже:
PARSE ARG - Разбираются строки, которые передаются программе, подпрограмме или функции в качестве входного списка аргументов. Для получения более подробной информации смотрите описание инструкции ARG.
Прим. | Строки аргументов в процедуру REXX или внутреннюю программу могут также передаваться с помощью встроенной функции ARG. |
PARSE LINEIN - Разбирается следующая строка из входного потока значений по умолчанию. (Смотрите документ Язык процедур 2/REXX для OS/2. Справочник для получения сведений о формате входных данных REXX). PARSE LINEIN - это краткая форма следующей инструкции:
Если нет готовых доступных строк, то выполнение программы временно приостанавливается до тех пор, пока строка не завершится. Отметим, что инструкцию PARSE LINEIN нужно использовать только в том случае, когда необходим прямой доступ к входному потоку символов.
Обычный построчный диалог с пользователем лучше вести с помощью инструкций PULL или PARSE PULL.
Чтобы проверить, есть ли доступные строки во входном потоке значений по умолчанию, используйте встроенную функцию LINES.
PARSE PULL - Разбирается следующая строка из очереди. Если очередь пуста, то строки считываются с устройства ввода, определенного по умолчанию; обычно это пользовательская клавиатура. Вы можете добавить данные в начало или конец очереди, пользуясь инструкциями PUSH и QUEUE соответственно. Вы можете также определить количество строк в очереди на данный момент, используя встроенную функцию QUEUED. Очередь остается активной до тех пор, пока активен языковый процессор. Очередь может изменяться другими программами в операционной системе и может использоваться как средство взаимодействия между этими программами и процедурами REXX.
Прим. | Инструкции PULL и PARSE PULL сначала считывают данные из текущей очереди данных. Если очередь пуста, то считывание производится из входного потока, принятого по умолчанию, - STDIN (обычно это клавиатура). |
Исходная строка содержит символы OS/2, за которыми могут следовать COMMAND, FUNCTION или SUBROUTINE в зависимости от того, как была вызвана программа: как команда системы, как функция в выражении или с помощью инструкции CALL. Указанные символы предшествуют спецификации полного пути программного файла.
Поэтому разобранная строка могла бы быть выведена в следующем виде: OS/2 COMMAND C:\OS2\REXTRY.CMD
PARSE VALUE - Данные, которые должны быть разобраны, являются результатом вычисления выражения. Следует отметить, что WITH в данном контексте является вложенным ключевым словом и поэтому не может использоваться в качестве символа внутри выражения. Например: PARSE VALUE time() WITH hours ':' mins ':' secs
получает текущее время и разбивает его на составные части.
PARSE VAR имя - Разбирается значение переменной, указанной с помощью имени. Имя должно быть символом, действительным для определения имени переменной; т.е.
не может начинаться с точки или цифры. Заметим, что переменная имя не изменяется до тех пор, пока она не появится в шаблоне. Например: PARSE VAR string word1 string извлекает первое слово из string и помещает его в переменную word1, передавая остаток назад в string. Аналогично: PARSE UPPER VAR string word1 string перед тем, как разобрать данные, переводит буквы string из строчных в прописные.
PARSE VERSION - Разбирается информация, содержащая сведения о версии языка и дате языкового процессора. Она состоит из пяти слов (разделенных пробелами): сначала строка "REXXSAA", затем описание версии языка ("4.00")и, наконец, даты выпуска("13 июня 1989").
Прим.   | Информация PARSE VERSION должна разбираться на основе слов, а не на основе абсолютной позиции столбца . |
PROCEDURE
Инструкцию PROCEDURE можно использовать во внутренней программе (подпрограмме или функции) для защиты всех существующих переменных путем удаления их из числа известных для последующих инструкций. При выполнении инструкции RETURN восстанавливается исходная среда переменных. Все переменные, использованные в программе (которые не были проявлены), освобождаются.
Режим EXPOSE изменяет приведенный порядок действий. Любая переменная, указанная именем, проявляется, т.е. любое обращение к ней (включая назначение и освобождение) направляется в среду переменных, которая принадлежит вызывающей программе. Указывая режим EXPOSE, Вы должны определить по крайней мере одно имя, т.е. символ, отделенный от другого имени одним или несколькими пробелами. При необходимости Вы можете заключить единственное имя в скобки, чтобы определить дополнительный список переменных. Все переменные, не указанные с помощью своих имен в инструкции PROCEDURE EXPOSE, остаются защищенными. Следовательно, некоторый ограниченный набор переменных вызываемой программы может быть доступным, и эти переменные могут изменяться (или создаваться новые переменные в этом множестве). Все выполненные изменения будут видимы для вызывающей программы после возвращения из подпрограммы.
Все переменные проявляются последовательно слева направо. Не считается ошибкой указание одного и того же имени переменной несколько раз или указание имени, которое не использовано в качестве переменной в вызывающей программе.
Пример: /* Это основная программа */ j=1; x.1='a' call toft say j k m /* выведет на экран "1 7 M" */ exit
toft: procedure expose j k x.j say j k x.j /* выведет на экран "1 K a" */ k=7; m=3 /* переменная "M" не проявляется */ return
Заметим, что если бы в предыдущем примере X.J в списке EXPOSE было помещено перед J, то значение J не было бы видимым в настоящий момент, таким образом и переменная X.1 не проявилась бы.
Если имя заключено в скобки (пробелы внутри или снаружи скобок необязательны, но при желании их можно добавить), то после проявления этой переменной ее значение немедленно будет использовано в качестве дополнительного списка переменных.
Принцип расположения переменных в дополнительном списке тот же, что и для основного списка, однако скобки или пробелы в начале и конце списка не допускаются. Переменные, перечисленные в дополнительном списке, тоже проявляются слева направо.
Пример: j=1;k=6;m=9 a ='j k m' test:procedure expose (a) /* будут проявлены j, k и m */
Если в списке имен указана основа, то проявляются все возможные составные переменные, чьи имена начинаются с этой основы. (Основа - это символ, содержащий только одну точку в качестве последнего знака).
Пример: lucky7:Procedure Expose i j a. b. /* Проявляет "I", "J" и все переменные, чьи */ /* имена начинаются с "A." или "B." */ A.1='7' /* Назначит "A.1" для среды вызывающей */ /* программы, даже если эта переменная */ /* ранее не существовала. */
При необходимости переменные могут проявляться и после выполнения ряда программ, но при этом нужные переменные должны быть включены во все промежуточные инструкции PROCEDURE.
На каждом уровне вызова программы допускается только одна инструкция PROCEDURE; все остальные (и те, которые встретились за пределами внутренних программ) считаются ошибочными.
Примечания:
Внутренняя программа может не содержать инструкцию PROCEDURE, в этом случае она будет работать с теми переменными, которые имеются в распоряжении вызывающей программы.
Инструкция PROCEDURE должна быть первой инструкцией, выполняющейся после CALL или вызова функции, т.е. первой инструкцией, следующей за меткой.
Для получения более подробной информации о вызове программ смотрите описание инструкции CALL.
PULL
Инструкция PULL используется для чтения первой строки из очереди данных REXX, активной в данный момент. ниже приведена краткая форма инструкции:
Текущее начало очереди данных читается как одна строка. Если в инструкции не указан шаблон, то никакие дальнейшие действия не производятся и считанная строка отвергается. Если шаблон указан, то он представляет собой список символов, отделенных друг от друга пробелами. Буквы в строке переводятся в прописные (например, строчные a-z в прописные A-Z), а затем строка разбирается по переменным в соответствии с правилами, описанными в разделе по разбору слов документа Язык процедур 2/REXX для OS/2. Справочник. Если не нужно переводить строчные буквы в прописные, то используйте инструкцию PARSE PULL.
Прим. | Если текущая очередь данных пуста, то инструкция PULL выполняет чтение из STDIN (обычно это клавиатура). Длина данных, прочитанных с помощью инструкции PULL, ограничивается длиной строк, содержащихся в переменных. |
Пример: Say 'Вы хотите удалить файл? Ответьте Да или Нет:' Pull answer . if answer='НЕТ' then Say 'Файл не будет удален.'
Здесь в шаблоне используется пустая метка-заполнитель "." для того, чтобы изолировать первое слово, введенное пользователем.
С помощью встроенной функции QUEUED можно определить количество строк в очереди на данный момент.
PUSH
Инструкция PUSH используется для занесения строки, являющейся результатом вычисления выражения, по принципу LIFO (последним вошел, первым вышел) в очередь данных REXX, активную в настоящий момент. Если Вы не указали выражение, то в очередь данных заносится пустая строка.
Пример: a='Fred' push /* Помещает в очередь пустую строку */ push a 2 /* Помещает в очередь строку "Fred 2" */
С помощью встроенной функции QUEUED можно определить количество строк, находящихся в очереди на данный момент.
QUEUE
Инструкция QUEUE используется для добавления строки, являющейся результатом вычисления выражения, в конец очереди данных REXX, активной в настоящий момент. При этом добавление осуществляется по принципу FIFO (первым вошел, первым вышел).
Если Вы не указали выражение, то в конец очереди данных добавится пустая строка.
Пример: a='Toft' queue a 2 /* Добавит в конец очереди строку "Toft 2" */ queue /* Добавит в конец очереди пустую строку */
С помощью встроенной функции QUEUED можно определить количество строк, находящихся в очереди на данный момент.
RETURN
Инструкция RETURN используется для возврата управления (и, возможно, результата) из программы REXX или внутренней программы в точку, откуда она была вызвана.
Если нет активной внутренней программы (подпрограммы или функции), то инструкции RETURN и EXIT идентичны по своему действию на выполняющуюся программу.
Если выполняется подпрограмма (см. инструкцию CALL), то вычисляется выражение (если оно указано), управление передается назад вызывающей программе и специальной переменной RESULT языка REXX присваивается значение выражения. Если выражение опущено, то специальная переменная RESULT освобождается (становится непроинициализированной). Различные назначения, сохраненные на время выполнения CALL (трассировка, адреса и т.д.), также восстанавливаются.
Если выполняется функция, то предпринимаемые действия идентичны описанным, исключая то, что в инструкции RETURN должно быть указано выражение. Результат вычисления выражения используется затем в исходном выражении в точке, из которой была вызвана функция.
Если внутри программы (подпрограммы или внутренней функции) выполняется инструкция PROCEDURE, то после вычисления выражения и до того, как результат будет использован или присвоен переменной RESULT, все переменные текущей генерации освобождаются (и проявленные переменные из предыдущей генерации тоже).
SAY
Инструкция SAY используется для записи в выходной поток результата вычисления выражения. Результат обычно выводится на экран пользователя, однако назначение для выходного потока зависит от конкретного применения. Результат вычисления выражения может иметь любую длину.
> Примечания:
Данные из инструкции SAY посылаются в выходной поток, принимаемый по умолчанию (STDOUT:). Однако для вывода инструкции SAY применимы стандартные правила перенаправления выходных потоков, принятые в OS/2.
Инструкция SAY не форматирует данные; упаковка строки выполняется операционной системой и аппаратурой. Несмотря на то, что форматирование все же происходит, выходные данные представляют собой единую логическую строку.
Пример: data=100 Say data ', разделенное на 4 =>' data/4 /* Выведет на экран: "100, разделенное на 4 => 25" */
SELECT
Инструкция SELECT используется для условного выполнения одной из нескольких альтернативных инструкций.
По очереди вычисляется каждое выражение после фразы WHEN. Результат вычисления должен быть равен 0 или 1. Если результат равен 1, то выполняется инструкция, следующая за фразой THEN (которая может быть составной инструкцией, например, IF, DO или SELECT), а затем управление передается фразе END. Если результат равен 0, то управление передается следующей фразе WHEN.
Если ни один из результатов вычисления выражений WHEN не равен 1, то управление передается инструкциям, следующим за OTHERWISE (если они есть). В этом случае отсутствие предложения OTHERWISE приводит к ошибке.
Пример balance = balance - check Select when balance > 0 then say 'Поздравляем! У Вас на счету' balance 'долларов.' when balance = 0 then do say 'Внимание! Баланс равен нулю! ПРЕКРАТИТЕ все траты!' say "Вы подрезали свой счет в этом месяце. Надеемся," say "что Вы не будете подписывать крупные чеки." end Otherwise say "Вы уже перекрыли свой счет." say "Ваш баланс составляет сейчас" balance "долларов." say "Ооо! Остается надеяться, что банк не закроет Ваш счет." end /* Select */
Примечания: В качестве инструкции может выступать любой оператор присваивания, команда или ключевая инструкция, включающая любую более сложную конструкцию, например, DO, IF или SELECT.
Предложение, содержащее пустую строку, не является инструкцией, поэтому указание за WHEN дополнительной точки с запятой не равнозначно помещению в файл фиктивной инструкции. Для этих целей предназначена инструкция NOP.
Слово THEN нельзя использовать внутри выражения, где оно не предназначается для начала предложения, так как ключевое слово THEN обрабатывается иначе. Если же оно используется, то это может привести к завершению выражения в предложении WHEN посредством слова THEN, указанного без требуемого разделителя ";".
SIGNAL
Инструкция SIGNAL используется для выполнения аварийного изменения потока управления или, если указаны ON или OFF, для управления отслеживанием некоторых условий.
Для управления отслеживанием укажите OFF или ON и условие, которое Вы хотите отследить. Значение OFF прекращает процесс отслеживания указанного условия. Значение ON запускает процесс отслеживания указанного условия.
Прим. Для получения информации по отслеживанию требуемых условий обращайтесь к документу Язык процедур 2/REXX для OS/2. Справочник.
Чтобы изменить поток управления, имя метки выбирается из имени-метки или принимается как результат вычисления выражения, следующего за VALUE. В качестве имени-метки можно указать символ, трактующийся буквально, или текстовую строку, которая является константой. Вложенное ключевое слово VALUE можно опустить, если выражение не начинается символом или текстовой строкой (например, если оно начинается со специального знака, такого как оператор или скобка). Все активные незавершенные инструкции DO, IF, SELECT и INTERPRET в текущей программе завершаются; т.е. их невозможно активизировать повторно. Затем управление передается первой метке в программе, которая соответствует требуемой строке.
Пример: Signal fred; /* Переходит на метку "FRED" */ .... .... Fred: say 'Привет!'
Так как поиск обычно начинается с начала программы, то при наличии нескольких одинаковых меток управление всегда передается первой метке в программе, которая соответствует указанной.
Когда управление передается на указанную метку, специальной переменной SIGL присваивается значение, равное номеру строки с инструкцией SIGNAL. Это помогает при отладке программы, так как можно определить, откуда был выполнен переход на метку.
Использование SIGNAL с инструкцией INTERPRET
Если инструкция SIGNAL выдается как результат выполнения инструкции INTERPRET или происходит событие, которое отслеживается, то остаток интерпретируемой строки не просматривается с целью поиска указанной метки. В действительности метки внутри интерпретируемых строк игнорируются.
TRACE
Альтернативная форма:
Инструкция TRACE используется для отладки. Она управляет трассировкой событий (т.е. выводом процесса их выполнения), имеющих место при работе программы REXX. Синтаксис инструкции TRACE более сжатый и конкретный, в отличие от других инструкций языка REXX. Немногочисленность ключевых слов, используемых в данной инструкции, особенно удобна, так как TRACE обычно вводится вручную в процессе диалоговой отладки.
Число представляет собой целое число.
Результатом вычисления строки или выражения может быть: Число Один из действительных префиксов, алфавитных режимов (слов), либо и то, и другое, как показано на данной панели. Ноль.
Символ является константой и может представлять собой: Число Один из действительных префиксов, алфавитных режимов (слов), либо и то, и другое, как показано на данной панели.
Действие трассировки определяется указанным режимом инструкции TRACE или результатом вычисления выражения. При наличии выражения можно опустить вложенное ключевое слово VALUE, если выражение начинается со специального символа или оператора (во избежание ошибок для символа или строки).
Алфавитные режимы (слова)
Несмотря на то, что режим можно задать полным словом, значащей является только первая прописная буква; остальные буквы игнорируются. Поэтому эти режимы и называются алфавитными.
Ниже приведено соответствие алфавитных режимов и действий, выполняемых при этом инструкцией TRACE:
All | Трассируются (выводятся) все предложения перед их выполнением. |
Commands | Трассируются все команды операционной системы перед их выполнением и выводятся все коды возврата. |
Error | Трассируется после своего выполнения любая команда операционной системы, завершившаяся с ненулевым кодом возврата. |
Failure | Трассируется после своего выполнения любая команда операционной системы, завершившаяся аварийно. Этот режим аналогичен режиму Normal. |
Intermediates | Трассируются все предложения перед их выполнением. Трассируются также промежуточные результаты вычисления выражений и имена, полученные после подстановки. |
Labels | Трассируются метки, встретившиеся в процессе выполнения. Использование этого режима особенно полезно при отладке, когда языковый процессор делает остановку после каждой метки. Пользователю также удобно отмечать при этом все вызовы подпрограмм. |
Normal | Трассируется после своего выполнения любая команда операционной системы, завершившаяся аварийно. Этот режим принимается по умолчанию.
Для стандартного командного процессора операционной системы OS/2 попытка выполнить несуществующую команду приводит к формированию условия FAILURE. Попытка направить команду на выполнение в несуществующую среду подкоманд также приводит к формированию условия FAILURE; в этом случае переменная RC принимает значение 2, что соответствует коду возврата для сообщения "Файл не найден" операционной системы OS/2. |
Off | Трассировка не выполняется. Все действия, выполнявшиеся ранее по указанным префиксам режимов (см. выше), завершаются. |
Results | Трассируются все предложения перед их выполнением. Трассируются конечные результаты вычисления выражений (в противоположность Intermediates). Также выводятся значения, присвоенные переменным при выполнении инструкций PULL, ARG и PARSE. Указанный режим рекомендуется использовать для общей отладки. |
Префиксный режим
Префикс ? может быть указан либо сам по себе, либо вместе с одним из алфавитных режимов. При желании можно указывать префикс несколько раз. Каждое указание префикса в инструкции приводит к выполнению действия, определенного предыдущим префиксом. Префикс следует указывать непосредственно перед режимом (без разделяющих пробелов).
Префикс ? изменяет трассировку и выполнение. Он используется для управления режимом диалоговой отладки. В процессе нормального выполнения инструкция TRACE, введенная с префиксом ?, приводит к включению режима диалоговой отладки.
Если режим диалоговой отладки активен, то Вы можете выключить его, используя инструкцию TRACE с префиксом ?. Таким образом, повторное использование префикса ? приводит к поочередному включению и выключению режима диалоговой отладки. Режим диалоговой отладки можно выключить в любое время, выполнив инструкцию TRACE O или TRACE без режимов.
Числовые режимы
Если диалоговая отладка активна и указанный режим представляет собой целое положительное число (или выражение, значение которого - целое положительное число), то это число определяет количество отладочных остановок, которые требуется пропустить. Однако если указанный режим представляет собой целое отрицательное число (или выражение, значение которого - целое отрицательное число), то вся трассировка, включая отладочные остановки, будет временно подавляться для указанного числа предложений.
Если диалоговая отладка неактивна, то числовые режимы игнорируются.
Формат вывода инструкции TRACE
Каждое трассируемое предложение будет выведено с автоматическим форматированием (отступом) в соответствии с глубиной его логической вложенности и т.д. Результаты (если они требуются) выводятся с отступом в два пробела и заключаются в двойные кавычки так, что обнаруживаются обрамляющие пробелы.
Все строки, выводимые в процессе трассировки, имеют трехсимвольный префикс для идентификации типа трассируемых данных. Префиксы и их определения перечислены ниже:
"*-*" | Определяет одно исходное предложение, т.е. данные, фактически указанные в программе. |
"+++" | Определяет сообщение трассировки. Это может быть ненулевой код возврата из команды, приглашающее сообщение, выдаваемое в режиме диалоговой отладки, индикация синтаксической ошибки в режиме диалоговой отладки или протрассированные предложения после синтаксической ошибки в программе. |
">>>" | Определяет результат выражения (для TRACE R), значение, присвоенное переменной в процессе разбора, или значение, возвращенное из подпрограммы после ее выполнения. |
">.>" | Определяет значение, присвоенное в процессе разбора метке-заполнителю. |