OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Четверг, 02 Февраль, 2023 04:36

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




Начать новую тему Ответить на тему  [ Сообщений: 31 ]  На страницу Пред.  1, 2
Автор Сообщение
 Заголовок сообщения: Re: Процедурные типы
СообщениеДобавлено: Понедельник, 14 Ноябрь, 2022 15:12 

Зарегистрирован: Воскресенье, 06 Август, 2017 19:33
Сообщения: 70
adimetrius писал(а):
При выгрузке модулей та же проблема вообще с любыми указателями: выгрузили М, а переменная п: М.Т осталась, и попытки вызвать связанные с М.Т процедуры - тоже в никуда. И в текущей реализации (в линукс) последствия непредсказуемы, т.к. платформенная защита памяти от исполнения не используется. Но, как я понимаю идеологию ББ: выгрузка модулей - действие этапа разработки, в "боевой системе" этого делать не следует; поэтому соответствующие защиты не реализованы.

В BlackBox`е для Windows импортируемый модуль можно выгрузить только после импортирующего.

Обычно я использую абстрактные процедуры когда надо описать что-то общее, универсальное, детали которого ещё не известны. Например, я абстрактные процедуры использовал для сортировки, когда сортирующая программа ничего не знает о ключах, по которым сравниваются два элемента:
Код:
CONST
   AsmallerB = 1;
   AequalB = 2;
   AlargerB = 3;
TYPE
   Element = POINTER TO ABSTRACT RECORD
   END;
   List = RECORD
      elements: ARRAY 100 OF Element;
   END;

PROCEDURE (a: Element) Compare* (b: Element): BYTE, NEW, ABSTRACT;

PROCEDURE (VAR obj: List) Sort*, NEW;
VAR
   i: INTEGER;
...
BEGIN
...
   CASE obj.elements[i].Compare (obj.elements[i+1]) OF
   AsmallerB: ...
   | AequalB: ...
   | AlargerB: ...
   ELSE
      ...
   END
...
END Sort;


Мне сейчас непонятно, как пользоваться процедурой, передаваемой как параметр. А именно, как указать тело этой процедуры, и как её вызвать? Она что, вызывается при присваивании?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Процедурные типы
СообщениеДобавлено: Вторник, 15 Ноябрь, 2022 02:45 

Зарегистрирован: Четверг, 08 Май, 2008 19:13
Сообщения: 1412
Откуда: Киев
Александр К писал(а):
В BlackBox`е для Windows импортируемый модуль можно выгрузить только после импортирующего.

Как раз благодаря косвенности ссылка на тип выгруженного модуля и может остаться у кода модуля, который не импортировал его напрямую.
Код:
MODULE A; 
IMPORT Log;
TYPE T* = POINTER TO EXTENSIBLE RECORD END;
VAR v: T;

PROCEDURE (v: T) Do*, NEW, EXTENSIBLE;
BEGIN Log.String("A.T.Do"); Log.Ln
END Do;

PROCEDURE Do*; BEGIN v.Do END Do;
PROCEDURE Set*(new: T); BEGIN v := new END Set;
BEGIN NEW(v)
END A.

(!)A.Do
Код:
MODULE B;
IMPORT A, Log;
TYPE T = POINTER TO RECORD(A.T) END;
PROCEDURE (v: T) Do*;
BEGIN
   Log.String("B: T.Do"); Log.Ln
END Do;

PROCEDURE Install*;
VAR v: T;
BEGIN
  NEW(v);
  A.Set(v)
END Install;

END B.

(!)B.Install
(!)DevDebug.Unload


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Процедурные типы
СообщениеДобавлено: Вторник, 15 Ноябрь, 2022 03:02 

Зарегистрирован: Четверг, 08 Май, 2008 19:13
Сообщения: 1412
Откуда: Киев
Александр К писал(а):
Мне сейчас непонятно, как пользоваться процедурой, передаваемой как параметр. А именно, как указать тело этой процедуры, и как её вызвать? Она что, вызывается при присваивании?
Что в случае с процедурой, что в случае с записью сравнитель лучше вынести в отдельную переменную, потому что одни и те же элементы может понадобиться сравнивать по разному. Сам же элемент мог бы выдавать некий сравнитель по умолчанию.

