Oberon space

General Category => Общий раздел => Тема начата: valexey_u от Сентябрь 04, 2013, 11:21:23 am

Название: [Oberon-07/11] RECORD&POINTER export.
Отправлено: valexey_u от Сентябрь 04, 2013, 11:21:23 am
В Oberon-report'e этот момент не уточнен (и вообще никак не описан), поэтому предлагаю обсудить, уточнить и договориться.

Итак, ситуация следующая - модуль A экспортирует указатель на структурный тип A.R, но сам A.R не экспортирует. Может ли модуль B импортирующий A.R создать в куче переменную типа A.R?

Код:
MODULE A;
TYPE
 R = RECORD END;
 P* = POINTER TO R;
END A.

MODULE B;
IMPORT A;
VAR
 p : A.P;
BEGIN
 NEW(p)
END B.
Технически мы это можем без проблем. Но в некоторых реализациях такое вот может быть не возможно, кроме того, если такое разрешить, то по сути мы лишаемся возможности создавать opaque-типы простым способом. Кроме того возникает логическое противоречие - почему то локальную переменную мы завести не можем, а переменную через NEW уже можем.

Поэтому предлагаю следующее:
1) Если импортирован только указательный тип, то с указателем можно делать все что обычно, но нельзя NEW. То есть новых экземпляров типа R пользователь заводить не может нигде.

2) Если импортирован еще и сам структурный тип (record or array), то создавать экземпляры (через NEW или иначе) можно, а доступ есть к тем полям которые экспортированны (помечены звездочкой), можно КОПИРОВАТЬ экземпляры (statement ":="). При этом конечно возможна ситуация когда тип экспортирован, но ни одного поля не экпортированно. Увы :-)

Ну и наконец есть особый случай, который тоже неоднозначен, и про который в репорте нет ничего:
MODULE A;
TYPE
 P* = POINTER TO RECORD foo* : INTEGER END;
END A.

MODULE B;
IMPORT A;
VAR
 p : A.P;
BEGIN
 NEW(p); (* это можно? *)
 p.foo := 42 (* а это? *)
END B.
Экспортирован тип-указатель на анонимную запись, причем у этой записи есть экспортированные поля. Таким образом переменную типа этой самой записи пользователь создать не может. Но, очевидно, он может обратиться к полю. Но может ли он создать через NEW новый экземпляр таковой безымянной записи?

Предлагаю создание экземпляра через NEW, в этом случае, также запретить. Таким образом у нас получается возможность создавать типы переменные которых могут создаваться ТОЛЬКО через фабрики (где они будут гарантированно инициализированны корректно), но при этом остается возможность прямого обращения к некоторым полям. (кроме того, опять таки, это логично, что если я не могу создать локальную переменную, то и через NEW тоже не могу её создать).

Как-то так. Какие будут мнения?
Название: Re: [Oberon-07/11] RECORD&POINTER export.
Отправлено: Geniepro от Сентябрь 04, 2013, 11:51:32 am
В Oberon-report'e этот момент не уточнен (и вообще никак не описан), поэтому предлагаю обсудить, уточнить и договориться.

Итак, ситуация следующая - модуль A экспортирует указатель на структурный тип A.R, но сам A.R не экспортирует. Может ли модуль B импортирующий A.R создать в куче переменную типа A.R?

Не могу согласиться с этим утверждением:

Цитата: Oberon07.Report
4. Declarations and scope rules
...
The scope rule has the following amendments:

1. If a type T is defined as POINTER TO T1 (see 6.4), the identifier T1 can be declared textually following the declaration of T, but it must lie within the same scope.

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

Экспорт какой-либо сущности -- это по сути расширение области видимости этой сущности на другие модули (через квалифицированный импорт), а значит, экспортироваться должен не только тип, указывающий на запись/массив, но и сами эти запись/массив...
Название: Re: [Oberon-07/11] RECORD&POINTER export.
Отправлено: Kemet от Сентябрь 04, 2013, 11:53:10 am
Поля записи, отмеченные знаком экспорта, должны быть доступны через экспортированный тип указателя на эту запись, независимо от того, экспортирован тип записи или нет, именован или нет.
Название: Re: [Oberon-07/11] RECORD&POINTER export.
Отправлено: valexey_u от Сентябрь 04, 2013, 11:57:49 am
В Oberon-report'e этот момент не уточнен (и вообще никак не описан), поэтому предлагаю обсудить, уточнить и договориться.

Итак, ситуация следующая - модуль A экспортирует указатель на структурный тип A.R, но сам A.R не экспортирует. Может ли модуль B импортирующий A.R создать в куче переменную типа A.R?

