Zorko писал(а):
Олег, ты заметь, насколько прост однострочный фикс под тип SHORTINT в два байта. Он как будто закрывает недоработанность Ofront'а: размер типа SHORTINT из Ofront.par читается, а значения переменных OPM.MinSInt и OPM.MaxSInt под него не фиксятся. Так что нам не нужно полагаться на константу -127 — что она всегда равна MIN(SHORTINT). Вот это неправильно будет. А достаточно взять просто значение переменной OPM.MinSInt, так что я даже слегка удивлён, что тебя здесь смущает. Ведь, заметь, это не константы, а переменные, не так ли?
Меня смущает, что я до сих пор и не думал об изменении разрядности типов.

Я работал только в системе ZXDev и только для типов 8-16-32. Поэтому очень легко написал непереносимый код, хотя и полагался на переменные Min\Max. Правда это касается только последней модификации, до этого рассуждения о FOR были достаточно общи и не зависели от разрядности типов. Далее меня смутила сама необходимость такого фикса. Ведь если это недоработано здесь, то может быть потребует изменений где-то еще?
Цитата:
Размер SHORTINT тоже берётся из Ofront.par, просто Дж.Темпл, видимо, никогда не предполагал, что он может быть двухбайтовым.
А вдруг это не просто забывчивость, а есть какие-то причины? Вдруг в каком-то месте Ofront существенно используется однобайтовость SHORTINT? Вот это тоже меня смущает.
Zorko писал(а):
В принципе, Ofront не препятствует задать размеры всех типов в файле Ofront.par, чем я активно пользуюсь, задавая двухбайтовый (для Z80) или четырёхбайтовый (для Wintel) размер типа INTEGER Получается, что задавать разрядность типов в Ofront'е внешним конфигуратором — это его встроенная возможность. И, осмелюсь заметить, полезная. Ибо разрядность типов стандартом Оберона не зафиксирована . …
Если сделать SHORTINT байтовым — мы не сможем работать с двухбайтовыми переменными. Или ты предлагаешь сделать INTEGER тоже фиксировано двухбайтовым?
По стандарту Оберона должно выполняться соотношение типов
SHORTINT <= INTEGER <=LONGINT,
Включение здесь нестрогое, т.е. INTEGER должно быть между SHORTINT и LONGINT, но может совпадать по разрядности с одним из них. Может теоретически быть совпадение и всех 3 типов, хотя на практике такие системы вряд ли нам встретятся. Учитывая текущие ограничения Ofront, имеем
INT8 <= SHORTINT <= INTEGER <=LONGINT <= INT32
Т.е. всего 3+3+1=7 возможных наборов целых типов (включая и тот вариант, когда все три однобайтовые ). И для всех этих вариантов Ofront должен давать правильный код.
Я же написал
node^.conval^.intval := SHORT(SHORT (v )); что работает, только если соотношение типов 8-16-32.
Сам Ofront работает с 32-разрядным типом lint (соответствует типу ББ INTEGER), что позволяет совершать все операции, не опасаясь переполнений. А когда нужно сделать приведение типов или произвести проверку границ, Ofront опирается на значения OPM.SIntSize, OPM.MinSInt и OPM.MaxSInt, OPM.IntSize, OPM.MinInt и т.д. Это действительно переменные, устанавливаемые по файлу параметров Ofront.par.
Вчера мне показалось хорошей идеей иметь систему внутренних типов компилятора, фиксированной разрядности, а гибкость обеспечивать не заданием границ, а привязкой через файл параметров внешних алиасов типа к внутренним фиксированным. Т.е. написали в файле параметров SHORTINT=INT8 – стал SHORTINT однобайтовым, написали SHORTINT=INT16 – стал в 2 раза шире. А компилятор работает с INT8 или INT16, а до имени SHORTINT ему и дела нет. Но не подходит это для Оберона, где операции привязаны к ИМЕНИ типа. Недостаточно компилятору технических данных о разрядности, ему надо знать какой смысл программист в этот тип вкладывает - считает ли его маленьким, нормальным или большим. Вот как выполнять SHORT(INT32)? Должен тип на 1 ступеньку меньше получиться, а это не обязательно INT16, может быть INT32, а может и INT8. Привязкой алиасов в лучшем случае можно сохранить соотношение - переключаться с 8-16-32 на 16-32-64, что не подходит т.к. негибко, да и 64 нет пока. Поэтому не подходит система фиксированных типов с настройкой внешних алиасов.
Так что предлагаю проверить (протестировать) Ofront на случай 2-байтового SHORTINT (раз он 2-байтовым никогда не был, то и не тестировал этот случай никто). При модификации учитывать все возможные наборы целых типов, которые могут быть заданы через Ofront.par. (это я сам себе предлагаю, ты, Олег, видимо, это всегда учитывал

)
Цитата:
Saferoll писал(а):
Иначе мне придется проводить особые исправления в реализации FOR для ZXDev, и особые для WinDev, а особые для какой-то еще системы, потому что там своя разрядность.
Так ты просто опирайся на значения переменных OPM.SIntSize, OPM.MinSInt и OPM.MaxSInt (для SHORTINT) и на OPM.IntSize, OPM.MinInt и OPM.MaxInt (для INTEGER). Ведь для типа INTEGER разрядность не зафиксирована в 2 байта. И коррекция MinInt и MaxInt под четырёхбайтовый тип в Ofront встроена, хотя, кажется, Темпл и не пользовался этой возможностью. Так что эти значения переменных для типа INTEGER зависят от конфигуратора Ofront.par.
Вот придется опираться, придется вместо
X:=SHORT(Y) писать
IF OPM.IntSize=2*OPM.SIntSize THEN X:=SHORT(Y) ELSE ..., потому, что типы Х и Y заранее известны, но неизвестны текущие разрядности этих типов в файле параметров. А вот была бы фиксированная система типов, было бы намного проще:
X:=SHORT(Y) можно было бы написать сразу. , а в файле параметров задавались бы
внешние имена типов. Но, увы, это не для Оберона. В Обероне операции привязаны именно к именам типов, без фиксации разрядности. Придется, внося модификации в Ofront, заранее думать об изменяющейся разрядности типов.
Цитата:
Saferoll писал(а):
А так мы получаем единый Ofront, c единым внутренним набором типов. И реализацию FOR (и другие модификации) тоже не придется писать для каждой платформы отдельно.
Что ты, и так не придётся.

Для разного размера INTEGER (2 или 4 байта) твой FOR уже и так работает.
Увы, не работает...Свертка констант при помощи OPB.NewUnsignedConst и OPB.SetUnsignedType
в предыдущем сообщении не работает для 4-байтовой переменной цикла. Да и для меньших типов работает, только если разрядность SHORTINT 8 бит, а INTEGER - 16 (из-за жесткого применения SHORT() и SHORT(SHORT()) без проверки соотношения разрядности). Придется переделать. Например, вот так:
Код: "OBERON"
PROCEDURE SetUnsignedType(node: OPT.Node);
(* превращает беззнаковую константу в знаковую *)
VAR v: INTEGER;
BEGIN v := node^.conval^.intval;
IF (0 <= v) & (v <= 2*OPM.MaxSInt+2) THEN
node^.typ := OPT.sinttyp;
IF 4*OPM.SIntSize = OPM.LIntSize THEN node^.conval^.intval := SHORT(SHORT (v))
ELSIF 2*OPM.SIntSize = OPM.LIntSize THEN node^.conval^.intval := SHORT (v)
ELSE ASSERT (OPM.SIntSize = OPM.LIntSize )
END
ELSIF (0 <= v) & (v <= 2*OPM.MaxInt+2) THEN
node^.typ := OPT.inttyp;
IF 4*OPM.IntSize = OPM.LIntSize THEN node^.conval^.intval := SHORT(SHORT (v))
ELSIF 2*OPM.IntSize = OPM.LIntSize THEN node^.conval^.intval := SHORT (v)
ELSE ASSERT (OPM.IntSize = OPM.LIntSize )
END
ELSE (* всё прочее - LINT. Дополнить, когда введем "настоящие" беззнаковые типы! *)
node^.typ := OPT.linttyp;
END
END SetUnsignedType;
PROCEDURE NewUnsignedConst*(uintval: LONGINT): OPT.Node;
(* создание новой знаковой константы, по соответствующей (кодируемой той же комбинацией битов)
беззнаковой константе uintval *)
VAR x: OPT.Node;
BEGIN
x := OPT.NewNode(Nconst); x^.conval := OPT.NewConst();
x^.conval^.intval :=SHORT( uintval); SetUnsignedType(x); RETURN x
END NewUnsignedConst;
К сожалению, это будет работать только для 1 и 2 байтовых типов. Для 4-байтового возможно переполнение при вычислении количества итераций. Будем думать.
Цитата:
Размер LONGINT для Wintel я бы конечно предпочёл сделать 64-битным. Это было бы полезно и для x86-64, и для ARM. И вписать в Ofront.par циферку 8 — не проблема, но чтобы это заработало — код, видимо, придётся серьёзно фиксить под эту возможность.
Да, придется фиксить. Ввести еще 1 константу типа и переменные для ее границ тоже не сложно, задать conval^.intval:LONGINT тоже. Но вот что-то не работает LONGINT в ББ. Т.е. он вроде бы и есть, но вот пользоваться им так свободно, как прочими типами не получается - срабатывает
ASSERT(reg IN WReg) в компиляторе ББ. Если уж в самом ББ 64-разрядность ограничена, то вряд ли нам удастся так легко ввести ее в Ofront.