Код:
TYPE
   Element* = POINTER TO ABSTRACT RECORD END;
   Compare* = PROCEDURE (a, b: Element): INTEGER;

PROCEDURE (a: Element) DefaultComparator*(): Compare, NEW, ABSTRACT;

PROCEDURE Sort*(elements: ARRAY OF Element; compare: Compare);
VAR
   i: INTEGER;
...
BEGIN
   IF compare = NIL THEN
      compare := elements[0].DefaultComparator();
   END;
...
   CASE compare(obj.elements[i], obj.elements[i+1]) OF
    -1: ...
   | 0: ...
   | 1: ...
   END
...
END Sort;

Код:
TYPE
   Element* = POINTER TO ABSTRACT RECORD END;
   Compare* = POINTER TO ABSTRACT RECORD END;

PROCEDURE (c: Compare) Do*(a, b: Element): INTEGER, NEW, ABSTRACT;
PROCEDURE (a: Element) DefaultComparator*(): Compare, NEW, ABSTRACT;

PROCEDURE Sort*(elements: ARRAY OF Element; compare: Compare);
VAR
   i: INTEGER;
...
BEGIN
   IF compare = NIL THEN
      compare := elements[0].DefaultComparator();
   END;
...
   CASE compare.Do(obj.elements[i], obj.elements[i+1]) OF
    -1: ...
   | 0: ...
   | 1: ...
   END
...
END Sort;


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Процедурные типы
СообщениеДобавлено: Среда, 16 Ноябрь, 2022 13:24 
Аватара пользователя

Зарегистрирован: Суббота, 16 Февраль, 2008 02:47
Сообщения: 635
Александр К писал(а):
Мне сейчас непонятно, как пользоваться процедурой, передаваемой как параметр. А именно, как указать тело этой процедуры, и как её вызвать? Она что, вызывается при присваивании?

