$$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 '--')
    • '*'
    • '/'
    • '%'
    • '|'
    • '&'
    • '>'
    • '='
    • '#'
 

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

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

  • или предыдущая строка завершается символами '(', '[', ','
  • или следующая строка не пуста и не может начинать новый оператор, т.е.:
    • не начинается с буквы,
    • с символа '{' (не начинает декларацию именем типа в фигурных скобках),
    • с символа '[' (не является условием для ветви 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 '{' (a variable declaration can start from a type name in figure brackets),
    • a symbol '[' (not a condition for a CASE statement),
    • a symbol '<' (an output statement can start from a symbol '<<'),
    • symbols '.' or ';' (it is not a separate ending of a code block or a function),
    • a symbol '--' (so it is not a block comment -------------- 'text').

 

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). Для отладки кода может использоваться блочный оператор 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). 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-подобного языка программирования).
  • Комментарии до конца строки, начинающихся с двойной дроби (//). Не завершают текущий оператор.
  • Комментарии, начинающиеся двумя символами --, имеют форму
    -------------- 'текст'
    и служат для разбиения блоков на разделы. Так же, используются в декларациях классов и в оглавлении модуля.
    Такой блочный комментарий может начинать переиспользуемый блок кода (операторы LIKE, REVERT). В этом случае он должен иметь модификатор REUSED (записывается через запятую после метки). Например:
    ---------------- 'start extracting', REUSED
  • 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).
  • Comment to the end of line (starting 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_record} 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 and collections 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
  • Только одно исключение: переменные цикла могут иметь только краткое имя:
    FOR x IN M[] : ... ;
  • Если имя должно заканчиваться символом подчёркивания (признак слабой ссылки), то подчёркиванием должны заканчиваться обе части имени, например:
    List_|of_items_[]
  • Для имён классов, записей и перечислений действует то же правило, и при подсчёте длины имени окружающие фигурные скобки не учитываются:
    {My_class|_to_do_something}
 

While declaring a variable, a function, a data type, those things can have two names - a short and a long. The first the short name is written, then, if present, a long name is following separated by the symbol '|'. So there are following rules:

  • The whole name length should not be less then 8 characters: S|ample_val
  • Only one exclusion for variable names: FOR loop variables can have only short name, even short, e.g.:
    FOR x IN M[] : ... ;
  • 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_[]
  • For class names, records and enumerations the same rule is active, and figure brackets are not accounting in names lengths:
    {My_class|_to_do_something}

 

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 :

 

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

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

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

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 do not change a result of the program (but can take an effect of changing its size / working speed, either increasing or decreasing it).

 

 

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) для массива.
  • Если левый операнд не указан, то это оператор записи строки в выходной поток (в консоль - для консольной программы).

 

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 not present, then such statement means writing a string to an output stream (to the console for a console application).

 

Аналогичная операция >> используется как замена вызова функции read для операнда слева (а так же для добавления нового объекта в массив объектов, см. в разделе, посвященном классам и объектам).
  • Операторы ввода-вывода << и >> могут комбинироваться в одном операторе в виде
    << строка [>> переменная] [>> переменная] ...
    Например:
    << 'Введите число:' >> Number

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).

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

 

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

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

 

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

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

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

     

    • если употреблено в левой части обычного оператора присваивания(a = b, a += b, a *= b, и т.п.);
    • является левой частью обычного оператора отправки данных (a << b, a[] << b, в том числе в случае, когда оператор '<<' заменяет вызов метода Write);
    • если в операторе в цепочке разыменования полей/методов использован псевдо-оператор '...' в позиции одинарной точки (например:
      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.);
    • 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;
    • if a pseudo-operator '...' is used in place of a single "dot" operation in a chain of unnamings/indexation 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. 2. e. Операторы инкремента и декремента

I. 2. e. Increment and decrement

 

Операторы ++ и -- могут использоваться для целочисленных переменных в постфиксном виде:

  • как отдельные операторы,
  • либо внутри индексов массивов,
  • и в других частях выражений.
  • Изменение значения переменной гарантируется только по окончании выполнения всего оператора.
  • Изменение одной и той же переменной несколько раз операциями ++ / -- в одном операторе считается ошибкой.
  • Не разрешается использовать операции ++/-- в выражении с условно вычисляемыми частями (имеющими операции && / ||).

 

 

Operators ++ and -- can be used for integer variables in a postfix form:

  • as separate statements
  • or in array indexes
  • in other parts of expression.
  • Changing the variable value is provided only after the statement is executed.
  • Changing the same variable more then once via ++ / -- in a single statement is not allowed.
  • It is not allowed to use operations ++/-- in an expression containing also operations && / ||.

 

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

I. 3. Expressions

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

 

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

 

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

 

 
Operator Description Group
- Negation Arithmetic operations (with numbers), result is a number
* / % Multiplication, division, rest of division
+ - Adding, subtracting
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 (for ??)
< <= > >= == != ?? Compares
~ Bitwise NOT Bitwise operations with integers, result again is integer

 

& ^^ Bitwise AND, eXclusive OR (xor)
| Bitwise OR
! Logical NOT Logical operations with Boolean, result also is Boolean
&& Logical AND (&&)
|| Logical OR (||)
~ Internal assignment Always in form (expression ~NName)
  • 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.

 

 

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

I. 3. a. Checking conains of an item

 

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

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

 

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

Операция 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.

 

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 позволяет продолжить или остановить внешний цикл из тела вложенного напрямую.

  • 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 an infinite FOR loop (having the modifier INFINITE). It is only possible to terminate such infinite 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.
 

 

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

I. 5. Conditional statement CASE

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

 

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:

RECORD {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}, STATIC :
   -------------------------------- 'direct version'
   CASE A == 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}, STATIC :
   ----------------------- 'sequentional version'
   REAL d|escriminant = B * B - 4 * A * C
   CASE ? ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
   [A == 0] ? ==>                                         
   [d == 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 ; . ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█

 

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

I. 6. FOR loop statements

 

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


    FOR переменная IN массив[] : тело ; ▄▄▄▄
 
 

 

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

 

FOR variable IN array[] : body ; ▄▄▄▄

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

 

  • The loop variable of such loop statement is always has the same type as a enumerating array items data type.
  • 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.
  • It is possible to apply an embedded function Index to it (it returns an index of the variable in the enumerating array).
  • By default, all the items are enumerated from the starting to the ending.
  • 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.
  • A variable of a FOR loop with a range can not be changed in a loop body (and used as a usual variable).
  • 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, INFINITE : тело цикла ; ▄▄▄▄

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

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

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

 

 

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.

 

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 operations
     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 требуются дополнительные классы, отсутствующие в основном списке импорта, рекомендуется использовать специальный оператор DEBUG IMPORT для добавления таких классов в импорт, специально для компиляции операторов DEBUG.

 

If there required additional classes to compile DEBUG blocks, it is recommended to use a special directive DEBUG IMPORT to declare such classes rather the add them into usual IMPORT list.

 

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

I. 9. LIKE statement

 

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

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

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

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 not possible to insert code from another 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).

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

 

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. 10. Оператор REVERT

I. 10. 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!!