Docu/ru/CP-New.odc

Что нового в Компонентном Паскале?
ENGLISH
Редакция перевода: Ф.В.Ткачев, 2009-10-05
За несколькими небольшими исключениями, Компонентный Паскаль является надмножеством языка Оберон2. По сравнению с Обероном-2, в нем сделаны несколько уточнений и усовершенствований, которые и перечислены в данном тексте. Некоторые из отличий были реализованы уже в предыдущих версиях системы Блэкбокс (BlackBox Component Framework), и все они реализованы в версии 1.3 и более поздних.
Пересмотр языка был вызван опытом разработки системы Блэкбокс и стремлением улучшить поддержку спецификации, документирования, разработки, экплуатации и реструктуризации компонентных каркасов. Цель состояла в том, чтобы дать архитектору каркаса средства для более полного контроля внутренней самосогласованности больших компонентных систем. Контроль внутренней самосогласованности системы  ключ к увеличению надежности, сокращению эксплуатационных издержек и большей уверенности в правильности развивающейся системы. 
Обращалось внимание на то, чтобы язык оставался маленьким, простым для использования и изучения. Новые возможности будут замечены прежде всего проектировщиками каркасов, в меньшей степени  теми, кто наращивает или расширяет каркас, и еще менее  программистами, просто использующими каркас. Это гарантирует, что различные категории разработчиков не будут грузиться тем, чего их задачи реально не требуют.
Более выразительная система типов
Ковариантные значения функций, возвращающих указатели
Функции, cвязанные с типами и возвращающие указатель, могут быть переопределены таким образом, чтобы возвращать переопределенный тип. Например, функция
	PROCEDURE (v: View) ThisModel (): Model
может быть переопределена в подтипе MyView, наследующем типу View, со следующей сигнатурой
	PROCEDURE (v: MyView) ThisModel (): MyModel
где MyModel является подтипом Model. Заметим, что ковариантные функции являются безопасными с точки зрения строгой типизации; они просто усиливают постусловие функции, что всегда допустимо. Это позволяет сделать объявления типов более точными.
Совместимость указателей
Правила совместимости для указателей были ослаблены и упрощены. Теперь указатели совместимы по структуре; то есть два указательных типа, имеющих общий базовый тип, являются совместимыми. Это может быть полезно в основном в сигнатурах процедур, где раньше было невозможно использовать функции, подобные следующей:
	PROCEDURE P (p: POINTER TO ARRAY OF INTEGER)
Указательные значения функций
В типе значения, возвращаемого функцией, теперь может стоять описание типа, а не просто идентификатор. Например, теперь допустимо писать:
	PROCEDURE Bla (): POINTER TO Rec
и из-за упрощенных правил совместимости (см. предыдущий пункт) их использование может быть реально полезным.
IN и OUT
Эти режимы передачи параметров подобны режиму VAR, за исключением некоторых ограничений. IN-параметры не могут быть напрямую изменены в процедуре, параметры OUT считаются неопределенными при входе в процедуру (за исключением указателей и процедурных переменных, которые устанавливаются в NIL перед входом в процедуру). Дла записевых OUT-параметров, типы формальных и фактических параметров должны совпадать.
Такие режимы передачи параметров важны для сигнатур процедур распределенных объектов, и они могут способствовать увеличению удобства и эффективности. Но важнее всего то, что они позволяют делать объявления интерфейсов более точными и самодокументированными. В частности, там, где VAR-параметры ранее использовались только в целях эффективности, теперь можно использовать IN-ппараметры. IN-параметры допускаются только для записевых и массивовых типов.
	Пример:
	PROCEDURE ShowModes (value: INTEGER; VAR inout: INTEGER;
																	(* параметры по значению и по ссылке *)
															IN in: ARRAY OF SET;
																	(* IN для быстродействия *)
															OUT res: INTEGER): INTEGER;
																	(* OUT параметр и значение функции *)

