Автор Тема: Интерфейс модуля как отдельная сущность  (Прочитано 38821 раз)

kkkk

  • Full Member
  • ***
  • Сообщений: 135
    • Просмотр профиля
Кто-то считает это необходимым, кто-то - ненужным. Меня интересует техническая сторона, точней одна её деталь. Как эффективно совместить локальные записи и закрытые элементы. В идеале интерфейс не должен содержать информации о скрытых элементах записи, пусть и помеченных как скрытые. Это легко достигается в интерфейсе уведомительного характера, но составляет проблему в интерфейсе для компилятора, так так тогда полный размер записи становится неизвестным, что является препятствием для размещения на стеке.

Более или менее правильные намётки на решение я знаю, которое нужно даже не для этого, но оно довольно сложное. А какие костыли вам по душе?

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Интерфейс модуля как отдельная сущность
« Ответ #1 : Ноябрь 12, 2016, 09:43:22 pm »
Немного не по теме, но отвечу за себя - меня вообще не волнует как там компилятор что будет компилировать. Если ему нужно - пусть смотрит не в спецификацию модуля, а прямо в реализацию и черпает горстями оттуда инфу.

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

Отделение спецификации от реализации она для человека в первую очередь, а не для машины. Чтобы можно было разбираться в структуре программы, в том где что доступно и кто что предоставляет, без IDE вообще, просто по текстовым статичным файликам, причем даже без возможности grep'a.
Y = λf.(λx.f (x x)) (λx.f (x x))

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Re: Интерфейс модуля как отдельная сущность
« Ответ #2 : Ноябрь 12, 2016, 10:00:26 pm »
Немного не по теме, но отвечу за себя - меня вообще не волнует как там компилятор что будет компилировать. Если ему нужно - пусть смотрит не в спецификацию модуля, а прямо в реализацию и черпает горстями оттуда инфу.
В общем случае компилятор может просто не иметь доступа к реализации модуля -- этот модуль ведь может дан его пользователю уже после того как его программа будет написана.
Вопросами определения размеров структур данных должен заниматься линкер-кодогенератор.
to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Интерфейс модуля как отдельная сущность
« Ответ #3 : Ноябрь 12, 2016, 10:16:10 pm »
Немного не по теме, но отвечу за себя - меня вообще не волнует как там компилятор что будет компилировать. Если ему нужно - пусть смотрит не в спецификацию модуля, а прямо в реализацию и черпает горстями оттуда инфу.
В общем случае компилятор может просто не иметь доступа к реализации модуля -- этот модуль ведь может дан его пользователю уже после того как его программа будет написана.
Вопросами определения размеров структур данных должен заниматься линкер-кодогенератор.

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

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

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

Во втором случае (про модуль как единицу компоновки) удобней вшить спецификацию модуля в сам получившийся бинарь (в бинарном же виде спецификацию). Но этот случай меня не волнует. Я говорю про удобство программиста в первую очередь. Средство организации исходников.
Y = λf.(λx.f (x x)) (λx.f (x x))

kkkk

  • Full Member
  • ***
  • Сообщений: 135
    • Просмотр профиля
Re: Интерфейс модуля как отдельная сущность
« Ответ #4 : Ноябрь 12, 2016, 10:34:41 pm »
Вот эта разница в модулях может быть реализована инструментами без изменения языка. Если же речь именно об удобстве пользователя, то тоже нет никаких технических проблем - это именно интерфейс уведомительного характера, и мелькающие то здесь, то там DEFINITION говорят о том, что, по крайней мере, для некоторых реализаций Оберона она воплощена, хотя, может, и не полностью.

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Интерфейс модуля как отдельная сущность
« Ответ #5 : Ноябрь 12, 2016, 10:44:11 pm »
Вот эта разница в модулях может быть реализована инструментами без изменения языка. Если же речь именно об удобстве пользователя, то тоже нет никаких технических проблем - это именно интерфейс уведомительного характера, и мелькающие то здесь, то там DEFINITION говорят о том, что, по крайней мере, для некоторых реализаций Оберона она воплощена, хотя, может, и не полностью.

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