Код:
MODULE M;
 
  TYPE Proc = PROCEDURE (x: INTEGER; ch: CHAR): BOOLEAN;
 
  PROCEDURE Lss (x: INTEGER; ch: CHAR): BOOLEAN; BEGIN RETURN ORD(ch) < x END A;
  ​PROCEDURE Gtr (x: INTEGER; ch: CHAR): BOOLEAN; BEGIN RETURN ORD(ch) > x ​END B;
 
  PROCEDURE Do (x: INTEGER; ch: CHAR; action: Proc);
    VAR res: BOOLEAN;
  BEGIN
    ASSERT(action # NIL, 20);  (* процедурные переменные можно сравнивать с NIL *)
    res := action(x, ch);  (* вызов процедуры, присвоенной параметру action *)
    res := action(x + 1, ch)    (* еще раз вызов процедуры, присвоенной параметру action *)
  END Do;
 
  PROCEDURE P;
  BEGIN
    Do(1, 'A', Lss);    (* процедура Lss присваивается параметру action. Но здесь Lss не вызывается *)
    Do(1, 'A', Gtr);    (* процедура Gtr присваивается параметру action. Но здесь Gtr не вызывается *)
    Do(1, 'A', NIL)    (* NIL присваивается параметру action. Это кончится авостом 20, т.к. Do на такое не рассчитана *)
  END P;

END M.


Именовать процедурные типы необязательно: PROCEDURE P (do: PROCEDURE (x: INTEGER)), поскольку в отношении них, как видно, действуют правила структурной совместимости, о которых писал Comdiv.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Процедурные типы
СообщениеДобавлено: Среда, 16 Ноябрь, 2022 13:32 
Аватара пользователя

Зарегистрирован: Суббота, 16 Февраль, 2008 02:47
Сообщения: 635
Comdiv писал(а):
adimetrius писал(а):
При выгрузке модулей та же проблема вообще с любыми указателями: выгрузили М, а переменная п: М.Т осталась, и попытки вызвать связанные с М.Т процедуры - тоже в никуда. И в текущей реализации (в линукс) последствия непредсказуемы, т.к. платформенная защита памяти от исполнения не используется. Но, как я понимаю идеологию ББ: выгрузка модулей - действие этапа разработки, в "боевой системе" этого делать не следует; поэтому соответствующие защиты не реализованы.
Тут, видимо, дело в трактовке процедурного типа - если его воплощать максимально прямо, а не как более сложный неявный объект, то переменная процедурного типа будет просто указателем на код без привязки к модулю с возможностью вызова непонятно чего. У объекта же потенциально больше возможностей по предотвращению обращения куда попало, пусть и с последствиями для кода, который пытается это делать.


Это, конечно, вопрос реализации, а не самого языка.
Большей устойчивости можно добиться и без объекта, а за счет запрета на исполнение в адресных промежутках, в которых располагался текст модуля, после его выгрузки. Если, конечно, платформа предусматривает такие средства.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Процедурные типы
СообщениеДобавлено: Среда, 16 Ноябрь, 2022 13:37 
Аватара пользователя

Зарегистрирован: Суббота, 16 Февраль, 2008 02:47
Сообщения: 635
Александр К писал(а):
adimetrius писал(а):
При выгрузке модулей та же проблема вообще с любыми указателями: выгрузили М, а переменная п: М.Т осталась, и попытки вызвать связанные с М.Т процедуры - тоже в никуда. И в текущей реализации (в линукс) последствия непредсказуемы, т.к. платформенная защита памяти от исполнения не используется. Но, как я понимаю идеологию ББ: выгрузка модулей - действие этапа разработки, в "боевой системе" этого делать не следует; поэтому соответствующие защиты не реализованы.

В BlackBox`е для Windows импортируемый модуль можно выгрузить только после импортирующего.

В любом ББ, конечно, так же. Но.
Модуль М может быть загружен, даже если его ни один другой модуль не импортирует. Например, М реализует некий вид В, я открываю вид типа В в окне, и затем выгружаю М. Выгрузка позволяется, поскольку никто не импортирует М; а следом возникает авария (или "зависание"), поскольку система вызывает процедуры открытого в окне вида типа М.В.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Процедурные типы
СообщениеДобавлено: Среда, 16 Ноябрь, 2022 21:59 

Зарегистрирован: Четверг, 08 Май, 2008 19:13
Сообщения: 1412
Откуда: Киев
adimetrius писал(а):
Это, конечно, вопрос реализации, а не самого языка.
Отчего же, для дизайна таких языков как Oberon не принято прятать что-то более сложное за чем-то более простым, иначе, вместо исключения процедурного типа, можно было говорить о его представлении как синтаксического сахара для небольшой записи.
Цитата:
Большей устойчивости можно добиться и без объекта, а за счет запрета на исполнение в адресных промежутках, в которых располагался текст модуля, после его выгрузки. Если, конечно, платформа предусматривает такие средства.
Большая "устойчивость" за счёт исчерпания адресного пространства с учётом прошлого, да и пока ещё текущего состояния Blackbox.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Процедурные типы
СообщениеДобавлено: Четверг, 17 Ноябрь, 2022 00:04 
Аватара пользователя

Зарегистрирован: Суббота, 16 Февраль, 2008 02:47
Сообщения: 635
Comdiv писал(а):
Большая "устойчивость" за счёт исчерпания адресного пространства с учётом прошлого, да и пока ещё текущего состояния Blackbox.

Да; у такого решения, как и любого, есть свой "за счет".
Исчерпание адресного пространства м.б. проблемой для долгоживущих активаций ББ. А выгрузка модулей, как я писал выше - операция времени разработки, т.е. используется в АРМ программиста. Является ли АРМ долгоживущей активацией? Вряд ли.
Организовать "исчерпывающую (адресное простанство)" защиту от выполнения мусорных байт легче, чем синтаксический сахар, т.к. не нужно править компилятор и среду выполнения; достаточно только среду.
Другое дело, если вообразить такую задачу: неограниченно долго работающий исполнитель на базе ББ получает команды, в ответ загружает некие модули, а по завершении команд или сессий может выгружать ненужные модули; и такой сервер должен работать неограниченно долго. Веб-сервер ББ-приложений, короче говоря. Тогда, вероятно, нельзя разбрасываться адресным пространством.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Процедурные типы
СообщениеДобавлено: Четверг, 17 Ноябрь, 2022 03:04 

Зарегистрирован: Четверг, 08 Май, 2008 19:13
Сообщения: 1412
Откуда: Киев
adimetrius писал(а):
А выгрузка модулей, как я писал выше - операция времени разработки, т.е. используется в АРМ программиста.Является ли АРМ долгоживущей активацией? Вряд ли.
Вы-то писали, но почему-то забыли работу с плагинами, да и в долгоживущем АРМ не вижу ничего необычного, если конечно, оно не будет вынуждать себя постоянно перезапускать.
adimetrius писал(а):
Другое дело, если вообразить
Вы так пишете, как-будто это не банальщина, а ведь BlackBox - это ОС, пусть и недо, если такое определение кого-то коробит.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Процедурные типы
СообщениеДобавлено: Суббота, 31 Декабрь, 2022 19:18 
Аватара пользователя

Зарегистрирован: Воскресенье, 09 Декабрь, 2018 15:14
Сообщения: 95
Откуда: Equestria
adimetrius писал(а):
Comdiv писал(а):
adimetrius писал(а):
При выгрузке модулей та же проблема вообще с любыми указателями: выгрузили М, а переменная п: М.Т осталась, и попытки вызвать связанные с М.Т процедуры - тоже в никуда. И в текущей реализации (в линукс) последствия непредсказуемы, т.к. платформенная защита памяти от исполнения не используется. Но, как я понимаю идеологию ББ: выгрузка модулей - действие этапа разработки, в "боевой системе" этого делать не следует; поэтому соответствующие защиты не реализованы.
Тут, видимо, дело в трактовке процедурного типа - если его воплощать максимально прямо, а не как более сложный неявный объект, то переменная процедурного типа будет просто указателем на код без привязки к модулю с возможностью вызова непонятно чего. У объекта же потенциально больше возможностей по предотвращению обращения куда попало, пусть и с последствиями для кода, который пытается это делать.


Это, конечно, вопрос реализации, а не самого языка.
Большей устойчивости можно добиться и без объекта, а за счет запрета на исполнение в адресных промежутках, в которых располагался текст модуля, после его выгрузки. Если, конечно, платформа предусматривает такие средства.

в мак-версии бб указатели на процедуру косвенные. а когда модуль выгружается - они подменяются на код для трапа "nil procedure dereference". причем эта фича кажется вообще не зависит от бэкэнда компилятора. надо только включать режим pVarInd в DevCPE и подменять указатели в Kernel.UnloadMod. так что можно вообще ничего не выдумывать.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Процедурные типы
СообщениеДобавлено: Вторник, 03 Январь, 2023 14:08 
Аватара пользователя

Зарегистрирован: Суббота, 16 Февраль, 2008 02:47
Сообщения: 635
Я недавно сделал себе ProtectedUnload, которая "зачищает" таблицы типовых процедур в дескрипторах типов - точнее, заносит адрес процедуры, вызывающей авост. Это для меня полезно, поскольку я делаю модули с видами; при перезагрузке модуля, если где-то остался в окнах его вид, поведение - зависание, падение всего ББ, при первом же вызове Restore. Теперь, при ProtectedUnload, нет зависаний и падений ББ, а возникает обычный авост, потом можно окно с устаревшим видом закрыть, а иногда - просто удалить вид из его контейнера.

Любопытно, если комплиятор может стоить таблицы процедур на i386 и делать косвенные вызовы. Вопрос, однако, в процедурных переменных: там что же, двойная косвенность - ссылка на таблицу, а оттуда - на процедуру?


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

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


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

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


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

Найти:
cron
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2022, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB