"switch_lang(event)">

$$OUT=-

$$START!

I. Синтаксис операторов

I. Syntax

I. 1. Форматирование операторов

I. 1. Formatting statements

I. 1. a. Один оператор - одна строка

I. 1. a. Continue statement lines

 

Простые операторы не требуют завершения специальным знаком (таким, как ';').

Знак ';' используется для завершения блока.

Например:

d|escriminant = B * B - 4 * A * C
CASE d.Sign ?
     [-1]: NONE
     [0] : R[] << -B / 2 / A
     [+1]: R[] << (-B - d.Sqrt) / 2 / A
           R[] << (-B + d.Sqrt) / 2 / A  ;

 

 

Statements need not any finalization symbol (like ';').

Symbol ';' is used to finish a block of statements.

E.g.:

d|escriminant = B * B - 4 * A * C
CASE d.Sign ?
     [-1]: NONE
     [0] : R[] << -B / 2 / A
     [+1]: R[] << (-B - d.Sqrt) / 2 / A
           R[] << (-B + d.Sqrt) / 2 / A  ;

 

 

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

Оператор может быть записан в нескольких строках,

но строка считается продолжающейся на следующую только если:

  • строка заканчивается символами ',', '(', '[' ;
  • следующая строка начинается символами:
    • '"' (двойная кавычка- начинает строчную константу)
    • '+'
    • '-' (одинарный знак минус)
    • '*'
    • '/'
    • '%'
    • '|'
    • '&'
    • '>'
    • '<' (но не '<<')
    • '='
    • '#'

 

A line of a code should not exceed 80 characters (without ending comments and spaces and tabulations).

Statement can be continued in several lines only in following cases:

  • a line is finished with ',', '(', '[';
  • the next line is starting with one of symbols (without quotas):
    • '"' (double quotas - starts string constant)
    • '+'
    • '-' (single only, not '--')
    • '*'
    • '/'
    • '%'
    • '|'
    • '&'
    • '>'
    • '<' (but not '<<')
    • '='
    • '#'
 

Другой способ запомнить правило переноса:

строка считается продолжающейся на следующую только если

  • или предыдущая строка завершается символами '(', '[', ','
  • или следующая строка не пуста и не может начинать новый оператор, т.е.:
    • не начинается с буквы,
    • с символа '{' (не начинает декларацию переменной),
    • с символа '[' (не начинает условие для ветви CASE),
    • с символа '<<' (не начинает оператор вывода в консоль),
    • с символов '.' или ';' (не является отдельно стоящим символом для завершения блока кода или функции)
    • с символа '--' (не начинает блочный комментарий).
 

Another way to remember the rule is that a statement is continued only if:

  • either the previous line is finished by one of symbols '(', '[', ','
  • or the next line is not empty and it can not a start of a new statement, that is, it is not start from:
    • a letter,
    • a symbol '{' (not a variable declaration),
    • a symbol '[' (not a condition for a CASE statement),
    • a symbol '<<' (not an output to console statement),
    • symbols '.' or ';' (it is not a separate ending of a code block or a function),
    • a symbol '--' (it is not starting a block comment).
 

Или использовать иллюстрацию ниже:

$$IF?LIGHTRU

$$IF?DARKRU

$$FI

 

Or use the following figure:

$$IF?LIGHTEN

$$IF?DARKEN

$$FI

 

I. 1. b. Блочные операторы

I. 1. b. Block statements

 

Блочные операторы создают вложенный уровень операторов.

Блок вложенных операторов завершается символом ';'.

Функции и другие блоки уровня класса завершаются символом '.' (точка). А именно: заголовок класса, список импорта, определение типа перечисления, определение блока констант.

Строка не может завершаться двумя и более подряд одинаковыми символами завершения ';' или '.'. Но сочетание ';. ' для завершения последней блочной конструкции в функции и самой функции допускается.

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

 

Block statements always are starting in a new line.

Nesting statements block is ended with the symbol ';'.

Functions and other blocks of a class level are ending with a symbol '.'. Such blocks are: a class header, an import list, enumeration declaration, constants definition block. (Though it is allowed to use ';' for an import list, too).

The last line in a nested block can not be ended with two same ending symbols ';' or '.'. But it is allowed to end nesting block with its upper leveled function by two symbols ';. ' at the end of the last line in the function.

So, if it is required to finish two nesting blocks, then the ending symbol of the external block will be placed in a separate line of code. E.g.:

 

 
FOR i  IN [1  TO  100] :
     CASE  i % 3 == 0 ? <<  "Fizz"  ;
     CASE  i % 5 == 0 ? <<  "Buzz"  ;
     CASE  i % 3 != 0 && i % 5 != 0 ?
         << i.Str  ;
;

 
 

Имеется только одно ключевое слово для условного оператора (CASE), одно для оператора цикла (FOR), один оператор сохранения и гарантированного восстановления (PUSH). Имеется так же оператор бесконечного цикла FOR, INFINITE , но его применение ограничено. Для отладки кода может использоваться блочный оператор DEBUG .

Все прочие операторы являются простыми: BREAK, CONTINUE, STOP, LIKE, REVERT, вызовы функций, декларация и модификация переменных, ввод и вывод (>>, <<). Оператор BREAK может использоваться только для прекращения цикла и не используется для других целей.

 

There is only a single keyword for a conditional statement (CASE), a single keyword for a basic loop statement ( FOR), a single save and restore statement (PUSH). There is also an infinitive loop statement (FOR, INFINITE) using it is restricted. For debugging, special blocks DEBUG  can be used also.

All other statements are simple: BREAK, CONTINUE, STOP, LIKE , REVERT, function calls, variable declarations and modifications, input and output (>>, <<). The BREAK statement can be used only to exit a FOR loop and not for any other purposes.

 

Компилятор требует помечать маркером BAD классы, в которых не соблюдаются правила структурирования кода:

  • Количество вложенных уровней операторов CASE и FOR не должно превышать трёх (блоки PUSH / DEBUG не учитываются).
  • Количество простых операторов в блоке не должно превышать семи.
  • Количество вложенных блочных операторов в блоке так же не должно превышать семи.
  • Специальный оператор-комментарий вида
    --------- 'текст комментария'
    может разделять группы операторов(число знаков '-' произвольно, но не менее двух), в этом случае подсчёт ведётся только внутри группы.
 