Поскольку IN и OUT являются конкретизациями VAR, через IN-параметры нельзя передавать константы. Есть только одно исключение: явные цепочки литер можно передавать через параметры, описанные как открытые IN-массивы, поскольку такие цепочки в любом случае реализованы компилятором как переменные только для чтения.
Новые методы (атрибут NEW)
Компонетный Паскаль требует, чтобы введение нового метода отмечалось явно. Для этого к сигнатуре метода добавляется атрибут NEW. В переопределяемых методах указывать NEW нельзя. В следующем примере метод SomeMethod заново введен в T и унаследован типом T1, который является расширением T:
	PROCEDURE (t: T) SomeMethod (x, y: INTEGER), NEW;
	BEGIN
		...
	END SomeMethod;
	PROCEDURE (t: T1) SomeMethod (x, y: INTEGER);
	BEGIN
		...
	END SomeMethod;
NEW показывает, что метод новый и не является переопределением. Требование явно помечать новые методы оказывается полезным при изменениях в каркасе, что часто происходит как на начальных итерациях разработки проекта, так и позже, когда архитектура ПО подвергается переработке. NEW позволяет компилятору отследить, например, чтобы при изменении имени базового метода переопределяющие методы тоже были переименованы. Кроме того, при введении нового метода компилятор может проверить, нет ли его уже в базовом типе. Эти проверки облегчают сохранение согласованности между компонентами после изменений в интерфейсах каркаса.
Записевые типы по умолчанию и с атрибутами EXTENSIBLE, ABSTRACT и LIMITED
Компонентный Паскаль использует единственное средство для обозначения как интерфейсов объектов, так и их реализаций  записевые типы. Эта унификация позволяет зафиксировать одни аспекты реализации интерфейса, оставляя открытыми другие. Такая гибкость часто желательна в сложных каркасах. Но такие архитектурные решения важно выражать как можно точнее, так как они могут повлиять на большое число клиентов.
В этих целях записевый тип в Компонентном Паскале может иметь атрибуты, которые позволяют проектировщику интерфейса явно сформулировать несколько фундаментальных архитектурных решений. Важно, что компилятор может проверить соответствие этим решениям. Такими тщательно подобранными атрибутами являются EXTENSIBLE, ABSTRACT и LIMITED. Они позволяют различать четыре разные комбинации возможностей расширения и размещения [allocation]:
атрибут	расширение	размещение	присваивание записей
отсутствует (FINAL)	нет	да	да
EXTENSIBLE	да	да	нет
ABSTRACT	да	нет	нет
LIMITED	нет*	нет*	нет
*за исключением определяющего модуля
Записевые типы могут быть либо расширяемыми, либо не расширяемыми (конечными). По умолчанию, записевый тип является конечным. Конечные типы позволяют закрыть тип, так что проектировщик может исчерпывающим образом проанализировать реализацию типа, например, чтобы усовершенствовать ее, не нарушив работу клиентов.
Записевые типы могут допускать размещение (статических и динамических переменных), либо размещение может быть запрещено (ABSTRACT) или ограничено определяющим модулем (LIMITED). Другими словами, размещение и расширение типов с атрибутом LIMITED возможно только в том модуле, где они определяются, но не в импортирующем модуле.
Конечные типы обычно являются простыми, вспомогательными типами данных, например:
	Point = RECORD
		x, y: INTEGER
	END
Переменные таких типов могут копироваться операторами присваивания, например, pt := pt2. Компилятору никогда не нужно генерировать скрытую проверку типа, которая иногда необходима для такого присваивания в Обероне.
С другой стороны, расширяемые записи не могут ни копироваться, ни передаваться по значению (так как параметры, передаваемые по значению, требуют присваивания записей).
Конечные типы, подобно расширяемым типам, могут быть расширениями других типов записей и могут иметь методы. 
Расширяемые типы объявляются следующим образом:
	Frame = EXTENSIBLE RECORD
		l-, t-, r-, b-: INTEGER
	END
Простые типы с атрибутом EXTENSIBLE используются редко, вместо них чаще используют типы с атрибутом ABSTRACT, которые являются частным случаем расширяемых типов и не допускают размещение соответствующих переменных. В следующем абзаце дается более точное описание смысла данного ограничения.
Типы значений никогда не могут быть абстрактными, но типы переменных могут быть абстрактными. Тип значения может отличаться от типа содержащей его переменной, только если переменная ссылочная, то есть является указателем, VAR, IN или OUT параметром. Следовательно, только такие переменные могут иметь абстрактный тип. Во всех других случаях, например, для статических переменных, полей записей, базовых типов массивов и параметров, передаваемых по значению, должны быть использованы неабстрактные типы либо указатели (возможно, на абстрактные типы). Так как операция NEW порождает значение типа аргумента, NEW может использоваться только для переменных неабстрактного типа.
Пример абстрактного типа:
	TextView = POINTER TO ABSTRACT RECORD (Views.View) END
