Оберон-клуб «ВЄДАsoft»

Твердыня модульных языков
Текущее время: 05 фев 2025, 09:36

Часовой пояс: UTC + 2 часа




Начать новую тему Ответить на тему  [ Сообщений: 20 ]  На страницу 1, 2  След.
Автор Сообщение
СообщениеДобавлено: 25 фев 2013, 05:39 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
Подготовил примерчик, показывающий как работать с беззнаковыми числами.
Код: "OBERON"
  1. MODULE Unsigned;
  2. IMPORT SYSTEM, P := Platform, B := Basic;
  3.  
  4. TYPE
  5. BYTE = SYSTEM.SHORTCARD;
  6. VAR
  7. byte: BYTE; (* 0..255 *)
  8.  
  9. BEGIN
  10. B.PAPER(B.Black); B.INK(B.Blue); B.BRIGHT(B.On);
  11. byte := P.Unsigned(150);
  12. REPEAT
  13. B.PRWORD(byte); B.PRCHAR(" "); DEC(byte); (* Print numbers 150 to 61 *)
  14. UNTIL byte = 60;
  15. B.INK(B.Cyan); B.BRIGHT(B.Off);
  16. FOR byte := 60 TO P.Unsigned(150) DO
  17. B.PRWORD(byte); B.PRCHAR(" "); (* Print numbers 60 to 150 *)
  18. END;
  19. B.INK(B.Green);
  20. byte := P.Unsigned(-1);
  21. B.PRWORD(byte); B.PRCHAR(" "); (* Print Unsigned(-1) as byte *)
  22. B.PRWORD(P.Unsigned(-1)); (* Print Unsigned(-1) as word *)
  23. END Unsigned.
Проблемы всё ещё есть, например, импортированные из других модулей (кроме SYSTEM) беззнаковые типы и переменные считаются знаковыми. Решать их предлагаю по мере необходимости в данном подходе. Мне важно показать, что всё, что понадобится, в технологию XDev/ZXDev можно добавить, причём не только библиотеки, но даже новые языковые конструкции, и сделать это достаточно легко.


Вложения:
Комментарий к файлу: Как работать с беззнаковыми числами
Unsigned.png
Unsigned.png [ 20.33 КБ | Просмотров: 25454 ]
Unsigned.tap [624 байт]
Скачиваний: 1120
Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 02 мар 2013, 11:18 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
В принципе, пока введены только два средства для работы с беззнаковыми числами:

    a) типы SYSTEM.SHORTCARD {0..255}, SYSTEM.CARDINAL {0..65535} и SYSTEM.LONGCARD (путём небольшого допиливания транслятора Ofront);

    b) функция Platform.Unsigned, которая трактует значение как беззнаковое.

Platform.Unsigned эффективна, и никакого оверхеда здесь нет — ведь на самом деле это не функция, а обёртка для приведения типа к беззнаковому, и реализована так:
Код: "EMPTY"
#define Platform_Unsigned(i) ((unsigned)(i)) 
Я тут подумал о том, что написанные с её помощью программы будет нетрудно портировать на другие диалекты и реализации Оберона, но лучше всё-таки не применять её для приведения заведомо отрицательных значений к положительным. А применять по назначению — чтобы втиснуть, допустим, в беззнаковый байт то, что в знаковый не влезет. И лучше не использовать Unsigned для обрезки старших битов в качестве &0xFF и &0xFFFF — Ofront’овские MOD 256 и MOD 65536 реализованы для эффективности именно через логическое “и”.

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

Ну а беззнаковые я ввёл не для путаницы, а потому что попросили спектрумисты, ну и чтобы посмотреть, что из этого получится. :)


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 10 апр 2013, 19:45 
Не в сети
Администратор
Аватара пользователя

Сообщения: 273
Откуда: Россия
В вышеприведенном примере попытался перебрать числа в байте с шагом 130 (ведь 130 входит в диапазон 0..255). Но не смог откомпилировать:
FOR byte := 60 TO P.Unsigned(190) BY 130 говорит, что число слишком большое.
FOR byte := 60 TO P.Unsigned(190) BY P.Unsigned(130) требует в качестве шага константное выражение.