Не могу согласиться с этим утверждением:

Цитата: Oberon07.Report
4. Declarations and scope rules
...
The scope rule has the following amendments:

1. If a type T is defined as POINTER TO T1 (see 6.4), the identifier T1 can be declared textually following the declaration of T, but it must lie within the same scope.

Как видно, тут написано, что тип, на который указывает указательный тип, должен быть видимым в той области видимости, где находится сам этот указательный тип.
Тут говорится о валидности объявлений (declaration, процесса объявления новых типо), я же говорю и спрашиваю о экспорте и импорте. То есть не про объявления, это разные понятия.
Название: Re: [Oberon-07/11] RECORD&POINTER export.
Отправлено: Geniepro от Сентябрь 04, 2013, 12:01:12 pm
Ну и наконец есть особый случай, который тоже неоднозначен, и про который в репорте нет ничего:
MODULE A;
TYPE
 P* = POINTER TO RECORD foo* : INTEGER END;
END A.

А вот, похоже, экспортировать указатели на анонимные записи вряд ли можно.
Но тогда, по аналогии, нельзя экспортировать и указатели на процедуры?
Название: Re: [Oberon-07/11] RECORD&POINTER export.
Отправлено: Geniepro от Сентябрь 04, 2013, 12:04:36 pm
Тут говорится о валидности объявлений (declaration, процесса объявления новых типо), я же говорю и спрашиваю о экспорте и импорте. То есть не про объявления, это разные понятия.

В оберонах модификатор экспорта -- это часть декларации. Так в чём проблема-то?
Название: Re: [Oberon-07/11] RECORD&POINTER export.
Отправлено: valexey_u от Сентябрь 04, 2013, 12:06:19 pm
Ну и наконец есть особый случай, который тоже неоднозначен, и про который в репорте нет ничего:
MODULE A;
TYPE
 P* = POINTER TO RECORD foo* : INTEGER END;
END A.

А вот, похоже, экспортировать указатели на анонимные записи вряд ли можно.
Но тогда, по аналогии, нельзя экспортировать и указатели на процедуры?
Ну, во первых указателей на процедуры в Обероне нет, есть лишь процедурные типы (пофиг как оно реализуется технически).

Во-вторых, почему нельзя? Процитированное тобою имеет несколько иные акценты:
Цитировать
1. If a type T is defined as POINTER TO T1 (see 6.4), the identifier T1 can be declared textually
following the declaration of T
, but it must lie within the same scope.
То есть это исключение из правил, то есть правило (1) введено для того, чтобы ослабить требования объявлений сверху-внизу для указателей. Всего лишь.
Название: Re: [Oberon-07/11] RECORD&POINTER export.
Отправлено: valexey_u от Сентябрь 04, 2013, 12:07:06 pm
Тут говорится о валидности объявлений (declaration, процесса объявления новых типо), я же говорю и спрашиваю о экспорте и импорте. То есть не про объявления, это разные понятия.

В оберонах модификатор экспорта -- это часть декларации. Так в чём проблема-то?
На тип этот модификатор никак не влияет. То есть не входит в сигнатуру.
Название: Re: [Oberon-07/11] RECORD&POINTER export.
Отправлено: Geniepro от Сентябрь 04, 2013, 12:23:00 pm
Ну, во первых указателей на процедуры в Обероне нет, есть лишь процедурные типы (пофиг как оно реализуется технически).

А, да, процедурные типы же без указателей объявляются, так что всё нормально тут... Вроде бы...
Название: Re: [Oberon-07/11] RECORD&POINTER export.
Отправлено: Kemet от Сентябрь 04, 2013, 12:27:36 pm
Поля записи, отмеченные знаком экспорта, должны быть доступны через экспортированный тип указателя на эту запись, независимо от того, экспортирован тип записи или нет, именован или нет.
Исходя из этого, объявить переменную типа экспортированный указатель на не экспортированную или безымянную запись и создать экземпляр он может, иначе полная бессмыслица получится.
Название: Re: [Oberon-07/11] RECORD&POINTER export.
Отправлено: Geniepro от Сентябрь 04, 2013, 12:29:51 pm
Исходя из этого, объявить переменную типа экспортированный указатель на не экспортированную или безымянную запись и создать экземпляр он может, иначе полная бессмыслица получится.

Это будет аналогией экземпляра класса сишарпа -- в куче создать можно, а на стеке -- нет...
Название: Re: [Oberon-07/11] RECORD&POINTER export.
Отправлено: Kemet от Сентябрь 04, 2013, 12:34:24 pm
Это будет аналогией экземпляра класса сишарпа -- в куче создать можно, а на стеке -- нет...
Мы и говорим про указатель
Название: Re: [Oberon-07/11] RECORD&POINTER export.
Отправлено: Geniepro от Сентябрь 04, 2013, 12:40:48 pm
Это будет аналогией экземпляра класса сишарпа -- в куче создать можно, а на стеке -- нет...

