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

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

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


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

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


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

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

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


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

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

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

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

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

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

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

Пример
1  //метод класса, указан класс
2  LList := TObjectList.Create(Name, Description, TObjectList, nil, nil, Folder);    
3
4  //метод экземпляра, указан экземпляр. Метод не имеет параметров.
5  LList.Destroy;
6
7  //свой либо унаследованный метод
8  BuildDefaultActions(Name, True); 

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

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

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

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

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

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

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

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

Пример
01while LList.Count > 0 do
02  LList.GetItem(0).Destroy;
03
04while True do
05begin
06  LValue := LValue.NextValue;
07  if LValue.Value > 10 then
08  begin
09    Result := LValue.Value;
10    exit;
11  end;
12end;

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

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

Пример
1repeat
2  Result := Result + 1;
3  LObject := LObject.Parent;
4until LObject = nil;

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

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

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

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

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

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

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

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

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


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

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


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

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

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

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

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

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

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

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

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

Пример
1// в теле конструктора
2Name := 'Object name';
3Description := 'Object description';
4inherited; //вызов предка с параметрами Name и Description,
5           //заданными двумя предыдущими операторами. Ссылка на
6           //созданный объект лежит в
7           //псевдопеременной Result
8Result.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 - первый попавшийся объект. Результат имеет тип ссылки на объект агрегируемого класса.
    Пример
    1any(TObject with Master = Self.Parent)  
    2//первый попавшийся объект, имеющий значение 
    3//свойства Master равным значению свойства 
    4//Parent текущего (контекстного) объекта.
    
  • count - количество объектов. Результат имеет целочисленный тип.
    Пример
    1count(TObject with Master = Self.Parent) 
    2//количество объектов, имеющих значение свойства 
    3//Master равным значению свойства Parent 
    4//текущего объекта.
    
  • sum - сумма значений свойства, поля или функции объектов. Результат имеет тип суммируемого поля, свойства или функции
    Пример
    1sum(TExam.Mark with Master = LStudent) //сумма 
    2//баллов студента по его испытаниям
    
  • max, min - соответственно максимальное и минимальное значений свойства, поля или функции объектов. Результат имеет тип агрегируемого поля, свойства или функции
    Пример
    1min(TObject.Created) // момент создания первого 
    2//объекта Системы.
    

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

  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:
    1      LObject := any(TObject with Name = 'Some name');
    2      if LObject = nil then
    3         .....
          
  3. Операции "Унарный минус" не существует. Для задания отрицательных констант пользуйтесь конструкцией 0-Значение:
    Result := 0-1;

