Глава 1. Элементы языка zCode

1.1. Используемые символы

1.2. Типы данных

Данные (константы, переменные, массивы и поля баз данных) относиться к одному из четырех типов: числовому, символьному, датовскому и логическому (NUM,CHAR,DATE и LOG).

Числовой тип (NUM) имеет внутреннее представление в виде числа с плавающей точкой двойной точности (double). Это дает возможность оперировать с числами, имеющими до 18 значащих десятичных цифр.

Символьный тип (CHAR) служит для описания строк символов длиной до 64 килобайт.

Датовский тип (DATE) служит для задания дат. Данные этого типа имеют длину 8 байт и хранятся в формате 'YYYYMMDD' ('ГГГГММДД').

Логический тип (LOG) описывает однобайтовые злементы, принимающие значение .TRUE. (.T.) или .FALSE. (.F.), что соответствует во внутреннем представлении 1 и 0.

1.3. Константы

Различают следующие типы констант: числовые, символьные и логические.

Числовая константа - десятичное число в виде целой или действительной величины со знаком или без знака. Может иметь до 18 значащих цифр. Поддерживается также формат с экспонентой, т.е. в конце числа может быть указано En или en, где n -целое число со знаком или без знака (это соответствует умножению числа на 10 в степени n).

Примеры: 115.75, -0.025, .075, -85, 2.1e-5, .23E3

Символьная константа (строка) - последовательность символов, заключенных в кавычки (" ") или апострофы (' '). Длина константы - до 64 килобайт.

Примеры:
      "Это строка символов",
       ""  -пустая строка,
       '------"123"---------' (кавычки в строке)

Логическая константа имеет вид (регистр букв не важен):

.TRUE. (или .t.) - истина
.FALSE.(или .f.) - ложь

1.4. Идентификаторы

Идентификатор задает имя объекта в программе и представляет собой последовательность букв (латинских и русских) и цифр. (Символ "_" относится к буквам; прописные и строчные буквы рассматриваются как различные символы). Идентификатор начинается с буквы или символа '_' (для глобальных переменных - с символа '@').
Длина идентификатора переменной (массива) - до 40 символов. Длина имен полей - до 10 символов.
На имена файлов (баз данных, индексов, кодовых таблиц и др.) накладываются ограничения, определяемые операционной системой.

1.5. Операции и выражения

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

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

Операции можно разделить на арифметические, строковые, операции с датами, операции отношений и логические операции.

Порядок выполнения (приоритет) операций :

1.  ()            Скобки

2.  **  ^         Степень
3.  * /           Умножение и деление
4.  + -           Сложение и вычитание (в т.ч. строк и дат)

5.  < > <= >=     Операции отношений
    =  #  <>
    $             Вхождение строки

6.  .NOT.         Логическое НЕ
7.  .AND.         Логическое И
8.  .OR.          Логическое ИЛИ

9.  ?:            Условная

10. => +>         Присваивание и накопление

1.5.1. Арифметические операции

        Описание (в порядке приоритетов)   Примеры
-------------------------------------------------------------------
1.  ()       Для групповых выражений       (4-3) * (12/N1)
2.  **, ^    Возведение в степень          3**2 + 2^3
3.  *,  /    Умножение и деление           2*7 + 8/4
4.  +,  -    Сложение и вычитание          4+15 - N1

Арифметические операции используются с числовыми данными.

1.5.2. Строковые операции

        Описание                           Примеры
-------------------------------------------------------------------
  +     Объединение (конкатенация) строк   '123  '+'45' ->'123  45'

  -     Объединение строк с переносом      '123  '-'45' ->'12345  '
        концевых пробелов первой строки
        в конец итоговой строки

  $     Сравнение. Проверяет вхождение     '34' $ 'ABC34D' -> .T.
        первой строки во вторую

1.5.3. Операции с датами

        Описание             Примеры
------------------------------------------------------------
  +     Сложение        date()+20
                      /* к текущей дате прибавить 20 дней */

  -     Вычитание       date()-20
                      /* из текущей даты вычесть 20 дней */
                        date()-ctod('20000209')
                      /* разница 2-х дат в днях */

1.5.4. Операции отношений

         Описание               Примеры (для всех результат =.T.)
-----------------------------------------------------------------
  <      Меньше, чем            (12+3)<43
  >      Больше, чем            'ABC'>'AB1'
  =      Равно                  'ABC'='AB'
  <> #   Не равно               'AB'#'ABC'
  <=     Меньше или равно       (12+3)<=43
  >=     Больше или равно       date()+20>=date()
Операции отношений используются со всеми типами данных и возвращают логическое значение.
Сравнение символьных строк выполняется лексикографически по длине второй строки (справа от знака отношения), остаток левой строки игнорируется (поэтому 'ABC'='AB', но 'AB'<'ABС'). Это позволяет искать данные по неполному ключу.

1.5.5. Логические операции

   Описание (в порядке приоритетов)   Примеры
-----------------------------------------------------------------
1.  ()    Для групповых выражений     (@L1.or.A2>30) .and. @L2
2. .NOT.  Логическое отрицание        .not. S1 $ 'ABCD'
3. .AND.  Логическое И                A1 > 10 .and. @L1
4. .OR.   Логическое ИЛИ              A1 < 20 .or. @L1
Логические операции используются со всеми типами данных и возвращают логическое значение.

1.6. Операторы

Оператор может занимать одну или более строк. На одной строке может быть несколько операторов. Друг от друга операторы отделяются точкой с запятой (;).

Можно выделить следующие виды операторов:

- Вызов функции (процедуры);
- Операторы присваивания и накопления;
- Условный оператор (?);
- Оператор CYCLE;
- Условный WHILE;
- Составной оператор (блок);
- Пустой оператор;
- Прочие операторы (см. следующие главы).

  • Вызов функции (процедуры) имеет вид:
  • Имя_функции (аргумент1, ..., аргументN)

    Функция (процедура) может быть встроенной (стандартной) и пользовательской (описанной с помощью оператора PROC). Аргументы (фактические параметры) представляют собой выражения соответствующих типов и передаются по значению.

        /* пример вызова */
        dks_init( Num_pos + 1, ' ')  
    

  • Составной оператор (блок) состоит из нескольких операторов, заключенных в фигурные скобки { } и разделенных точкой с запятой (;).

  • Пустой оператор состоит из точки с запятой (;) и используется для указания отсутствия действия.

    1.6.1. Операторы присваивания и накопления

  • Оператор присваивания имеет вид:
  • Выражение => Идентификатор

    Оператор присваивания передает значение левой части в правую часть.

    Левая часть представляет собой поле базы данных,переменную либо вычисляемое выражение. Правая часть может преставлять собой поле базы данных либо переменную.
    Присвоение определено для любых типов выражений (LOG, NUM, CHAR, DATE). Типы левой и правой частей должны совпадать.

    Пример:
          @S0 + Rtrim( old->FIO) => new->FIO ;  /* CHAR тип */
          "Символьная константа" => @S2 ;       /* CHAR тип */
          old->Date + 10 => new->Date ;         /* DATE тип */
          a > b => @L0                          /* LOG тип */
    
  • Оператор накопления имеет вид:
  • Выражение +> Идентификатор

    Операция накопления определена только для числовых значений и заключается в добавлении вычисленного значения левой части оператора в правую часть.

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

    Примеры:
                 1 +> count [1] ; /* добавление единицы к элементу массива */
                 Sum +> ALL_Sum   /* накопление общей суммы в перемеменной */
    

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

    0 => Num1 => CODE1 /* обнуление переменных */

    Данный оператор по своему действию аналогичен двум операторам:

    0 => Num1 ; 0 => CODE1

    Операции присваивания и накопления в цепочке могут чередоваться, например :

    Num1 +> @1 => @2 /* одновременное присваивание и накопление */

    Данный оператор по своему действию аналогичен двум операторам:

    Num1 +> @1 ; Num1 => @2 /* но не Num1 +> @1 ; @1 => @2 !!! */

    Каждому последующему операнду в цепочке присваивается значение не предыдущей переменной по цепочке, а значение левой части данного оператора в целом. (Таким образом, системной переменной @2 в последнем примере будет присваивано значение Num1, но не значение переменной @1).

    1.6.2. Условный оператор

    Условный оператор имеет вид:

    логич_выр ? оператор1 [: оператор2 ]

    где

    логич_выр - любое допустимое выражение языка, возвращающее логическое значение;
    оператор1 - простой или составной оператор, выполняемый если логич_выр истинно;
    оператор2 - простой или составной оператор, выполняемый если логич_выр ложно (может отсутствовать).
      NM > 5 ? { 0 => COD ; WRITE() } 
    
    Это означает, что если поле NM имеет значений больше 5, то
    обнуляется поле COD и производится запись в базу нового
    значения текущей записи.
    
      NM > 5 .and. Sum < 100 ?
        { 0 => COD ; WRITE() } : Sum +> ALL_Sum 
    
    Это означает, что если NM > 5 и SUM <100, то обнуляется
    поле COD и производится запись в базу нового значения
    текущей записи, в противном случае в переменную ALL_Sum
    добавляется значение переменной Sum.
    
    

    1.6.3. Оператор CYCLE

    Оператор CYCLE позволяет организовать цикл выполнения одного или нескольких операторов и имеет вид:

    CYCLE (нач_знач, кон_знач) тело_цикла

    где

    нач_знач, кон_знач - целочисленные выражения, задающие начальное и конечное значение переменной цикла. В качестве переменной цикла неявно используется системная переменная @J.
    тело_цикла - простой или составной оператор, выполняемый в цикле.
    Пример:
    -------
      /* Мax уровень налогов =
         Max поля '1' код. таблицы kptab */
    
      0 => Max_Level ;
      Cycle( 1, Codemax( kptab))
      {
        Val( Codefield( kptab, @J, '1')) => Cur_Level ;
        Cur_Level > Max_Level ? Cur_Level => Max_Level ;
      }
    

    1.6.4. Оператор WHILE

    Оператор WHILE позволяет организовать цикл выполнения одного или нескольких операторов и имеет вид:

  • WHILE (логич_выр) тело_цикла
    или
  • DO тело_цикла WHILE (логич_выр)

    где

  • логич_выр - любое допустимое выражение языка, возвращающее логическое значение;
    тело_цикла - простой или составной оператор, выполняемый пока значение логич_выр истинно.

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

    Примеры:
    --------
      1  => EXT_ ; .T. => @L0  ;
      While ( @L0 )
      { /* пытаемся найти вексель в картотеке */
        Seek( blanks:bl_id, script->Type +
           STR(script->Num_fr+@J,sizeof(blanks->Number)) +
           script->Series + STR(script->Nominal,15,2) +
           STR(EXT_,Sizeof(blanks->Ext))
        ) ;
        /* если у бланка пуста ссылка на документ приема ,
           то остаемся на этом бланке, иначе продолжаем цикл */
        Empty(blanks->Nknd)
        ? .F. => @L0  :  1 +> EXT_ ;
      } /* Конец цикла WHILE */
    
    /* ---- Удаление пробелов в начале строки -----*/
      0 => Nm1; Len(Per) => Nm2;
      do 1 +> Nm1 while(Nm1 < Nm2 .and. Substr(Per,Nm1) = " ");
      Substr(Per,Nm1) => Per;