A compiler requires to mark with a modifier BAD classes in which rules of code structuring are not satisfied:

  • Number of nested levels of block statements CASE and FOR should not exceed 3 (blocks PUSH / DEBUG are not considered).
  • Number of simple statement in a section of a block should not exceed 7.
  • Number of nested block statements in a section of a block also should not exceed 7.
  • A special block comment
    --------- 'text'
    can separate groups of statements (number of signs '-' at least 2) treated as sections in a block.

 

 

I. 1. c. Комментарии

I. 1. c. Comments

  • Многострочные комментарии начинаются в начале строки (не считая начальных пробелов) с символов
    */
    и заканчиваются строкой,
    завершающейся символами /*

  • Текстовой файл, содержащий исходный код, считается всегда начинающимся с многострочных комментариев. Признаком завершения таких комментариев является строка, завершающаяся символами /*. Т.е., код AL-IV всегда должен находиться между строками /* и */ (как если бы он был комментарием для C-подобного языка программирования).

Иллюстрация:

$$IF?LIGHTRU

$$IF?DARKRU

$$FI

 

  • Multi-line comments:  starting brackets are always placed at the begin of a line (may be following leading spaces) from the symbol
    */
    and finishing with a string
    started from symbols
    /*

  • A text file containing the AL-IV source code is always treating to be started from multi-line comments. A line containing at the end the symbol /* becomes the end of such leading comments lines. I.e. the AL-IV code should be located always between lines with symbols /* and */ (as it would be comments for some C-like programming language around).

See the figure:

$$IF?LIGHTEN

$$IF?DARKEN

