Oberon space

General Category => Общий раздел => Тема начата: kkkk от Ноябрь 12, 2016, 08:59:51 pm

Название: Интерфейс модуля как отдельная сущность
Отправлено: kkkk от Ноябрь 12, 2016, 08:59:51 pm
Кто-то считает это необходимым, кто-то - ненужным. Меня интересует техническая сторона, точней одна её деталь. Как эффективно совместить локальные записи и закрытые элементы. В идеале интерфейс не должен содержать информации о скрытых элементах записи, пусть и помеченных как скрытые. Это легко достигается в интерфейсе уведомительного характера, но составляет проблему в интерфейсе для компилятора, так так тогда полный размер записи становится неизвестным, что является препятствием для размещения на стеке.

Более или менее правильные намётки на решение я знаю, которое нужно даже не для этого, но оно довольно сложное. А какие костыли вам по душе?
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: valexey_u от Ноябрь 12, 2016, 09:43:22 pm
Немного не по теме, но отвечу за себя - меня вообще не волнует как там компилятор что будет компилировать. Если ему нужно - пусть смотрит не в спецификацию модуля, а прямо в реализацию и черпает горстями оттуда инфу.

От компилятора мне нужно, чтобы он гарантировал соответствие и непротиворечивость спецификации и реализации модуля.

Отделение спецификации от реализации она для человека в первую очередь, а не для машины. Чтобы можно было разбираться в структуре программы, в том где что доступно и кто что предоставляет, без IDE вообще, просто по текстовым статичным файликам, причем даже без возможности grep'a.
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: Geniepro от Ноябрь 12, 2016, 10:00:26 pm
Немного не по теме, но отвечу за себя - меня вообще не волнует как там компилятор что будет компилировать. Если ему нужно - пусть смотрит не в спецификацию модуля, а прямо в реализацию и черпает горстями оттуда инфу.
В общем случае компилятор может просто не иметь доступа к реализации модуля -- этот модуль ведь может дан его пользователю уже после того как его программа будет написана.
Вопросами определения размеров структур данных должен заниматься линкер-кодогенератор.
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: valexey_u от Ноябрь 12, 2016, 10:16:10 pm
Немного не по теме, но отвечу за себя - меня вообще не волнует как там компилятор что будет компилировать. Если ему нужно - пусть смотрит не в спецификацию модуля, а прямо в реализацию и черпает горстями оттуда инфу.
В общем случае компилятор может просто не иметь доступа к реализации модуля -- этот модуль ведь может дан его пользователю уже после того как его программа будет написана.
Вопросами определения размеров структур данных должен заниматься линкер-кодогенератор.

Попрошу не путать разделение на модули для того чтобы поделить программу на логические части и тем самым упростить программисту жизнь (чтобы ему было проще ориентироваться в коде) и разделение на "модули" которые являются единицей компоновки (динамической ли, статической ли). Это РАЗНЫЕ модули, они могут быть (и, вероятно, должны) реализованы по разному в любом ЯП, который не является игрушечным.

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

А ещё в ЯП бывает штука под названием "единица компиляции" - это может быть вообще третьей сущностью.

Во втором случае (про модуль как единицу компоновки) удобней вшить спецификацию модуля в сам получившийся бинарь (в бинарном же виде спецификацию). Но этот случай меня не волнует. Я говорю про удобство программиста в первую очередь. Средство организации исходников.
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: kkkk от Ноябрь 12, 2016, 10:34:41 pm
Вот эта разница в модулях может быть реализована инструментами без изменения языка. Если же речь именно об удобстве пользователя, то тоже нет никаких технических проблем - это именно интерфейс уведомительного характера, и мелькающие то здесь, то там DEFINITION говорят о том, что, по крайней мере, для некоторых реализаций Оберона она воплощена, хотя, может, и не полностью.
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: valexey_u от Ноябрь 12, 2016, 10:44:11 pm
Вот эта разница в модулях может быть реализована инструментами без изменения языка. Если же речь именно об удобстве пользователя, то тоже нет никаких технических проблем - это именно интерфейс уведомительного характера, и мелькающие то здесь, то там DEFINITION говорят о том, что, по крайней мере, для некоторых реализаций Оберона она воплощена, хотя, может, и не полностью.

Мы про оберон говорим? Я слабо себе представляю как без изменения языка, инструментом я смогу указать что вот этот модуль первого типа я хочу побить на 4 модуля второго типа (с вот такими вот спеками), а вон те 10 модулей первого типа я хочу сделать единым модулем второго типа и тоже вот с такой спекой и такими вот экспортами (ну и очевидными импортами).

В обероне DEFINITION, насколько я помню, просто генерился по исходнику. Это несколько не то, что мне нужно. Точнее - это совсем не то, что мне нужно.
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: kkkk от Ноябрь 12, 2016, 11:30:39 pm
Мы про оберон говорим?
Такое можно провернуть на многих языках.

Цитировать
Я слабо себе представляю как без изменения языка, инструментом я смогу указать
Введением дополнительного спец-языка, с которым работает инструмент. Это, в общем-то, перпендикулярные сущности и пихать это в основной язык совершенно не обязательно. Что-то подобное есть в GNAT, насколько можно судить. Является ли это частью стандарта или собственные заморочки неважно с технической стороны.

Цитировать
модуль первого типа я хочу побить на 4 модуля второго типа
Конкретно это выглядит, на мой вгляд, как блажь, а не потребность.
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: Valery Solovey от Ноябрь 13, 2016, 09:29:28 am
Как эффективно совместить локальные записи и закрытые элементы.
Делать то же самое, что делается и сейчас, только вынести работу с интерфейсами наружу.

Как я понимаю - проблема в наследовании, да? То есть, какой-то интерфейс использует для одного из своих типов в качестве базового тип из другого интерфейса. И необходимо, чтобы в расширенном типе присутствовали переменные, объявленные в базовом типе.

Сначала компилируется интерфейс с базовым типом, и получается символьный файл этого интерфейса, который используется в компиляции интересуемого интерфейса. Из символьного файла можно извлекать интерфейс, который предоставляется пользователю, и интерфейс, которым пользуется компилятор.
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: kkkk от Ноябрь 13, 2016, 12:05:28 pm
Как я понимаю - проблема в наследовании, да?
Не только. Дело в раздельной трансляции.
Есть, к примеру, интерфейс модуля, являющегося первичным исходником, а не сгенерированным из модуля.
interface A {
    type S = struct {
        a int
    }
    proc Init(var s: S)
    proc Do(var s: S, i: int)
}
Есть возможное воплощение этого интерфейса
module A {
    type S = struct {
        a: int
        b: [16] char
        s: *S
    }
    proc Init(var s: S) {
        ...
    }
    proc Do(var s: S, i: int) {
       ...
    }
}
Есть пользователь модуля A, которому передают интерфейс, а не сам модуль, так как именно интерфейс первичен.
module B {
     import A;

     proc Go {
         var s: [22] A.S
         var a: int
         for i = 0 .. last(s) {
              A.Init(s[i])
              A.Do(s[i], i)
              a = s[i].a
         }
     }
}
Как, имея только интерфейс A, транслятору собрать модуль B с эффективным размещением локального массива s из элементов структур S неизвестного размера.
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: Geniepro от Ноябрь 13, 2016, 12:17:14 pm
interface A {
    type S = struct {
        a int
    }
...

module A {
    type S = struct {
        a: int
        b: [16] char
        s: *S
    }
...
Обычно в реализации модуля не указывают повторно поля записей или переменные, которые были описаны в спецификации модуля. Ибо зачем это дублирование, которое лишь может спровоцировать ошибки?

Как, имея только интерфейс A, транслятору собрать модуль B с эффективным размещением локального массива s из элементов структур S неизвестного размера.
Думаю, такая проблема может быть лишь в однопроходных трансляторах, которые сразу же по мере чтения генерируют машинный код.
В случае разделения трансляции на отдельные фазы "парсинг->проверка типов->компоновка->кодогенерация" не видно, в чём проблема. После компоновки уже известны размеры всех структур, так что у кодогенерации вся информация есть.
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: kkkk от Ноябрь 13, 2016, 01:16:05 pm
Вот именно, такое сложное решение я и имел ввиду в начальном сообщении, хотя оно, очевидно, не является единственным. 
Вопрос, насколько оправданно требование к языку, которое требует таких возможностей транслятора или более простых, но менее эффективных?
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: Geniepro от Ноябрь 13, 2016, 02:27:47 pm
Простой однопроходный компилятор в принципе не способен генерировать качественный оптимизированный код, так что зачем вообще рассматривать эту проблему?
Для модульных языков скорость компиляции не является узким местом, так зачем о ней беспокоиться?
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: kkkk от Ноябрь 13, 2016, 04:13:48 pm
Тут ведь есть и другой вопрос - какие радикальные преимущества даёт подход, непременно требующий более сложных инструментов?
Лично мне нравится, что язык позволяет использовать самые простые средства для создания транслятора, что, впрочем, не означает, что эти средства всегда должны использоваться.
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: Geniepro от Ноябрь 13, 2016, 06:00:12 pm
Чем проще решать задачи на каком-нибудь ЯП, тем сложнее он в реализации. Самый сложный в реализации -- это какой-нибудь формализованный (контроллируемый) русский язык. Просто сформулировал задачу -- и готов машинный код. Кто бы ещё сумел бы сделать для него транслятор...
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: Valery Solovey от Ноябрь 13, 2016, 09:11:41 pm
Как, имея только интерфейс A, транслятору собрать модуль B с эффективным размещением локального массива s из элементов структур S неизвестного размера.
Ну, в общем, я дал ответ на этот вопрос. Делается исходник интерфейса, компилируется и получается символьный файл. Программист сможет получить из него интерфейс, а транслятор - полное описание всех структур. То есть, символьный файл - это и есть интерфейс.
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: Geniepro от Ноябрь 13, 2016, 09:24:29 pm
Как, имея только интерфейс A, транслятору собрать модуль B с эффективным размещением локального массива s из элементов структур S неизвестного размера.
Ну, в общем, я дал ответ на этот вопрос. Делается исходник интерфейса, компилируется и получается символьный файл. Программист сможет получить из него интерфейс, а транслятор - полное описание всех структур. То есть, символьный файл - это и есть интерфейс.
Ваш вариант работает лишь, если интерфейс модуля неотделим от его реализации, как в оберонах.
В других языках, таких как ада или модула-2, при компиляции исходника интерфейса компилятору может быть просто недоступна реализация модуля, в котором записи доопределяются, например, в них добавляются приватные поля.
В этом случае ваш вариант просто не работает.
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: trurl от Ноябрь 15, 2016, 08:27:16 am
Это в обероне все типы модулей слепили в один, чтобы не усложнять и не думать. В реальной жизни это не годится.
В реальной жизни вообще обходятся без модулей.
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: valexey_u от Ноябрь 15, 2016, 12:51:35 pm
Это в обероне все типы модулей слепили в один, чтобы не усложнять и не думать. В реальной жизни это не годится.
В реальной жизни вообще обходятся без модулей.

Вовсе нет. Используютс повсеместно и под разными соусами.
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: Valery Solovey от Ноябрь 15, 2016, 09:13:50 pm
при компиляции исходника интерфейса компилятору может быть просто недоступна реализация модуля, в котором записи доопределяются, например, в них добавляются приватные поля.
Я потому и предложил компилировать исходник интерфейса, что в нём содержатся и скрытые поля.
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: Valery Solovey от Ноябрь 15, 2016, 09:19:32 pm
Ещё вариант - доопределять расширяемые типы на этапе компоновки. То есть, настоящие свои размеры тип узнает только после того, как ему предоставят реализацию интерфейса, который он импортировал.
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: Geniepro от Ноябрь 16, 2016, 04:48:07 am
при компиляции исходника интерфейса компилятору может быть просто недоступна реализация модуля, в котором записи доопределяются, например, в них добавляются приватные поля.
Я потому и предложил компилировать исходник интерфейса, что в нём содержатся и скрытые поля.
Это может быть невозможно в виду несуществования реализации модуля на момент раздачи разработчикам необходимых интерфейсов.
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: Geniepro от Ноябрь 16, 2016, 04:48:58 am
Ещё вариант - доопределять расширяемые типы на этапе компоновки. То есть, настоящие свои размеры тип узнает только после того, как ему предоставят реализацию интерфейса, который он импортировал.
Вот об этом варианте я и говорю, но для kkkk этот вариант неприемлем как слишком сложный, неоднопроходный...
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: kkkk от Ноябрь 16, 2016, 09:30:19 am
Для удовлетворения любопытства было бы интересно узнать, такой вариант где-нибудь воплощён?
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: Valery Solovey от Ноябрь 16, 2016, 08:05:13 pm
Это может быть невозможно в виду несуществования реализации модуля на момент раздачи разработчикам необходимых интерфейсов.
Под абстрактные типы выделять память невозможно. Тип должен быть полностью реализован (то есть иметь полный набор полей). Но это не налагает необходимость использовать для компиляции весь реализованный модуль. Достаточно будет только интерфейса, если в нём будут все поля.

То есть, предложенное мной решение работать будет, но в нём есть другая неприятность. Если будет изменён модуль реализации, то он перестанет удовлетворять своему интерфейсу, который был импортирован в другом модуле. Придётся поработать компилятором, чтобы восстановить согласованность. Правда, сейчас тоже придётся всё перекомпилировать, чтобы всё пришло в норму. Но сейчас, если возникнет такая проблема, то её можно будет увидеть глазами, потому что невидимых частей у интерфейса нет.
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: Valery Solovey от Ноябрь 16, 2016, 08:09:57 pm
Для удовлетворения любопытства было бы интересно узнать, такой вариант где-нибудь воплощён?
Конкретно в таком виде - нет, наверное. Но был же Juice. Чтобы это воплотить, нужно работать в том же ключе - отложить часть компоновки исходника на момент загрузки приложения.
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: Kemet от Ноябрь 29, 2016, 04:20:18 am
Кто-то считает это необходимым, кто-то - ненужным. Меня интересует техническая сторона, точней одна её деталь. Как эффективно совместить локальные записи и закрытые элементы. В идеале интерфейс не должен содержать информации о скрытых элементах записи, пусть и помеченных как скрытые. Это легко достигается в интерфейсе уведомительного характера, но составляет проблему в интерфейсе для компилятора, так так тогда полный размер записи становится неизвестным, что является препятствием для размещения на стеке.

Более или менее правильные намётки на решение я знаю, которое нужно даже не для этого, но оно довольно сложное. А какие костыли вам по душе?
Это сделано в Модуле-3
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: kkkk от Ноябрь 29, 2016, 10:58:04 am
Можете немного осветить, как это сделано?
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: Kemet от Ноябрь 30, 2016, 06:21:40 pm
Есть "непрозрачные" типы. Интерфей к типу определяется в интерфейсных модулях, в обще случае, тип может иметь несколько интерфнйсов, которые могут находится в различгых интерфейсных модулях. Таким образом, клиент видит только то, что ему позволено в импортированном интерфейсе.
В модулях реализации тип "открывается" (REVEAL ) и соответственно, реализуется. Реализация также может быть "размазана" по нескольким модулям(файлам).
То есть это то, что в Шарпе назвали partial types (из Модулы-3 идею и позаимствовали).
При сборке тип в итоге должен быть полностью "открыт" и реализован.
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: kkkk от Ноябрь 30, 2016, 09:19:41 pm
Как происходит компоновка модуля, собранного с использованием интерфейса и модуля, являющегося воплощением этого интерфейса, если модуль-клиент использовал недоопределённые записи в массиве, в статической памяти или в как компонент других записей?
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: Kemet от Декабрь 01, 2016, 05:25:53 am
Тип не может быть "недоопределен" - я же написал, что при сборке тип должен быть полностью открыт и реализован, поэтому его размер компилятору известен. Но, так как состав сборки определяетяс сборочным скриптом, то содержимое типа, конечно, может быть различным для разных платформ или режимов компиляции(отладка/релиз), но, тем не менее, тип должен быть полностью определен до момента его использования.
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: kkkk от Декабрь 01, 2016, 09:42:33 am
Ясно, то есть речь идёт об уведомительном интерфейсе, с помощью которого можно проверить правильность модуля-клиента, но нельзя собрать в машинный код.
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: Geniepro от Декабрь 01, 2016, 12:31:18 pm
Ясно, то есть речь идёт об уведомительном интерфейсе, с помощью которого можно проверить правильность модуля-клиента, но нельзя собрать в машинный код.
А зачем отдавать заказчику код модуля в виде машинного кода? Отдавайте ему в виде AST -- а заказчик уже сделает сборку с генерацией машинного кода...
Название: Re: Интерфейс модуля как отдельная сущность
Отправлено: valexey_u от Декабрь 01, 2016, 12:41:22 pm
Ясно, то есть речь идёт об уведомительном интерфейсе, с помощью которого можно проверить правильность модуля-клиента, но нельзя собрать в машинный код.
А зачем отдавать заказчику код модуля в виде машинного кода? Отдавайте ему в виде AST -- а заказчик уже сделает сборку с генерацией машинного кода...
Отдавайте заказчику исходники. Всё остальное - от лукавого.