Опытным путем убеждаемся, что допустим шаг в диапазоне -128..127. Получается, что FOR считает байт знаковым, несмотря на BYTE = SYSTEM.SHORTCARD;
MIN(BYTE), MAX(BYTE) тоже дают (-128) и 127 соответственно.
Это потому, что "допиливание транслятора Ofront" было "небольшое" и не затронуло MIN,MAX и шаг FOR?

_________________
А кроме того, я думаю, что корFORген должен быть разрушен!


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 10 апр 2013, 21:39 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
Saferoll писал(а):
Получается, что FOR считает байт знаковым, несмотря на BYTE = SYSTEM.SHORTCARD;
MIN(BYTE), MAX(BYTE) тоже дают (-128) и 127 соответственно.
Это потому, что "допиливание транслятора Ofront" было "небольшое" и не затронуло MIN,MAX и шаг FOR?
Да.

Но это не FOR считает байт знаковым. Это весь Ofront считает все беззнаковые типы знаковыми и дальше, хотя уже и описывает их в сишном исходнике по-другому.

Проблема возникает из-за того, что Ofront проверяет все константные выражения на допустимость присваивания заданному типу — влезает ли присваивание по разрядности. Поскольку беззнаковые — это в сделанной мною реализации просто флёр над Офронтом, чтобы типы описывались как беззнаковые, а по сути он продолжает считать их теми же знаковыми. Чтобы обойти контроль — мною сперва предлагалось замаскировать бОльшие, чем это допустимо, значения с помощью обёртки Platform.Unsigned, однако ты обнаружил ситуацию, в которой это не работает. Самое простое, что можно сделать, — это отключить проверку на допустимость присваивания вообще (потеряется возможность контролировать при компиляции выход за пределы типа). Ещё лучше было бы конечно усовершенствовать проверку, чтобы она корректно работала и для беззнаковых типов, что я и собираюсь сделать. Это действительно проблема, которая требует вдумчивого допиливания. Я уверен, там строчку-другую кода поправить, но очень много времени нужно чтобы понять, что именно править. Но что ж, проблема назрела — буду ею заниматься. Может заодно и в направлении реализации «правильного» FOR продвинемся.


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 11 апр 2013, 18:21 
Не в сети
Администратор
Аватара пользователя

