(*~\Глагол\ПриложенияLink\МПГ2008 (комп., но не раб.)\~~~~~~~~~~~~~~~~~~~~~~~~*)
(**)                                            ОТДЕЛ Запуск;
(*============================================================================*
 * НАЗНАЧЕНИЕ: находит ещё не преобразованные отделы и запускает их
 *             на преобразование
 *============================================================================*)

ИСПОЛЬЗУЕТ
        (*  \Глагол\              *)
 оЦепи    ИЗ "..\..\Отделы\Иное\",
  Пустой  ИЗ "..\..\Отделы\Иное\",  
ЧэргаСлеД ИЗ "..\..\Отделы\Иное\",
        (*  \Глагол\              *)
  Текст   ИЗ "..\..\Отделы\Обмен\",
    Файл  ИЗ "..\..\Отделы\Обмен\",

   ВФайл  ИЗ "..\..\Отделы\Обмен\ВводВывод\",
  НаЭкран ИЗ "..\..\Отделы\Обмен\ВводВывод\",

  Ошибка,
  Разбор,
  Выражения,
  Данные,
  Узел,
  Рег,
  Настрой,
  Обмен;

            (* имена служебных файлов *)
ПОСТ
  ИмяСпискаНовых="СписокПК.bat"; (* для преобразования кода *)
  ИмяСпискаВсех="Otdely.spi";    (* для редактора связей только лат. буквы *) 

ВИД
  ДкОтделу = ДОСТУП К (*нОтдел;
                        нОтдел =*) НАБОР(ЧэргаСлеД.нПустой)
    имя  :Настрой.Имя;
    имяФ :Пустой.ДкЦепи;
    время:Файл.шцВремя
                                   КОН;

(*---
                    набор-список отделов с известными предками
  ---*)
ПЕР
    сПредками,                        (* список отделов с известными предками *)
  наОбработку :ЧэргаСлеД.нСписок;     (* список отделов на обработку *)


(*----------------------------------------------------------------------------*)
ЗАДАЧА НайтиПредков(отдМесто-:ЦЕПЬ; отдИмя-:Настрой.Имя):ДкОтделу;
(*
 * Цель:  или находит <отделД> в списке <сПредками> или создает новый <отделД>,
 *        находит его предков и включает его в список <сПредками>
 * До:    <отдМесто> - местоположение файла данного отдела
 *        <отдИмя>   - имя данного отдела
 * Ответ: <отделД> с предками
 *)
ПЕР
        звеноД:ЧэргаСлеД.ДкЗвену_телоД;
      испИмена:ЧэргаСлеД.нСписок;
        испИмя:Выражения.ДкИспИмя;
      испМесто:Файл.ВПути;
       предокД,
        отделД:ДкОтделу;
  времяПредков:Файл.шцВремя;
       отдИмяФ:Файл.ВПолного;
УКАЗ
  Файл.СобратьИмя(отдИмяФ,отдМесто,отдИмя,"отд");

           (* может <отделД> уже есть в списке <сПредками> *)
(*
   Обход списка с 1-го звена до N-го, т.е. пока звеноД.слеД # ПУСТО
 *)
           звеноД:=ЧэргаСлеД.Дк1муЗвену(сПредками);
  ПОКА
           звеноД # ПУСТО
  ВЫП                                           (* преобразование полиморфное  
                   телоД          из ЧэргаСлеД.ДкПустомуНабору в
                         ДкОтделу <- ЧэргаСлеД.ДкПустомуНабору                *)
    отделД:=звеноД.телоД(ДкОтделу);

    ЕСЛИ   отделД.имяФ^ = отдИмяФ ТО
      ЕСЛИ
           отделД.время = МИН(Файл.шцВремя)
      ТО
        Ошибка.Отметить(Ошибка.ПЕРЕКРЕСТНОЕ_ИСПОЛЬЗОВАНИЕ)
      КОН;
      ВОЗВРАТ отделД
    КОН;
           звеноД:=звеноД.слеД
  КОН;
                                          (* создаем и запоминаем новый отдел *)
  ЕСЛИ НЕ Файл.Существует(отдИмяФ) ТО
    Ошибка.ОтметитьИмя(Ошибка.ФАЙЛ_НЕ_ОТКРЫВАЕТСЯ,отдИмяФ)
  КОН;
  СОЗДАТЬ(отделД);
  СПИСАТЬ(отдИмя,отделД.имя);
  СОЗДАТЬ(отделД.имяФ,отдИмяФ);
                               (* для обнаружения перекрёстного использования *)
  отделД.время:=МИН(Файл.шцВремя);

  ЧэргаСлеД.ДобавитьНовЗвеноВконСписка(сПредками,отделД);
                                               (* смотрим используемые отделы *)
  Обмен.НовоеИмяФ(отдИмяФ);
  Выражения.Отдел(отдИмя,испИмена,ВКЛ);              (* найти только испИмена *)
  времяПредков:=МИН(Файл.шцВремя);
