Info21 писал(а):
Это, кстати, добавляет трудности при его освоении и развитии.
В надежде на выделение ветки, продолжу в более конструктивном ключе.
Модули, пользующиеся выгрузкой: DevCommanders (командер выгружает модули по Ctrl+Click), DevCompiler (CompileAndUnload) и DevDebug (процедура Unload выгружает модуль из текущего окна; кроме того, здесь же экспортированы UnloadModuleList и UnloadThis). Последние два модуля импортируют первый, что как бы намекает разместить общую процедуру в нём. Однако, логичнее всё же поместить её в DevDebug, так как там у нас концентрируется всё отладочное. Соответственно, предлагаю всего лишь опубликовать существующую процедуру DevDebug.UnloadMod в следующей редакции:
Код:
PROCEDURE UnloadMod* (name: ARRAY OF CHAR; VAR ok: BOOLEAN);
VAR mod: Kernel.Module; str: Dialog.String; n: Kernel.Name;
BEGIN
n := SHORT(name$); mod := Kernel.ThisLoadedMod(n);
IF mod # NIL THEN
Dialog.ShowParamStatus("#Dev:Unloading", name, "", "");
Kernel.UnloadMod(mod);
IF mod.refcnt < 0 THEN
Dialog.MapParamString("#Dev:Unloaded", name, "", "", str);
StdLog.String(str); StdLog.Ln;
Controls.Relink
ELSE
Dialog.ShowParamMsg("#Dev:UnloadingFailed", name, "", "");
ok := FALSE
END
ELSE
Dialog.ShowParamMsg("#Dev:NotFound", name, "", "");
ok := FALSE;
END
END UnloadMod;
Что изменено:
- добавлен маркер экспорта (*);
- параметр name сделан универсальным ARRAY OF CHAR вместо TextMappers.String;
- добавлен вызов Controls.Relink, присутствующий в двух других реализациях выгрузки модуля.
Соответственно, DevCompiler.CompileAndUnload превращается в...:
Код:
PROCEDURE CompileAndUnload*;
VAR t: TextModels.Model; error: BOOLEAN;
BEGIN
Open;
t := TextViews.FocusText();
IF t # NIL THEN
Do(t, StdLog.text, 0, defopt, error);
IF error THEN DevMarkers.ShowFirstError(t, TextViews.focusOnly)
ELSE DevDebug.UnloadMod(DevCPT.SelfName$, error)
END
ELSE Dialog.ShowMsg("#Dev:NoTextViewFound")
END;
Close
END CompileAndUnload;
(В список импорта DevCompiler надо добавить DevDebug.)
DevCommanders не может циклически импортировать DevDebug, поэтому придётся ввести процедурную переменную (при желании - объектный разъём):
Код:
UnloadMod*: PROCEDURE (name: ARRAY OF CHAR; VAR ok: BOOLEAN);
Инициализировать в DevDebug.BEGIN:
Код:
DevCommanders.UnloadMod := UnloadMod;
DevCommanders.Unload принять в следующей редакции:
Код:
PROCEDURE Unload (cmd: Dialog.String);
VAR modname: Kernel.Name; i: INTEGER; ch: CHAR; ok: BOOLEAN;
BEGIN
ASSERT(UnloadMod # NIL, 20);
i := 0; ch := cmd[0];
WHILE (ch # 0X) & (ch # ".") DO modname[i] := SHORT(ch); INC(i); ch := cmd[i] END;
modname[i] := 0X;
UnloadMod(modname$, ok)
END Unload;
В данном решении добавляется только одна новая межмодульная зависимость: DevCompiler -> DevDebug. Если разместить общую процедуру выгрузки в модуле DevCommanders, то новых зависимостей не появится (и не нужен будет разъём), но это представляется нелогичным: кому придёт в голову её там искать? Ещё вариант - создать новый модуль DevUnload, но это, кажется, перебор (хотя, последнее решение подкупает эргономической очевидностью).