В обероне DEFINITION, насколько я помню, просто генерился по исходнику. Это несколько не то, что мне нужно. Точнее - это совсем не то, что мне нужно.
Y = λf.(λx.f (x x)) (λx.f (x x))

kkkk

  • Full Member
  • ***
  • Сообщений: 135
    • Просмотр профиля
Re: Интерфейс модуля как отдельная сущность
« Ответ #6 : Ноябрь 12, 2016, 11:30:39 pm »
Мы про оберон говорим?
Такое можно провернуть на многих языках.

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

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

Valery Solovey

  • Hero Member
  • *****
  • Сообщений: 509
    • Просмотр профиля
Re: Интерфейс модуля как отдельная сущность
« Ответ #7 : Ноябрь 13, 2016, 09:29:28 am »
Как эффективно совместить локальные записи и закрытые элементы.
Делать то же самое, что делается и сейчас, только вынести работу с интерфейсами наружу.

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

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

kkkk

  • Full Member
  • ***
  • Сообщений: 135
    • Просмотр профиля
Re: Интерфейс модуля как отдельная сущность
« Ответ #8 : Ноябрь 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 неизвестного размера.

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Re: Интерфейс модуля как отдельная сущность
« Ответ #9 : Ноябрь 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 неизвестного размера.
Думаю, такая проблема может быть лишь в однопроходных трансляторах, которые сразу же по мере чтения генерируют машинный код.
В случае разделения трансляции на отдельные фазы "парсинг->проверка типов->компоновка->кодогенерация" не видно, в чём проблема. После компоновки уже известны размеры всех структур, так что у кодогенерации вся информация есть.
to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…

kkkk

  • Full Member
  • ***
  • Сообщений: 135
    • Просмотр профиля
Re: Интерфейс модуля как отдельная сущность
« Ответ #10 : Ноябрь 13, 2016, 01:16:05 pm »
Вот именно, такое сложное решение я и имел ввиду в начальном сообщении, хотя оно, очевидно, не является единственным. 
Вопрос, насколько оправданно требование к языку, которое требует таких возможностей транслятора или более простых, но менее эффективных?

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Re: Интерфейс модуля как отдельная сущность
« Ответ #11 : Ноябрь 13, 2016, 02:27:47 pm »
Простой однопроходный компилятор в принципе не способен генерировать качественный оптимизированный код, так что зачем вообще рассматривать эту проблему?
Для модульных языков скорость компиляции не является узким местом, так зачем о ней беспокоиться?
to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…

kkkk

  • Full Member
  • ***
  • Сообщений: 135
    • Просмотр профиля
Re: Интерфейс модуля как отдельная сущность
« Ответ #12 : Ноябрь 13, 2016, 04:13:48 pm »
Тут ведь есть и другой вопрос - какие радикальные преимущества даёт подход, непременно требующий более сложных инструментов?
Лично мне нравится, что язык позволяет использовать самые простые средства для создания транслятора, что, впрочем, не означает, что эти средства всегда должны использоваться.

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Re: Интерфейс модуля как отдельная сущность
« Ответ #13 : Ноябрь 13, 2016, 06:00:12 pm »
Чем проще решать задачи на каком-нибудь ЯП, тем сложнее он в реализации. Самый сложный в реализации -- это какой-нибудь формализованный (контроллируемый) русский язык. Просто сформулировал задачу -- и готов машинный код. Кто бы ещё сумел бы сделать для него транслятор...
to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…

Valery Solovey

  • Hero Member
  • *****
  • Сообщений: 509
    • Просмотр профиля
Re: Интерфейс модуля как отдельная сущность
« Ответ #14 : Ноябрь 13, 2016, 09:11:41 pm »
Как, имея только интерфейс A, транслятору собрать модуль B с эффективным размещением локального массива s из элементов структур S неизвестного размера.
Ну, в общем, я дал ответ на этот вопрос. Делается исходник интерфейса, компилируется и получается символьный файл. Программист сможет получить из него интерфейс, а транслятор - полное описание всех структур. То есть, символьный файл - это и есть интерфейс.