Мельница данных- Язык PascalScript  (раздел целиком)  (29.03.2020)
Язык PascalScript

На языке PascalScript на платформе "Мельница данных" описываются тела методов и выражения. Выражения используются в условиях отбора объектов определенного класса при их отображении в представлениях, а также как встраиваемые выражения, которые могут служить членами класса для чтения свойств.

Здесь и далее зарезервированные слова выделены жирным шрифтом.


1. Структура программного блока тела метода
  [Описание переменных]
  begin
    //Операторы
  end;

Комментарии расположены между символами { и } либо от символов // до конца строки.


2. Описание переменных
var
    Имя переменной[, Имя переменной…]: Тип;
    Имя переменной[, Имя переменной…]: Тип;
    ...
Имя переменной должно быть идентификатором (последовательность символов a-z, A-Z, 0-9, _). "Тип" может быть одним из следующих:
  • integer - определяет переменные целочисленного типа;
  • string[целое_число] - определяет переменные строкового типа с заданной максимальной длиной; максимальная длина задается в квадратных скобках и обязательна для задания;
  • float - определяет переменные вещественного типа;
  • date - определяет переменные типа "дата";
  • time - определяет переменные типа "время";
  • datetime - определяет переменные типа "дата со временем";
  • boolean - определяет переменные логического типа;
  • blob - определяет переменные типа больших двоичных объектов;
  • Имя класса - определяет переменные-ссылки на экземпляры соответствующих классов;
       
  var
   I: integer;
   LSomeObject: TObject;
   LStart, LStop: datetime;
   LNewName: string[64];

3. Операторы PascalScript

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


3.1. Составной оператор
begin
  //Другие операторы
end
Операторы, размещенные внутри составного оператора, разделяются точкой с запятой. Никаких ограничений на состав операторов и количество уровней вложенности не накладывается.
       
begin
  Result := LCurrentValue;
  Exit;
end;

3.2. Оператор присваивания
Выражение1 := Выражение2

Присваивает значение выражения Выражение2 выражению Выражение1. Типы Выражения1 и Выражения2 должны быть совместимы (совпадать по классу домена либо оба быть числовыми). Для этого на Выражение1 (стоящее слева от знака равенства, lvalue) накладывается ряд ограничений. Это выражение должно быть:

  • Полем или свойством экземпляра класса
  • Локальной переменной
  • Параметром
  • Зарезервированной переменной Result
       
LObject.Name := 'Новое имя';
       
Result := 25;
       
LStartTime := StrToDateTime('01.01.2006 00:00:30'); 
       
var
  LObject: TObject;
  LClass: TClass;
  I: Integer; 
  F: Float;
begin
  I := F;  //неверно
  F := I;  //верно
  LObject := LClass; //верно
  LClass := LObject; //неверно. Должно быть LClass := (LObject as TClass);
end;  

3.3. Оператор вызова
ИмяПроцедуры [(Параметр1, Параметр2 ...)]

"ИмяПроцедуры" должно быть:

  • Именем метода класса и вызываться с указанием класса либо экземпляра;
  • Именем метода экземпляра и вызываться с указанием экземпляра;
  • Именем метода своего класса либо предка и вызываться без указания спецификаторов.
Порядок и количество параметров в операторе вызова должны строго совпадать с описанием метода.

       
  //метод класса, указан класс
  LList := TObjectList.Create(Name, Description, TObjectList, nil, nil, Folder);    

  //метод экземпляра, указан экземпляр. Метод не имеет параметров.
  LList.Destroy;

  //свой либо унаследованный метод
  BuildDefaultActions(Name, True); 

3.4. Оператор ветвления
if Выражение then
  //Оператор1