(*
   Обход списка с 1-го звена до N-го, т.е. пока звеноД.слеД # ПУСТО
 *)
                 звеноД:=ЧэргаСлеД.Дк1муЗвену(испИмена);
  ПОКА
                 звеноД # ПУСТО
  ВЫП                            (* преобразование полиморфное  
                        телоД                    из ЧэргаСлеД.ДкПустомуНабору в
                              Выражения.ДкИспИмя <- ЧэргаСлеД.ДкПустомуНабору   *)
         испИмя:=звеноД.телоД(Выражения.ДкИспИмя);

    ЕСЛИ испИмя.имя # "ОБХОД" ТО
      Разбор.начСлова:=испИмя.начСлова;
      Файл.НайтиМесто(отдМесто,испИмя.путь^,испМесто);
      предокД:=НайтиПредков(испМесто,испИмя.имя);
                                              (* возвращаем в Обмен "отдИмяФ" *)
      Обмен.НовоеИмяФ(отдИмяФ);

      ЕСЛИ предокД.время > времяПредков ТО
                                                   (* наибольшее время предка *)
        времяПредков:=предокД.время
      КОН
    КОН;
                 звеноД:=звеноД.слеД
  КОН;

  ЕСЛИ
       Обмен.НужнаОбр(времяПредков)
  ТО
    отделД.время:=МАКС(Файл.шцВремя);

    ЧэргаСлеД.ДобавитьНовЗвеноВконСписка(наОбработку,отделД)
  ИНАЧЕ
    Файл.ВремяИзменения(Обмен.опгИмяФ,отделД.время)
  КОН;
  ВОЗВРАТ отделД
КОН НайтиПредков;

(*----------------------------------------------------------------------------*)
ЗАДАЧА ПреобрОтдел(отделД:ДкОтделу);
ПЕР
  испИмена:ЧэргаСлеД.нСписок;
УКАЗ
  Данные.Обновить;
  Рег.Обновить;
  Обмен.НовоеИмяФ(отделД.имяФ^);
  Выражения.Отдел(отделД.имя,испИмена,ОТКЛ)
КОН ПреобрОтдел;

(*----------------------------------------------------------------------------*)
ЗАДАЧА СохранитьСписокВсех;
(* Запись в файл "Otdely.spi" списка всех используемых .код файлов *)
ПЕР
   звеноД:ЧэргаСлеД.ДкЗвену_телоД;
   отделД:ДкОтделу;
   потокД:ВФайл.ДкПотоку;

  кодИмяФ:Файл.ВПолного;
     путь:Файл.ВПути;
      имя:Настрой.Имя;
      тип:Файл.ВТипа;
УКАЗ
       потокД:=ВФайл.Открыть(ИмяСпискаВсех);
  ЕСЛИ
       потокД = ПУСТО
  ТО
    Ошибка.ОтметитьИмя(Ошибка.ФАЙЛ_НЕ_ОТКРЫВАЕТСЯ,ИмяСпискаВсех)
  КОН;
       потокД.цВидЗнаков:=ВФайл.знВин;