$$FI

 
  • Комментарии до конца строки начинаются с двойной дроби (//). Не завершают текущий оператор.
  • Комментарии, начинающиеся двумя символами --, имеют форму
    -------------- 'текст'
    и служат для разбиения блоков на разделы. Так же, используются в декларациях классов и в оглавлении модуля.
    Такой блочный комментарий может начинать переиспользуемый блок кода (операторы LIKE, REVERT ). В этом случае он должен иметь модификатор REUSED (записывается через запятую после метки). Например:
    ---------------- 'start extracting ', REUSED

 

  • Comment to the end of line (start from //). Such comments do not finish current statement.
  • Comments starting with two minuses:
    ----------- 'text'
    are used to separate blocks of code onto sections. These also are used in class declarations and in module headers.
    A block comment statement can start a reused block of code (in statements LIKE / REVERT). In such case it should have a modifier REUSED (which is written after the label comma separated). E.g.:
    --------------- 'start extracting ', REUSED

 

 

I. 1. d. Регистрозависимость для идентификаторов

I. 1. d. Case sensitivity for keywords, types and other identifiers

  • КЛЮЧЕВЫЕ И ЗАРЕЗЕРВИРОВАННЫЕ СЛОВА записываются только в ВЕРХНЕМ регистре.
    CASE
    являются ключевым словом, но Case , case - нет.
  • KEYWORDS can be written in the UPPER case only.
    CASE if a keyword but case, cAsE and Case - not.
  • {Имена классов} (а так же перечислений и структур) заключаются в фигурные скобки.
  • имена простых типов данных являются зарезервированными: BOOL, BYTE, INT , REAL, STR (и других простых типов, кроме этих пяти, нет).
  • {Имена классов} начинаются с прописных букв: {My_class}, {Car|_mobile}.
  • {имена_перечислений_и_структур} начинаются со строчной буквы: {color|s_fill}.

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

 

  • {Type names} are enclosed into figure brackets.
  • simple type names are reserved keywords: BOOL, BYTE, INT, REAL, STR (and there no simple types except these 5 listed here).
  • {Class names} are starting from uppercase letters.
  • {enumeration_and_structure} names are starting from lowercase letters.

Type names create a name space not intersecting other names at all.

  • Рекомендуется использовать КАПИТАЛИЗИРОВАННЫЕ имена для констант.
  • CONSTANT names are case sensitive.

It is desired to be written CAPITALIZED.

 

  • Имена 'КОНСТАНТ', являющихся элементами перечислений, всегда заключаются в апострофы.
  • Names of 'CONSTANTS' which are items of enumerations are always enclosed into apostrophes.
  • Все имена регистро-зависимы.

Например, A и a - это разные переменные (или константы).

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

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

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

  • Символ подчеркивания в конце имени_ является неотъемлемой частью имени (и служит атрибутом слабой ссылки для объектов).
  • Variable and field names (of structures and classes) are case sensitive.

So, A and a are different variables (or constants).

Names of Public fields, functions, variables, types are always starting from a capital letter.

All other names are local in a module. (This does not concern local variables which are always local in its functions and can be written from any case).

  • The underscore at the end of a name_ is an integral part of the name (and used as a marker of a pointer to a structure or of a weak pointer to an object).

 

I. 1. e. Именование

I. 1. e. Naming

 

При декларации переменной, функции, типа данных, элемента перечисления, таблицы - ее длинное имя может быть разделено на части символом '|'. Первая часть - это краткое имя. Так же, символом '||' от первой цепочки именования может быть отделена вторая цепочка, и так далее. Единственное требование: все цепочки должны начинаться с той же буквы (без учета регистра).

 

При этом:

  • Длина полного имени должна быть не менее 8 знаков:
    S|ample|_val (переменная доступна в коде по именам S, Sample и Sample_val);
  • Исключение: переменным цикла необязательно давать длинное имя, допускается краткое имя короче 8 символов:
    FOR x IN M[] : ... ;
  • Также: если при декларации переменной ей придан атрибут INDEXING, достаточно иметь краткое имя:
    INT k INDEXING {record}
  • Если имя должно заканчиваться символом подчёркивания (признак слабой ссылки), то подчёркиванием должны заканчиваться обе части имени, например:
    List_|of_items_ || L_items_ []
  • Для имён классов, записей и перечислений действует то же правило, и при подсчёте длины имени - окружающие фигурные скобки и разделители '|'не учитываются:
    {My|_class}, итого 8 символов.
 

While declaring a variable, a function, a data type, a table or an enumeration item it's long name can be separated by the symbol '|' onto parts, the first of which is a short name. Also, the symbol '||' can be used to define another name chain, and so on. It is therefore required that all such chains should start from the same letter (though letter case can be different).

 

There are following rules:

  • The whole name length should not be less then 8 characters: S|ample|_val (the variable can be refrenced by names S, Sample and Sample_val);
  • The exclusion for variable names: FOR loop variables can have only short name, even short, e.g.:
    FOR x IN M[] : ... ;
  • Another exclusion: if for the variable while declaration the attribute INDEXING is provided, it is enough for it to have only short name:
    INT k INDEXING {record}
  • If a name should be finished by an underscore character (which is a mark for a weak reference in the AL-IV), then both variants of the name should be ended with the underscore, e.g.:
    List_|of_items_ || L_items_ []
  • For class names, records and enumerations the same rule is active, and figure brackets and split symbols '|' are not accounting in names lengths:
    {My|_class}, 8 symbols in the name.

 

I. 1. f. Модификаторы

I. 1. f. Modifiers

 

Многие декларации языка (заголовок модуля, оператор, декларация переменной или типа данных) могут иметь модификаторы.

  • записываются в форме , ИМЯ в конце оператора (или декларации), к которому относятся.
  • Если модификаторов несколько, то они перечисляются через запятые.

 

Например, в заголовке класса:
CLASS  {My|_class}BITWISE, RECURSIVE :

 

Many language declarations (module header, statement, variable of data type declaration) can have modifiers.

  • Modifiers are written in form , NAME at the end of a declaration (usually).
  • If there are several modifiers then these are listed via ','.
  • Modifiers are written in the upper case. E.g.:
    CLASS  {My|_class} BITWISE, RECURSIVE :

 

Модификаторы не воздействуют на основную семантику кода.

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

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

 

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

Modifiers do not affect main code semantics.

These just help to compiler to provide more security and sometimes help to optimize resulting code.

If to remove all modifiers in a ready program (and suppose that a language do not require it), this (usually) do not change a result of the program (but can take an effect of changing its size / working speed, either increasing or decreasing it).
 

In some cases a presence of some identifier in the name of a variable itself is used as a "modifier". E.g., the word "dummy" as a part of a name can be used to prevent the compiler to warn about a variable which is not used in code. And the word temp in a local variable name determines for the compiler that the variable is a temporary and it is not necessary to warn the programmer about assigning a new object to that variable only.

 

 

I. 2. Оператор присваивания

I. 2. Assignment

I. 2. a. Простой оператор присваивания

I. 2. a. Simple assignment statement

x = y

где x - переменная или поле структуры или объекта, y - выражение.

x = y

where x is a variable or a field of a structure or an object and y is an expression.

 

Для сравнения на равенство двух операндов используется си-подобный оператор ==.

 

To compare for equality of two operands a "C"-like operator == is used.

 

I. 2. b. Операторы присваивания в комбинации с арифметической, логической или поразрядной логической операцией

I. 2. b. Assignment in combination with arithmetic, logic or bitwise operation

 

Дополнительные операции +=, -= , *= , /=, %=, |= , &=, ^=, ||= , &&=, могут использоваться как эквивалент присваивания результата соответствующей операции + , - , * ,... между переменной, которой присваивается результат, и выражением справа от знака операции.

 

Additional operations +=, -=, *= , /= , %= , |= , &= , ^= , ||= , &&= can be used as an equivalent of the assignment of a result of a correspondent operation + , -, *, ... between the variable left to the symbol of the operation and the right-sided expression.

 

I. 2. c. Операторы отправки данных

I. 2. c. Data sending operations

 

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

  • Для строковой переменной A и строкового выражения B запись A << B эквивалентна оператору присваивания вида A = A B
  • в случае массива A[] и выражения B запись A[] << B эквивалентна вызову функции A[].Add(B) для массива.
  • Если операнд слева - объект класса, имеющего метод Write, то вызывается этот метод, с передачей выражения справа (строкового типа) в качестве результата;
  • Если слева структура, а справа - объект класса, имеющего метод Read (возвращающий структуру), то вызывается этот метод, далее как в предыдущем пункте;
  • Если левый операнд не указан, то это оператор записи строки в выходной поток (в консоль - для консольной программы).

 

 

Operation << is used to append a string to a string or to append an item to an array, or to output text to a current output console.

  • For a string variable A and a string expression B, a statement A << B is equal to A = A B
  • In case of an array A[] and an expression B, statement A[] << B is equal to a function call A[].Add(B)
  • If the left operand is an object of a class having the method Write (accepting a string) then it is called passing the result of the right (string) expression as a parameter;
  • If a structure is on the left side but the right object is of a class having the method Read (returning a structure), then the method is called then as in the previous item;
  • If the left operand is not present, then such statement means writing a string to an output stream (to the console for a console application).

 

 

Аналогичная операция >> используется как замена вызова функции Read для операнда слева (а так же для добавления нового объекта в массив объектов, см. в разделе, посвященном классам и объектам).

 

Справа от оператора >> может находиться декларация новой переменной.

  • Операторы ввода-вывода << и >> могут комбинироваться в одном операторе в виде
    << строка [>> переменная] [>> переменная] ...
    Например:
    <<  "Введите число:"  >>  REAL Number|_entered

 

A similar operation >> is used as a replacement of a call of a function Read for the left operand as a source (and also to add a newly created object to an objects array, see in a section devoted to classes and objects ).

 

Additionally, right to the >> operator a declaration of a new variable can be specified.

  • Input-output operators << and >> can be combined in a single statement in a form:
    << string [>> variable] [>>variable] ...
    E.g.:
    <<  "Enter number:"  >> REAL Number|_entered

 

I. 2. d. Операторы повторного присваивания и отправки данных

I. 2. d. Repeating assignment and sending data operators

 

Если оператор начинается с символа '..' (без кавычек), то это ссылка на левую часть предыдущего оператора присваивания(или на зафиксированную левую часть присваивания). Соответственно, три точки подряд означают такую ссылку с последующей операцией обращения к полю или методу объекта, или обращения к функции с указанным операндом в качестве первого параметра.

Для такого повторного присваивания (или отправки данных):

  • не ведется подсчет операторов (нет ограничения на количество таких повторных присваиваний);
  • выражение фиксируется в качестве левой части для последующих "повторных" присваиваний:

     

    • если употреблено в левой части обычного оператора присваивания(a = b, a += b, a *= b, и т.п.);
      Например:
      Text = New_memo( THIS"TEXT""VH" )
      ...Set_width(200)
      ...Set_anchor_bottom(TRUE )
    • является левой частью обычного оператора отправки данных (a << b, a[] << b, в том числе в случае, когда оператор '<<' заменяет вызов метода Write);
      Например:
      Lines[] <<  "#!/bin/bash"
      ..[] <<  "echo run WinE"
      ..[] <<  "wine"
    • если в операторе в цепочке разыменования полей/методов использован псевдо-оператор '...' в позиции одинарной точки (например:
      A.Field1[indexA]...Do_something(params)
      ...Color = RED
      ...Foo(params)

      В приведенном примере в двух последних строчках символ '..' замещается компилятором выражением A.Field1[indexA]

 

 

If a statement is starting from a symbol '..' (without quotas), then this represents a reference to the left side of the previous assignment statement. So, three dots are meaning such reference with a following "dot operation" used to either name a field or a method of an object or to name a function giving the operand referred by the '..' symbol as the first parameter.

For such repeating assignment statement (or data sending statement):

  • statements are not counting as simple or nesting (there are no restrictions on such repeating assignments);
  • an expression is fixed to be a destination for following repeating assignments if:

     

    • it is used as the left side of a usual assignment (a = b, a += b, a *= b etc.);
      E.g.:
      Text = New_memo( THIS"TEXT""VH" )
      ...Set_width(200)
      ...Set_anchor_bottom(TRUE )
    • it is used as a destination in a usual sending data statement (a << b, a[] << b), including a case when the sending operator is replacing a method Write call;
      E.g.:
      Lines[] <<  "#!/bin/bash"
      ..[] <<  "echo run WinE"
      ..[] <<  "wine"
    • if a pseudo-operator '...' is used in place of a single "dot" operation in a chain of unnamings / indexing operations applied to an expression. E.g.:
      A.Field1[indexA]...Do_something(params)
      ...Color = RED
      ...Foo(params)

      In the example above, in two last lines, the symbol '..' is replaced by a compiler with an expression A.Field1[indexA]

 

I. 3. Выражения

I. 3. Expressions

 
Приоритет Операция Расшифровка Группа
1 - Взятие обратного знака Арифметика (чисел), на выходе число
2 * / % Умножение, деление, остаток от деления
3 + - Сложение, вычитание
4 IN !IN Проверка на вхождениезначения в диапазон или массив Сравнение чисел, строк, классов, результат булевское
5 LIKE !LIKE Сравнение строк без учета регистра букв и с учетом шаблонных символов '?' и '%' во втором операнде
6 < <= > >= == != <> Сравнения
7 ~ Поразрядное отрицание Поразрядные операции с целыми, результат - целое

 

8 & ^ И, Исключающее или (xor) - поразрядные
9 | ИЛИ поразрядное
10 ! Логическое НЕ Логические операции (с булевскими, результат - булевское)
11 && Логическое И (&&)
12 || Логическое ИЛИ (||)

 

  • Операция конкатенации строк не имеет специального знака. Используется пробел.
  • При наличии поразрядных логических операций в модуле в список модификаторов модуля добавляется BITWISE.
  • смешение поразрядных и арифметических операций в одном выражении недопустимо.
  • побитовые операции сдвигов реализуются с помощью встроенных функций ShiftL|eft, ShiftR|ight, RotateL|eft, RotateR|ight - отдельные знаки бинарных операций для этого отсутствуют.
  • допускается использовать цепочки сравнений.
    a < b <= c == 1 > d эквивалентно:
    a < b && b <= c && c == 1 && 1 > d

 

 
Priority Operator Description Group
1 - Negation Arithmetic operations (with numbers), result is a number
2 * / % Multiplication, division, rest of division
3 + - Adding, subtracting
4 IN !IN Check for presence a value in a set or array, check for an object belonging to a class Comparing numbers, strings, classes, result is Boolean or integer
5 LIKE !LIKE Compares two strings without case sensitivity and interpreting special symbols '?' and '%' in the second operand as patterns 'any character' and 'any amount of any symbols'
6 < <= > >= == != <> Comparisons
7 ~ Bitwise NOT Bitwise operations with integers, result again is integer

 

8 & ^ Bitwise AND, eXclusive OR(xor)
9 | Bitwise OR
10 ! Logical NOT Logical operations with Boolean, result also is Boolean
11 && Logical AND (&&)
12 || Logical OR (||)
  • Concatenation operation has no special sign (use space).
  • If any bitwise operations are used in a module, then a modifier BITWISE must be added for the module.
  • Using both bitwise and arithmetic operations in the same expression is not allowed.
  • bitwise shift and rotate operations are implemented with embedded functions ShiftL|eft, ShiftR|ight, RotateL|eft , RotateR|ight, there are no separate binary operation signs for them.
  • it is allowed to write chains of comparisons.
    a < b <= c == 1 > d is the same as:
    a < b && b <= c && c == 1 && 1 > d

 

 

I. 3. a. Операции проверки наличия

I. 3. a. Checking the contant of an item

 

Операторы IN и !IN могут использоваться в выражениях:

  • для проверки наличия скалярного значения в массиве (при этом массив может быть переменной или конструкцией вида
    [ значение1, значение2, ..., значение3 ])
  • для проверки наличия подстроки в строке
  • так же в SQL-выражениях может использоваться IN (но для противоположной проверки используется синтаксис SQL: NOT IN)

 

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

Операция IN / !IN не применима к паре вещественное число - вещественный массив (так же как запрещено сравнение на равенство значений типа REAL).

 

 

Operators IN and !IN can be used in expressions:

  • for checking if a scalar value is present in an array of values (and an array to the right can be either an array variable or a construction in form
    [ value1, value2, ..., valueN ])
  • to check is a substring is present in a string
  • also in SQL-expressions the operation IN can be used (but for opposite operation, SQL syntax is used: NOT IN )

 

In case of a constructed array, all its items must be constant expressions. And in case when the left value is a string, it is not allowed to construct an array from a single string value. Either a string should be to the right of IN / !IN ( the case 2).

Operations IN / !IN are not applicable to REAL numbers (still it is not allowed to compare REAL values for equality/inequality).

 

I. 4. Прочие простые операторы

I. 4. Other simple statements

  • Для возврата из функции до окончания ее кода используется оператор возврата ==> .
    • Такой оператор может записываться отдельно либо следом за другим простым оператором в той же строке, образуя простой оператор с выходом из функции.
      Например:

      CASE  R > 0 ?  RESULT = R  ==>   ;
  • To return from a function before its code ends, a statement ==> used.
    • Such statement can be written either separately or following another simple statement (in the same line of code).
      E.g.:

      CASE  R > 0 ?  RESULT  = R  ==>   ;
  • Для завершения и продолжения цикла FOR используются операторы BREAK и CONTINUE , для которых обязательно указывается переменная цикла, Например:
    FOR  x  IN  [1  TO  100] :
        do_something
        CASE  condition ?  BREAK x;
    ;

  • В цикле FOR, INFINITE нельзя использовать операторы CONTINUE и BREAK. Завершить такой цикл можно только выходом из функции (оператор ==> ) или в результате срабатывания исключительной ситуации.
  • Наличие метки в операторах BREAK / CONTINUE позволяет продолжить или остановить внешний цикл из тела вложенного напрямую (однако необходимо записать BREAK для всех вложенных циклов через запятую:
    BREAK k, BREAK j, CONTINUE i).

  • To terminate or continue a loop, keywords  BREAK and CONTINUE are used, together with a loop label, e.g.:
    FOR  x  IN  [1  TO  100] :
        do_something
        CASE  condition ? BREAK x;
    ;
  • It is not allowed to use BREAK / CONTINUE in the FOR, INFINITE loop. It is only possible to terminate such loop by the return statement (==> ) or in result of an exception firing.
  • Using a label in BREAK / CONTINUE statements allows to continue or terminate an outer loop from an inner loop directly (but it is necessary to write first BREAK statements for all the nested loops first:
    BREAK k, BREAK j, CONTINUE i)
 

 

I.  5. Условный оператор CASE

I. 5. Conditional statement CASE

  • Выражение в операторе CASE должно иметь значение булевского, целочисленного, перечислимого или строкового типа.
  • Выражения других типов (вещественных или объектных) не допускаются.
  • Заголовок всегда завершается знаком '?'.
  • В случае булевского типа условия, немедленно начинается блок кода, который выполняется при выполнении условия. И за ним может следовать блок ELSE (см. ниже).
  • В остальных случаях, каждая ветвь начинается с массива иди диапазона значений в квадратных скобках
    [массив значений]:код
  • В качестве значений должны использоваться целочисленные, строчные или перечислимые константные значения (литеральные или именованные константы), тип значений которых соответствует типу выражения в заголовке.
  • Значение в списке значений может быть одиночным или представлять диапазон значений в виде X TO Y , где X и Y - константы (только для целочисленного условия).
  • Повторение значений (и пересечение диапазонов) не допускается.
  • В случае перечислимого типа условия, должны быть перечислены все значения соответствующего перечислимого типа, и не может использоваться ветвь ELSE.
  • Общая ветвь ELSE выполняется (при её наличии), если ни одна из констант не совпала, и ни одна из ветвей не была выполнена.
  • Обычно ELSE (при его наличии) располагается начиная с новой строки. Но допускается размещать ELSE в той же строке, что и CASE , если весь оператор вместе с завершающей ';' умещается в одну строку (80 символов). В случае однострочного CASE ... ELSE ... ; оператора, ключевое слово ELSE должно отделяться от предыдущего оператора (ветви "then") как минимум одним пробелом или табуляцией;
  • Символ ';' завершает весь оператор CASE.

 

Оператор BREAK не используется для завершения ветви.

По исполнении любой ветви всегда происходит выход из всего оператора CASE.

 

  • An expression in the CASE statement should be of Boolean, integer,  enumerated or string type.
  • Expressions of other types (e.g., REAL, stuctures, objects, etc.) are not allowed.
  • The header is always finished by the symbol '? '.
  • In case of the Boolean condition, a block of code follows which is executed in case when the condition is true. And an ELSE block can be following (see below).
  • In other cases each branch is starting from a constant array of constant values in square brackets:
    [array of values]: code
  • Constants (literal or named) should be listed in the array having a type correspondent to the type of the condition in the header.
  • The value can be a single, or it can be represented with a list of values, or by a range X TO Y (which is allowed in case of integer condition).
  • All the items in all sets or arrays must be distinct.
  • In case of enumerated condition, all the enumeration items must be listed in arrays starting branches, and in such case it is not allowed to use ELSE branch.
  • If a common part ELSE is present, it is executed if the expression in the header were not matching any constant listed, and there was no a branch executed.
  • Usually the ELSE keyword is starting a new line. But it is allowed to place it in the same line as the CASE statement if the entire CASE statement fits a single line (80 symbols). In such case the ELSE keyword must be separated from the previous statement (then-clause) by spaces;
  • Symbol ';' ends entire CASE block, together with all its branches and ELSE clause.

 

A BREAK statement is not used to finish a branch.

After any branch execution entire CASE statement is finished.

 

 

Классический пример - решение квадратного уравнения в области вещественных чисел:

 

Classic example - solving a square equation for real numbers:



STRUCTURE  {roots_sq|uare_equation} :
     INT  N|umber_solutions
     REAL  X1|_solution
     REAL  X2|_solution  .

FUNCTION  Square_eq|uation(
          REAL  A|_coefficient,
          REAL  B|_coefficient,
          REAL  c|_coefficient)  ==>   {roots_sq} :

    CASE  A.Near(0) ?  ==>   ;
    REAL  d|escriminant = B * B - 4 * A * C
    CASE  d.Sign ? [0]: RESULT .N = 1
                       RESULT .X1 = -B / (2 * A)
                       RESULT .X2 =  RESULT .X1
                 [1]: d = d.Sqrt
                       RESULT .X1 = (-B - d) / (2 * A)
                       RESULT .X2 = (-B + d) / (2 * A)
                       RESULT .N = 2  ;   .

 

 

 

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

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

 

Especial version of the CASE ? statement - with a condition in the header but with sequential calculation of conditions in square brackets until either the first one is found with value TRUE (in such case a correspondent branch is executed only), or until the ELSE part (or the end of the CASE statement) is found.

In such case symbols '?' are written after each expression rather then ':'.


FUNCTION  Square_eq2|uation(
REAL  A|_coefficient,
REAL  B|_coefficient,
REAL  c|_coefficient)  ==>   {roots_sq}
   :
    -----------------------  'sequentional version'
   REAL  d|escriminant = B * B - 4 * A * C
    CASE  ?
   [A.Near(0)]?  ==>
   [d.Near(0)]?RESULT.N = 1
               RESULT.X1 = -B / (2 * A)
               RESULT .X2 =  RESULT .X1
   [d > 0] ? d = d.Sqrt
              RESULT.X1 = (-B - d) / (2 * A)
              RESULT.X2 = (-B + d) / (2 * A)
              RESULT .N = 2  ;   .


 

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

 

Also there is a special variant CASE ? purposed to use in generic functions. See detailed in a correspondent section.

 

I. 6. Операторы цикла FOR

I. 6. FOR loop statements

 

Оператор цикла FOR с перечислением элементов массива - это единственный вариант контролируемого цикла:


      'KEYW_CS1'>FOR переменная  IN массив[диапазон] : тело  ;
или
    'KEYW_CS1'>FOR переменная  IN [диапазон]: тело  ;
или
    FOR  переменная  ENUM|ERATE  метод: тело  ;
 

 

 A loop statement FOR enumerating array items - is a single possible controlled loop statement:

 

FOR  variable  IN  array[range] : body  >;
or
   FOR  variable  IN [range ]:  body  ;
or
   FOR 
variable  ENUM|ERATE  method:  body  ;
 

  • Переменная такого цикла всегда имеет тип, совпадающий с типом элементов перечисляемого массива.
  • В случае диапазона значений без массива, тип переменной - целое число;
  • Такая переменная:
     
    • Не требует декларации.
    • Не требует длинного синонима.
    • Не может использоваться вне цикла, кроме как в другом цикле FOR .
    • Используется как метка операторов BREAK имя и CONTINUE имя.
  • Переменная цикла FOR с диапазоном значений (не на основе массива) не может быть изменена в теле цикла.
  • В случае массива с пустым диапазоном в цикле перечисляются все элементы с индекса 0 до индекса * (индекс последнего элемента в массиве).
  • Для изменения границ перечисления и направления перечисления следует либо в индексной части массива, либо использовать конструируемый с помощью диапазона массив целых в форме [X TO Y] или [Y DOWNTO X], где X и Y - целочисленные выражения.
  • К переменной цикла применима псевдо-функция INDEX, возвращающая целочисленный индекс элемента в массиве.
  • Границы перечисления индексов вычисляются до начала цикла, и изменение размера динамического массива в процессе работы цикла не влияют на порядок просмотра индексов. Это может приводить к выходу индекса за границы массива, в результате чего переменная цикла будет получать значение NONE.
  • Для варианта FOR x ENUM y : ... ; y должен быть вызовом любого метода, возвращающего булевское значение и не имеющего параметров. Этот метод должен вернуть TRUE для прекращения цикла, и вызывается перед каждой итерацией. Однако, переменная цикла при этом всегда отсчитывает значения от 0 до максимального значения, и если эта максимальная величина превышена, цикл прекращается. Предельное значение по умолчанию равно 1_000_000. Но может быть изменено явно:
    FOR x ENUM(MAX 1000) method : ... ;

 

  • The loop variable of such loop statement is always has the same type as a enumerating array items data type.
  • In case of a range without an array, the variable type is integer;
  • It:
     
    • Does not require declaration.
    • Does not require a long synonym.
    • Can not be used out of the loop, except in another FOR loop.
    • It is used as a label in statements BREAK variable and CONTINUE variable, related to the loop.
  • A variable of a FOR loop with a range can not be changed in a loop body (and used as a usual variable).
  • In case of empty range all the items are enumerated from the start (index 0) to the end (index *).
  • To indexes change direction and bounds, it is necessary to use a constructed array [X TO Y] or [Y DOWNTO X], where X and Y - are integer expressions.
  • It is possible to apply an embedded function INDEX to it (it returns an index of the variable in the enumerating array).
  • Bounds of indices enumerating are calculated before the loop, and even if size of an array is changed during a loop, this does not affect enumerated indices. As a result, this can lead to violating array bounds, and an array variable will be set to NONE in such cases.
  • For the variant FOR x ENUM y : ... ; the "y" should be a call to a method which does not have parameters and return a Boolean. Such method should return TRUE to stop iterations, and it is called before each loop iteration. Therefore the loop variable ("x") is changed from 0 to some maximal value and then its value becomes greater the limit, the loop is stopped. The default limit value is 1_000_000 but it can be redefined explicitly:
    FOR x ENUM(MAX 1000) method : ... ;
 

Для организации неконтролируемого бесконечного цикла используется блочный оператор
FOR, INFIINITE  : тело цикла  ;

  • Цикл FOR, INFINITE может быть завершён только оператором выхода из функции ==> .
  • Операторы BREAK и CONTINUE не используются.
  • Класс, в котором встречается цикл FOR, INFINITE, должен быть отмечен маркером INFINITIVE.
 

To create an unguided infinitive loop, a special block statement is used:
FOR, INFINITE : loop body  ;

  • The FOR, INFINITE loop can be terminated only by a return from the function statement ==> .
  • Statements CONTINUE / BREAK can not be used.
  • A class where statements FOR, INFINITE are used, must be marked with a modifier INFINITIVE.

 

 

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

 

A loop variable it it is integer can (as well as any integer variable) to have an attribute INDEXING type or INDEXING (list, of, types) . See more detailed in a section devoted to control of types of indexing arrays.

 

В случае завершения блока оператора FOR оператором выхода из блока (BREAK), финальная последовательность операторов (после последнего оператора CONTINUE в этом цикле) может быть отделена специальным оператором DONE. Например:


FOR a IN A[] :
    CASE !a.satisfying_conditions ? CONTINUE a ;
    DONE // искомый элемент найден
         a.do_something
         do_something_more
         BREAK a ;

 

 

In case when a FOR block is ending with the BREAK statement, its final sequence of statements can be separated with the special statement DONE. E.g.:


FOR a IN A[] :
    CASE !a.satisfying_conditions ? CONTINUE a ;
    DONE // we've found desired item
         a.do_something
         do_something_more
         BREAK a ;

 

Оператор DONE уменьшает уровень вложенности блочных операторов (как если бы блок оператора FOR уже завершился).

 

The DONE statement decreases the counting nesting level of nesting statements (as the statement FOR would already finished).

 

I. 6. a. О возможности присваивания значений переменным цикла:

  • Если переменная цикла изменяется в диапазоне значения (массив не перечисляется), присваивание другого значения переменной запрещено в цикле;
  • в случае, когда переменная цикла пробегает все или часть элементов массива (например, строкового, целочисленного и других типов, кроме структур) - присваивание нового значения изменяет эту переменную, но не изменяет соответствующий элемент массива. Например:
    FOR s IN Strings_array[]:
        s = s.Trim
        ... work with trimmed String_array[s.INDEX] ...
    ;
  • В случае массива структур, переменная цикла является макросом, обеспечивающим доступ к текущему элементу массива. Соответственно, изменение полей, или присваивание нового значения этой переменной меняет соответствующие (или все) поля текущего элемента структуры;
  • В любом случае, изменение переменной цикла не влияет на обращение к псевдо-функции переменная.INDEX - она всегда возвращает целочисленный индекс текущего (пробегаемого в цикле) элемента в массива.
 

I. 6. a. About assigning a value to a loop variable:

  • If a loop variable is changed in a certain range of values (not lists items of an array), then it is not allowed to change it in the loop;
  • In case when the loop variable iterates on all (or part of) items of an array (e.g. string or integer or other type array except an array of structures) - assigning new value to such variable changes it but does not affect the array item enumerating. E.g.:
    FOR s IN Strings_array[]:
        s = s.Trim
        ... work with trimmed String_array[s.INDEX] ...
    ;
  • In case of an array of structures, the variable of the loop actually is a macros providing the access to a current item array. So, changing its fields or assigning another structure to it changes correspondent array item as well as it was accessing;
  • In any case this does not affect the result of an expression Variable.INDEX returning an integer index of an array item currently iterating.

 

I. 7. Блок операторов PUSH

I. 7. PUSH statements block

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

 

Восстанавливающие действия гарантируются в том числе:

  • При выполнении принудительного выхода из блока из-за срабатывания операторов BREAK, CONTINUE
  • При выходе из функции оператором возврата ==>
  • При возникновении исключительной ситуации (например, по прерыванию длительной операции или операции, вызвавшей слишком глубокую рекурсию вызовов функций)

 

Синтаксис:
PUSH  переменная = выражение : тело  ;

или
PUSH  переменная : тело  ;

 

A PUSH statement is purposed to create procedural "brackets" with saving some state before and obligatory restoring this state after the block.

 

Restoring is always guaranteed:

  • When the block is left by a BREAK / CONTINUE statement.
  • When a function is left by a ==> (return) statement.
  • When an exceptional situation occur (e.g. when an operation is interrupting of a too long operation by the user, or an operation resulting too deep recursion of function calls)

 

Syntax:
PUSH  variable = expression : body  ;

or:
PUSH  variable : body  ;

 

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

 

  • On entry into the block a value of a variable is saved.
    E.g. in a local stack or in a local dynamic array.
  • Then new value is assigned to it (if specified).
  • When the finishing bracket is achieved (it is executed even in case of a failure), the value of the variable is restored.
  • Any simple or object data type scalar variable or an array item is allowed to be used as a PUSH block variable.
 

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

Например:

 

A special method with modifier POP(method2) can be called in the PUSH statement. At the end of such PUSH block, the method2 specified in parentheses (of the POP modifier of a method called in the PUSH), is called obligatory.

Such method2 should not have parameters, and it can not be called directly (as well as opening method, having the POP modifier, which therefore can be called in the PUSH statements). E.g.:


PUSH db.Transaction :
     // some database oper ations
     db.Commit
;

 


 

I. 8. Блок операторов DEBUG

I. 8. DEBUG statements block

 

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

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


DEBUG :
    тело  ;

 

A DEBUG block is intended for a temporary code injection which is required for debug purposes. In such blocks, levels of nesting blocks are not controlled. A compiler is always warning about such blocks not removed from a code. Such blocks should be removed when debugging is finished.

In DEBUG blocks it is possible to declare local variables as usual. But it is not allowed to use such variables out of DEBUG blocks (though it is allowed to use it in another DEBUG block in the same function).


DEBUG :
    body  ;

 

Если для правильной компиляции блоков DEBUG требуются дополнительные классы, отсутствующие в основном списке импорта, рекомендуется использовать оператор IMPORT со специальным модификатором DEBUG.

 

If there are required additional classes to compile DEBUG blocks, it is recommended to use a special directive IMPORT with the modifier DEBUG.

 

Для оператора DEBUG:

  • не учитываются уровни вложенности кода: компилятор не выдает предупреждений или ошибок по поводу чрезмерно большой вложенности самого оператора DEBUG или вложенных в него блочных операторов;
  • разрешается опускать двоеточие:
    DEBUG count_passes += 1 ;
  • если первый оператор в блоке DEBUG - это вывод в консоль строки, и первое выводимое значение - строчный литерал, то можно опустить символ << :
    DEBUG: "test!"#NL ;
    DEBUG "another test" ;
 

For the DEBUG statement:

  • nesting levels are not taking into account both for the DEBUG block itself and for its nesting code, too;
  • it is allowed to omit colon:
    DEBUG count_passes += 1 ;
  • if the first statement is the output to console with the first output string literal, than it is allowed to omit the symbol << :
    DEBUG: "test!"#NL ;
    DEBUG "another test" ;

 

I. 9. Блок операторов SILENT

I. 9. SILENT statements block

 

Предназначен для предотвращения выдачи компилятором предупреждений в некотором участке кода. Например, предупреждений о наличии отладочных блоков DEBUG:



>SILENT:
    DEBUG :
        тело ;
;

 

The block SILENT purposed to prevent the compiler from warnings on some block of code. E.g. about DEBUG statements in code.


SILENT:
    DEBUG :
        тело ;
;

I. 10. Оператор LIKE

I. 10. LIKE statement

 

(Не путать с операцией LIKE в выражении!)

 

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

Имеются правила:

  • Используемый блок должен быть помечен модификатором REUSED.
  • Если вставляется блок из другой функции, после LIKE записывается имя этой функции.
  • Далее следует мульти-точие (множество точек, количество которых не ограничивается- но не менее трёх), после чего записывается метка вставляемого блока кода.
  • Возможна вставка только кода из своего класса.
  • Вставляемый код должен быть расположен выше по тексту.
  • Сам вставляемый код не должен содержать операторов LIKE.
  • Вставка происходит "как есть", контроль синтаксиса и семантики происходит только при компиляции оператора LIKE, поэтому следует не допускать дублирования деклараций, имён переменных, переменных циклов (во избежание ошибок компиляции).
  • Количество повторных использований в операторах LIKE одного используемого блока кода никак не ограничивается.
  • На время вставки кода счётчик вложенности блоков сбрасывается в ноль (т.е. проблем со слишком большой вложенностью блоков CASE/FOR не будет, даже если суммарный уровень вложенности превысит допустимые три уровня).
 

(Do not mean the comparison operation LIKE between two strings in an expression!)

 

The LIKE statement is intended to insert earlier written code without changes in a position of the LIKE statement. An inserted code should be placed between two block comments (on the same nesting level). A label of the first block comment (together with a function name) is used to identify the code to insert. There are rules:

  • A reused block of code should be marked with a modifier REUSED .
  • If a block is inserted from another function, the name of the function is written following the LIKE keyword.
  • A multi-dot is written next (amount of dots is not restricted, at least three should present).
  • It is possible to insert code only from the same class.
  • Inserted code should be located above the LIKE statement.
  • An inserted block should not have LIKE statements itself (recursion or nesting are not possible like in macro).
  • An inserted code is injected "as is", its syntax and semantics are controlled only while compiling the LIKE statement. So do not duplicate variable names, declarations etc. to avoid compiler errors.
  • A reused block can be inserted so many times as it is needed, without restrictions.
  • For a time while a block is inserted by the LIKE statement, a counter of nesting FOR/CASE levels is reset to zero, so there are no problems of total nesting level exceeding allowed amount (3 nesting levels).


Пример:

 

 

An example:


...
---------------------------  'find a dot'
pos = s.Find(".")
CASE pos < 0 ? pos = s.Len ;
-------------------------------  'end of find'
...
...
LIKE ............. 'find a dot'   // place in the same function
or
LIKE Method1 ..... 'find a dot'   // place in another function
 

 

Дополнительно, при использовании оператора LIKE, можно выполнить замены некоторых фрагментов кода:


LIKE [method].......'label', BUT (образец1 ==> замена1) [*N1] [, (образец2 ==> замена2) [*N2] ]

 

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

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

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

 

 

Additionally, while calling the LIKE statement, it is possible to replace some fragments of code with other:

 

LIKE [method].......'label', BUT (pattern1 ==> replacement1) [*N1] [, (pattern2 ==> replacement2) [*N2] ]

 

Lists of replacements are enclosed into parentheses and listed via comma. A replacement should have a multiplier following its right bracket in form * number if there are several such patterns in code. The multiplier can be omitted only in case when only a single such pattern is there.

All the replacements are done just before compiling the LIKE statement having such replacements defined.

Both pattern and replacement strings can be enclosed into apostrophes. Only the string right to the symbol ==> can be empty, but patterns always should not be empty strings.

 

И, пожалуйста, помните:

  • Лучше использовать LIKE ......... 'имя', чем просто копировать код.
  • НО Лучше выносить общий код в отдельную функцию, если это возможно (нежели использовать LIKE).

Поэтому не злоупотребляйте использованием LIKE без необходимости.

 

And please remember:

  • It is better to use LIKE ..... 'name' then just to copy/paste a code.
  • BUT It is better to move a common code into separate functions if this is possible (then to use LIKE).

So do not overuse the LIKE statement without necessity.

 

I. 11. Оператор REVERT

I. 11. REVERT statement

 

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

Имеются правила:

  • Используемый блок должен быть помечен модификатором REUSED.
  • Если вставляется блок из другой функции, после REVERT записывается имя этой функции.
  • Далее следует мульти-точие (множество точек, количество которых не ограничивается- но не менее трёх), после чего записывается метка вставляемого блока кода.
  • Возможна вставка только кода из своего класса.
  • Вставляемый код должен быть расположен выше по тексту.
  • Сам вставляемый код может содержать только операторы присваивания, причём левая и правая сторона должны допускать переворачивание (хотя бы переходом к использованию сеттеров и геттеров).
  • Если вставляется код из другого метода, он не должен использовать обращений к локальным переменным (и параметрам).
  • Количество операторов REVERT для одного используемого блока кода никак не ограничивается.
 

The REVERT statement is intended to insert earlier written sequence of assignments reverting its direction of assignment in a position of the REVERT statement. An inserted code should be placed between two block comments (on the same nesting level). A label of the first block comment (together with a function name) is used to identify the code to insert. There are rules:

  • A reused block of code should be marked with a modifier REUSED .
  • If an inverting code block is from another function, the name of the function is written following the REVERT keyword.
  • A multi-dot is written next (amount of dots is not restricted, at least three should present).
  • It is not possible to revert code from another class.
  • Inverted code should be located above the REVERT statement.
  • An inverted block should contain only assignment statements, in those destination and source parts can be reverted (at least using correspondent getters / setters).
  • An inverted code should not use local variables (including parameters and a special variable RESULT).
  • A reused block can be inserted so many times as it is needed, without restrictions.
 

Пример:

 

An example:

 

----------------  'save form coordinates '
config.Set_i("Left", Left)
config.Set_i("Top", Top)
config.Set_i("Width", Width)
config.Set_i("Left", Height)
-------------------------------  'end of save'
...
...
REVERT .............  'save form coordinates'

 

 

$$STOP!!