[else
  //Оператор2]

Выражение должно быть логического типа. В случае если значение Выражения истинно, выполняется Оператор1. Часть else является необязательной и относится к последнему оператору if, не имеющему таковой. В случае ее наличия Оператор2 выполняется, если значение Выражения ложно.

       
if LIndex > 25 then
  raise 'Индекс слишком большой.';
       
if LMonth = 'январь' then
  January
else if LMonth = 'февраль' then
  February
else   
  OtherMonth;  //обратите внимание на точки с запятой.

3.5. Оператор выбора
case Выражение of
  Значение1: //Оператор1
  Значение2: //Оператор2
  ...
[else
  //Оператор ]
end

Заменяет каскад операторов if. Значение Выражения должно быть числового типа. Часть else выполняется в случае, если Выражение не равно ни одному из перечисленных вариантов. Эта часть не является обязательной.

       
сase LIndex of
  0: ZeroIndex;
  1,2,3: SmallIndex;
  4,5,6,7,8,9,10: BigIndex;
else
  raise 'Слишком большой или отрицательный индекс.';
end;

3.6. Цикл с предусловием
while Выражение do
  //Оператор

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

       
while LList.Count > 0 do
  LList.GetItem(0).Destroy;

while True do
begin
  LValue := LValue.NextValue;
  if LValue.Value > 10 then
  begin
    Result := LValue.Value;
    exit;
  end;
end;

3.7. Цикл с постусловием
repeat
  //Операторы
until Выражение

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

       
repeat
  Result := Result + 1;
  LObject := LObject.Parent;
until LObject = nil;

3.8. Цикл с параметром
for Параметр := Выражение1 (to|downto) Выражение2 do
  //Оператор

Параметр цикла обязан быть простой локальной переменной. Функционально цикл с параметром эквивалентен циклам:

  • Для формы to
    Параметр := Выражение1;
    while Параметр <= Выражение2 do
    begin Оператор; Параметр := Параметр + 1; end;
  • Для формы downto
    Параметр := Выражение1;
    while Параметр >= Выражение2 do
    begin Оператор; Параметр := Параметр - 1; end;
Если Выражение1 равно Выражению2, тело цикла будет выполнено один раз.

       
for I := LList.Length - 1 downto 0 do
// если LList.Length = 0, тело цикла ни разу не будет выполнено.
begin
  LClass := LList.GetItem(I);
  LMethod := any(TMethod with (Name = LName) and (Master = LClass));
  LParamList.Add(any(TMethod with (Name = LName) and (Master = LClass)));
end; 

3.9. Цикл по экземплярам
for each Параметр of ИмяКласса [with Выражение]
       [by [-] Выражение [, [-] Выражение]] do
         //Оператор

Цикл осуществляется по выборке среди экземпляров класса ИмяКласса, для которых истинно Выражение. Если Выражение не задано, то по всем экземплярам. Ссылка на текущий в рамках цикла экземпляр присваивается в локальную переменную Параметр. Выражение должно определяться относительно переменной Параметр. Выраженния, следующие за ключевым словом by, определяют порядок обхода экземпляров. Знак "-" перед выражением (любого типа) определяет обратный порядок обхода.

       
for each LOption of TOption with LOption.Domain.Required do
    // для каждой настройки, домен которой обязателен
  LOption.SetDefaultValue;

3.10. Оператор прекращения цикла
break

Происходит немедленный выход из цикла. Выполняется финализация операторов защиты завершения, которыми защищено тело цикла. Допустим только в теле цикла с предусловием, цикла с постусловием, цикла с параметром или цикла по экземплярам.


3.11. Оператор выхода из подпрограммы
exit

Происходит немедленный выход из программного блока. Выполняется финализация операторов защиты завершения.


3.12. Оператор защиты завершения
try
  //Операторы1
finally
  //Операторы2
end

Выполняются операторы Операторы1, разделенные точкой с запятой. В случае возникновения исключительной ситуации управление сразу передается на Операторы2, и после их выполнения исключение остается активным. Если исключения не произошло, выполняются Операторы2. Если среди Операторов1 встречается оператор exit, то Операторы2 все равно выполняются.

       
//создание временного объекта-списка
LList := TObjectList.Create(Name, Description, TObjectList, nil, nil, Folder);    
try
  LList.Add(LValue);
  Exit;
finally
  //гарантированное уничтожение созданного объекта независимо от исключений.
  LList.Destroy;
end;

3.13. Оператор обработки исключительных ситуаций
try
  //Операторы1
except
  //Операторы2
end

Выполняются операторы Операторы1. В случае возникновения исключительной ситуации управление передается на Операторы2. Если исключительных ситуаций не возникло, Операторы2 не выполняются никогда. При передаче управления на Операторы2 исключительная ситуация деактивирована. Для ее повторного возбуждения можно воспользоваться оператором возбуждения исключения без указания текстовой строки сообщения.

       
try
  LObject.NeverTouch := True;
  LObject.ExecuteCoolMethod; //если метод выполнен неудачно
except
  LObject.NeverTouch := True;  //установить флаг и ничего не сообщать пользователю.
end;
       
try
   LObject.ExecuteCoolMethod; //если метод выполнен неудачно
except
   LObject.Destroy; //удалить неудачный объект
   raise;           // продолжить обработку исключения.
end;

3.14. Оператор возбуждения исключения
raise [Выражение]
Возбуждает исключение, которое, если не было обработано блоком except оператора обработки, дойдет до пользователя. Пользователь увидит сообщение, определяемое Выражением. Выражение должно иметь строковый тип и является обязательным для всех случаев, кроме части except оператора обработки исключений.

3.15. Оператор унаследованного вызова
inherited

Работает только в унаследованном переопределенном методе. Вызывается метод предка с параметрами, заданными в параметрах к моменту вызова. Если программный блок представляет собой тело функции, то в псевдопеременной Result будет результат выполнения метода предка.

       
// в теле конструктора
Name := 'Object name';
Description := 'Object description';
inherited; //вызов предка с параметрами Name и Description, 
           //заданными двумя предыдущими операторами. Ссылка на 
           //созданный объект лежит в 
           //псевдопеременной Result
Result.Name := 'New name';

4. Выражения и операции

4.1. Состав выражения
Любое выражение имеет тип. Выражения состоят из следующих элементов:
  • Целая числовая константа (0 3 234);
  • Вещественная числовая константа. Дробная часть отделяется от целой точкой (".") (3.14 2.71);
  • Строковая константа. Заключается в апострофы. ('Some string' '10', '01.01.2006' 'now');
  • Логическая константа (True False);
  • Безтиповая (любого типа) константа nil;
  • Зарезервированное слово Self. Обозначает разный объект в зависимости от контекста:
    • В методах класса кроме конструктора - использование запрещено.
    • В методах экземпляра - всегда экземпляр, для которого вызван метод.
    • В конструкторе - до вызова унаследованного метода значение не определено. После вызова - ссылка на сконструированный объект.
    • В выражениях условий отбора - объект, для которого принимается решение о его вхождении в отбор.
  • Квалификатор.
  • Агрегат.

4.2. Квалификатор

Квалификатор обозначает объект, переменную, параметр, свойство, поле, вызов функции. Квалификатор состоит из идентификаторов, разделенных точкой.

        Result
        AName
        Caption
        LObject.Name
        LObject.Parent.Name
        LObject.ChildCount
        LObject.HasAsParent(LOtherObject)

При интерпретации квалификатора используется следующий порядок разбора идентификатора:

  1. Контекстная переменная (для выражений условий отбора доменов)
  2. Локальная переменная
  3. Параметр
  4. Имя элемента перечисления
  5. Имя класса. Вне контекста означает ссылку на соответствующий объект класса TClass
  6. Имя поля
  7. Имя метода
  8. Имя свойства

При интерпретации квалификатора внутри выражения агрегата правила разбора идентификатора изменяются:

  1. Контекстная переменная (для выражений условий отбора доменов)
  2. Имя элемента перечисления
  3. Имя класса. Если это имя агрегируемого класса, то дальнейшие разыменования относятся к агрегируемому объекту
  4. Имя поля
  5. Имя метода
  6. Имя свойства
  7. Локальная переменная
  8. Параметр


4.3. Агрегат

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

  • any - первый попавшийся объект. Результат имеет тип ссылки на объект агрегируемого класса.
           
    any(TObject with Master = Self.Parent)  
    //первый попавшийся объект, имеющий значение 
    //свойства Master равным значению свойства 
    //Parent текущего (контекстного) объекта.
    
  • count - количество объектов. Результат имеет целочисленный тип.
           
    count(TObject with Master = Self.Parent) 
    //количество объектов, имеющих значение свойства 
    //Master равным значению свойства Parent 
    //текущего объекта.
    
  • sum - сумма значений свойства, поля или функции объектов. Результат имеет тип суммируемого поля, свойства или функции
           
    sum(TExam.Mark with Master = LStudent) //сумма 
    //баллов студента по его испытаниям
    
  • max, min - соответственно максимальное и минимальное значений свойства, поля или функции объектов. Результат имеет тип агрегируемого поля, свойства или функции
           
    min(TObject.Created) // момент создания первого 
    //объекта Системы.
    

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

  1. Контекстная переменная (для выражений условий отбора доменов)
  2. Имя элемента перечисления
  3. Имя класса. Если это имя агрегируемого класса, то дальнейшие разыменования относятся к агрегируемому объекту
  4. Имя поля
  5. Имя метода
  6. Имя свойства
  7. Локальная переменная
  8. Параметр


4.4. Операции

Операции связывают элементы выражений.

Таблица операций в порядке приоритета:
Левый
операнд
Правый операнд
Целый Вещест-
венный
Дата Время Дата со временем Логи-
ческий
Строковый Объект nil
not
Нет ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено Логи-
ческий
ЗапрещеноЗапрещеноЗапрещено
* (звездочка)
Целый Целый Вещест-
венный
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Вещест-
венный
Вещест-
венный
Вещест-
венный
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Дата ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Время ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Дата со временем ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Логи-
ческий
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Строковый ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Объект ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
nil ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
/ (слэш, дробь)
Целый Вещест-
венный
Вещест-
венный
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Вещест-
венный
Вещест-
венный
Вещест-
венный
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Дата ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Время ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Дата со временем ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Логи-
ческий
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Строковый ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Объект ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
nil ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
div
Целый Целый ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Вещест-
венный
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Дата ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Время ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Дата со временем ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Логи-
ческий
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Строковый ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Объект ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
nil ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
and
Целый ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Вещест-
венный
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Дата ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Время ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Дата со временем ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Логи-
ческий
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено Логи-
ческий
ЗапрещеноЗапрещеноЗапрещено
Строковый ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Объект ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
nil ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
or
Целый ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Вещест-
венный
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Дата ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Время ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Дата со временем ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Логи-
ческий
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено Логи-
ческий
ЗапрещеноЗапрещеноЗапрещено
Строковый ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Объект ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
nil ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
+ (плюс)
Целый Целый Вещест-
венный
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Вещест-
венный
Вещест-
венный
Вещест-
венный
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Дата Дата Дата со временем Запрещено Дата со временем ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Время Время Время Дата со временем Время Дата со временем ЗапрещеноЗапрещеноЗапрещеноЗапрещено
Дата со временем Дата со временем Дата со временем Запрещено Дата со временем ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Логи-
ческий
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Строковый ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено Строковый ЗапрещеноЗапрещено
Объект ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
nil ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
- (минус)
Целый Целый Вещест-
венный
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Вещест-
венный
Вещест-
венный
Вещест-
венный
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Дата Дата Дата со временем Целый Дата со временем Вещест-
венный
ЗапрещеноЗапрещеноЗапрещеноЗапрещено
Время Время Время Дата со временем Время Дата со временем ЗапрещеноЗапрещеноЗапрещеноЗапрещено
Дата со временем Дата со временем Дата со временем Вещест-
венный
Дата со временем Вещест-
венный
ЗапрещеноЗапрещеноЗапрещеноЗапрещено
Логи-
ческий
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Строковый ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Объект ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
nil ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
=, <> (равно, не равно)
Целый Логи-
ческий
Логи-
ческий
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено Логи-
ческий
Вещест-
венный
Логи-
ческий
Логи-
ческий
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено Логи-
ческий
Дата ЗапрещеноЗапрещено Логи-
ческий
Запрещено Логи-
ческий
ЗапрещеноЗапрещеноЗапрещено Логи-
ческий
Время ЗапрещеноЗапрещеноЗапрещено Логи-
ческий
ЗапрещеноЗапрещеноЗапрещеноЗапрещено Логи-
ческий
Дата со временем ЗапрещеноЗапрещено Логи-
ческий
Запрещено Логи-
ческий
ЗапрещеноЗапрещеноЗапрещено Логи-
ческий
Логи-
ческий
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено Логи-
ческий
ЗапрещеноЗапрещено Логи-
ческий
Строковый ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено Логи-
ческий
Запрещено Логи-
ческий
Объект ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено Логи-
ческий
Логи-
ческий
nil ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено Логи-
ческий
<, >, <=, >= (меньше, больше, меньше либо равно, больше либо равно)
Целый Логи-
ческий
Логи-
ческий
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Вещест-
венный
Логи-
ческий
Логи-
ческий
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Дата ЗапрещеноЗапрещено Логи-
ческий
Запрещено Логи-
ческий
ЗапрещеноЗапрещеноЗапрещеноЗапрещено
Время ЗапрещеноЗапрещеноЗапрещено Логи-
ческий
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Дата со временем ЗапрещеноЗапрещено Логи-
ческий
Запрещено Логи-
ческий
ЗапрещеноЗапрещеноЗапрещеноЗапрещено
Логи-
ческий
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено Логи-
ческий
ЗапрещеноЗапрещеноЗапрещено
Строковый ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено Логи-
ческий
ЗапрещеноЗапрещено
Объект ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
nil ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
is
Целый ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Вещест-
венный
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Дата ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Время ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Дата со временем ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Логи-
ческий
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Строковый ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Объект ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено Логи-
ческий
Запрещено
nil ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
as
Целый ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Вещест-
венный
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Дата ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Время ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Дата со временем ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Логи-
ческий
ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Строковый ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено
Объект ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено Объект Запрещено
nil ЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещеноЗапрещено


4.4.1. Особенности применения операций
  1. Приоритет сравнений ниже приоритета операций булевой логики. Поэтому выражение
    LObject.Master = LMaster and LObject.Parent = LParent
    будет интерпретироваться следующим образом:
    LObject.Master = (LMaster  and LObject.Parent) = LParent
    и вызовет ошибку компиляции из-за применения операции and к объектам. Необходимо писать:
    (LObject.Master = LMaster) and (LObject.Parent = LParent)
  2. Любое значение (выражение любого типа) сравнивается с безтиповой константой nil:
          LObject := any(TObject with Name = 'Some name');
          if LObject = nil then
             .....
          
  3. Операции "Унарный минус" не существует. Для задания отрицательных констант пользуйтесь конструкцией 0-Значение:
    Result := 0-1;

5. Формальная грамматика
Goal: MethodBody | Expression;

MethodBody: [ConstantDeclaration] [VariableDeclaration] CompoundStatement ";";

ConstantDeclaration: "const" Ident ":" DomainSpecification ";" 
  [{Ident ":" DomainSpecification ";"}];

VariableDeclaration: "var" DomainDefinition [{DomainDefinition}];

DomainDefinition: Ident ":" DomainSpecification ";";

DomainSpecification: IntegerDomainDefinition
  | StringDomainDefinition
  | FloatDomainDefinition
  | DateDomainDefinition
  | TimeDomainDefinition
  | DateTimeDomainDefinition
  | BooleanDomainDefinition
  | BlobDomainDefinition
  | EnumerationDomainDefinition
  | Ident;

IntegerDomainDefinition: "integer";
StringDomainDefinition: "string" "[" Number "]";
FloatDomainDefinition: "float" ["(" Number ["." Number] ")"];
DateDomainDefinition: "date";
TimeDomainDefinition: "time";
DateTimeDomainDefinition: "datetime";
BooleanDomainDefinition: "boolean";
BlobDomainDefinition: "blob" | "clob";
EnumerationDomainDefinition: "(" Ident {"," Ident} ")";

CompoundStatement: "begin" Statement [{";" Statement}] "end";

Statement:
  | CompoundStatement
  | AssignmentStatement
  | InheritedStatement
  | CallStatement
  | IfStatement
  | CaseStatement
  | ForStatement
  | WhileStatement
  | RepeatStatement
  | TryFinallyStatement
  | TryExceptStatement
  | RaiseStatement
  | ForEachStatement
  | ExitStatement;

AssignmentStatement:  Qualifier ":=" Expression;

CallStatement: Qualifier;

InheritedStatement: "inherited";

IfStatement: "if" Expression "then" Statement ["else" Statement];

CaseStatement: "case" Expression "of" {CaseBranch} ["else" Statement ";"] "end";

CaseBranch: CaseLabel [{',' CaseLabel}] ":" Statement ";";

CaseLabel: Number | Ident;

ForStatement: "for" Ident ":=" Expression ("to"|"downto") 
  Expression "do" Statement;

WhileStatement: "while" Expression "do" Statement;

RepeatStatement: "repeat" Statement [{";" Statement}] "until" Expression;

TryFinallyStatement: "try" Statement [{";" Statement}] "finally" 
  Statement [{";" Statement}] "end";

TryExceptStatement: "try" Statement [{";" Statement}] "except" 
  Statement [{";" Statement}] "end";

RaiseStatement: "raise" [Expression];

ForEachStatement: "for" "each" Ident "of" Ident ["with" Expression] 
  ["by" Expression] "do" Statement;

ExitStatement: "exit";

Expression: ComparedExpression [{RelationOperation Expression}];

ComparedExpression: Addon [{AdditionOperaton ComparedExpression}];

Addon: Factor [{MultiplicativeOperation Addon}];

Factor: "(" Expression ")"
  | "not" Expression
  | Number ["." Number]
  | StringConstant
  | Qualifier
  | "nil"
  | "True"
  | "False"
  | "(" Expression "is" Ident ")"
  | "any" Aggregate
  | "count" Aggregate
  | "sum" Aggregate
  | "max" Aggregate
  | "min" Aggregate;

Aggregate: "(" Ident ["." Ident] ["with" Expression] ")";

Qualifier: QualifierPart [{"." QualifierPart}];

QualifierPart: Ident ["(" Expression [{", " Expression}] ")"]
  | "self"
  | "(" Qualifier "as" Ident ")";

RelationOperation: "<"
  | ">"
  | "<="
  | ">="
  | "="
  | "<>";

AdditionOperaton: "+"
  | "-"
  | "or";

MultiplicativeOperation: "*"
  | "/"
  | "div"
  | "and";

6. Соглашения

6.1. Соглашения о наименованиях

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

  • Имя класса должно начинаться с латинской буквы 'T'.
           
    Имя Наименование
    TObjectList Список объектов
    TLearnPlan Учебный план
  • Имя поля должно начинаться с латинской буквы 'F'.
           
    Имя Наименование
    FLearnPeriod Период обучения
    FExamMark Оценка за экзамен
  • Имя свойства не имеет префикса.
           
    Имя Наименование
    ExamKind Вид рубежного испытания
    ContactPhone Контактный телефон
    Если членом класса для чтения свойства является поля, то имя свойства должно повторять имя поля без префикса 'F'. Если членом класса для чтения свойства является метод, то имя поля должно повторять имя метода без слова 'Get'.
  • Имя параметра не имеет префикса.
           
    Имя Наименование
    OrderNumber Номер приказа
    ExamDate Дата проведения экзамена
    Параметры, используемые для инициализации значений полей, должны иметь имя, повторяющее имя поля без префикса 'F'. При компиляции тела метода, написанного на языке PascalScript имена параметров и имена свойств будут распознаваться в соответствии с порядком разбора идентификаторов, как это описано здесь и здесь.
  • Имена методов должны представлять собой императивный глагол на английском языке, выражающий смысл того, что метод делает. Имена методов не имеют префикса. Имена методов, используемых для получения значений свойств должны (как члены класса для чтения), должны начинаться со слова Get. Имена методов, используемых для установки значений свойств должны (как члены класса для записи), должны начинаться со слова Set.
           
    Имя Наименование
    CountMarkSumm Вычислить сумму баллов
    GetAge Получить значение возраста
    SetMark Установить значение оценки
  • Имена локальных переменных должны начинаться с латинской буквы 'L'.
            LMarkSumm (сумма баллов), LObjectCount (количество объектов).
  • Имена доменов должны начинаться с латинской буквы 'T'. В именах доменов допустимы пробелы. Рекомендуется к имени домена добавлять слово 'domain' (через пробел), а для обязательных доменов 'required domain' (через пробел) тогда, когда необходимо исключить возможность использования этих доменов в текстах на PascalScript. Первым словом в имени домена-ссылки должно быть имя класса домена. Исключением являются имена доменов, соответствующих простым типам данных без дополнительных ограничений. Имена таких доменов могут повторять имена типов языка PascalScript (Integer, Boolean, Float).
           
    Имя Класс домена Наименование
    TPrice domain Вещественный домен Цена
    TWeight required domain Целочисленный домен Вес (обязательный)
    Boolean Логический Логический
    TClassMember required domain Ссылка домен Член класса
  • Имена элементов перечислений должны иметь префикс из двух или трех символов, идентифицирующий соответствующий домен-перечисление. Префикс записывается строчными буквами. Например,
           
    Имя Наименование
    для домена TExamKind (вид испытания)
    ekTest зачет
    ekExam экзамен
    ekDifTest дифференцированный зачет
    для домена TAggregateKind (вид агрегата)
    agCount количество
    agSumm сумма
    agAverage среднее значение
    Настоятельно рекомендуется давать уникальные имена элементов перечислений в пределах всей системы.

6.2. Cтилевое оформление исходного кода

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


6.2.1. Использование строк, пробелов и отступов

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

Пробелы, запрещенные к использованию:

  • До или после точки "."
  • Между именем вызываемого метода и открывающей скобкой "("
  • После открывающей скобки "(" или перед закрывающей ")"
  • Перед точкой с запятой ";"
  • Перед двоеточием ":"
  • Перед запятой ","

Двоеточие для всех объявлений переменных не должно содержать перед собой пробелов и иметь один пробел после перед именем типа.

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

Существует несколько исключений из этого правила. Зарезервированные слова var, begin и end, относящиеся к программному блоку вцелом, всегда должны примыкать к левой границе. Код внутри блока begin..end должен иметь отступ два символа.

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

Нельзя переносить строки в тех местах, где не допускаются пробелы, например между именем метода и открывающей скобкой. Никогда нельзя помещать зарезервированное слово begin на строку, содержащую другой код.


6.2.2. Оформление объявлений и операторов

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

Простые операторы содержат одну точку с запятой. Если Вам необходимо разделить оператор, то перенесите продолжение оператора на следующую строку с отступом в два пробела.
       
  MyValue :=
    MyValue + (SomeVeryLongStatement / OtherLongStatement);

Составные операторы всегда заканчиваются точкой с запятой.
       
begin
  MyStatement;
  MyNext Statement;
  MyLastStatement;
end;

Каждое присвоение и каждое выражение должно располагаться на разных строках.

Оператор "if"

Оператор if всегда должен располагаться по крайней мере на двух строках
       
if A < B then DoSomething; 
       
if A < B then
  DoSomething;
В случае составного оператора необходимо поместить каждый оператор на новую строку.
       
  if A < B then begin
    DoSomething;
    DoSomethingElse;
  end else begin
    DoThis;
    DoThat;
  end;
       
  if A < B then
  begin
    DoSomething;
    DoSomethingElse;
  end
  else
  begin
    DoThis;
    DoThat;
  end;
Все остальные варианты расположения операторов не рекомендуются и не одобряются, хотя и являются синтаксически правильными.

Оператор "for"

       
  for i := 0 to 10 do begin
    DoSomething;
    DoSomethingElse;
  end;
       
  for i := 0 to 10 do
  begin
    DoSomething;
    DoSomethingElse;
  end;

  for I := 0 to 10 do
    DoSomething;

Оператор "while"

       
  while x < j  do begin
    DoSomething;
    DoSomethingElse;
  end;
       
  while x < j do
  begin
    DoSomething;
    DoSomethingElse;
  end;

  while x < j do
    Something;

Оператор "repeat..until"

       
  repeat
    x := j;
    j := UpdateValue;
  until j > 25;

Оператор "case"

Несмотря на то, что существует множество синтаксически правильных конструкций, одобренной и рекомендованной считается следующая:
       
  case LCode of
    1, 3:
      begin
        Incr := FIncrement + 1;
        FinalIncr := FIncrement div FLineDiv;
        Count := FLineDiv;
      end;
    2, 4:
      begin
        Incr := FPageIncrement;
        FinalIncr := Incr + 1;
        Incr := Incr div FPageDiv;
        Count := FPageDiv;
      end;
  else
    begin
      Count := 0;
      Incr := 0;
      FinalIncr := 0;
    end;
  end;

Оператор "try"

Несмотря на то, что существует множество синтаксически правильных конструкций, одобренной и рекомендованной считается следующая:
       
try
  try
    EnumItems(CurrentThreadID, LDisable, 0);
    Result := TaskList;
  except
    EnableItems(TaskList);
    raise;
  end;
finally
  TaskList := SaveList;
  TaskActive := SaveActive;
end;