(*
   Обход списка с 1-го звена до N-го, т.е. пока звеноД.слеД # ПУСТО
 *)
            звеноД:=ЧэргаСлеД.Дк1муЗвену(сПредками);
  ПОКА
            звеноД # ПУСТО
  ВЫП                                           (* преобразование полиморфное  
                   телоД          из ЧэргаСлеД.ДкПустомуНабору в
                         ДкОтделу <- ЧэргаСлеД.ДкПустомуНабору                *)
    отделД:=звеноД.телоД(ДкОтделу);

    Файл.РазобратьИмя(отделД.имяФ^,путь,имя,тип);

    оЦепи.ДобавитьВКонец(путь,"Код\");                                  
 (*  Цепь.Добавить(путь,"Код\"); *)

     Файл.СобратьИмя(кодИмяФ,путь,имя,"маш^");

    ВФайл.ЦепьЗнаков(потокД,кодИмяФ);
 (* ВФайл.Цепь(потокД,кодИмяФ); *)

            звеноД:=звеноД.слеД
  КОН;
  ВФайл.Закрыть(потокД)
КОН СохранитьСписокВсех;

(*----------------------------------------------------------------------------*)
ЗАДАЧА СохранитьСписокНовых;
                 (* Запись в файл "СписокПК.bat" списка обрабатываемых файлов *)
ПЕР
  звеноД:ЧэргаСлеД.ДкЗвену_телоД;
  отделД:ДкОтделу;
  потокД:ВФайл.ДкПотоку;

  имяФ:Файл.ВПолного;
  путь:Файл.ВПути;
   имя:Настрой.Имя;
   тип:Файл.ВТипа;
УКАЗ
       потокД:=ВФайл.Открыть(ИмяСпискаНовых);
  ЕСЛИ
       потокД = ПУСТО
  ТО
    Ошибка.ОтметитьИмя(Ошибка.ФАЙЛ_НЕ_ОТКРЫВАЕТСЯ,ИмяСпискаНовых)
  КОН;
       потокД.цВидЗнаков:=ВФайл.знДос;
(*
   Обход списка с 1-го звена до N-го, т.е. пока звеноД.слеД # ПУСТО
 *)
            звеноД:=ЧэргаСлеД.Дк1муЗвену(наОбработку);
  ПОКА
            звеноД # ПУСТО
  ВЫП                                           (* преобразование полиморфное  
                   телоД          из ЧэргаСлеД.ДкПустомуНабору в
                         ДкОтделу <- ЧэргаСлеД.ДкПустомуНабору                *)
    отделД:=звеноД.телоД(ДкОтделу);

    Файл.РазобратьИмя(отделД.имяФ^,путь,имя,тип);

    оЦепи.ДобавитьВКонец(путь,"Код\");                                  
 (*  Цепь.Добавить(путь,"Код\"); *)

    Файл.СобратьИмя(имяФ,путь,имя,"^");

    оЦепи.Вставить("call ПК ",имяФ,0);
 (*  Цепь.Вставить("call ПК ",имяФ,0); *)

    ВФайл.ЦепьЗнаков(потокД,имяФ);
 (* ВФайл.Цепь(потокД,имяФ); *)

            звеноД:=звеноД.слеД
  КОН;
  ВФайл.Закрыть(потокД)
КОН СохранитьСписокНовых;

(*----------------------------------------------------------------------------*)
ЗАДАЧА ВыводОшибки(текст-:ЦЕПЬ);
УКАЗ
  НаЭкран.ВсяЦепь(Обмен.отдИмяФ);
  НаЭкран.Цел4числа(" (%d:%d) - ",Разбор.начСлова.строка,Разбор.начСлова.колонка,0,0);
  НаЭкран.ВсяЦепь(текст);
  НаЭкран.ВсяЦепь(".^");
  Обмен.УдалитьКод;
  СТОП(1)
КОН ВыводОшибки;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА ПреобрОтделы-(отдИмяФ-,срдМесто-:ЦЕПЬ; настройки:МНОЖ; свод:ЦЕЛ);
(*
 * Цель:  преобразовать текст данного отдела и всех обновлённых отделов,
 *        которые он использует (явно или неявно) в машинный код
 * До:    <отдИмяФ>   - местоположение преобразуемого отдела
 *        <срдМесто>  - корневой путь к "СРЕДА.отд"
 *        <настройки> - множество ключей преобразования
 *        <свод>      - свод настроек
 * После: *.опм       - общедоступные понятия (двоичный вид) каждого отдела 
 *        *.код       - машинный код (текстовый вид) каждого отдела
 *)
ПЕР
  отделД:ДкОтделу;
  звеноД:ЧэргаСлеД.ДкЗвену_телоД;
  потокД:ВФайл.ДкПотоку;

   место:Файл.ВПути;
     имя:Настрой.Имя;
     тип:Файл.ВТипа;
УКАЗ
                                                             (* очистим файлы *)
  потокД:=ВФайл.Открыть(ИмяСпискаНовых);
  ВФайл.Закрыть(потокД);
  потокД:=ВФайл.Открыть(ИмяСпискаВсех);
  ВФайл.Закрыть(потокД);
  ЧэргаСлеД.ОчиститьСписок(сПредками);
  ЧэргаСлеД.ОчиститьСписок(наОбработку);
  Ошибка.Подготовить(ВыводОшибки);
  Настрой.Подготовить(настройки,свод);
  Выражения.Подготовить(срдМесто);
  Файл.РазобратьИмя(отдИмяФ,место,имя,тип);
  отделД:=НайтиПредков(место,имя);
(*
   Обход списка с 1-го звена до N-го, т.е. пока звеноД.слеД # ПУСТО
 *)
            звеноД:=ЧэргаСлеД.Дк1муЗвену(наОбработку);
  ПОКА
            звеноД # ПУСТО
  ВЫП                                           (* преобразование полиморфное  
                   телоД          из ЧэргаСлеД.ДкПустомуНабору в
                         ДкОтделу <- ЧэргаСлеД.ДкПустомуНабору                *)
    отделД:=звеноД.телоД(ДкОтделу);

    НаЭкран.ВсяЦепь(отделД.имяФ^);
    НаЭкран.ВсяЦепь("^");

    ПреобрОтдел(отделД);

            звеноД:=звеноД.слеД
  КОН;
  СохранитьСписокНовых;
  СохранитьСписокВсех
КОН ПреобрОтделы;

КОН Запуск.
