Илья Ермаков писал(а):
Но можно принять размерность CHAR решением этапа компиляции.
Получается, чтобы истолковать программу, недостаточно держать в руках программу и определение языка. Необходимо еще знать, с какими опциями предполагается компилировать эту программу. Или с какими она была скомпилирована. Т.е. фактически это две разных программы. Или три? тридцать три? ведь у компилятора может много быть опций.
Предлагаю провести анализ ситуаций.
Я полагаю, условно можно разделить программы на А) прикладные и Б) системные.
А) Прикладным программам дела нет до того, какой размерности CHAR. Главное - это (абстрактное) множество всех доступных литер. Значение переменной типа CHAR всегда принадлежит этому множеству. В идеале, если прикладная программа написана грамотно, от изменения представления CHAR вообще не должна зависеть ее работа. Это, кмк, и было надеждой ЯВУ.
Б) Для некоторых системных программ может иметь значение размерность типа CHAR. Причем в двух случаях.
Б1) когда нужно взаимодействовать с внешним беспорядочным миром, который оперирует адресами и буферами вместо литер и строк. (См. LinLibc.printf, например)
Код:
TYPE LinLibc.PtrSTR* = POINTER TO ARRAY [untagged] OF SHORTCHAR;
PROCEDURE [ccall] LinLibc.printf* (s: PtrSTR): int;
Б2) когда нужны какие-нибудь фокусы с упаковкой. Например, компилятор, генерируя код, вставляет этот код в ARRAY OF SHORTCHAR; ядро кое-где предоставляет метасведения в виде SHORTCHAR.
Код:
TYPE DevCPE.CodeBlock = POINTER TO ARRAY CodeLength OF SHORTCHAR;
PROCEDURE Kernel.GetRefVar (VAR ref: INTEGER; OUT mode, form: SHORTCHAR; OUT desc: Type; OUT adr: INTEGER; OUT name: Utf8Name
Б1, кмк, адекватно можно закрыть с помощью имеющегося SHORTCHAR. Но, будь моя воля, я бы упихал его в SYSTEM - раз уж он нужен для системных программ. Могу тут сослаться в свою поддержку на документ
Programming conventions писал(а):
3 Basic types
Use the types INTEGER, REAL and CHAR as defaults. BYTE, SHORTINT, LONGINT, SHORTREAL and SHORTCHAR should only be used if there is a strong particular reason to justify this choice. The auxiliary types are there mainly for interfacing purposes, for packing of very large structures, or for computation of extremely large integers. This rule is more important for exported interfaces than for hidden implementations, of course.
Эти типы могут создавать иллюзию экономии памяти, однако там, в памяти, все настолько безжалостно выравнивается, что в амд64 при передаче в стек булевых значений КПД составляет 1/64.
Эти типы в прикладных программах заставляют морочить голову с приведением типов. А так, были бы они в SYSTEM - еще трижды подумаешь, прежде чем ими пользоваться.
Б2) Кмк, этот фокус - использование SHORTCHAR Там, где на самом деле нужно беззнаковое целое, а вовсе не литера. Всамделе, и генератор кода ведь генерирует байты, и ядро в метасведениях передает какие-то байты. Как раз байты, в отличие от литер - понятие системного уровня, а не прикладного. И я полагаю, что использование SHORTCHAR здесь - вынужденная мера ввиду отсутствия понятия байтов в языке. Собственно тип BYTE - это не байт, это знаковое целое, которое влезает в 8 бит. В Обероне, емнип, был тип SYSTEM.BYTE - это как раз был беззнаковый байт, просто 8 бит. Его из КП исключили. Но в недрах компилятора он остался: там есть Byte, который соответствует SYSTEM.BYTE, и есть Int8, который соответствует просто BYTE. И правила обращения с ними соответственно беззнаковые и знаковые. Как я понимаю, СР2 компилировал и Оберон-программы (может, и сейчас умеет, если опцию включить).
Поэтому есть и такой вариант:
Language report писал(а):
CHAR the characters of the Unicode character set (MIN(CHAR) .. MAX(CHAR))
Platform-specific issues писал(а):
SYSTEM.BYTE the integers between 0 and 255
а SHORTCHAR... может, в топку его?
Коллеги, какие ситуации следует еще добавить к предложенному анализу?