Сообщения: 273
Откуда: Россия
Цитата:
Поскольку беззнаковые — это в сделанной мною реализации просто флёр над Офронтом, чтобы типы описывались как беззнаковые, а по сути он продолжает считать их теми же знаковыми.
Т.е. всякие SYSTEM.SHORTCARD - это просто пометки имеющихся знаковых типов, учитываемые только при трансляции в Си (signed или unsigned)? А до трансляции всё так знаковое и есть и разницы между SHORTCARD и SYSTEM.BYTE нету? Я не так представлял... :( Правда глубоко и не исследовал.
Цитата:
Чтобы обойти контроль — мною сперва предлагалось замаскировать бОльшие, чем это допустимо, значения с помощью обёртки Platform.Unsigned, однако ты обнаружил ситуацию, в которой это не работает.
А нельзя сделать, чтобы Platform.Unsigned (константное выражение) тоже считалось константным выражением?
Цитата:
Самое простое, что можно сделать, — это отключить проверку на допустимость присваивания вообще (потеряется возможность контролировать при компиляции выход за пределы типа). Ещё лучше было бы конечно усовершенствовать проверку, чтобы она корректно работала и для беззнаковых типов, что я и собираюсь сделать. Это действительно проблема, которая требует вдумчивого допиливания. Я уверен, там строчку-другую кода поправить, но очень много времени нужно чтобы понять, что именно править. Но что ж, проблема назрела — буду ею заниматься. Может заодно и в направлении реализации «правильного» FOR продвинемся.
У FOR диапазон возможных значений для шага должен быть совсем другим, не как сейчас "Step имеет такой же тип, как и переменная n". Иначе мы не сможем написать FOR n:=255 TO 0 BY -1, ведь (-1) вне диапазона 0..255! Подробнее в другой теме.

_________________
А кроме того, я думаю, что корFORген должен быть разрушен!


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 11 апр 2013, 19:21 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
Saferoll писал(а):
Т.е. всякие SYSTEM.SHORTCARD - это просто пометки имеющихся знаковых типов, учитываемые только при трансляции в Си (signed или unsigned)?
В текущей реализации — да, действительно всё обстоит именно так.

Saferoll писал(а):
А до трансляции всё так знаковое и есть и разницы между SHORTCARD и SYSTEM.BYTE нету?
Разница есть. Попробуй откомпилировать цикл со счётчиком типа SYSTEM.BYTE. Как я понимаю, тип BYTE в Обероне вообще не предназначен для арифметических операций, а служит для системных нужд, а также в качестве прослойки для совместимости несистемных типов (например, ARRAY OF SYSTEM.BYTE ложится на ARRAY OF CHAR).

Saferoll писал(а):
А нельзя сделать, чтобы Platform.Unsigned (константное выражение) тоже считалось константным выражением?
Это сделать очень непросто, т.к. модуль Platform является для Офронта равнозначным с другими модулями, да и идеологически наверное всё-таки плохо. Гораздо проще сделать SYSTEM.Unsigned, но надо продумать его семантику. Разрешить ему преобразовывать насильно отрицательные значения в положительное, как машине на голову вздумается (или как повсеместно принято), или же по-обероновски контролировать приведение типов на выход за пределы значений. Мне кажется, Platform.Unsigned должен потерять свой смысл когда будут нормально реализованы беззнаковые типы (чтобы контроль присваивания, MAX и MIN учитывали беззнаковость). Я придумал ещё случай, где не сработает Platfrom.Unsigned — это метка CASE.

Saferoll писал(а):
У FOR диапазон возможных значений для шага должен быть совсем другим, не как сейчас "Step имеет такой же тип, как и переменная n". Иначе мы не сможем написать FOR n:=255 TO 0 BY -1, ведь (-1) вне диапазона 0..255!
Ты прав, этот случай обязательно надо учесть.

Согласен, я реализовываю беззнаковые не научно, без тщательной продумки, а как придётся, но на самом деле невесело было делать это только для себя самого. Теперь хоть интереса побольше. :)

А путь доработки Офронта, возможно, не так прост, как я думаю. Автор Офронта Josef Templ высказался о введении в его детище беззнаковых типов так:
Josef Templ писал(а):
As far as I know, there is no simple way to support new types without significantly extending the compiler incl. the symbol file format and the code generator. This may get messy.

What you can do is use native code procedures for calling special functions (expressed as macros in Ofront) on such types by casting to unsigned types but defining the parameters as signed types.


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 11 апр 2013, 20:36 
Не в сети
Администратор
Аватара пользователя

Сообщения: 273
Откуда: Россия
Цитата:
Это сделать очень непросто, т.к. модуль Platform является для Офронта равнозначным с другими модулями, да и идеологически наверное всё-таки плохо.
Верно ли я понял, что Platform.Unsigned внутри Оберона - это функция, транслирующая числа 128..255 в -128..-1. А в Си она волшебным образом превращается в макрос #define Platform_Unsigned(i) ((unsigned)(i)) ? Так и все обероновские процедуры библиотеки Basic пустые, т.е .вроде бы ничего не должны делать, а в Си они подменяются на процедуры с кусочками кодов на Ассемблере?

_________________
А кроме того, я думаю, что корFORген должен быть разрушен!


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 11 апр 2013, 21:44 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
Да, всё верно, Олег.

    Для библиотек Lib/Mod:

На Обероне мы делаем модуль с описанием типов, констант, но только заглушек процедур, Ofront транслирует это в Lib/Obj, и мы получаем ценный для наших нужд символьный файл Lib/Sym/LibModule.sym, который важен, когда мы хотим импортировать этот библиотечный модуль.

Файлы Lib/Obj/LibModule.h и Lib/Obj/LibModule.c, которые сгенерировал Ofront, мы не компилируем, а вместо них компилируем Lib/LibModule.h и Lib/LibModule.c, которые написаны ручками на Си. В них конечно могут быть и асмовые вставки, и прямое включение заголовков сишных библиотек, ОС API и что угодно другое.