Абстрактные типы  средство проектирования, они описывают интерфейсы объектов. Они являются основным средством моделирования интерфейсов компонентов в Компонентном Паскале. Определение записей с атрибутом ABSTRACT позволяет точнее указать использование записи как интерфейсной конструкции в отличие от реализации.
Тем не менее, абстрактный тип может иметь все виды методов (см. ниже), то есть он не обязан быть полностью абстрактным.
Ограниченные типы, определяемые с атрибутом LIMITED,  особый случай конечных типов. Их особенность в том, что соответствующие записи могут размещаться только в определяющем модуле, и их нельзя копировать. Например, клиент не может выполнить NEW для переменных таких типов. Так как размещение целиком контролируется определяющим модулем, проектировщик этого модуля может гарантировать, что вновь размещаемые переменные корректно инициализируются до их передачи клиентским модулям. Это означает, что клиенты видят только переменные, удовлетворяющие инвариантам типа (которые устанавливаются при инициализации). Проектировщик волен изменить внутреннее представление с меньшим риском нарушить функционирование клиентского кода; отпадает необходимость в методах отложенной инициализации; невозможны поздние ошибки при выполнении программы из-за неверной инициализации; наконец, невозможно рарушить инварианты копированием (например, инварианты с участием скрытых полей записи).
Для создания новых экземпляров динамических ограниченных типов обычно предусматриваются фабричные функции или объекты.
Пример:
	Semaphore = POINTER TO LIMITED RECORD END;
	PROCEDURE New (level: INTEGER): Semaphore;
В системе Блэкбокс большинство абстракций представлено абстрактными типами, для которых даются реализации (неэкспортированными) конечными типами. Это еще один способ гарантировать корректную инициализацию, но он слишком неудобен для простых нерасширяемых абстракций. Кроме того, клиенты не могут заменить LIMITED-типы своими расширениями. Это важно, поскольку позволяет защитить нерасширяемые службы, такие как ядро реального времени, от использования с недопустимыми типами.
Синтаксис записей
Синтаксис записей выглядит следующим образом:
	RecordType = [EXTENSIBLE | ABSTRACT | LIMITED] 
RECORD ["(" QualIdent ")"] FieldList {";" FieldList} END.
Заметим, что программисту чисто клиентских приложений никогда не потребуется писать  эти атрибуты. То же самое касается проектировщиков расширений каркаса. Но проектировщик каркаса может сэкономить усилия благодаря их использованию, поскольку эти атрибуты представляют собой важную часть документации, которую можно извлечь из исходного кода автоматически.
Целью введения этих атрибутов было увеличить статическую выразительность интерфейсов, чтобы нужные архитектурные решения могли быть выписаны явно, причем так, чтобы компилятор мог проверить соответствие клиентской реализации интерфейсному контракту. В языке, предназначенном только для реализации, нет нужды в этих новых атрибутах, и только язык для компонентно-ориентированной реализации и проектирования нуждается в выразительных средствах для подобных проектных ограничений. Контроль таких ограничений позволяет проектировщику каркаса ввести важные инварианты, касающиеся всей программной системы (= системной архитектуры), повышая таким образом безопасность, сопровождаемость и развиваемость.
Некоторые из новых атрибутов также повышают удобство; например, абстрактным методам не нужно тело процедуры. Такое дополнительное удобство приветствуется, но само по себе не могло быть весомой причиной для введения описанных атрибутов.
Стандартные и расширяемые методы (без атрибутов и атрибут EXTENSIBLE)
Подобно записевым типам, методы этих типов тоже могут иметь атрибуты. Допустимы вариант по умолчанию (без атрибута), EXTENSIBLE (расширяемый), ABSTRACT (абстрактный) и EMPTY (пустой).
Как и для записевых типов, методы по умолчанию являются конечными:
	PROCEDURE (t: T) StaticProcedure (x, y: INTEGER), NEW;
	BEGIN
		...
	END StaticProcedure;
Методы, которые одновременно новые и конечные, могут трактоваться компилятором как обычные процедуры, так как они не требуют позднего связывания. Тем не менее, их использование может быть уместным, если они с очевидностью принадлежат конкретному типу.
С другой стороны, расширяемые (переопределяемые) методы должны помечаться как таковые, например:
	PROCEDURE (t: T) Method (x, y: INTEGER), NEW, EXTENSIBLE;
	BEGIN
		...
	END Method;
Гораздо чаще используются астрактные или пустые методы, которые являются частными случаями расширяемых методов (см. ниже).
Метод объявляется конечным простым отбрасыванием атрибута EXTENSIBLE:
	PROCEDURE (t: T) FinalInheritedMethod (x, y: INTEGER);
	BEGIN
		...
	END FinalInheritedMethod;
Если проектировать каркас в стиле черного ящика, то большинство методов, которые нужно будет реализовывать при расширении каркаса, будут иметь вышеуказанный тип, когда никаких специальных атрибутов в сигнатуре метода не требуется. Это разумно, потому что больше программистов занимаются расширением каркасов, нежели их проектированием, следовательно, писать расширения должно быть как можно удобней.
Конечные методы могут быть привязаны к любому типу записей. Расширяемые методы могут быть привязаны только к расширяемым типам (т.е. EXTENSIBLE или ABSTRACT).
Поскольку конечные методы не могут быть переопределены, то инварианты, которые они гарантируют, и постусловия, которые они устанавливают, не могут быть нарушены. Заметим, что корректное расширение метода подразумевает, что расширяющий метод является в некотором смысле усовершенствованным вариантом расширяемого. Семантически это значит, что расширяющий метод может принимать более слабые предусловия или устанавливает более сильные постусловия по сравнению с расширяемым методом.
Абстрактные методы (атрибут ABSTRACT)
Абстрактный метод объявляется следующим образом:
	PROCEDURE (t: T) SomeMethod (s: SET), NEW, ABSTRACT;
	PROCEDURE (t: T) CovariantMethod2 (): NarrowedType, ABSTRACT;
Абстрактные методы расширяемы (переопределяемы). Компилятор проверяет, что конкретный тип реализует все абстрактные методы, которые он унаследовал. Конкретное расширение абстрактного метода (или типа) может считаться его реализацией. Абстрактные методы не имеют тела процедуры, они существуют лишь в виде сигнатур. Поэтому больше нет необходимости писать тело процедуры с оператором HALT.
Пустые методы (атрибут EMPTY)
Метод может быть объявлен как пустой (empty). Пустые методы являются расширяемыми. Пустые методы очень похож на асбтрактные в том, что они являются заглушками для функциональности, которая может быть предоставлена в дальнейших расширениях. Однако пустые методы являются конкретными и могут вызываться. Если они не расширялись (т.е. не были реализованы), то их вызов не дает никакого эффекта.
Пустые методы представляют собой необязательные интерфейсы. Например, тип View в системе Блэкбокс имеет пустой метод для обработки сигналов от пользователя (HandleCtrlMsg). Интерактивные объекты изображения (вьюшки) реализуют этот метод, а пассивные его игнорируют.
Пустая процедура не может содержать кода. Поэтому пустой метод не имеет тела и не может быть вызван посредством супервызов.
Пустые процедуры не могут быть функциям и не могут иметь OUT-параметров.
Пример:
	PROCEDURE (t: T) Broadcast (msg: Message), NEW, EMPTY;
Синтаксис методов
Синтаксис методов выглядит следующим образом:
	TBProc = PROCEDURE Receiver IdentDef [FormalPars] [Attribution].
	Attribution = ["," NEW] ["," (EXTENSIBLE | ABSTRACT | EMPTY)].
Заметим, что программисту чисто клиентских приложений никогда не потребуется писать  эти атрибуты. То же самое касается проектировщиков расширений каркаса. Но проектировщик каркаса может сэкономить усилия благодаря их использованию, поскольку эти атрибуты представляют собой важную часть документации, которую можно извлечь из исходного кода автоматически.
Экспорт методов только для реализации
Теперь также можно экспортировать методы только для реализации, для чего используется метка экспорта - вместо *. Экспорт только для реализации означает, что метод может быть реализован вне определяющего модуля, но не может быть оттуда вызван.
Решение о том, как экспортируется метод  обычным образом или только для реализации, принимается при определении метода (новый метод с атрибутом NEW). Дальнейшие расширения должны использовать тот же режим экпорта, либо вообще не экспортировать метод.
Методы, экспортированные только для реализации, вызываются из того модуля, где метод был введен; вызовы таких методов идут вверх по модульной иерархии (восходящий вызов). Для каркасов характерны такие восходящие вызовы. Экпорт только для реализации позволяет лишить клиентов каркаса возможности нарушить его инварианты, но в то же время дать им возможность предоставлять новые реализации типов каркаса.
Каждый каркас имеет два лица: интерфейс для клиентов и интерфейс для проектировщиков, так называемый интерфейс специализации. Эти два интерфейса могут частично перекрываться. Экспорт только для реализации позволяет явно пометить те части интерфейса, которые относятся только к интерфейсу специализации.
Супервызовы
Из-за так называемой семантической проблемы хрупких базовых классов рекомендуется по-возможности избегать супервызовов. Новое ПО можно проектировать так, чтобы они не требовались, отдавая предпочтение композиции перед наследованием реализации. Супервызовы считаются устаревшим средством. Для обратной совместимости они временно сохранены. В перспективе поддержка супервызовов может быть уменьшена.
Процедурные типы
Процедурные типы обладают меньшей гибкостью, чем объекты с методами. Даже в обычных примерах использования процедурных типов в ПО для числовых расчетов можно получить выигрыш, моделируя их посредством объектов. Объекты расширяемы, а процедурные типы  нет. Процедурные типы могут создавать значительные трудности для безопасной выгрузки модулей. Пока что они сохранены для обратной совместимости, а также для реализации низкоуровневого интерфейсного кода (обратные вызовы, callbacks). В перспективе поддержка процедурных типов может быть уменьшена.
ANYREC и ANYPTR
Каждая базовая запись считается расширением нового стандартного абстрактного типа ANYREC, даже если она объявлена без указания базового типа. ANYREC  это пустая запись, которая является кореннем всей иерархии записей. ANYPTR  это новый стандартный тип, который соотвествует конструкции POINTER TO ANYREC.
Эти новые типы облегчают взаимодействие между независимо разрабатываемыми каркасами, давая возможность использовать параметры без какой-либо информации об их типах.
Подразумеваются следующие псевдоопределения:
	ANYREC = ABSTRACT RECORD END;
	ANYPTR = POINTER TO ANYREC;
	PROCEDURE (a: ANYPTR) FINALIZE-, NEW, EMPTY;
Процедура FINALIZE  пустая. Она может быть реализована для расширений указательных типов. Процедура вызывается в неопределенный момент времени после того, как объект становится недоступным через другие указатели (не имеет глобального якоря), и перед тем, как объект уничтожается. Методы FINALIZE необходимы для освобождения ресурсов, которые не являются объектами непосредственно Компонентного Паскаля; например, селекторов файлов, дескрипторов шрифтов, указателей на окна операционной системы и т.п.
Порядок финализации неопределен. Объект финализируется только один раз.
Поддержка литерных цепочек (strings)
Явные цепочечные типы (string types)
Можно различать цепочечное значение (конкретные литеры) и переменную, в которой это значение содержится (массив литер). Некоторые операции в Компонентном Паскале производятся над цепочечными значениями (например, сравнение на равенство), другие  над переменной (например, присваивание). Компилятор может автоматически определять, какая интерпретация нужна в каждой конкретной ситуации. К сожалению, есть ситуации, когда допустимы обе интерпретации. Например, подстановка цепочки литер на место параметра, передаваемого по значению (который тоже является массивом литер) должна интерпретироваться как присваивание. Но часто более эффективно копировать только цепочечное значение, а не весь массив. Это имеет место, например, при передаче имени пути для системы Unix, объявляемого как литерный массив из 2048 элементов, но обычно реально содержащего только несколько литер.
В Компонентном Паскале можно явно указать, что имеется в виду цепочечное значение, а не переменная-массив. Для этого служит оператор $; например:
	OpenFile(pathname$)
где OpenFile объявлена как
	PROCEDURE OpenFile (name: ARRAY 2048 CHAR)
Дополнительная выгода здесь в том, что теперь более привлекательно объявлять параметры как массивы литер с фиксированным числом элементов, как в предыдущем примере. В Обероне это неудобно, так как тип фактического параметра часто не совместим с формальным. Так как цепочечные значения всегда совместимы с массивами литер, эта проблема исчезает в Компонентном Паскале. Это важно, поскольку указание фиксированного размера для массива точнее передает смысл, если известно, что длина возможных значений ограничена. Заметим, что объявление открытого массива означало бы согласие принимать массив любой длины (так что при выполении программы никогда не может возникнуть ошибка выхода за границу диапазона!).
Конкатенация цепочек
Оператор + теперь позволяет выполнять конкатенацию цепочек. Целевая переменная должна быть достаточной длины, чтобы вместить цепочку-результат.
Отсутствие COPY
Вспомогательная процедура COPY теперь не нужна, так как оператор $ делает ее лишней. Например,
	COPY(a, varpar)	заменяется на	varpar := a$
Фиксированные диапазоны значений типов
Чтобы добиться полностью переносимого кода, необходимо полностью задать диапазоны значений для всех элементарных типов. Элементарные типы Компонентного Паскаля составляют надмножество для элементарных типов Java.
Тип	Размер	Область значений
SHORTCHAR	1 byte	набор литер Latin-1
		(первая страница Unicode и надмножество ASCII)
CHAR	2 byte	набор литер Unicode
BYTE	1 byte	целое со знаком
SHORTINT	2 byte	целое со знаком
INTEGER	4 byte	целое со знаком
LONGINT	8 byte	целое со знаком
SHORTREAL	32 bit	IEEE
REAL	64 bit	IEEE
SET	4 byte	набор бит
BOOLEAN	1 byte	FALSE или TRUE
Тип LONGREAL был исключен. Специальные длинные константы с плавающей точкой были исключены; например, следует использовать 1.0E2 вместо 1.0D2. Идентификатор LONGREAL зарезервирован для возможного использования в будущем. Вещественные константы всегда представляют значения типа REAL (64-бит).
Шестнадцатеричные константы теперь могут быть заданы либо как 4-байтовые (например, 0FFFFFFFFH), либо как 8-байтовые константы (например, 0FFFFFFFFFFFFFFFFL). Это позволяет отличать отрицательные шестнадцатеричные константы типа INTEGER от положительных констант типа LONGINT. Например, 0FFFFFFFF обозначает -1, когда интерпретируется как INTEGER, но 4294967295, когда интерпретируется как LONGINT.
Целочисленные константы всегда представляют значения типа INTEGER (4 байт). Присваивание целочисленной константы меньшему типу (например, BYTE) допустимо, если константа лежит в диапазоне значений целевого типа. Целые константы других типов могут быть созданы только с использованием SHORT или LONG, но достаточно большие константы автоматически получают тип LONGINT.
Целая арифметика теперь всегда выполняется с 32-битной точностью, кроме выражений с участием значений типа LONGINT. В последнем случае используется 64-битная точность. Это правило уменьшает вероятность труднообнаружимых переполнений в промежуточных результатах, если последние вычисляются с недостаточной точность.
Арифметика с плавающей точкой всегда выполняется с 64-битной точностью.
Прочее
Семантика DIV уточнена определением результата деления на отрицательные числа.
Введено новое вещественное значение INF для бесконечности. Это значение может порождаться, например, при вещественном делении на нуль. Значение бесконечность для чисел с плавающей точкой определено стандартом IEEE для чисел с плавающей точкой.
Более полно определено, когда подразумевается разыменование указателя. Например, это теперь возможно при передаче указательной переменной формальному параметру записевого типа.
Записевые типы можно объявлять как расширения других типов записей, указывая в качестве базового типа указательный тип (вместо записевого). Это делает излишним явное именование записевого типа, если переменные этого типа используются только через указатели.
В пределах одной области видимости имена любых типов могут использоваться до их объявления. Старые опережающие объявления указателей, вроде T = POINTER TO TDesc, по-прежнему допустимы как простой частный случай нового правила, но они больше не являются необходимыми.
BITS  новая стандартная функция; она преобразует значения INTEGER в значения SET, так что BITS(1) дает {0}. Это позволяет, например, писать лучше переносимые драйверы устройств, так как результаты вычислений здесь не зависят от порядка бит процессора (который отличается, например, для 68k и PowerPC).
ORD теперь может также применяться к значениям SET (операция, обратная к BITS).
MIN и MAX теперь могут также принимать два параметра; например, real0 := MAX(someInt, real1). Они выбирают минимальное/максимальное значение их двух указанных, которые должны иметь числовой тип.
LEN может также быть применима к цепочкам литер. LEN(chararray) возвращает длину переменной-массива chararray, в то время как LEN(chararray$) возвращает длину значения-цепочки литер. Заметим, что литерный массив должен иметь хотя бы на один элемент больше, чем число литер в цепочечном значении, чтобы вместить завершающую литеру 0X.
Обозначения переменных (designators) теперь обобщены для поддержки разыменований и т.п. в результатах функций. Например, теперь допустим следующий код:
	length := view.ThisModel()(TextModels.Model).Length()   или
	view.Context().GetSize(w, h)
Такое расширение синтаксических возможностей для обозначения переменных облегчает использование методов вместо полей записей. Методы обеспечивают большую гибкость, чем поля записей, и упрощают реализацию оберток (передачу вызовов методов обернутым объектам (forwarding)).
Глобальные переменные, включая динамические, размещаемые посредством NEW, теперь имеют определенное начальное значение (FALSE, 0X, 0, 0.0, {}, NIL, ""). Локальные (то есть стековые) переменные не инициализируются, за исключением указателей и процедурных переменных, которые устанавливаются в NIL из соображений безопасности.
Приложение к Сообщению о языке определяет минимальные требования к среде, которым должна удовлетворять любая реализация Компонентного Паскаля. В частности, команды, динамическая загрузка и сборщик мусора являются основополагающими требованиями для компонентно-ориентированных систем. Как и для всех динамических языков, это приложение является признанием того, что язык не может рассматриваться совершенно независимо от своей среды. Объектная модель, независимо от того, включается ли она в определение языка или используется как внешний сервис, всегда является частью среды.
Для упрощения взаимодействия с существующими библиотеками, написанными на языке C, в идентификаторах допускается литера подчеркивание.
Правила для меток экспорта были упрощены по сравнению с Обероном: расширяющей (переопределяющий) метод может иметь только такую же метку экспорта, что и расширяемый метод. Единственное исключение  метод, связанный с неэкспортируемой записью; в этом случае он не может быть экспортирован.
Модуль теперь имеет необязательную секцию CLOSE, после секции BEGIN. Секция CLOSE вызывается перед выгрузкой модуля. Секция BEGIN модуля вызывается после выполнения секций BEGIN всех импортированных модулей. Секция CLOSE должна выполняться только после выполнения секций CLOSE всех импортированных модулей.
Подводя итог, подчеркнем, что новое определение языка содержит одно значительное добавление: более выразительное подмножество языка определения интерфейса (IDL) (NEW; EXTENSIBLE; ABSTRACT; LIMITED; EMPTY; экспорт методов только для реализации), что дает возможность указывать архитектурные свойства компонентного каркаса. 
Другие пункты  это, в основном, уточнение деталей, опирающееся на десятилетний опыт использования языка. Особого внимания заслуживают новая, более общая и систематическая трактовка литерных цепочек, а также новая спецификация размеров элементарных типов.
Благодарности
Я хотел бы поблагодарить своих коллег по компании Oberon microsystems  Бета Хеба, Доминика Грунца, Маттиаса Хаузнера и Даниеля Диеса (Beat Heeb, Dominik Gruntz, Matthias Hausner, and Daniel Diez)  за их ценный вклад в эту работу. В частности, без усилий Бета (Beat Heeb) этот проект был бы невозможен. Самые важные предложения извне были получены от Клеменса Шиперского, Технологический университет г. Квинсленд, Австралия (Clemens Szyperski, Queensland University of Technology, Australia) и Вольфганга Века из Академии Эбо, Финляндия (Wolfgang Weck, Еbo Akademi, Finland). Наконец, я хотел бы поблагодарить профессора Никлауса Вирта (Niklaus Wirth) за комментарии по первому варианту Сообщения о языке Компонентный Паскаль, а также за то, он заложил такой замечательный фундамент для нашей работы.