Мы и говорим про указатель

Блекбоксёры постоянно ставят в достоинство КП то, что в нём записи можно создавать не только в куче, но и на стеке, в отличие от Явы, где все объекты создаются только на куче.
Этим они объясняют высокую производительность свой шины сообщений.

Экспорт же записи только через указательный тип не позволит использовать такие записи на куче и сводит на нет это преимущество оберонов перед явой.

Так что с точки зрения оберонщиков такой экспорт лишён смысла...
Название: Re: [Oberon-07/11] RECORD&POINTER export.
Отправлено: DddIzer от Сентябрь 04, 2013, 12:43:14 pm
Лично моя позиция - не запрещено + имеет смысл = разрешено.
Название: Re: [Oberon-07/11] RECORD&POINTER export.
Отправлено: DddIzer от Сентябрь 04, 2013, 12:53:37 pm
 "за сценой", дополнительно - не  забудьте
1. Вирт и так ограничил по максимуму язык
2. Мы не имеем четкого представления куда идет эта реализация
3. УЖЕ получается не совсем то, что хотелось (в частности , строгости и непротиворечивости).
4. Любое ограничение уменьшает выгоду от простоты языка и накладывает трудно прогнозируемые ограничения на область использования
5. Мы пока еще неспособны аргументировать введение ограничений на хорошем уровне.
Название: Re: [Oberon-07/11] RECORD&POINTER export.
Отправлено: Kemet от Сентябрь 04, 2013, 12:58:15 pm
Блекбоксёры постоянно ставят в достоинство КП то, что в нём записи можно создавать не только в куче, но и на стеке, в отличие от Явы, где все объекты создаются только на куче.
Этим они объясняют высокую производительность свой шины сообщений.
Во всех Оберонах так - записи создаются в стеке, динамические(через указатель) экземпляры в куче.
Экспорт же записи только через указательный тип не позволит использовать такие записи на куче и сводит на нет это преимущество оберонов перед явой.
Для этого и предназначены opaque типы. Там, где нужны статические объекты в стеке - нужно использовать записи, естественно, экспортируя тип записи.
Название: Re: [Oberon-07/11] RECORD&POINTER export.
Отправлено: valexey_u от Сентябрь 04, 2013, 02:16:35 pm
"за сценой", дополнительно - не  забудьте
1. Вирт и так ограничил по максимуму язык
2. Мы не имеем четкого представления куда идет эта реализация
3. УЖЕ получается не совсем то, что хотелось (в частности , строгости и непротиворечивости).
4. Любое ограничение уменьшает выгоду от простоты языка и накладывает трудно прогнозируемые ограничения на область использования
5. Мы пока еще неспособны аргументировать введение ограничений на хорошем уровне.
Все мои предложения основаны на практической необходимости возникающей при попытке написания либ и биндингов. Попозже попробую оформить примеры.
Название: Re: [Oberon-07/11] RECORD&POINTER export.
Отправлено: DddIzer от Сентябрь 04, 2013, 02:32:24 pm
Все мои предложения основаны на практической необходимости возникающей при попытке написания либ и биндингов. Попозже попробую оформить примеры.
давайте посмотрим - только в нашем случае биндинги должны быть к js- либам, ну и учтите, что для работы  с js можно всегда ввести дополнительные фичи не затрагивая основной язык.
Название: Re: [Oberon-07/11] RECORD&POINTER export.
Отправлено: valexey_u от Сентябрь 04, 2013, 03:07:13 pm
Поля записи, отмеченные знаком экспорта, должны быть доступны через экспортированный тип указателя на эту запись, независимо от того, экспортирован тип записи или нет, именован или нет.
Исходя из этого, объявить переменную типа экспортированный указатель на не экспортированную или безымянную запись и создать экземпляр он может, иначе полная бессмыслица получится.

Гм. А как на счет вот такого примера:
MODULE M;
TYPE
 R  = RECORD foo* : INTEGER END;
 P* = POINTER TO R;
END M.
Название: Re: [Oberon-07/11] RECORD&POINTER export.
Отправлено: akron1 от Сентябрь 04, 2013, 03:22:05 pm
Гм. А как на счет вот такого примера:
MODULE M;
TYPE
 R  = RECORD foo* : INTEGER END;
 P* = POINTER TO R;
END M.

Репорт:
6.3 Record types