5. Формальная грамматика
001Goal: MethodBody | Expression;
002
003MethodBody: [ConstantDeclaration] [VariableDeclaration] CompoundStatement ";";
004
005ConstantDeclaration: "const" Ident ":" DomainSpecification ";" 
006  [{Ident ":" DomainSpecification ";"}];
007
008VariableDeclaration: "var" DomainDefinition [{DomainDefinition}];
009
010DomainDefinition: Ident ":" DomainSpecification ";";
011
012DomainSpecification: IntegerDomainDefinition
013  | StringDomainDefinition
014  | FloatDomainDefinition
015  | DateDomainDefinition
016  | TimeDomainDefinition
017  | DateTimeDomainDefinition
018  | BooleanDomainDefinition
019  | BlobDomainDefinition
020  | EnumerationDomainDefinition
021  | Ident;
022
023IntegerDomainDefinition: "integer";
024StringDomainDefinition: "string" "[" Number "]";
025FloatDomainDefinition: "float" ["(" Number ["." Number] ")"];
026DateDomainDefinition: "date";
027TimeDomainDefinition: "time";
028DateTimeDomainDefinition: "datetime";
029BooleanDomainDefinition: "boolean";
030BlobDomainDefinition: "blob" | "clob";
031EnumerationDomainDefinition: "(" Ident {"," Ident} ")";
032
033CompoundStatement: "begin" Statement [{";" Statement}] "end";
034
035Statement:
036  | CompoundStatement
037  | AssignmentStatement
038  | InheritedStatement
039  | CallStatement
040  | IfStatement
041  | CaseStatement
042  | ForStatement
043  | WhileStatement
044  | RepeatStatement
045  | TryFinallyStatement
046  | TryExceptStatement
047  | RaiseStatement
048  | ForEachStatement
049  | ExitStatement;
050
051AssignmentStatement:  Qualifier ":=" Expression;
052
053CallStatement: Qualifier;
054
055InheritedStatement: "inherited";
056
057IfStatement: "if" Expression "then" Statement ["else" Statement];
058
059CaseStatement: "case" Expression "of" {CaseBranch} ["else" Statement ";"] "end";
060
061CaseBranch: CaseLabel [{',' CaseLabel}] ":" Statement ";";
062
063CaseLabel: Number | Ident;
064
065ForStatement: "for" Ident ":=" Expression ("to"|"downto") 
066  Expression "do" Statement;
067
068WhileStatement: "while" Expression "do" Statement;
069
070RepeatStatement: "repeat" Statement [{";" Statement}] "until" Expression;
071
072TryFinallyStatement: "try" Statement [{";" Statement}] "finally" 
073  Statement [{";" Statement}] "end";
074
075TryExceptStatement: "try" Statement [{";" Statement}] "except" 
076  Statement [{";" Statement}] "end";
077
078RaiseStatement: "raise" [Expression];
079
080ForEachStatement: "for" "each" Ident "of" Ident ["with" Expression] 
081  ["by" Expression] "do" Statement;
082
083ExitStatement: "exit";
084
085Expression: ComparedExpression [{RelationOperation Expression}];
086
087ComparedExpression: Addon [{AdditionOperaton ComparedExpression}];
088
089Addon: Factor [{MultiplicativeOperation Addon}];
090
091Factor: "(" Expression ")"
092  | "not" Expression
093  | Number ["." Number]
094  | StringConstant
095  | Qualifier
096  | "nil"
097  | "True"
098  | "False"
099  | "(" Expression "is" Ident ")"
100  | "any" Aggregate
101  | "count" Aggregate
102  | "sum" Aggregate
103  | "max" Aggregate
104  | "min" Aggregate;
105
106Aggregate: "(" Ident ["." Ident] ["with" Expression] ")";
107
108Qualifier: QualifierPart [{"." QualifierPart}];
109
110QualifierPart: Ident ["(" Expression [{", " Expression}] ")"]
111  | "self"
112  | "(" Qualifier "as" Ident ")";
113
114RelationOperation: "<"
115  | ">"
116  | "<="
117  | ">="
118  | "="
119  | "<>";
120
121AdditionOperaton: "+"
122  | "-"
123  | "or";
124
125MultiplicativeOperation: "*"
126  | "/"
127  | "div"
128  | "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. Стилевое оформление исходного кода

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


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

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

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

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

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

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

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

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

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


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

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

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

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

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

Оператор "if"

Оператор if всегда должен располагаться по крайней мере на двух строках
Неправильно
if A < B then DoSomething; 
Правильно
if A < B then
  DoSomething;
В случае составного оператора необходимо поместить каждый оператор на новую строку.
Неправильно
1  if A < B then begin
2    DoSomething;
3    DoSomethingElse;
4  end else begin
5    DoThis;
6    DoThat;
7  end;
Правильно
1  if A < B then
2  begin
3    DoSomething;
4    DoSomethingElse;
5  end
6  else
7  begin
8    DoThis;
9    DoThat;
  end;
Все остальные варианты расположения операторов не рекомендуются и не одобряются, хотя и являются синтаксически правильными.

Оператор "for"

Неправильно
1  for i := 0 to 10 do begin
2    DoSomething;
3    DoSomethingElse;
4  end;
Правильно
1  for i := 0 to 10 do
2  begin
3    DoSomething;
4    DoSomethingElse;
5  end;
6
7  for I := 0 to 10 do
8    DoSomething;

Оператор "while"

Неправильно
1  while x < j  do begin
2    DoSomething;
3    DoSomethingElse;
  end;
Правильно
1  while x < j do
2  begin
3    DoSomething;
4    DoSomethingElse;
5  end;
6
7  while x < j do
8    Something;

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

Правильно
1  repeat
2    x := j;
3    j := UpdateValue;
4  until j > 25;

Оператор "case"

Несмотря на то, что существует множество синтаксически правильных конструкций, одобренной и рекомендованной считается следующая:
Правильно
01  case LCode of
02    1, 3:
03      begin
04        Incr := FIncrement + 1;
05        FinalIncr := FIncrement div FLineDiv;
06        Count := FLineDiv;
07      end;
08    2, 4:
09      begin
10        Incr := FPageIncrement;
11        FinalIncr := Incr + 1;
12        Incr := Incr div FPageDiv;
13        Count := FPageDiv;
14      end;
15  else
16    begin
17      Count := 0;
18      Incr := 0;
19      FinalIncr := 0;
20    end;
  end;

Оператор "try"

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