Если мы хотим писать библиотеки на Обероне — последовательность действий та же самая: кусочки сгенерированного Офронтом сишного кода переносим из Lib/Obj/LibModule.c в Lib/LibModule.c вручную. Автоматизировать этот процесс вряд ли разумно, ведь есть ещё Си-фактор смартлинковки. Чтобы она получилась — нам надо разделить все сущности на атомы, помещая между сущностями комментарий специального вида. Вот здесь об этом подробнее (а также в разделе ZXDev/Docu/ZXDevRus.txt "Умная" линковка (smart linking) ).

    Для модулей Mod:

Все Оберон-исходники на Си автоматически транслирует Ofront, продуцируя Obj/Module.h, Obj/Module.c и Sym/Module.sym. Их компилируем, их собираем. Возможность смарт-линковки при этом теряется.

В подсистеме WinDev не применяются куски на ассемблере, ведь Ofront позволяет определить системные процедуры, описанные как вызов сишных, но, к сожалению, не позволяет подставить в тело обероновской сишную процедуру во много строк, в которой можно применить и асмовые вставки (может я не нашёл как это сделать?). В целях смартлинковки всё делаю так же, как и в ZXDev (т.е. написаные на Обероне процедуры транслирую Офронтом в Си и ручками переношу в сишные исходники).

Если есть мысли как усовершенствовать технологию процесса — милости прошу.


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 14 апр 2013, 16:20 
Не в сети
Администратор
Аватара пользователя

Сообщения: 273
Откуда: Россия
Zorko писал(а):
Saferoll писал(а):
У FOR диапазон возможных значений для шага должен быть совсем другим, не как сейчас "Step имеет такой же тип, как и переменная n". Иначе мы не сможем написать FOR n:=255 TO 0 BY -1, ведь (-1) вне диапазона 0..255!
Ты прав, этот случай обязательно надо учесть.
Для FOR можно пока оставить знаковый шаг. Это на практике не слишком плохо и пока терпимо.

Zorko писал(а):
Я придумал ещё случай, где не сработает Platfrom.Unsigned — это метка CASE.
Вот c CASE хуже. Для чего нужен Platform.Unsigned? Чтобы написать Platform.Unsigned(255) и в тексте программы было видно 255, а на самом деле стояло "-1"? Так может вместо функции завести набор констант: Platform.Unsigned_255=-1; Platform.Unsigned_254=-2;... Platform.Unsigned_128=-128? Писать константу, где в имени видно нужное беззнаковое число, а фактически будет знаковое.

_________________
А кроме того, я думаю, что корFORген должен быть разрушен!


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 14 апр 2013, 18:54 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
Да, но будем рассматривать это решение не более чем временное. А "шобы всё по уму" — конечно же надо без этого. Я, кстати, хотел бы внести в Ofront и другие изменения — кроме "правильных" беззнаковых типов и "правильного FOR", реализующих более надёжную и удобную работу с типами малой разрядности, также ещё и константные массивы, параметры процедур IN (с контролем неизменности) и OUT как в КП, ведь сейчас в Обероне-2 все массивы, переданные не как VAR, копируются, а в ряде случаев это лишние накладные расходы. Я, грешным делом, надеялся, что компилятор сам сможет определить, копировать массив или можно без этого обойтись, но ни в одной реализации Оберона такого автоопределения нет (да и для этого нужен многопроходный компилятор). Но от IN ещё польза есть — грубо ткнёт носом, когда аргумент, помеченный как неизменный, попытаются изменить. Альтернатива для указания, что массив можно не копировать, — директива, как в Amiga Oberon. Остроумно, но решение не на постоянку (выглядит как заплатка, затыкающая прореху в языке (или реализации, вернее, во всех реализациях)):
Код: "OBERON"
  1. PROCEDURE Request(Text: ARRAY OF CHAR); (* $CopyArrays- *)


Вернуться к началу
 Профиль  
Ответить с цитатой  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 20 ]  На страницу 1, 2  След.

Часовой пояс: UTC + 2 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Создано на основе phpBB® Forum Software © phpBB Group
© VEDAsoft Oberon Club