...
If a record type is exported, field identifiers that are to be visible outside the declaring module must
be marked.

Т.е., если тип-запись не экспортируется, то его поля не должны экспортироваться.

Название: Re: [Oberon-07/11] RECORD&POINTER export.
Отправлено: valexey_u от Сентябрь 04, 2013, 03:27:59 pm
Гм. А как на счет вот такого примера:
MODULE M;
TYPE
 R  = RECORD foo* : INTEGER END;
 P* = POINTER TO R;
END M.

Репорт:
6.3 Record types

...
If a record type is exported, field identifiers that are to be visible outside the declaring module must
be marked.

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

Соответственно я вижу тут две возможности (и нам надо выбрать одну из них)
1) Такая ситуация, как приведенном мное исходнике, является ошибочной, и мы должны получить ошибку компиляции (с указанием на то, что сам тип записи не экспортируется).
2) Такая ситуация не ошибочна, и мы к полям записи можем получить доступ через указатель, но при этом экземпляры записи вне данного модуля создавать не можем.
Название: Re: [Oberon-07/11] RECORD&POINTER export.
Отправлено: Kemet от Сентябрь 04, 2013, 04:03:41 pm
Гм. А как на счет вот такого примера:
MODULE M;
TYPE
 R  = RECORD foo* : INTEGER END;
 P* = POINTER TO R;
END M.
Думаю, так:
MODULE N;
IMPORT M;
VAR
  p : M.P;
BEGIN
  NEW( p );
 p.foo := 1;
END N;
Название: Re: [Oberon-07/11] RECORD&POINTER export.
Отправлено: akron1 от Сентябрь 04, 2013, 04:33:20 pm
Только сейчас подумал о том, что такие путаные правила экспорта возможно обусловлены стремлением упростить инструмент генерации def-файлов, ведь тогда такой инструмент сводится к простому цитированию фрагментов модуля:

MODULE M;
TYPE
 R*  = RECORD foo*, foo2 : INTEGER END;
 P* = POINTER TO R;
END M.

DEFINITION M;
TYPE
 R  = RECORD foo : INTEGER END;
 P = POINTER TO R;
END M.

А если тип-запись не экспортируется, но при этом экспортируются его поля, то как тогда создать def? Ну, а если def-файлы в принципе не нужны, то тогда можно упростить правила и лепить метки экспорта где угодно.
Название: Re: [Oberon-07/11] RECORD&POINTER export.
Отправлено: vlad от Сентябрь 04, 2013, 04:55:17 pm
1) Такая ситуация, как приведенном мное исходнике, является ошибочной, и мы должны получить ошибку компиляции (с указанием на то, что сам тип записи не экспортируется).

Сейчас оно именно так и работает (пишет ошибку).

2) Такая ситуация не ошибочна, и мы к полям записи можем получить доступ через указатель, но при этом экземпляры записи вне данного модуля создавать не можем.

Возможно так правильнее - тогда можно использовать запись без NEW внутри модуля. Хотя практического смысла пока не вижу.
Название: Re: [Oberon-07/11] RECORD&POINTER export.
Отправлено: Valery Solovey от Сентябрь 04, 2013, 08:29:41 pm
Тут говорится о валидности объявлений (declaration, процесса объявления новых типо), я же говорю и спрашиваю о экспорте и импорте. То есть не про объявления, это разные понятия.

В оберонах модификатор экспорта -- это часть декларации. Так в чём проблема-то?
На тип этот модификатор никак не влияет. То есть не входит в сигнатуру.
Не входит в сигнатуру типа, но входит в сигнатуру модуля.
Название: Re: [Oberon-07/11] RECORD&POINTER export.
Отправлено: Valery Solovey от Сентябрь 04, 2013, 08:45:20 pm
2) Такая ситуация не ошибочна, и мы к полям записи можем получить доступ через указатель, но при этом экземпляры записи вне данного модуля создавать не можем.
Эту идею ещё стоит обдумать, но мне кажется, что не стоит разрешать делать NEW для импортируемых типов. А объявлять переменные можно разрешать для любых импортируемых типов.

Таким образом, если экспортируемый тип предполагает размещение в куче, то его значение мы можем получить из импортированной процедуры. А если на стеке - то память выделится на стеке вне зависимости от того используем ли мы инициализатор из импортируемого модуля или нет. Если экспортируется указатель, а запись осталась скрытой, то инициализировать переменную получится только процедурой из того модуля.

То есть, указатель или запись влияют на поведение импорта только в этом ключе. А для доступа к полям, если они экспортированы, достаточно, чтобы хотя бы один типов указатель/запись были экспортированы.