Все так.
Модуль в КП - это текст. Модуль в ББ - несколько сложнее: это совокупность текста, символьного и кодового представления (файла), а также можно к модулю отнести и его "образ" в памяти ЭВМ, когда модуль загружен (в терминах Сообщения - added to the system). (Прим: в памяти ЭВМ модуль - это совокупность Метаданных, Машкодов, Дескриптора и Переменных)
Ну и если уж совсем претендовать на полноту - "останки" модуля после его удаления из системы (выгрузки) тоже сюда можно отнести (это Дескриптор).
Действительно, когда мы говорим "В модуле М есть переменная П", это может относиться к любому из перечисленных представлений.
За неимением устоявшегося и, возможно, более подходящего термина, буду называть эти все "проявления" модуля его ипостасями.
Есть тж соглашение о расположении ипостасей модуля в файловой системе. Если некоему инструменту необходима та или иная ипостась, то этот инструмент, следуя соглашению, отображает имя модуля в имя директории и файла, находит нужный файл в нужной директории и оттуда достает нужную ему ипостась модуля.
Обсуждали с коллегами возможность абстрактного интерфейса, отвечающего этому соглашению. Он позволил бы а) явно обозначить наличие некоего соглашения о расположении ипостасей; б) в едином месте собрать реализацию этого соглашения, избавив инструменты от необходимости реализовывать его каждый раз самостоятельно и в) (легко) решить ряд системных задач.
Назовем здесь такой интерфейс Библиотекарем - Librarian. Вот он, например:
Код:
DEFINITION Lib;
IMPORT Files;
CONST
(* hypostases *)
source = 0; symbols = 1; code = 2; docu = 3;
TYPE
Name = ARRAY 256 OF CHAR;
Librarian = POINTER TO ABSTRACT RECORD
PROCEDURE ThisSpec (IN mod: Name; hypostasis: INTEGER; OUT loc: Files.Locator; OUT name: Files.Name; OUT type: Files.Type), NEW, ABSTRACT;
(* Translate (mod, hypostatis) ⇒ (loc, name, type) *)
END;
VAR
lib*, stdLib-: Librarian;
END HrLib.
Где его применять и что с него взять.
Летом я публиковал небольшой проект Cross; по опыту использования с тех пор, его стоит назвать Sandbox - песочница. Это - дубликат компилятора СР2 с единственным отличием: он умеет брать символьные файлы импортируемых модулей не из папки ББ, а откуда укажут; и выкладывать артефакты компиляции тоже не в папку ББ, а куда укажут. Это позволяет мне, например, сделать папку Sandbox, в ней - Sub/Mod/, разместить там файл Module.odc с текстом модуля SubModule. И тогда SandboxCompiler.Compile создаст Sandbox/Code/Module.odc и Sandbox/Sym/Module.osf. При этом я могу указать, что брать символьные файлы следует из папки, например, bb18; а могу - что из папки bb17. Это оч удобно, если я правлю модули, от которых зависит работа не только моего приложения, но и всего ББ, т.е. ИДЕ, "мастерской" программиста: мастерская всегда остается работоспособной, даже если я ошибся в критически важных модулях.
Изменения для этого потребовались совершенно незначительные в единственном модуле DevCPM (SandboxCPM) в процедурах OldSym, NewSym, RegisterSym, NewCode, RegisterCode, CloseSym, CloseCode.
Если ввести интерфейс библиотекаря, то они все будут полагаться на библиотекарное отображение имени модуля в локатор, имя и тип файла; сейчас же они это отображение выполняют сами.
Это позволит (проще) реализовать Песочницу; что еще важнее - систематизировать работу со сборками ББ для разных платформ: реализации библиотекаря можно поручить разбираться, как и куда складывать модульные ипостаси для той или иной платформы, или разрядности целевой платформы, или версии ББ, или еще каких нужно вариантов. Также можно систематизировать работу стыковщика: он должен будет научиться работать с библиотекарем, сообщать ему, какова, напр., целевая платформа, затем получать от него модули и собсно стыковать их. При этом все "переменные разделены": библиотекарь - выделенный компонент, отвечающий за систематизацию доступа к ипостасям модулей; компилятору, стыковщику, отладчику, прочим инструментам делать это не нужно.
Кроме того, откроется возможность, например, организовать хранение ипостасей не в файловой системе, а, к примеру, в БД, или в едином мегафайле, или в сетевом хранилище, и т.д. Что подготовит ББ к пересадке на мобильные, напр., платформы )).
В Гершеле я экспериментировал (-ую) с библиотекарем; HrM использует его, и, например, Гершель выкладывает артефакты компиляции не в папку ББ, а в Hr/Demo/Mod/ , Code/, Sym/; когда придет пора Гершелю стать наравне с СР2 - достаточно будет подменить реализацию библиотекаря, и ипостаси окажутся аккуратно разложенными в подсистемные папки в папке ББ.
И да, я согласен с Евгением, что нужно в Библиотекаря ввести и понятие ресурсов и документации подсистемы. Однако с этим я не экспериментировал. Предполагаю, это заслуживает отдельной процедуры:
Код:
PROCEDURE (lib: Librarian) ThisSubSpec (IN sub: Name; hypostases: INTEGER): Files.Locator, NEW, ABSTRACT;
Если же отображение имени модуля в имена документов - неоднозначное, то... Ну, в этом особом случае я бы предложил ввести процедуру в расширении Librarian:
Код:
TYPE Lib = POINTER TO RECORD (Lib.Librarian) ... END;
PROCEDURE (lib: Lib) TheseDocs (IN mod: Name): DocList, NEW;
Хотя для задач перечисления я предпочитаю использовать не связные списки, а сканеры или чтецы. Нечто подобное у меня было в EdTools, тоже опубликован на форуме летом:
Код:
TYPE
Shelve = POINTER TO RECORD ... END;
(* "Полочка": папка, в которой есть структура подсистем ББ *)
PROCEDURE (sh: Shelve) NewReader (old: Shelver): Shelver, NEW;
Shelver = POINTER TO RECORD (* Перечислитель содержимого "полочки" *)
type*: INTEGER; (* eot, modu, docu, rsrc, arbi *)
modName*: Ident; (* module name, valid iff .type = modu *)
loc*: Files.Locator; (* if applicable, determines the text's file and locator *)
fname*: Files.Name;
END;
PROCEDURE (sh: Shelver) Read, NEW;