Приведу список новых возможностей...
Изменения в языке
1. Добавлена поддержка вложенных типов (в том числе - классов), классовых переменных и локальных констант.
То есть, теперь можно написать так:
type
TA = class
strict private
const Value = 1; // Константа для внутреннего использования
type
innerA = class // Вложенный класс, невидимый снаружи
// ...
end;
public
var
myVariable : Integer; // Статическая переменная
// (принадлежит типу, а не экземпляру)
type
availableA = class // Вложенный класс, доступный извне
// ...
end;
end;
2. Расширенный синтаксис записей.
То, что в Дельфи называется advanced record syntax, теперь есть и в FPC. В записях можно использовать спецификаторы private/public, можно описывать вложенные типы, конструкторы, статические поля, свойства, классовые конструкторы, классовые деструкторы и классовые операторы (конструкторы записей пока не поддерживаются). На всякий случай, отличия таких расширенных записей от классов:
1) не поддерживается наследование;
2) записи могут содержать вариантные части, классы - нет;
3) записи - это не ссылки, а значения, в отличие от классов.
3. Энумераторы записей.
В предыдущих версиях FPC энумераторы (перечислители) могли быть классами, объектами или интерфейсами. Теперь они могут быть также и расширенными записями.
4. Поддержка хелперов классов и записей.
Это позволяет добавлять методы, свойства и перечислители к классам и записям, не прибегая к наследованию. Пример использования хелпера:
typeПодробное описание - Здесь (англ.)
TObjectHelper = class helper for TObject
function ToString(const aFormat: String): String; overload;
end;
function TObjectHelper.ToString(const aFormat: String): String;
begin
Result := Format(aFormat, [ToString]);
end;
var
Obj: TObject;
begin
Writeln(Obj.ToString('The object''s name is %s'));
end.
5. Дженерики: записи, массивы и процедурные типы.
В предыдущих версиях FPC поддерживались только шаблонные (вернее, обобщенные) классы, объекты и интерфейсы. Теперь стало возможным делать обобщенными всё вышеперечисленное.
6. Поддержка локальных перечислений.
В режиме {$SCOPEDENUMS ON} перечисления не добавляются в глобальную область видимости:
type
TFoo = (A, B, Foo);
{$SCOPEDENUMS ON}
TBar = (A, B, Bar);
{$SCOPEDENUMS OFF}
begin
WriteLn(Integer(Foo));
WriteLn(Integer(A)); // Выводится TFoo.A
WriteLn(Integer(TBar.B));
WriteLn(Integer(TBar.Bar));
WriteLn(Integer(Bar)); // Ошибка: нет глобального Bar
end;
7. Поддержка собственных сообщений об устаревших элементах.
unit OldUnit deprecated 'Use NewUnit instead';(также допустимо использовать с константами)
interface
implementation
procedure OldRoutine; deprecated 'Use NewRoutine instead';
begin
end;
end.
8. Поддержка диалекта Objective Pascal
Для большего удобства работы в MacOS X. (В настоящее время этот диалект поддерживается только на Darwin-платформах, включая iOS). Основы языка Objective Pascal описаны здесь
9. Добавлен режим, поддерживающий стандарт ISO 7185
{$MODE ISO}, или -Miso из командной строки
10. Поддержка вложенных процедурных переменных.
Теперь возможно определить переменную процедурного типа, которая совместима по присваиванию с вложенными процедурами/функциями. Эта фича включена по умолчанию в режимах {$mode MacPas} и {$mode ISO}, в остальных режимах ее надо включить явно: {$modeswitch NestedProcVar}. Возможно также присвоить обычную (не вложенную) подпрограмму подобной переменной, и вызывать ее таким образом.
Разрешение этой фичи изменяет соглашение вызова вложенной подпрограммы. Это "сломает" код времен Турбо-Паскаля, который использует вложенные процедуры/функции как Callback-и при работе с коллекциями из модуля Objects.
Тип процедурной переменной может хранить ссылку на вложенную подпрограмму в двух случаях:
а) когда он описан внутри списка параметров другой процедуры (описание в стиле ISO:
procedure caller(procedure ToBeCalled);)
begin
ToBeCalled;
end;
procedure Main;
procedure InnerToMain;
begin
// ...
end;
begin { Main }
Caller(@InnerToMain);
end; { Main }
begin
Main;
end.
б) когда в объявлении присутствует "is nested" (подобно описанию "of object" для методов класса):
При использовании этого способа надо быть внимательным, поскольку очень просто написать неправильный код: если присвоить ссылку на вложенную процедуру соответствующей переменной, выйти из области видимости внешней функции, и только потом попытаться вызвать вложенную - подобный вызов приведет к UB (неопределенному поведению)
type NestedProc = procedure is nested;
var
T : NestedProc;
procedure Caller(p : NestedProc);
begin
T := p;
T;
end;
procedure Main;
procedure InnerToMain;
begin
// ...
end;
begin
Caller(@InnerToMain);
end;
begin
Main;
end.
11. Поддержка нелокальных Goto (я просто описываю нововведение, нравится оно мне или нет - это другой вопрос)
Теперь возможно перейти по Goto на метку в другой подпрограмме, т.е., быстро выйти из глубоко вложенной подпрограммы в менее вложенную. Эта возможность включена по умолчанию в режимах ISO/MacPas, в остальных - ее надо (а лучше - не надо) включить: {$modeswitch NonLocalGoto}. Невозможно обойти нелокальным Goto стековые фреймы, требующие финализации (во избежание проблем с подсчетом ссылок).
12. Поддержка & для экранирования ключевых слов.
Можно использовать экранированные служебные слова как идентификаторы:
var
&do: string;
&in: boolean;
begin
&do:='abc';
&in:=true;
end.
13. Поддержка параметров univ для режима MacPas
Предыдущие версии компилятора просто игнорировали квалификатор univ для параметров. Теперь FPC его нормально парсит и интерпретирует как и все другие компиляторы MacPascal-я: то есть, разрешает передачу любых фактических параметров, если их размер соответствует размеру формального параметра подпрограммы. Эта возможность - только для режима {$mode macpas}. Пользоваться ей нужно с большой осторожностью, так как она вообще предназначена для портирования Legacy-кода.
14. Вещественный тип CExtended
С точки зрения точности этот тип аналогичен типу Extended, но он соответствует свойствам/поведению эквивалентного Extended типа в C. С практической точки зрения это означает, что на платформах i386/x86_64 тип CExtended соответствует типу long double, а на остальных платформах - типу double. В основном это необходимо в случаях, когда с С переводятся описания структур, чтобы гарантировать правильное выравнивание, и для описания параметров к Сишным подпрограммам.
Внимание: на данный момент FPC не поддерживает эквивалент long double на других платформах (кроме вышеперечисленных).
15. Встроенный SAR (shift arithmetic right)
В отличие от SHL/SHR, SAR реализован не как оператор, а как встроенная функция. Она имеет разные имена для разных целочисленных типов (SarInt64/SarLongint/SarSmallint) чтобы избежать проблем при присваивании результата функции в выражении.
16. Встроенные ROL/ROR
Вместе с SAR добавлена поддержка и для ROL (Rotate Overflow Left) и ROR (Rotate Overflow Right). Также как и в случае SAR, функции реализованы под разными именами для разных типов параметров.
17. Встроенные функции Bit Scan.
Добавлена поддержка еще двух функций: BSF (Bit Scan Forward) и BSR (Bit Scan Reverse).
18. Типы Boolean16, Boolean32 и Boolean64.
Эти 3 типа аналогичны по поведению стандартному типу Boolean, за исключением того, что их размеры - соответственно 2, 4 и 8 байт. Очень удобно в случае организации интерфейса с библиотеками.
Внимание: существующие типы WordBool/LongBool/QWordBool подразумевают, что False = 0, а True <> 0. В случае использования новых типов False = 0, True = 1, а все остальные значения - не валидны.
Изменения в языке
1. Поддержка VFPv2/VFPv3
Была добавлена поддержка модулей Vector Floating Point (VFP) второй и третьей версии. Эти модули обычно включаются на процессорах семейств Cortex-A8 и Cortex-A9, а также на устройствах, основанных на iOS.
2. Поддержка Thumb-2
Была добавлена поддержка для генерации Thumb-2 кода для ARMv7-M так же, как это реализовано в семействе Cortex-M3.
На данный момент эта архитектура поддерживается только для встроенных (embedded) систем, она еще не работает ни для Linux ни для iOS.
(продолжение следует. Есть еще немало изменений на уровне использования - usage changes - с описаниями, как было, как стало и почему внесено изменение. Чуть позже опишу их тоже подробно)