(*~\Глагол\ПриложенияLink\ПГ\~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
(**)                              ОТДЕЛ ПД;
(*============================================================================*)
(* НАЗНАЧЕНИЕ: Построение синтаксического Дерева                              *)
(*============================================================================*)

ИСПОЛЬЗУЕТ
  ОБХОД,
        (*  \Глагол\                    *)
    Асм   ИЗ "..\..\Отделы\Заграница\",

  ВД,НП,ОО,СС;

(*------------------------------------ ВидУзел -------------------------------*)
ВИД
  ДкУзлу- = ДОСТУП К нУзел;
                     нУзел- = НАБОР
    роду+,подроду+:ЦЕЛ;
    лево+,право+,след+:ПД.ДкУзлу;
    толькочт+:КЛЮЧ;
    вид+:ВД.ДкВиду;
    пон+:ВД.ДкПонятию;
   пост+:ВД.ДкПост;
 текстп+:ОО.нТекстПоз; (* позиция в тексте отдела *)
    конСтрока+:ЦЕЛ  (* номер последней строки в составных построениях: ЗАДАЧА,
                     * указания ЕСЛИ...КОН и т.д. *)
                              КОН;

(*----------------------------------------------------------------------------*)
ПОСТ
                    (* Род понятий (нПонятие.родп). Из ВД. *)
  пОтдел     =0;
  пОбласть   =1;
  пВид       =2;
  пПост      =3;
  пПер       =4;
  пПрСсылки  =5;
  пЗадача    =6;
  пВстрЗадача=7;
  пСвойство  =8;
(*
  родп       | n адр   пост    след     область
  ============================================================================
  пОтдел     | 0                        верх    Отдел
  пОбласть   | 1 нстр                   первпер Область действия
  пВид       | 2                                Именованный вид
  пПост      | 3       val                      Постоянная
  пПер       | 4 адр           next             Переменная или приёмник значения
  пПрСсылки  | 5 vadr          next             Приемник переменной
  пЗадача    | 6 сно   sizes   firstpar область Задача
  пВстрЗадача| 7 fno   sizes                    Встроенная задача
  пСвойство  | 8 off           next             Свойство набора

  <сно> является номером в символьной таблице COFF (если <сно> <= 0, то это - адр для связки заготовок)
*)

                    (* Признаки понятия (нПонятие.признаки). Из ВД. *)
  прОбщедоступная=0;
  прНеизменяемая =1;
  прОбъявлена    =2;
  прВложенная    =3;
  прГоловная     =4;
  прПередаваемая =5;
(*
  прОбщедоступная- действует во всех отделах
  прНеизменяемая - только для чтения
  прОбъявлена    - для полностью объявленных задач
  прВложенная    - для вложенных задач
  прГоловная     - для задачи _Zapusk 
  прПередаваемая - для иноязычных приложений
*)

  (*                        Род видов (нВид.родв). Из ВД.
 Причём:
          вЯчейка <= вЦел8 <= вЗнак <= вЦел16 <= вЦел32 <= вЦел64.
   *)
  вНеопр  =0;
  вЯчейка =1;
  вКлюч   =2;
  вЗнак   =3;
  вЦел8   =4;
  вЦел16  =5;
  вЦел32  =6;
  вЦел64  =7;
  вВещ32  =8;
  вВещ64  =9;
  вМнож   =10;
  вПЦепь  =11;
  вПусто  =12;
  вНет    =13;
  вДоступ =14;
  вЗадача =15;
  вБегунок=16;
  вРяд    =17;
  вОРяд   =18;
  вНабор  =19;
  вКон    =20; (* вКон для ДВ. При изменении вКон нужно 3 преобразования с уборка:=ОТКЛ. *)
(*
  родв    | n          овид      след     вхнотд  адрОВ    текстп
  ===============================================================
  вНеопр  | 0
  вЯчейка | 1
  вКлюч   | 2
  вЗнак   | 3
  вЦел8   | 4
  вЦел16  | 5
  вЦел32  | 6
  вЦел64  | 7
  вВещ32  | 8
  вВещ64  | 9
  вМнож   | 10
  вПЦепь  | 11
  вПусто  | 12
  вНет    | 13
  вДоступ | 14         PBaseTyp           вхнотд           текстп
  вЗадача | 15         ResTyp    params   вхнотд           текстп
  вБегунок| 16 шаг     основание          вхнотд  адрОВ    текстп
  вРяд    | 17 nofel   ElemTyp            вхнотд           текстп
  вОРяд   | 18 dim     ElemTyp            вхнотд  lenoff   текстп
  вНабор  | 19         RBaseTyp  fields   вхнотд  адрОВ    текстп
*)

  множЦел={вЦел8..вЦел64};
  множВещ={вВещ32,вВещ64};

                   (* Программные ловушки (АвОсты). Из СК. *)
  пределыАвОст=1;
    номерАвОст=2;
    арифмАвОст=3;
   охранаАвОст=4;
    пустоАвОст=5;
      дляАвОст=6;
  выбратьАвОст=7;
    ответАвОст=8;
проверитьАвОст=9;
     нольАвОст=10;
  бегунокАвОст=11;

                   (* Род узлов (нУзел.роду). Из ПД. *)
  Nvar     =0;
  Nvarpar  =1;
  Nfield   =2;
  Nderef   =3;
  Nindex   =4;
  Nguard   =5;
  Neguard  =6;
  Nconst   =7;
  Ntype    =8;
  Nproc    =9;
  Nupto    =10;
  Nmop     =11;
  Ndop     =12;
  NcallTuda=13;
  NcallSuda=14;
  Ncall    =15;
  Nif      =16;
  Ncaselse =17;
  Ncasedo  =18;
  Nenter   =19;
  Nassign  =20;
  Nifelse  =21;
  Ncase    =22;
  Nwhile   =23;
  Nrepeat  =24;
  Nloop    =25;
  Nexit    =26;
  Nreturn  =27;
  Nwith    =28;
  Ntrap    =29;

                   (* Номера задач (нУзел.подроду). Из ПД. *)
  assign    =0;
  зВЦел     =1;
  зВШирЦел  =2;
  зЧет      =3;
  зВЗнак    =4;
  зМодуль   =5;
  зМин      =6;
  зМакс     =7;
  зУзк      =8;
  зУвеличить=9;
  зУменьшить=10;
  зСтоп     =11;
  зРазмер   =12;
  зДлина    =13;
  зСоздать  =14;
  зСписать  =15;
  зЗадано   =16;
  зПроверить=17;
  зПоставить=18;
  зСместить =19;
  зОбнулить =20; 
  зЦелЧасть =21;

                   (* Номера задач ОБХОД отдела (нУзел.подроду). Из ПД. *)
  зПолучитьАдрес=23;
  зИзПамяти     =24;
  зВПамять      =25;
  зЗначение     =26;
  зОбраз        =27;
  зОУзк         =28;


(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       СоздатьУзел-(роду:ЦЕЛ):ПД.ДкУзлу;
ПЕР
  узел:ПД.ДкУзлу;
УКАЗ
  СОЗДАТЬ(узел);
  узел.роду:=роду;
  узел.конСтрока:=-1;
  ВОЗВРАТ узел
КОН СоздатьУзел;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       NewLeaf-(пон:ВД.ДкПонятию):ПД.ДкУзлу;
ПЕР
  узел:ПД.ДкУзлу;
УКАЗ
  ВЫБРАТЬ пон.родп ИЗ
  | пПер:
      узел:=СоздатьУзел(Nvar);
      узел.толькочт:=(прНеизменяемая В пон.признаки) И (пон.уровень # 0)
  | пПрСсылки:
      узел:=СоздатьУзел(Nvarpar);
      узел.толькочт:=прНеизменяемая В пон.признаки
  | пПост:
      узел:=СоздатьУзел(Nconst);
      узел.пост:=ВД.СоздатьПост();
      узел.пост^:=пон.пост^ 
  | пВид:
      узел:=СоздатьУзел(Ntype)
  | пЗадача,пВстрЗадача:
      узел:=СоздатьУзел(Nproc)
  КОН;
  узел.пон:=пон;
  узел.вид:=пон.вид;
  ВОЗВРАТ узел
КОН NewLeaf;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       Construct-(
                  роду :ЦЕЛ;
                    x+,
                    y  :ПД.ДкУзлу
                 );
ПЕР
  узел:ПД.ДкУзлу;
УКАЗ
  узел:=СоздатьУзел(роду);
  узел.вид:=ВД.нетвид;
  узел.лево:=x;
  узел.право:=y;
  x:=узел
КОН Construct;

(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА BindNodes(роду :ЦЕЛ;
                  вид :ВД.ДкВиду;
                   x+,
                   y  :ПД.ДкУзлу);
ПЕР
  узел:ПД.ДкУзлу;
УКАЗ
  узел:=СоздатьУзел(роду);
  узел.вид:=вид;
  узел.лево:=x;
  узел.право:=y;
  x:=узел;
КОН BindNodes;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       Link-(   перв+,
             последн+,
                узлы  :ПД.ДкУзлу);
(* привязывает к <последн> узлу списка с началом в <перв> узлы <узлы> *)
УКАЗ
  ЕСЛИ перв = ПУСТО ТО
    перв:=узлы
  ИНАЧЕ
    последн.след:=узлы
  КОН;
  ПОКА
       узлы.след # ПУСТО
  ВЫП
       узлы:=узлы.след
  КОН;
  последн:=узлы
КОН Link;

(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА BoolToInt(b:КЛЮЧ):ЦЕЛ;
УКАЗ
  ЕСЛИ b ТО ВОЗВРАТ 1 ИНАЧЕ ВОЗВРАТ 0 КОН
КОН BoolToInt;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       IntToBool-(i:ШИРЦЕЛ):КЛЮЧ;
УКАЗ
  ЕСЛИ i = 0 ТО ВОЗВРАТ ОТКЛ ИНАЧЕ ВОЗВРАТ ВКЛ КОН
КОН IntToBool;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       NewBoolConst-(boolval:КЛЮЧ):ПД.ДкУзлу;
ПЕР
  x:ПД.ДкУзлу;
УКАЗ
  x:=СоздатьУзел(Nconst);
  x.вид:=ВД.ключвид;
  x.пост:=ВД.СоздатьПост();
  x.пост.цел:=BoolToInt(boolval);
  ВОЗВРАТ x
КОН NewBoolConst;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       OptIf-(x+:ПД.ДкУзлу);
           (* x.след = ПУСТО *)
ПЕР
  if,pred:ПД.ДкУзлу;
УКАЗ
       if:=x.лево;
  ПОКА
       if.лево.роду = Nconst
  ВЫП
    ЕСЛИ IntToBool(if.лево.пост.цел) ТО
      x:=if.право;
      ВОЗВРАТ
    АЕСЛИ if.след = ПУСТО ТО
      x:=x.право;
      ВОЗВРАТ
    ИНАЧЕ
      if:=if.след;
      x.лево:=if
    КОН
  КОН;
  pred:=if;
  if:=if.след;
  ПОКА if # ПУСТО ВЫП
    ЕСЛИ if.лево.роду = Nconst ТО
      ЕСЛИ IntToBool(if.лево.пост.цел) ТО
        pred.след:=ПУСТО;
        x.право:=if.право;
        ВОЗВРАТ
      ИНАЧЕ
        if:=if.след;
        pred.след:=if
      КОН
    ИНАЧЕ
      pred:=if;
      if:=if.след
    КОН
  КОН
КОН OptIf;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       Nil-():ПД.ДкУзлу;
ПЕР
  x:ПД.ДкУзлу;
УКАЗ
  x:=СоздатьУзел(Nconst);
  x.вид:=ВД.пустовид;
  x.пост:=ВД.СоздатьПост();
  x.пост.цел:=0;
  ВОЗВРАТ x
КОН Nil;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       EmptySet-():ПД.ДкУзлу;
ПЕР
  x:ПД.ДкУзлу;
УКАЗ
  x:=СоздатьУзел(Nconst);
  x.вид:=ВД.множвид;
  x.пост:=ВД.СоздатьПост();
  x.пост.множ:={};
  ВОЗВРАТ x
КОН EmptySet;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       SetIntType(узел:ПД.ДкУзлу);
ПЕР
  v:ШИРЦЕЛ;
УКАЗ
  v:=узел.пост.цел;
  ЕСЛИ  (НП.МинЦел8  <= v) И (v <= НП.МаксЦел8) ТО
    узел.вид:=ВД.цел8вид
  АЕСЛИ (НП.МинЦел16 <= v) И (v <= НП.МаксЦел16) ТО
    узел.вид:=ВД.цел16вид
  АЕСЛИ (НП.МинЦел32 <= v) И (v <= НП.МаксЦел32) ТО
    узел.вид:=ВД.цел32вид
  ИНАЧЕ
    узел.вид:=ВД.цел64вид
  КОН
КОН SetIntType;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       NewIntConst-(цел:ШИРЦЕЛ):ПД.ДкУзлу;
ПЕР
  x:ПД.ДкУзлу;
УКАЗ
  x:=СоздатьУзел(Nconst);
  x.пост:=ВД.СоздатьПост();
  x.пост.цел:=цел;
  SetIntType(x);
  ВОЗВРАТ x
КОН NewIntConst;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       NewRealConst-(вещ:ШИРВЕЩ; вид:ВД.ДкВиду):ПД.ДкУзлу;
ПЕР
  x:ПД.ДкУзлу;
УКАЗ
  x:=СоздатьУзел(Nconst);
  x.пост:=ВД.СоздатьПост();
  x.пост.вещ:=вещ;
  x.вид:=вид;
  x.пост.цел1:=НП.АдрНеопр;
  ВОЗВРАТ x
КОН NewRealConst;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       NewString-(цепь:ДОСТУП К ЦЕПЬ):ПД.ДкУзлу;
ПЕР
  x:ПД.ДкУзлу;
УКАЗ
  x:=СоздатьУзел(Nconst);
  x.вид:=ВД.пцепьвид;
  x.пост:=ВД.СоздатьПост();
  x.пост.цел1:=НП.АдрНеопр;
  x.пост.цепьД:=цепь;
  ВОЗВРАТ x
КОН NewString;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       CharToString-(у:ПД.ДкУзлу);
ПЕР
  зн:ЗНАК;
УКАЗ
  у.вид:=ВД.пцепьвид;
  зн:=ВЗНАК(у.пост.цел);
  ЕСЛИ зн = 0X ТО
    СОЗДАТЬ(у.пост.цепьД,1);
  ИНАЧЕ
    СОЗДАТЬ(у.пост.цепьД,2);
            у.пост.цепьД[1]:=0X
  КОН;
  у.пост.цепьД[0]:=зн;
  у.пост.цел1:=НП.АдрНеопр;
  у.пон:=ПУСТО
КОН CharToString;

(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА NotVar(x:ПД.ДкУзлу):КЛЮЧ;
УКАЗ
  ВОЗВРАТ (x.роду >= Nconst) И
    ((x.роду # Nmop) ИЛИ (x.подроду # СС.значение) ИЛИ (x.лево.роду >= Nconst))
КОН NotVar;

(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА CheckRealType(      f,
                     errCode :ЦЕЛ;
                           x :ВД.ДкПост);
ПЕР
  min,max:ШИРВЕЩ;
УКАЗ
  ЕСЛИ f = вВещ32 ТО
    min:=НП.МинВещ32;
    max:=НП.МаксВещ32
  ИНАЧЕ
    min:=НП.МинВещ64;
    max:=НП.МаксВещ64
  КОН;
  ЕСЛИ (x.вещ > max) ИЛИ (x.вещ < min) ТО
    ОО.Ошибка(errCode);
  КОН;
  ЕСЛИ f = вВещ32 ТО
    x.вещ:=УЗК(x.вещ)  (* single precision only *)
  КОН;
  x.цел1:=НП.АдрНеопр;
КОН CheckRealType;

(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА Convert( x+:ПД.ДкУзлу;
               вид:ВД.ДкВиду);
ПЕР
  узел:ПД.ДкУзлу;
  св,нв:ЦЕЛ;
  r:ШИРВЕЩ;
УКАЗ
  св:=x.вид.родв;
  нв:=вид.родв;
  ЕСЛИ x.роду = Nconst ТО
    ЕСЛИ св В множЦел ТО
      ЕСЛИ нв В множЦел ТО
        ЕСЛИ св > нв ТО
          SetIntType(x);
          ЕСЛИ x.вид.родв > нв ТО
            ОО.Ошибка(ОО.БОЛЬШОЕ_ЧИСЛО)
          КОН
        КОН
      АЕСЛИ нв В множВещ ТО
        x.пост.вещ:=x.пост.цел;
        x.пост.цел1:=НП.АдрНеопр
      АЕСЛИ нв = вЗнак ТО
        ЕСЛИ (x.пост.цел < ВЦЕЛ(МИН(ЗНАК))) ИЛИ (x.пост.цел > ВЦЕЛ(МАКС(ЗНАК))) ТО
          ОО.Ошибка(ОО.НЕВЕРНЫЙ_ИСТОЧНИК)
        КОН
      КОН
    АЕСЛИ св В множВещ ТО
      ЕСЛИ нв В множВещ ТО
        CheckRealType(нв,ОО.БОЛЬШОЕ_ЧИСЛО,x.пост)
      ИНАЧЕ (*нв В множЦел*)
        r:=x.пост.вещ;
        ЕСЛИ (r < МИН(ШИРЦЕЛ)) ИЛИ (r > МАКС(ШИРЦЕЛ)) ТО
          ОО.Ошибка(ОО.БОЛЬШОЕ_ЧИСЛО)
        КОН;
        x.пост.цел:=ВШИРЦЕЛ(r);
        SetIntType(x)
      КОН
    КОН;
    x.пон:=ПУСТО
  АЕСЛИ (x.роду = Nmop) И (x.подроду = СС.преобр) И 
        ((x.лево.вид.родв < св) ИЛИ (св > нв)) ТО
    (* don't create new узел *)
    ЕСЛИ x.лево.вид = вид ТО (* СС.и suppress existing узел *)
      x:=x.лево
    КОН
  ИНАЧЕ
    узел:=СоздатьУзел(Nmop);
    узел.подроду:=СС.преобр;
    узел.лево:=x;
    x:=узел
  КОН;
  x.вид:=вид
КОН Convert;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       DeRef-(x+:ПД.ДкУзлу);
УКАЗ
  ЕСЛИ x.роду >= Nconst ТО
    ОО.Ошибка(ОО.ССЫЛКА_НЕ_ОТ_ПЕР)
  АЕСЛИ НЕ ((x.вид.родв = вДоступ) ИЛИ (x.вид.родв = вБегунок)) ТО
    ОО.Ошибка(ОО.ССЫЛКА_НЕ_ОТ_ДОСТУПА)
  КОН;
  BindNodes(Nderef,x.вид.овид,x,ПУСТО);
  x.толькочт:=x.лево.толькочт
КОН DeRef;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       Index-(x+,y:ПД.ДкУзлу);
УКАЗ
  ЕСЛИ (y.роду = Ntype) ИЛИ (y.роду = Nproc) ТО
    ОО.Ошибка(ОО.ЗАДАЧИ_И_ВИДЫ_ЗАПРЕЩЕНЫ)
  АЕСЛИ x.роду >= Nconst ТО
    ОО.Ошибка(ОО.НОМЕР_НЕ_ОТ_ПЕР)
  АЕСЛИ НЕ (x.вид.родв В {вРяд,вОРяд}) ТО
    ОО.Ошибка(ОО.ЭТО_НЕ_РЯД)
  АЕСЛИ НЕ (y.вид.родв В множЦел) ТО
    ОО.Ошибка(ОО.НОМЕР_НЕ_ЦЕЛЫЙ)
  АЕСЛИ (x.вид.родв = вРяд) И (y.роду = Nconst) И
        ((y.пост.цел < 0) ИЛИ (y.пост.цел >= x.вид.n)) ТО
    ОО.Ошибка(ОО.ВЫХОД_ЗА_ГРАНИЦЫ_РЯДА)
  КОН;
  ЕСЛИ y.вид.родв = вЦел64 ТО
    Convert(y,ВД.цел32вид)
  КОН;
  BindNodes(Nindex,x.вид.овид,x,y);
  x.толькочт:=x.лево.толькочт
КОН Index;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       Field-(x+:ПД.ДкУзлу;
              y :ВД.ДкПонятию);
УКАЗ(* x.вид.родв = вНабор *)
  ЕСЛИ x.роду >= Nconst ТО
    ОО.Ошибка(ОО.ЭТО_НЕ_НАБОР)
  АЕСЛИ (y = ПУСТО) ИЛИ (y.родп # пСвойство) ТО
    ОО.Ошибка(ОО.НЕТ_СВОЙСТВА);
  КОН;
  BindNodes(Nfield,y.вид,x,ПУСТО);
  x.пон:=y;
  x.толькочт:=x.лево.толькочт ИЛИ ((прНеизменяемая В y.признаки) И (y.уровень < 0))
КОН Field;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       TypTest-(  x+:ПД.ДкУзлу;
                пон :ВД.ДкПонятию;
        нужнаОхрана :КЛЮЧ);
(*
 * Цель: охрана или проверка вида
 * До:   <x>           - проверяемая переменная
 *       <пон>         - понятие охраняющего вида
 *       <нужнаОхрана> - ВКЛ, если нужна охрана, а не просто проверка
 *)
ПЕР
  пвид:ВД.ДкВиду;  (* последний проверяемый вид *)

 (*...............................................подЗадача...*)
  ЗАДАЧА СравнитьВиды(в1,в2:ВД.ДкВиду);
  ПЕР
    узел:ПД.ДкУзлу;
  УКАЗ
    ЕСЛИ в1 # в2 ТО
      ВД.НаборРасширен(пвид,в2);
      ЕСЛИ нужнаОхрана ТО
        BindNodes(Nguard,ПУСТО,x,ПУСТО);
        x.толькочт:=x.лево.толькочт  (* пропускаем след. охрану *)
      ИНАЧЕ
        узел:=СоздатьУзел(Nmop);
        узел.подроду:=СС.является;
        узел.лево:=x;
        узел.пон:=пон;
        x:=узел
      КОН
    АЕСЛИ НЕ нужнаОхрана ТО
      x:=NewBoolConst(ВКЛ)
    КОН
  КОН СравнитьВиды;

УКАЗ
  ЕСЛИ NotVar(x) ТО
    ОО.Ошибка(ОО.ЭТО_НЕ_ПЕРЕМЕННАЯ)
  КОН;
  пвид:=x.вид;
  ЕСЛИ x.роду = Nguard ТО x:=x.лево КОН;  (* пропускаем след. (только одну) охрану *)
  ЕСЛИ x.вид.родв = вДоступ ТО
    ЕСЛИ x.вид.овид.родв # вНабор ТО
      ОО.Ошибка(ОО.ЭТО_НЕ_РАСШИРЕНИЕ)
    АЕСЛИ пон.вид.родв # вДоступ ТО
      ОО.Ошибка(ОО.ОХРАНА_НЕ_У_ДОСТУПА)
    КОН;
    пвид:=пвид.овид;
    СравнитьВиды(x.вид.овид,пон.вид.овид)
  АЕСЛИ (x.вид.родв = вНабор) И (x.роду = Nvarpar) И (пон.вид.родв = вНабор) ТО
    СравнитьВиды(x.вид,пон.вид)
  ИНАЧЕ
    ОО.Ошибка(ОО.ОХРАНА_НЕВОЗМОЖНА)
  КОН;
  ЕСЛИ нужнаОхрана ТО x.вид:=пон.вид ИНАЧЕ x.вид:=ВД.ключвид КОН
КОН TypTest;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       In-(x+,y:ПД.ДкУзлу);
ПЕР
  f:ЦЕЛ;
  k:ШИРЦЕЛ;
УКАЗ
  f:=x.вид.родв;
  ЕСЛИ (x.роду = Ntype) ИЛИ (x.роду = Nproc) ИЛИ (y.роду = Ntype) ИЛИ (y.роду = Nproc) ТО
    ОО.Ошибка(ОО.ЗАДАЧИ_И_ВИДЫ_ЗАПРЕЩЕНЫ)
  АЕСЛИ НЕ (f В множЦел) ИЛИ (y.вид.родв # вМнож) ТО
    ОО.Ошибка(ОО.ВИД_НЕ_ДЛЯ_В);
  КОН;
  ЕСЛИ x.роду = Nconst ТО
    k:=x.пост.цел;
    ЕСЛИ (k < 0) ИЛИ (k > НП.МаксМнож) ТО
      ОО.Ошибка(ОО.ГРАНИЦЫ_МНОЖЕСТВА);
    КОН;
    ЕСЛИ y.роду = Nconst ТО
      x.пост.цел:=BoolToInt(k В y.пост.множ);
      x.пон:=ПУСТО
    ИНАЧЕ
      BindNodes(Ndop,ВД.ключвид,x,y);
      x.подроду:=СС.в
    КОН
  ИНАЧЕ
    BindNodes(Ndop,ВД.ключвид,x,y);
    x.подроду:=СС.в
  КОН;
  x.вид:=ВД.ключвид
КОН In;

(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА степень2(           шцN :ШИРЦЕЛ;
                        (* шцN = 2^показСт2 *)
                      показСт2+:ЦЕЛ
               ):КЛЮЧ;
УКАЗ
                      показСт2:=0;   (* шцN = 2^0 = 2^показСт2 *)
  ЕСЛИ
         шцN > 0
  ТО
    ПОКА ЧЕТ(шцN) ВЫП
         шцN:=шцN ДЕЛИТЬ 2;
            УВЕЛИЧИТЬ(показСт2)
    КОН;
    ЕСЛИ шцN = 1 ТО
      ВОЗВРАТ ВКЛ
    КОН
  КОН;
      ВОЗВРАТ ОТКЛ
КОН степень2;

(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА NewMOp(op:ЦЕЛ;
               x:ПД.ДкУзлу):ПД.ДкУзлу;
ПЕР
  узел:ПД.ДкУзлу;
УКАЗ
  узел:=СоздатьУзел(Nmop);
  узел.подроду:=op;
  узел.вид:=x.вид;
  узел.лево:=x;
  ВОЗВРАТ узел
КОН NewMOp;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА MOp-(op:ЦЕЛ; x+:ПД.ДкУзлу);
ПЕР
  f:ЦЕЛ;
  вид:ВД.ДкВиду;
УКАЗ
  ЕСЛИ (x.роду = Ntype) ИЛИ (x.роду = Nproc) ТО
    ОО.Ошибка(ОО.ЗАДАЧИ_И_ВИДЫ_ЗАПРЕЩЕНЫ)
  КОН;
  f:=x.вид.родв;
  ВЫБРАТЬ op ИЗ
    СС.не:
      ЕСЛИ f # вКлюч ТО
        ОО.Ошибка(ОО.НЕ_НЕ_С_КЛЮЧОМ)
      КОН;
      ЕСЛИ x.роду = Nconst ТО
        x.пост.цел:=BoolToInt(НЕ IntToBool(x.пост.цел));
        x.пон:=ПУСТО
      ИНАЧЕ
        x:=NewMOp(op,x)
      КОН
  | СС.плюс:
      ЕСЛИ НЕ (f В множЦел+множВещ) ТО
        ОО.Ошибка(ОО.ПЛЮС_НЕПРИМЕНИМ)
      КОН
  | СС.минус:
      ЕСЛИ НЕ (f В множЦел+множВещ+{вМнож}) ТО
        ОО.Ошибка(ОО.МИНУС_НЕПРИМЕНИМ)
      КОН;
      ЕСЛИ x.роду = Nconst ТО
        ЕСЛИ f В множЦел ТО
          x.пост.цел:=-x.пост.цел;
          SetIntType(x)
        АЕСЛИ f В множВещ ТО
          x.пост.вещ:=-x.пост.вещ
        ИНАЧЕ
          x.пост.множ:=-x.пост.множ
        КОН;
        x.пон:=ПУСТО
      ИНАЧЕ
        x:=NewMOp(op,x)
      КОН
  КОН
КОН MOp;

(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА CheckPtr(x,y:ПД.ДкУзлу);
ПЕР
  f:ЦЕЛ;
  p,q,t:ВД.ДкВиду;
УКАЗ
  f:=y.вид.родв;
  ЕСЛИ f = вДоступ ТО
    p:=x.вид.овид;
    q:=y.вид.овид;
    ЕСЛИ (p.родв # вНабор) ИЛИ (q.родв # вНабор) ТО
      ОО.Ошибка(ОО.НЕСОВМЕСТИМЫЕ_ВИДЫ)
    КОН;
    ЕСЛИ p.колено < q.колено ТО t:=p; p:=q; q:=t КОН;
    ВД.НаборРасширен(q,p)
  АЕСЛИ f # вПусто ТО
    ОО.Ошибка(ОО.НЕСОВМЕСТИМЫЕ_ВИДЫ)
  КОН
КОН CheckPtr;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА CheckParameters-(fp,
                        ap :ВД.ДкПонятию;
                checkNames :КЛЮЧ);
ПЕР
  ft,at:ВД.ДкВиду;
УКАЗ
  ПОКА fp # ПУСТО ВЫП
    ЕСЛИ ap = ПУСТО ТО
      ОО.Ошибка(ОО.МАЛО_ИСТОЧНИКОВ)
    КОН;
    ft:=fp.вид;
    at:=ap.вид;
    ПОКА (ft.родв = вОРяд) И (at.родв = вОРяд) ВЫП
      ft:=ft.овид;
      at:=at.овид
    КОН;
    ЕСЛИ ft # at ТО
      ЕСЛИ (ft.родв # вЗадача) ИЛИ (at.родв # вЗадача) ТО
        ОО.Ошибка(ОО.НЕСООТВЕТСТВИЕ_ПРИЕМНИКА)
      АЕСЛИ ft.овид # at.овид ТО
        ОО.Ошибка(ОО.НЕВЕРНЫЙ_ВИД_ОТВЕТА)
      КОН;
      CheckParameters(ft.след,at.след,ОТКЛ)
    КОН;
    ЕСЛИ (fp.родп # ap.родп) ИЛИ (fp.признаки # ap.признаки)
      ИЛИ checkNames И (fp.имя # ap.имя) ТО
      ОО.Ошибка(ОО.НЕСООТВЕТСТВИЕ_ПРИЕМНИКА)
    КОН;
    ap:=ap.след;
    fp:=fp.след
  КОН;
  ЕСЛИ ap # ПУСТО ТО
    ОО.Ошибка(ОО.МНОГО_ИСТОЧНИКОВ)
  КОН
КОН CheckParameters;

(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА CheckProc(x:ВД.ДкВиду;
                 y:ВД.ДкПонятию);
(*
 * Проверка совместимости x:=y, где:
 * x - переменная вида ЗАДАЧА
 * y - ЗАДАЧА
 *)
УКАЗ
  ЕСЛИ y.родп # пЗадача ТО
    ОО.Ошибка(ОО.НЕСОВМЕСТИМОЕ_ПРИСВАИВАНИЕ)
  АЕСЛИ прВложенная В y.признаки ТО
    ОО.Ошибка(ОО.НУЖНО_0_УРОВЕНЬ)
  АЕСЛИ x.овид # y.вид ТО
    ОО.Ошибка(ОО.НЕВЕРНЫЙ_ВИД_ОТВЕТА)
  АЕСЛИ (прПередаваемая В y.признаки) # (x.n = 1) ТО
    ОО.Ошибка(ОО.НЕСОВМЕСТИМОЕ_ПРИСВАИВАНИЕ)
  КОН;
  CheckParameters(x.след,y.след,ОТКЛ)
КОН CheckProc;

(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА ConstOp( op:ЦЕЛ;
               x,
               y  :ПД.ДкУзлу);
ПЕР
  xf,yf:ЦЕЛ;
  xval,yval:ВД.ДкПост;
  xv,yv:ШИРЦЕЛ;
  ключ:КЛЮЧ; (* спасаемся от ошибки НЕТ_РЕГИСТРОВ *)

 (*...............................................подЗадача...*)
  ЗАДАЧА ConstCmp():ЦЕЛ;
  ПЕР
    отв:ЦЕЛ;
  УКАЗ
    ВЫБРАТЬ xf ИЗ
      вНеопр:
        отв:=СС.равно
    | вЯчейка,вЗнак..вЦел64:
        ЕСЛИ xval.цел < yval.цел ТО отв:=СС.меньше
        АЕСЛИ xval.цел > yval.цел ТО отв:=СС.больше
        ИНАЧЕ отв:=СС.равно
        КОН
    | вВещ32,вВещ64:
        ЕСЛИ xval.вещ < yval.вещ ТО отв:=СС.меньше
        АЕСЛИ xval.вещ > yval.вещ ТО отв:=СС.больше
        ИНАЧЕ отв:=СС.равно
        КОН
    | вКлюч:
        ЕСЛИ xval.цел # yval.цел ТО отв:=СС.неравно
        ИНАЧЕ отв:=СС.равно
        КОН
    | вМнож:
        ЕСЛИ xval.множ # yval.множ ТО отв:=СС.неравно
        ИНАЧЕ отв:=СС.равно
        КОН
    | вПЦепь:
        ЕСЛИ  xval.цепьД^ < yval.цепьД^ ТО отв:=СС.меньше
        АЕСЛИ xval.цепьД^ > yval.цепьД^ ТО отв:=СС.больше
        ИНАЧЕ отв:=СС.равно
        КОН
    | вПусто,вДоступ,вЗадача:
        ЕСЛИ xval.цел # yval.цел ТО отв:=СС.неравно
        ИНАЧЕ отв:=СС.равно
        КОН
    КОН;
    x.вид:=ВД.ключвид;
    ВОЗВРАТ отв
  КОН ConstCmp;

УКАЗ
  xf:=x.вид.родв;
  yf:=y.вид.родв;
  xval:=x.пост;
  yval:=y.пост;
  ЕСЛИ xf # yf ТО
    ВЫБРАТЬ xf ИЗ
      вЗнак:
        ЕСЛИ yf # вПЦепь ТО
          ОО.Ошибка(ОО.НЕСОВМЕСТИМЫЕ_ВИДЫ)
        КОН;
        CharToString(x)
    | вПЦепь:
        ЕСЛИ yf # вЗнак ТО
          ОО.Ошибка(ОО.НЕСОВМЕСТИМЫЕ_ВИДЫ)
        КОН;
        CharToString(y);
        yf:=вПЦепь
    | вЦел8:
        ЕСЛИ yf В множЦел ТО x.вид:=y.вид
        АЕСЛИ yf = вВещ32 ТО x.вид:=ВД.вещ32вид; xval.вещ:=xval.цел
        АЕСЛИ yf = вВещ64 ТО x.вид:=ВД.вещ64вид; xval.вещ:=xval.цел
        ИНАЧЕ
          ОО.Ошибка(ОО.НЕСОВМЕСТИМЫЕ_ВИДЫ);
        КОН
    | вЦел16:
        ЕСЛИ yf = вЦел8 ТО y.вид:=ВД.цел16вид
        АЕСЛИ yf В множЦел ТО x.вид:=y.вид
        АЕСЛИ yf = вВещ32 ТО x.вид:=ВД.вещ32вид; xval.вещ:=xval.цел
        АЕСЛИ yf = вВещ64 ТО x.вид:=ВД.вещ64вид; xval.вещ:=xval.цел
        ИНАЧЕ
          ОО.Ошибка(ОО.НЕСОВМЕСТИМЫЕ_ВИДЫ);
        КОН
    | вЦел32:
        ЕСЛИ (yf = вЦел8) ИЛИ (yf = вЦел16) ТО y.вид:=ВД.цел32вид
        АЕСЛИ yf В множЦел ТО x.вид:=y.вид
        АЕСЛИ yf = вВещ32 ТО x.вид:=ВД.вещ32вид; xval.вещ:=xval.цел
        АЕСЛИ yf = вВещ64 ТО x.вид:=ВД.вещ64вид; xval.вещ:=xval.цел
        ИНАЧЕ
          ОО.Ошибка(ОО.НЕСОВМЕСТИМЫЕ_ВИДЫ);
        КОН
    | вЦел64:
        ЕСЛИ yf В множЦел ТО y.вид:=ВД.цел64вид
        АЕСЛИ yf = вВещ32 ТО x.вид:=ВД.вещ32вид; xval.вещ:=xval.цел
        АЕСЛИ yf = вВещ64 ТО x.вид:=ВД.вещ64вид; xval.вещ:=xval.цел
        ИНАЧЕ
          ОО.Ошибка(ОО.НЕСОВМЕСТИМЫЕ_ВИДЫ);
        КОН
    | вВещ32:
        ЕСЛИ yf В множЦел ТО y.вид:=x.вид; yval.вещ:=yval.цел
        АЕСЛИ yf = вВещ64 ТО x.вид:=ВД.вещ64вид
        ИНАЧЕ
          ОО.Ошибка(ОО.НЕСОВМЕСТИМЫЕ_ВИДЫ);
        КОН
    | вВещ64:
        ЕСЛИ yf В множЦел ТО y.вид:=x.вид; yval.вещ:=yval.цел
        АЕСЛИ yf = вВещ32 ТО y.вид:=ВД.вещ64вид
        ИНАЧЕ
          ОО.Ошибка(ОО.НЕСОВМЕСТИМЫЕ_ВИДЫ);
        КОН
    | вПусто:
        ЕСЛИ НЕ (yf В {вДоступ,вЗадача}) ТО
          ОО.Ошибка(ОО.НЕСОВМЕСТИМЫЕ_ВИДЫ)
        КОН
    | вДоступ:
        CheckPtr(x,y)
    | вЗадача:
        ЕСЛИ yf # вПусто ТО
          ОО.Ошибка(ОО.НЕСОВМЕСТИМЫЕ_ВИДЫ)
        КОН
    ИНАЧЕ
      ОО.Ошибка(ОО.НЕСОВМЕСТИМЫЕ_ВИДЫ)
    КОН;
    xf:=x.вид.родв
  КОН;  (* {x.вид = y.вид} *)
  ВЫБРАТЬ op ИЗ
    СС.умножить:
      ЕСЛИ xf В множЦел ТО
        xv:=xval.цел;
        yv:=yval.цел;
        ЕСЛИ (xv = 0) ИЛИ (yv = 0) ИЛИ  (* division with negative numbers не defined *)
          (xv > 0) И (yv > 0) И (yv <= МАКС(ШИРЦЕЛ) ДЕЛИТЬ xv) ИЛИ
          (xv > 0) И (yv < 0) И (yv >= МИН(ШИРЦЕЛ) ДЕЛИТЬ xv) ИЛИ
          (xv < 0) И (yv > 0) И (xv >= МИН(ШИРЦЕЛ) ДЕЛИТЬ yv) ИЛИ
          (xv < 0) И (yv < 0) И (xv # МИН(ШИРЦЕЛ)) И (yv # МИН(ШИРЦЕЛ)) И (-xv <= МАКС(ШИРЦЕЛ) ДЕЛИТЬ (-yv)) ТО
          xval.цел:=xv * yv;
          SetIntType(x)
        ИНАЧЕ
          ОО.Ошибка(ОО.БОЛЬШОЕ_ПРОИЗВЕДЕНИЕ)
        КОН
      АЕСЛИ xf В множВещ ТО
        ключ:=МОДУЛЬ(yval.вещ) <= 1.0;
        ЕСЛИ ключ ИЛИ (МОДУЛЬ(xval.вещ) <= МАКС(ШИРВЕЩ) / МОДУЛЬ(yval.вещ)) ТО
          xval.вещ:=xval.вещ * yval.вещ;
          CheckRealType(xf,ОО.БОЛЬШОЕ_ПРОИЗВЕДЕНИЕ,xval)
        ИНАЧЕ
          ОО.Ошибка(ОО.БОЛЬШОЕ_ПРОИЗВЕДЕНИЕ)
        КОН
      АЕСЛИ xf = вМнож ТО
        xval.множ:=xval.множ * yval.множ
      АЕСЛИ xf # вНеопр ТО
        ОО.Ошибка(ОО.УМНОЖЕНИЕ_НЕПРИМЕНИМО)
      КОН
  | СС.косая:
      ЕСЛИ xf В множЦел ТО
        ЕСЛИ yval.цел = 0 ТО
          ОО.Ошибка(ОО.ДЕЛЕНИЕ_НА_НОЛЬ);
        КОН;
        xval.вещ:=xval.цел / yval.цел;
        CheckRealType(вВещ32,ОО.ДЕЛЕНИЕ_НА_НОЛЬ,xval);
        x.вид:=ВД.вещ32вид
      АЕСЛИ xf В множВещ ТО
        ключ:=МОДУЛЬ(yval.вещ) >= 1.0;
        ЕСЛИ ключ ИЛИ (МОДУЛЬ(xval.вещ) <= МАКС(ШИРВЕЩ) * МОДУЛЬ(yval.вещ)) ТО
          xval.вещ:=xval.вещ / yval.вещ;
          CheckRealType(xf,ОО.ДЕЛЕНИЕ_НА_НОЛЬ,xval)
        ИНАЧЕ
          ОО.Ошибка(ОО.ДЕЛЕНИЕ_НА_НОЛЬ)
        КОН
      АЕСЛИ xf = вМнож ТО
        xval.множ:=xval.множ / yval.множ
      АЕСЛИ xf # вНеопр ТО
        ОО.Ошибка(ОО.ДЕЛЕНИЕ_НЕПРИМЕНИМО)
      КОН
  | СС.делить:
      ЕСЛИ xf В множЦел ТО
        ЕСЛИ yval.цел = 0 ТО
          ОО.Ошибка(ОО.ДЕЛЕНИЕ_НА_НОЛЬ)
        КОН;
        xval.цел:=xval.цел ДЕЛИТЬ yval.цел;
        SetIntType(x)
      АЕСЛИ xf # вНеопр ТО
        ОО.Ошибка(ОО.ДЕЛИТЬ_НЕПРИМЕНИМО)
      КОН
  | СС.остаток:
      ЕСЛИ xf В множЦел ТО
        ЕСЛИ yval.цел = 0 ТО
          ОО.Ошибка(ОО.ДЕЛЕНИЕ_НА_НОЛЬ)
        КОН;
        xval.цел:=xval.цел ОСТАТОК yval.цел;
        SetIntType(x)
      АЕСЛИ xf # вНеопр ТО
        ОО.Ошибка(ОО.ОСТАТОК_НЕПРИМЕНИМО)
      КОН
  | СС.и:
      ЕСЛИ xf # вКлюч ТО
        ОО.Ошибка(ОО.И_НЕ_С_КЛЮЧОМ)
      КОН;
      xval.цел:=BoolToInt(IntToBool(xval.цел) И IntToBool(yval.цел))
  | СС.плюс:
      ЕСЛИ xf В множЦел ТО
        ключ:=(yval.цел >= 0) И (xval.цел <= МАКС(ШИРЦЕЛ) - yval.цел);
        ЕСЛИ ключ ИЛИ (yval.цел < 0) И (xval.цел >= МИН(ШИРЦЕЛ) - yval.цел) ТО
          УВЕЛИЧИТЬ(xval.цел,yval.цел);
          SetIntType(x)
        ИНАЧЕ
          ОО.Ошибка(ОО.БОЛЬШАЯ_СУММА)
        КОН
      АЕСЛИ xf В множВещ ТО
        ключ:=(yval.вещ >= 0.0) И (xval.вещ <= МАКС(ШИРВЕЩ) - yval.вещ);
        ЕСЛИ ключ ИЛИ (yval.вещ < 0.0) И (xval.вещ >= -МАКС(ШИРВЕЩ) - yval.вещ) ТО
          xval.вещ:=xval.вещ + yval.вещ;
          CheckRealType(xf,ОО.БОЛЬШАЯ_СУММА,xval)
        ИНАЧЕ
          ОО.Ошибка(ОО.БОЛЬШАЯ_СУММА)
        КОН
      АЕСЛИ xf = вМнож ТО
        xval.множ:=xval.множ + yval.множ
      АЕСЛИ xf # вНеопр ТО
        ОО.Ошибка(ОО.ПЛЮС_НЕПРИМЕНИМ)
      КОН
  | СС.минус:
      ЕСЛИ xf В множЦел ТО
        ЕСЛИ (yval.цел >= 0) И (xval.цел >= МИН(ШИРЦЕЛ) + yval.цел) ИЛИ (yval.цел < 0) И (xval.цел <= МАКС(ШИРЦЕЛ) + yval.цел) ТО
          УМЕНЬШИТЬ(xval.цел,yval.цел);
          SetIntType(x)
        ИНАЧЕ
          ОО.Ошибка(ОО.БОЛЬШАЯ_РАЗНОСТЬ)
        КОН
      АЕСЛИ xf В множВещ ТО
        ключ:=(yval.вещ >= 0.0) И (xval.вещ >= -МАКС(ШИРВЕЩ) + yval.вещ);
        ЕСЛИ ключ ИЛИ (yval.вещ < 0.0) И (xval.вещ <= МАКС(ШИРВЕЩ) + yval.вещ) ТО
          xval.вещ:=xval.вещ - yval.вещ;
          CheckRealType(xf,ОО.БОЛЬШАЯ_РАЗНОСТЬ,xval)
        ИНАЧЕ
          ОО.Ошибка(ОО.БОЛЬШАЯ_РАЗНОСТЬ)
        КОН
      АЕСЛИ xf = вМнож ТО
        xval.множ:=xval.множ - yval.множ
      АЕСЛИ xf # вНеопр ТО
        ОО.Ошибка(ОО.МИНУС_НЕПРИМЕНИМ)
      КОН
  | СС.или:
      ЕСЛИ xf # вКлюч ТО
        ОО.Ошибка(ОО.ИЛИ_НЕ_С_КЛЮЧОМ)
      КОН;
      xval.цел:=BoolToInt(IntToBool(xval.цел) ИЛИ IntToBool(yval.цел))
  | СС.равно:
      xval.цел:=BoolToInt(ConstCmp() = СС.равно)
  | СС.неравно:
      xval.цел:=BoolToInt(ConstCmp() # СС.равно)
  | СС.меньше:
      ЕСЛИ xf В {вКлюч,вМнож,вПусто,вДоступ} ТО
        ОО.Ошибка(ОО.СРАВНЕНИЕ_НЕПРИМЕНИМО)
      КОН;
      xval.цел:=BoolToInt(ConstCmp() = СС.меньше)
  | СС.мравно:
      ЕСЛИ xf В {вКлюч,вМнож,вПусто,вДоступ} ТО
        ОО.Ошибка(ОО.СРАВНЕНИЕ_НЕПРИМЕНИМО)
      КОН;
      xval.цел:=BoolToInt(ConstCmp() # СС.больше)
  | СС.больше:
      ЕСЛИ xf В {вКлюч,вМнож,вПусто,вДоступ} ТО
        ОО.Ошибка(ОО.СРАВНЕНИЕ_НЕПРИМЕНИМО)
      КОН;
      xval.цел:=BoolToInt(ConstCmp() = СС.больше)
  | СС.бравно:
      ЕСЛИ xf В {вКлюч,вМнож,вПусто,вДоступ} ТО
        ОО.Ошибка(ОО.СРАВНЕНИЕ_НЕПРИМЕНИМО)
      КОН;
      xval.цел:=BoolToInt(ConstCmp() # СС.меньше)
  КОН
КОН ConstOp;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       Op-(op:ЦЕЛ; x+,y:ПД.ДкУзлу);
ПЕР
  xf,yf:ЦЕЛ;
  t:ПД.ДкУзлу;
  вид:ВД.ДкВиду;
  do:КЛЮЧ;
  val:ШИРЦЕЛ;
  exp:ЦЕЛ;

 (*...............................................подЗадача...*)
  ЗАДАЧА NewOp( op  :ЦЕЛ;
               вид  :ВД.ДкВиду;
                 x+,
                 y  :ПД.ДкУзлу);
  ПЕР
    узел:ПД.ДкУзлу;
  УКАЗ
    узел:=СоздатьУзел(Ndop);
    узел.подроду:=op;
    узел.вид:=вид;
    узел.лево:=x;
    узел.право:=y;
    x:=узел
  КОН NewOp;

 (*...............................................подЗадача...*)
  ЗАДАЧА strings(x+,y+:ПД.ДкУзлу):КЛЮЧ;
  ПЕР
    ok,xCharArr,yCharArr:КЛЮЧ;
  УКАЗ
    xCharArr:=((xf В {вРяд,вОРяд}) И (x.вид.овид.родв=вЗнак)) ИЛИ (xf=вПЦепь);
    yCharArr:=((yf В {вРяд,вОРяд}) И (y.вид.овид.родв=вЗнак)) ИЛИ (yf=вПЦепь);
    ЕСЛИ xCharArr И (yf=вЗнак) И (y.роду=Nconst) ТО
      CharToString(y);
      yf:=вПЦепь;
      yCharArr:=ВКЛ
    КОН;
    ЕСЛИ yCharArr И (xf=вЗнак) И (x.роду=Nconst) ТО
      CharToString(x);
      xf:=вПЦепь;
      xCharArr:=ВКЛ
    КОН;
    ok:=xCharArr И yCharArr;
    ЕСЛИ ok ТО  
      (* при возможности подменим сравнение с "" цепочкой на сравнение со знаком 0X *)
      ЕСЛИ (xf=вПЦепь) И (РАЗМЕР(x.пост.цепьД^) = 1) ТО  (* y является array of char *)
        x.вид:=ВД.знаквид;
        x.пост.цел:=0;
        Index(y,NewIntConst(0))
      АЕСЛИ (yf=вПЦепь) И (РАЗМЕР(y.пост.цепьД^) = 1) ТО  (* x является array of char *)
        y.вид:=ВД.знаквид;
        y.пост.цел:=0;
        Index(x,NewIntConst(0))
      КОН
    КОН;
    ВОЗВРАТ ok
  КОН strings;

УКАЗ
  ЕСЛИ (x.роду = Ntype) ИЛИ (x.роду = Nproc) ИЛИ (y.роду = Ntype) ИЛИ (y.роду = Nproc) ТО
    ОО.Ошибка(ОО.ЗАДАЧИ_И_ВИДЫ_ЗАПРЕЩЕНЫ);
  КОН;
  ЕСЛИ (x.роду = Nconst) И (y.роду = Nconst) ТО
    ConstOp(op,x,y);
    x.пон:=ПУСТО;
  ИНАЧЕ
    yf:=y.вид.родв;
    ЕСЛИ x.вид # y.вид ТО
      ВЫБРАТЬ x.вид.родв ИЗ
      | вЦел8:
          ЕСЛИ yf В множЦел + множВещ ТО
            Convert(x,y.вид)
          ИНАЧЕ
            ОО.Ошибка(ОО.НЕСОВМЕСТИМЫЕ_ВИДЫ)
          КОН
      | вЦел16:
          ЕСЛИ yf = вЦел8 ТО
            Convert(y,x.вид)
          АЕСЛИ yf В множЦел + множВещ ТО
            Convert(x,y.вид)
          ИНАЧЕ
            ОО.Ошибка(ОО.НЕСОВМЕСТИМЫЕ_ВИДЫ)
          КОН
      | вЦел32:
          ЕСЛИ (yf = вЦел8) ИЛИ (yf = вЦел16) ТО
            Convert(y,x.вид)
          АЕСЛИ yf В множЦел + множВещ ТО
            Convert(x,y.вид)
          ИНАЧЕ
            ОО.Ошибка(ОО.НЕСОВМЕСТИМЫЕ_ВИДЫ)
          КОН
      | вЦел64:
          ЕСЛИ yf В множЦел ТО
            Convert(y,x.вид)
          АЕСЛИ yf В множВещ ТО
            Convert(x,y.вид)
          ИНАЧЕ
            ОО.Ошибка(ОО.НЕСОВМЕСТИМЫЕ_ВИДЫ)
          КОН
      | вВещ32:
          ЕСЛИ yf В множЦел ТО
            Convert(y,x.вид)
          АЕСЛИ yf В множВещ ТО
            Convert(x,y.вид)
          ИНАЧЕ
            ОО.Ошибка(ОО.НЕСОВМЕСТИМЫЕ_ВИДЫ)
          КОН
      | вВещ64:
          ЕСЛИ yf В множЦел + множВещ ТО
            Convert(y,x.вид)
          АЕСЛИ yf В множВещ ТО
            Convert(y,x.вид)
          ИНАЧЕ
            ОО.Ошибка(ОО.НЕСОВМЕСТИМЫЕ_ВИДЫ)
          КОН
      | вПусто:
          ЕСЛИ НЕ (yf В {вДоступ,вЗадача,вБегунок}) ТО
            ОО.Ошибка(ОО.НЕСОВМЕСТИМЫЕ_ВИДЫ)
          КОН
      | вДоступ:
          CheckPtr(x,y)
      | вЗадача:
          ЕСЛИ yf # вПусто ТО
            ОО.Ошибка(ОО.НЕСОВМЕСТИМЫЕ_ВИДЫ)
          КОН
      | вБегунок:
          ЕСЛИ (yf # вПусто) И (x.вид.овид # y.вид.овид) ТО
            ОО.Ошибка(ОО.НЕСОВМЕСТИМЫЕ_ВИДЫ)
          КОН
      | вПЦепь,вРяд,вОРяд:
      ИНАЧЕ
        ОО.Ошибка(ОО.НЕСОВМЕСТИМЫЕ_ВИДЫ)
      КОН
    КОН;  (* {x.вид = y.вид} *)
    вид:=x.вид;
    xf:=вид.родв;
    ВЫБРАТЬ op ИЗ
      СС.умножить:
        do:=ВКЛ;
        ЕСЛИ xf В множЦел ТО
          ЕСЛИ x.роду = Nconst ТО
            val:=x.пост.цел;
            ЕСЛИ val = 1 ТО
              do:=ОТКЛ;
              x:=y
            АЕСЛИ val = 0 ТО
              do:=ОТКЛ
            АЕСЛИ степень2(val,exp) ТО
              t:=y; y:=x; x:=t;
              op:=СС.сдвиг;
              y.вид:=ВД.оячвид;
              y.пост.цел:=exp;
              y.пон:=ПУСТО
            КОН
          АЕСЛИ y.роду = Nconst ТО
            val:=y.пост.цел;
            ЕСЛИ val = 1 ТО
              do:=ОТКЛ
            АЕСЛИ val = 0 ТО
              do:=ОТКЛ;
              x:=y
            АЕСЛИ степень2(val,exp) ТО
              op:=СС.сдвиг;
              y.вид:=ВД.оячвид;
              y.пост.цел:=exp;
              y.пон:=ПУСТО
            КОН
          КОН
        АЕСЛИ НЕ (xf В {вНеопр,вВещ32..вМнож}) ТО
          ОО.Ошибка(ОО.ПЛЮС_НЕПРИМЕНИМ);
        КОН;
        ЕСЛИ do ТО
          NewOp(op,вид,x,y)
        КОН
    | СС.косая:
        ЕСЛИ xf В множЦел ТО
          ЕСЛИ (y.роду = Nconst) И (y.пост.цел = 0) ТО
            ОО.Ошибка(ОО.ДЕЛЕНИЕ_НА_НОЛЬ)
          КОН;
          вид:=ВД.вещ32вид;
          Convert(x,вид);
          Convert(y,вид)
        АЕСЛИ xf В множВещ ТО
          ЕСЛИ (y.роду = Nconst) И (y.пост.вещ = 0.0) ТО
            ОО.Ошибка(ОО.ДЕЛЕНИЕ_НА_НОЛЬ)
          КОН
        АЕСЛИ НЕ (xf В {вМнож,вНеопр}) ТО
          ОО.Ошибка(ОО.ДЕЛЕНИЕ_НЕПРИМЕНИМО)
        КОН;
        NewOp(op,вид,x,y)
    | СС.делить:
        do:=ВКЛ;
        ЕСЛИ xf В множЦел ТО
          ЕСЛИ y.роду = Nconst ТО
            val:=y.пост.цел;
            ЕСЛИ val = 0 ТО
              ОО.Ошибка(ОО.ДЕЛЕНИЕ_НА_НОЛЬ)
            АЕСЛИ val = 1 ТО
              do:=ОТКЛ
            АЕСЛИ степень2(val,exp) ТО
              op:=СС.сдвиг;
              y.вид:=ВД.оячвид;
              y.пост.цел:=-exp;
              y.пон:=ПУСТО
            КОН
          КОН
        АЕСЛИ xf # вНеопр ТО
          ОО.Ошибка(ОО.ДЕЛИТЬ_НЕПРИМЕНИМО)
        КОН;
        ЕСЛИ do ТО
          NewOp(op,вид,x,y)
        КОН
    | СС.остаток:
        ЕСЛИ xf В множЦел ТО
          ЕСЛИ y.роду = Nconst ТО
            val:=y.пост.цел;
            ЕСЛИ val = 0 ТО
              ОО.Ошибка(ОО.ДЕЛЕНИЕ_НА_НОЛЬ)
            АЕСЛИ степень2(val,exp) ТО
              op:=СС.сбрбиты;
              y.пост.цел:=Асм.ЗнаковыйСдвиг64(-1,exp);
              y.пон:=ПУСТО
            КОН
          КОН
        АЕСЛИ xf # вНеопр ТО
          ОО.Ошибка(ОО.ОСТАТОК_НЕПРИМЕНИМО)
        КОН;
        NewOp(op,вид,x,y)
    | СС.и:
        ЕСЛИ xf = вКлюч ТО
          ЕСЛИ x.роду = Nconst ТО
            ЕСЛИ IntToBool(x.пост.цел) ТО x:=y КОН
          АЕСЛИ (y.роду = Nconst) И IntToBool(y.пост.цел) ТО
                     (* optimize x & TRUE -> x *)
          ИНАЧЕ
            NewOp(op,вид,x,y)
          КОН
        АЕСЛИ xf # вНеопр ТО
          ОО.Ошибка(ОО.И_НЕ_С_КЛЮЧОМ)
        КОН
    | СС.плюс:
        ЕСЛИ НЕ (xf В {вНеопр,вЦел8..вМнож}) ТО
          ОО.Ошибка(ОО.ПЛЮС_НЕПРИМЕНИМ)
        КОН;
        do:=ВКЛ;
        ЕСЛИ xf В множЦел ТО
          ЕСЛИ (x.роду = Nconst) И (x.пост.цел = 0) ТО
            do:=ОТКЛ;
            x:=y
          КОН;
          ЕСЛИ (y.роду = Nconst) И (y.пост.цел = 0) ТО
            do:=ОТКЛ
          КОН
        КОН;
        ЕСЛИ do ТО
          NewOp(op,вид,x,y)
        КОН
    | СС.минус:
        ЕСЛИ НЕ (xf В {вНеопр,вЦел8..вМнож}) ТО
          ОО.Ошибка(ОО.МИНУС_НЕПРИМЕНИМ)
        КОН;
        ЕСЛИ НЕ (xf В множЦел) ИЛИ (y.роду # Nconst) ИЛИ (y.пост.цел # 0) ТО
          NewOp(op,вид,x,y)
        КОН
    | СС.или:
        ЕСЛИ xf = вКлюч ТО
          ЕСЛИ x.роду = Nconst ТО
            ЕСЛИ НЕ IntToBool(x.пост.цел) ТО
              x:=y
            КОН
          АЕСЛИ (y.роду = Nconst) И НЕ IntToBool(y.пост.цел) ТО
            (* optimize x OR FALSE -> x *)
          ИНАЧЕ
            NewOp(op,вид,x,y)
          КОН
        АЕСЛИ xf # вНеопр ТО
          ОО.Ошибка(ОО.ИЛИ_НЕ_С_КЛЮЧОМ)
        КОН
    | СС.равно,СС.неравно:
        ЕСЛИ (xf В {вНеопр..вМнож,вПусто,вДоступ,вЗадача,вБегунок}) ИЛИ strings(x,y) ТО
          вид:=ВД.ключвид
        ИНАЧЕ
          ОО.Ошибка(ОО.СРАВНЕНИЕ_НЕПРИМЕНИМО);
        КОН;
        NewOp(op,вид,x,y)
    | СС.меньше,СС.мравно,СС.больше,СС.бравно:
        ЕСЛИ (xf В {вНеопр,вЗнак..вВещ64,вБегунок}) ИЛИ strings(x,y) ТО
          вид:=ВД.ключвид
        ИНАЧЕ
          ОО.Ошибка(ОО.СРАВНЕНИЕ_НЕПРИМЕНИМО)
        КОН;
        NewOp(op,вид,x,y)
    КОН
  КОН
КОН Op;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       SetRange-(x+,y:ПД.ДкУзлу);
ПЕР
  k,l:ШИРЦЕЛ;
УКАЗ
  ЕСЛИ (x.роду = Ntype) ИЛИ (x.роду = Nproc) ИЛИ (y.роду = Ntype) ИЛИ (y.роду = Nproc) ТО
    ОО.Ошибка(ОО.ЗАДАЧИ_И_ВИДЫ_ЗАПРЕЩЕНЫ)
  АЕСЛИ НЕ (x.вид.родв В множЦел) ИЛИ НЕ (y.вид.родв В множЦел) ТО
    ОО.Ошибка(ОО.МНОЖЕСТВО_НЕ_ИЗ_ЦЕЛЫХ)
  КОН;
  ЕСЛИ x.роду = Nconst ТО
    k:=x.пост.цел;
    ЕСЛИ (k < 0) ИЛИ (k > НП.МаксМнож) ТО
      ОО.Ошибка(ОО.ГРАНИЦЫ_МНОЖЕСТВА)
    КОН
  КОН;
  ЕСЛИ y.роду = Nconst ТО
    l:=y.пост.цел;
    ЕСЛИ (l < 0) ИЛИ (l > НП.МаксМнож) ТО
      ОО.Ошибка(ОО.ГРАНИЦЫ_МНОЖЕСТВА)
    КОН
  КОН;
  ЕСЛИ (x.роду = Nconst) И (y.роду = Nconst) ТО
    ЕСЛИ k > l ТО
      ОО.Ошибка(ОО.ПЕРЕПУТАНЫ_ГРАНИЦЫ)
    КОН;
    x.пост.множ:={k..l};
    x.пон:=ПУСТО
  ИНАЧЕ
    BindNodes(Nupto,ВД.множвид,x,y)
  КОН;
  x.вид:=ВД.множвид
КОН SetRange;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       Элемент-(x+:ПД.ДкУзлу);
ПЕР 
  узел:ПД.ДкУзлу;
  k:ШИРЦЕЛ;
УКАЗ
  ЕСЛИ (x.роду = Ntype) ИЛИ (x.роду = Nproc) ТО
    ОО.Ошибка(ОО.ЗАДАЧИ_И_ВИДЫ_ЗАПРЕЩЕНЫ)
  АЕСЛИ НЕ (x.вид.родв В множЦел) ТО
    ОО.Ошибка(ОО.МНОЖЕСТВО_НЕ_ИЗ_ЦЕЛЫХ)
  КОН;
  ЕСЛИ x.роду = Nconst ТО
    k:=x.пост.цел;
    ЕСЛИ (k < 0) ИЛИ (k > НП.МаксМнож) ТО
      ОО.Ошибка(ОО.ГРАНИЦЫ_МНОЖЕСТВА)
    КОН;
    x.пост.множ:={k};
    x.пон:=ПУСТО
  ИНАЧЕ
    узел:=СоздатьУзел(Nmop);
    узел.подроду:=СС.элем;
    узел.лево:=x;
    x:=узел
  КОН;
  x.вид:=ВД.множвид
КОН Элемент;

(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА ОРядПодобен(x,y:ВД.ДкВиду);
(* 
   Цель:  проверка возможности присвоения доступа ряда <y> к доступу оряда <x>
   Для:   CheckAssign, Param
 *)
УКАЗ
  x:=x.овид;
  y:=y.овид;
  ЕСЛИ x = y ТО
    (* хорошо *)
  АЕСЛИ (x.родв = вОРяд) И (y.родв В {вРяд,вОРяд}) ТО
    ОРядПодобен(x,y)
  АЕСЛИ (x.родв = вДоступ) И (y.родв = вДоступ) ТО
    x:=x.овид;
    y:=y.овид;
    ЕСЛИ (x.родв = вНабор) И (y.родв = вНабор) ТО
      ВД.НаборРасширен(x,y)
    ИНАЧЕ
      ОО.Ошибка(ОО.НЕСОВМЕСТИМОЕ_ПРИСВАИВАНИЕ)
    КОН
  ИНАЧЕ
    ОО.Ошибка(ОО.НЕСОВМЕСТИМОЕ_ПРИСВАИВАНИЕ)
  КОН
КОН ОРядПодобен;

(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА CheckAssign(
                        x:ВД.ДкВиду;
                    ynode:ПД.ДкУзлу
                  ); (* x:=y *)
ПЕР
  y:ВД.ДкВиду;
  vx,vy:ЦЕЛ;
  ox,oy:ВД.ДкВиду;
УКАЗ
  y:=ynode.вид;
  vx:=x.родв;
  vy:=y.родв;
  ЕСЛИ (ynode.роду = Ntype) ИЛИ (ynode.роду = Nproc) И (vx # вЗадача) ТО
    ОО.Ошибка(ОО.ЗАДАЧИ_И_ВИДЫ_ЗАПРЕЩЕНЫ)
  КОН;
  ВЫБРАТЬ vx ИЗ
    вНеопр:
  | вЯчейка:
      ЕСЛИ НЕ (vy В {вЯчейка,вЦел8}) ТО
        ОО.Ошибка(ОО.НЕСОВМЕСТИМОЕ_ПРИСВАИВАНИЕ)
      КОН
  | вКлюч,вЗнак,вЦел8,вМнож:
      ЕСЛИ vy # vx ТО
        ОО.Ошибка(ОО.НЕСОВМЕСТИМОЕ_ПРИСВАИВАНИЕ)
      КОН
  | вЦел16:
      ЕСЛИ НЕ (vy В {вЦел8,вЦел16}) ТО
        ОО.Ошибка(ОО.НЕСОВМЕСТИМОЕ_ПРИСВАИВАНИЕ)
      КОН
  | вЦел32:
      ЕСЛИ НЕ (vy В {вЦел8,вЦел16,вЦел32}) ТО
        ОО.Ошибка(ОО.НЕСОВМЕСТИМОЕ_ПРИСВАИВАНИЕ)
      КОН
  | вЦел64:
      ЕСЛИ НЕ (vy В множЦел) ТО
        ОО.Ошибка(ОО.НЕСОВМЕСТИМОЕ_ПРИСВАИВАНИЕ)
      КОН
  | вВещ32:
      ЕСЛИ НЕ (vy В {вЦел8..вВещ32}) ТО
        ОО.Ошибка(ОО.НЕСОВМЕСТИМОЕ_ПРИСВАИВАНИЕ)
      КОН
  | вВещ64:
      ЕСЛИ НЕ (vy В {вЦел8..вВещ64}) ТО
        ОО.Ошибка(ОО.НЕСОВМЕСТИМОЕ_ПРИСВАИВАНИЕ)
      КОН
  | вДоступ:
      ЕСЛИ (x = y) ИЛИ (vy = вПусто) ИЛИ (x = ВД.одоствид) И (vy = вДоступ) ТО
        (* хорошо *)
      АЕСЛИ vy = вДоступ ТО
        ox:=x.овид;
        oy:=y.овид;
        ЕСЛИ (ox.родв = вНабор) И (oy.родв = вНабор) ТО
          ВД.НаборРасширен(ox,oy)
        АЕСЛИ (ox.родв = вОРяд) И (oy.родв В {вРяд,вОРяд}) ТО
          ОРядПодобен(ox,oy)
        ИНАЧЕ
          ОО.Ошибка(ОО.НЕСОВМЕСТИМОЕ_ПРИСВАИВАНИЕ)
        КОН
      ИНАЧЕ
        ОО.Ошибка(ОО.НЕСОВМЕСТИМОЕ_ПРИСВАИВАНИЕ)
      КОН
  | вЗадача:
      ЕСЛИ ynode.роду = Nproc ТО
        CheckProc(x,ynode.пон)
      АЕСЛИ (x = y) ИЛИ (vy = вПусто) ТО
        (* хорошо *)
      ИНАЧЕ
        ОО.Ошибка(ОО.НЕСОВМЕСТИМОЕ_ПРИСВАИВАНИЕ)
      КОН
  | вБегунок:
      ЕСЛИ (vy # вПусто) И (x.овид # y.овид) ТО
        ОО.Ошибка(ОО.НЕСОВМЕСТИМЫЕ_ВИДЫ)
      КОН
  | вНет,вПусто:
      ОО.Ошибка(ОО.НЕСОВМЕСТИМОЕ_ПРИСВАИВАНИЕ)
  | вНабор:
      ЕСЛИ x = y ТО
        (* хорошо *)
      АЕСЛИ vy = вНабор ТО
        ВД.НаборРасширен(x,y)
      ИНАЧЕ
        ОО.Ошибка(ОО.НЕСОВМЕСТИМОЕ_ПРИСВАИВАНИЕ)
      КОН
  | вРяд:
      ЕСЛИ (ynode.роду = Nconst) И (vy = вЗнак) ТО
        CharToString(ynode);
        y:=ynode.вид;
        vy:=вПЦепь
      КОН;
      ЕСЛИ x = y ТО
        (* хорошо *)
      АЕСЛИ (vy = вПЦепь) И (x.овид = ВД.знаквид) ТО (*check length of string*)
        ЕСЛИ РАЗМЕР(ynode.пост.цепьД^) > x.n ТО
          ОО.Ошибка(ОО.СТРОКА_ВЕЛИКА)
        КОН;
      ИНАЧЕ
        ОО.Ошибка(ОО.НЕСОВМЕСТИМОЕ_ПРИСВАИВАНИЕ)
      КОН
  | вОРяд:
      ОО.Ошибка(ОО.НЕСОВМЕСТИМОЕ_ПРИСВАИВАНИЕ)
  КОН;
  ЕСЛИ (ynode.роду = Nconst) И (vy < vx) И (vy В {вЦел8..вВещ32}) И (vx В {вЦел16..вВещ64}) ТО
    Convert(ynode,x)
  КОН
КОН CheckAssign;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       StPar0-(
                   прием0+:ПД.ДкУзлу;
                       нз :ЦЕЛ
              );(* прием0 - первый приёмник встроенной задачи *)
ПЕР
  f:ЦЕЛ;
  вид:ВД.ДкВиду;
  x,y:ПД.ДкУзлу;
УКАЗ
  x:=прием0;
  f:=x.вид.родв;
  ЕСЛИ (НЕ (нз В {зМакс,зМин,зЗначение})) И
    ((x.роду = Ntype) ИЛИ (x.роду = Nproc)) ТО
    ОО.Ошибка(ОО.ЗАДАЧИ_И_ВИДЫ_ЗАПРЕЩЕНЫ)
  КОН;
  ВЫБРАТЬ нз ИЗ
  | зСоздать:
      вид:=ВД.нетвид;
      ЕСЛИ NotVar(x) ТО
        ОО.Ошибка(ОО.ЭТО_НЕ_ПЕРЕМЕННАЯ)
      АЕСЛИ f # вДоступ ТО
        ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      АЕСЛИ x.толькочт ТО
        ОО.Ошибка(ОО.ПЕР_ДЛЯ_ЧТЕНИЯ)
      КОН;
      f:=x.вид.овид.родв;
      ЕСЛИ НЕ (f В {вНабор,вОРяд,вРяд}) ТО
        ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН;
      ЕСЛИ f = вОРяд ТО вид:=x.вид.овид КОН;
      BindNodes(Nassign,вид,x,ПУСТО);
      x.подроду:=зСоздать
  | зОбнулить:
      ЕСЛИ NotVar(x) ТО
        ОО.Ошибка(ОО.ЭТО_НЕ_ПЕРЕМЕННАЯ)
      АЕСЛИ x.толькочт ТО
        ОО.Ошибка(ОО.ПЕР_ДЛЯ_ЧТЕНИЯ)
      АЕСЛИ НЕ (f В {вНабор,вОРяд,вРяд}) ТО
        ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН;
      BindNodes(Nassign,ВД.нетвид,x,ПУСТО);
      x.подроду:=зОбнулить
  | зЦелЧасть:
      ЕСЛИ НЕ (f В множВещ) ТО
        ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН;
      ЕСЛИ x.роду = Nconst ТО
        x.пост.вещ:=ЦЕЛЧАСТЬ(x.пост.вещ);
        x.пон:=ПУСТО
      ИНАЧЕ
        x:=NewMOp(СС.целчасть,x)
      КОН
  | зМодуль:
      ЕСЛИ НЕ (f В множЦел+множВещ) ТО
        ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН;
      ЕСЛИ x.роду = Nconst ТО
        ЕСЛИ f В множЦел ТО
          x.пост.цел:=МОДУЛЬ(x.пост.цел);
          SetIntType(x)
        ИНАЧЕ
          x.пост.вещ:=МОДУЛЬ(x.пост.вещ)
        КОН;
        x.пон:=ПУСТО
      ИНАЧЕ
        x:=NewMOp(СС.модуль,x)
      КОН
  | зСтоп:
      ЕСЛИ НЕ (f В множЦел) ТО
        ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН;
      y:=СоздатьУзел(Nassign);
      y.подроду:=зСтоп;
      y.лево:=x;
      y.вид:=ВД.нетвид;
      x:=y
  | зВЦел:
      ЕСЛИ f = вЗнак ТО
        Convert(x,ВД.цел32вид)
      ИНАЧЕ
        ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН
  | зВШирЦел:
      ЕСЛИ НЕ (f В множВещ) ТО
        ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН;
      Convert(x,ВД.цел64вид)
  | зЧет:
      ЕСЛИ НЕ (f В множЦел) ТО
        ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН;
      ЕСЛИ x.роду = Nconst ТО
        x.пост.цел:=BoolToInt(ЧЕТ(x.пост.цел));
        x.пон:=ПУСТО
      ИНАЧЕ
        x:=NewMOp(СС.чет,x)
      КОН;
      x.вид:=ВД.ключвид
  | зМин:
      ЕСЛИ x.роду # Ntype ТО
        ОО.Ошибка(ОО.ЭТО_НЕ_ВИД)
      КОН;
      ВЫБРАТЬ f ИЗ
        вКлюч:  x:=NewBoolConst(ОТКЛ)
      | вЗнак:  x:=NewIntConst(НП.МинЗнак); x.вид:=ВД.знаквид
      | вЦел8:  x:=NewIntConst(НП.МинЦел8)
      | вЦел16: x:=NewIntConst(НП.МинЦел16)
      | вЦел32: x:=NewIntConst(НП.МинЦел32)
      | вЦел64: x:=NewIntConst(НП.МинЦел64)
      | вМнож:  x:=NewIntConst(0); x.вид:=ВД.цел32вид
      | вВещ32: x:=NewRealConst(НП.МинВещ32,ВД.вещ32вид)
      | вВещ64: x:=NewRealConst(НП.МинВещ64,ВД.вещ64вид)
      ИНАЧЕ
        ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН
  | зМакс:
      ЕСЛИ x.роду # Ntype ТО
        ОО.Ошибка(ОО.ЭТО_НЕ_ВИД)
      КОН;
      ВЫБРАТЬ f ИЗ
        вКлюч:  x:=NewBoolConst(ВКЛ)
      | вЗнак:  x:=NewIntConst(НП.МаксЗнак); x.вид:=ВД.знаквид
      | вЦел8:  x:=NewIntConst(НП.МаксЦел8)
      | вЦел16: x:=NewIntConst(НП.МаксЦел16)
      | вЦел32: x:=NewIntConst(НП.МаксЦел32)
      | вЦел64: x:=NewIntConst(НП.МаксЦел64)
      | вМнож:  x:=NewIntConst(НП.МаксМнож); x.вид:=ВД.цел32вид
      | вВещ32: x:=NewRealConst(НП.МаксВещ32,ВД.вещ32вид)
      | вВещ64: x:=NewRealConst(НП.МаксВещ64,ВД.вещ64вид)
      ИНАЧЕ
        ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН
  | зВЗнак:
      ЕСЛИ НЕ (f В {вНеопр,вЦел8..вЦел64}) ТО
        ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН;
      Convert(x,ВД.знаквид)
  | зУзк,зОУзк:  (* УЗК, ОБХОД.Узк *)
      ВЫБРАТЬ f ИЗ
      | вЦел16:  Convert(x,ВД.цел8вид)
      | вЦел32:  Convert(x,ВД.цел16вид)
      | вЦел64:  Convert(x,ВД.цел32вид)
      | вВещ64:  Convert(x,ВД.вещ32вид)
      ИНАЧЕ
        ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН
  | зУвеличить,зУменьшить:
      ЕСЛИ NotVar(x) ТО
        ОО.Ошибка(ОО.ЭТО_НЕ_ПЕРЕМЕННАЯ)
      АЕСЛИ НЕ (f В множЦел) ТО
        ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      АЕСЛИ x.толькочт ТО
        ОО.Ошибка(ОО.ПЕР_ДЛЯ_ЧТЕНИЯ)
      КОН
  | зРазмер:
      ЕСЛИ НЕ (x.вид.родв В {вОРяд,вРяд}) ТО
        ОО.Ошибка(ОО.РАЗМЕР_БЕЗ_РЯДА)
      КОН
  | зДлина:
      ЕСЛИ (x.роду = Nconst) И (f = вЗнак) ТО
        CharToString(x);
        f:=вПЦепь
      КОН;
      ЕСЛИ (НЕ (x.вид.родв В {вОРяд,вРяд}) ИЛИ (x.вид.овид.родв # вЗнак))
        И (f # вПЦепь) ТО
        ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН;
      ЕСЛИ x.роду = Nconst ТО
        x.пост.цел:=ДЛИНА(x.пост.цепьД^); 
        x.пон:=ПУСТО
      ИНАЧЕ
        x:=NewMOp(СС.длина,x)
      КОН;
      x.вид:=ВД.цел32вид
  | зЗадано:
      ЕСЛИ (x.роду = Nconst) И (f = вЗнак) ТО
        CharToString(x);
        f:=вПЦепь
      КОН;
      ЕСЛИ f # вПЦепь ТО
        ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН;
      x:=NewBoolConst(НП.ЕстьКлюч(x.пост.цепьД^))
  | зСписать:
      ЕСЛИ (x.роду = Nconst) И (f = вЗнак) ТО
        CharToString(x);
        f:=вПЦепь
      КОН;
      ЕСЛИ (НЕ (x.вид.родв В {вОРяд,вРяд}) ИЛИ (x.вид.овид.родв # вЗнак))
        И (f # вПЦепь) ТО
        ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН
  | зПолучитьАдрес:
      ЕСЛИ (x.роду >= Nconst) И (f # вПЦепь) ТО
        ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН;
      x:=NewMOp(СС.адрес,x);
      x.вид:=ВД.цел32вид
  | зИзПамяти,
    зВПамять,
    зОбраз:
      ЕСЛИ (x.роду = Nconst) И (f В {вЦел16,вЦел64}) ТО
        Convert(x,ВД.цел32вид)
      АЕСЛИ f # вЦел32 ТО
        ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН
  | зПоставить,зСместить:
      ЕСЛИ NotVar(x) ТО
        ОО.Ошибка(ОО.ЭТО_НЕ_ПЕРЕМЕННАЯ)
      АЕСЛИ f # вБегунок ТО
        ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      АЕСЛИ x.толькочт ТО
        ОО.Ошибка(ОО.ПЕР_ДЛЯ_ЧТЕНИЯ)
      КОН
  | зЗначение:
      ЕСЛИ x.роду # Ntype ТО
        ОО.Ошибка(ОО.ЭТО_НЕ_ВИД)
      АЕСЛИ (f В {вНеопр,вПЦепь,вНет}) ИЛИ (x.вид.родв = вОРяд) ТО
        ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН
  | зПроверить:
      ЕСЛИ НП.клВклПроверить ТО
        ЕСЛИ f # вКлюч ТО
          ОО.Ошибка(ОО.ОЖИДАЕТСЯ_КЛЮЧ)
        КОН;
        MOp(СС.не,x);
        y:=ПУСТО;
        Construct(Ntrap,y,NewIntConst(проверитьАвОст));
        y.текстп:=ОО.текПоз;
        Construct(Nif,x,y);
        x.текстп:=ОО.текПоз;
        Construct(Nifelse,x,ПУСТО);
        OptIf(x)
      ИНАЧЕ
        x:=ПУСТО
      КОН
  КОН;
  прием0:=x;
  ЕСЛИ прием0 # ПУСТО ТО
    прием0.текстп:=ОО.текПоз
  КОН
КОН StPar0;

(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА Значение(  x+:ПД.ДкУзлу;
                вид :ВД.ДкВиду);
(*
 * (из OPB) ОБХОД.Значение, меняем вид <x> на <вид>,
 * без преобразования, только отображение
 *)
ПЕР
  t:ПД.ДкУзлу;
  xродв,родв:ЦЕЛ;
  готово:КЛЮЧ;
УКАЗ
  xродв:=x.вид.родв;
  родв:=вид.родв;
  ЕСЛИ (x.роду = Ntype) ИЛИ (x.роду = Nproc) ИЛИ (xродв В {вНеопр,вПЦепь,вНет}) ТО
    ОО.Ошибка(ОО.ЗАДАЧИ_И_ВИДЫ_ЗАПРЕЩЕНЫ)
  КОН;
  готово:=ОТКЛ;
  (* проверка на размер будет позже *)
  ЕСЛИ x.роду = Nconst ТО
    (* из целых *)
    ЕСЛИ xродв В множЦел ТО
      ЕСЛИ родв = вВещ32 ТО
        ЕСЛИ xродв = вЦел64 ТО
          ОО.Ошибка(ОО.НЕСОВПАДЕНИЕ_РАЗМЕРОВ)
        КОН;
        x:=NewRealConst(ОБХОД.Значение(ВЕЩ,УЗК(x.пост.цел)),вид);
        готово:=ВКЛ
      АЕСЛИ родв = вВещ64 ТО
        x:=NewRealConst(ОБХОД.Значение(ШИРВЕЩ,x.пост.цел),вид);
        готово:=ВКЛ
      АЕСЛИ родв = вМнож ТО
        ЕСЛИ xродв = вЦел64 ТО
          ОО.Ошибка(ОО.НЕСОВПАДЕНИЕ_РАЗМЕРОВ)
        КОН;
        x.пост.множ:=ОБХОД.Значение(МНОЖ,УЗК(x.пост.цел));
        готово:=ВКЛ
      АЕСЛИ родв В множЦел ТО
        ЕСЛИ xродв <= родв ТО
          готово:=ВКЛ
        ИНАЧЕ
          ОО.Ошибка(ОО.НЕСОВПАДЕНИЕ_РАЗМЕРОВ)
        КОН
      КОН
    (* в целые *)
    АЕСЛИ родв В множЦел ТО
      ЕСЛИ xродв = вВещ64 ТО
        x:=NewIntConst(ОБХОД.Значение(ШИРЦЕЛ,x.пост.вещ));
        готово:=ВКЛ
      АЕСЛИ xродв = вВещ32 ТО
        x:=NewIntConst(ОБХОД.Значение(ЦЕЛ,УЗК(x.пост.вещ)));
        готово:=ВКЛ
      АЕСЛИ xродв = вМнож ТО
        x.пост.цел:=ОБХОД.Значение(ЦЕЛ,x.пост.множ);
        готово:=ВКЛ
      КОН
    АЕСЛИ (xродв = вВещ32) И (родв = вМнож) ТО
      x.пост.множ:=ОБХОД.Значение(МНОЖ,УЗК(x.пост.вещ));
      готово:=ВКЛ
    АЕСЛИ (xродв = вМнож) И (родв = вВещ32) ТО
      x.пост.вещ:=ОБХОД.Значение(ВЕЩ,x.пост.множ);
      готово:=ВКЛ
    КОН
  КОН;
  ЕСЛИ НЕ готово ТО
    t:=СоздатьУзел(Nmop);
    t.подроду:=СС.значение;
    t.лево:=x;
    x:=t
  КОН;
  x.вид:=вид
КОН Значение;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       StPar1-(
               прием0+,
                    x  :ПД.ДкУзлу;
                   нз  :ЦЕЛ
              ); (* x - второй приёмник встроенной задачи *)
ПЕР
  f,L:ЦЕЛ;
  вид:ВД.ДкВиду;
  p,t:ПД.ДкУзлу;

 (*...............................................подЗадача...*)
  ЗАДАЧА NewOp(роду,подроду:ЦЕЛ;
               лево,право:ПД.ДкУзлу):ПД.ДкУзлу;
  ПЕР
    узел:ПД.ДкУзлу;
  УКАЗ
    узел:=СоздатьУзел(роду);
    узел.подроду:=подроду;
    узел.лево:=лево;
    узел.право:=право;
    ВОЗВРАТ узел
  КОН NewOp;

УКАЗ
  p:=прием0;
  f:=x.вид.родв;
  ВЫБРАТЬ нз ИЗ
    зУвеличить,зУменьшить:
      ЕСЛИ (x.роду = Ntype) ИЛИ (x.роду = Nproc) ТО
        ОО.Ошибка(ОО.ЗАДАЧИ_И_ВИДЫ_ЗАПРЕЩЕНЫ)
      КОН;
      ЕСЛИ x.вид # p.вид ТО
        ЕСЛИ НЕ (f В множЦел) ТО
          ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
        КОН;
        Convert(x,p.вид)
      КОН;
      p:=NewOp(Nassign,нз,p,x);
      p.вид:=ВД.нетвид
  | зРазмер:
      ЕСЛИ НЕ (f В множЦел) ИЛИ (x.роду # Nconst) ТО
        ОО.Ошибка(ОО.ИСТОЧНИК_НЕ_ЦЕЛАЯ_ПОСТ)
      КОН;
      L:=УЗК(x.пост.цел);
      вид:=p.вид;
      ПОКА (L > 0) И (вид.родв В {вОРяд,вРяд}) ВЫП
        вид:=вид.овид;
        УМЕНЬШИТЬ(L)
      КОН;
      ЕСЛИ (L # 0) ИЛИ НЕ (вид.родв В {вОРяд,вРяд}) ТО
        ОО.Ошибка(ОО.НЕВЕРНАЯ_РАЗМЕРНОСТЬ)
      КОН;
      x.пон:=ПУСТО;
      ЕСЛИ вид.родв = вОРяд ТО
        ПОКА p.роду = Nindex ВЫП
          p:=p.лево;
          УВЕЛИЧИТЬ(x.пост.цел)
        КОН;  (* possible side effect ignored *)
        p:=NewOp(Ndop,СС.размер,p,x);
        p.вид:=ВД.цел32вид
      ИНАЧЕ
        p:=x;
        p.пост.цел:=вид.n;
        SetIntType(p)
      КОН
  | зСписать:
      ЕСЛИ NotVar(x) ТО
        ОО.Ошибка(ОО.ЭТО_НЕ_ПЕРЕМЕННАЯ)
      АЕСЛИ НЕ (x.вид.родв В {вРяд,вОРяд}) ИЛИ (x.вид.овид.родв # вЗнак) ТО
        ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      АЕСЛИ x.толькочт ТО
        ОО.Ошибка(ОО.ПЕР_ДЛЯ_ЧТЕНИЯ)
      КОН;
      t:=x; x:=p; p:=t;
      p:=NewOp(Nassign,нз,p,x);
      p.вид:=ВД.нетвид
  | зСоздать: (* СОЗДАТЬ(p,x...) *)
      ЕСЛИ (x.роду = Ntype) ИЛИ (x.роду = Nproc) ТО
        ОО.Ошибка(ОО.ЗАДАЧИ_И_ВИДЫ_ЗАПРЕЩЕНЫ)
      АЕСЛИ p.вид.родв # вОРяд ТО
        ОО.Ошибка(ОО.МНОГО_ИСТОЧНИКОВ)
      АЕСЛИ НЕ (f В множЦел) ТО
        ЕСЛИ (x.роду = Nconst) И (f = вЗнак) ТО
          CharToString(x);
          f:=вПЦепь
        КОН;
        ЕСЛИ (НЕ (x.вид.родв В {вОРяд,вРяд}) ИЛИ (x.вид.овид.родв # вЗнак))
          И (f # вПЦепь) ТО
          ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
        КОН;
        (* цепочка по цепочке *)
        ЕСЛИ x.роду = Nconst ТО
          t:=NewIntConst(ДЛИНА(x.пост.цепьД^)+1)
        ИНАЧЕ
          t:=NewMOp(СС.длина,x);
          t.вид:=ВД.цел32вид;
          t:=NewOp(Ndop,СС.плюс,t,NewIntConst(1))
        КОН;
        p.право:=t;
        t.след:=x
      АЕСЛИ (x.роду = Nconst) И (x.пост.цел <= 0) ТО
        ОО.Ошибка(ОО.НЕВЕРНАЯ_ПОСТОЯННАЯ)
      ИНАЧЕ
        p.право:=x
      КОН;
      p.вид:=p.вид.овид
  | зИзПамяти,зВПамять:
      ЕСЛИ (x.роду = Ntype) ИЛИ (x.роду = Nproc) ТО
        ОО.Ошибка(ОО.ЗАДАЧИ_И_ВИДЫ_ЗАПРЕЩЕНЫ)
      АЕСЛИ НЕ (f В {вНеопр..вМнож,вДоступ,вЗадача}) ТО
        ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН;
      ЕСЛИ нз = зИзПамяти ТО
        ЕСЛИ NotVar(x) ТО
          ОО.Ошибка(ОО.ЭТО_НЕ_ПЕРЕМЕННАЯ)
        КОН;
        t:=x; x:=p; p:=t
      КОН;
      p:=NewOp(Nassign,нз,p,x);
      p.вид:=ВД.нетвид
  | зЗначение:
      Значение(x,p.вид);
      p:=x
  | зОбраз:
      ЕСЛИ (x.роду = Ntype) ИЛИ (x.роду = Nproc) ТО
        ОО.Ошибка(ОО.ЗАДАЧИ_И_ВИДЫ_ЗАПРЕЩЕНЫ)
      АЕСЛИ (x.роду = Nconst) И (f В {вЦел16,вЦел64}) ТО
        Convert(x,ВД.цел32вид)
      АЕСЛИ f # вЦел32 ТО
        ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН;
      p.след:=x
  | зПоставить:
      ЕСЛИ x.вид.родв # вРяд ТО
        ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН;
      p.след:=x
  | зСместить:
      ЕСЛИ НЕ (f В множЦел) ИЛИ (x.роду # Nconst) ТО
        ОО.Ошибка(ОО.ИСТОЧНИК_НЕ_ЦЕЛАЯ_ПОСТ)
      КОН;
      p:=NewOp(Nassign,нз,p,x);
      p.вид:=ВД.нетвид
  ИНАЧЕ
    ОО.Ошибка(ОО.МНОГО_ИСТОЧНИКОВ)
  КОН;
  прием0:=p
КОН StPar1;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       StParN-(
                прием0+,
                     x  :ПД.ДкУзлу;
                  нз,n  :ЦЕЛ
              );  (* x - n+1-й приёмник встроенной задачи *)
ПЕР
  узел:ПД.ДкУзлу;
  f:ЦЕЛ;
УКАЗ
  f:=x.вид.родв;
  ЕСЛИ нз = зСоздать ТО (* СОЗДАТЬ(прием0,...,x...*)
    ЕСЛИ (x.роду = Ntype) ИЛИ (x.роду = Nproc) ТО
      ОО.Ошибка(ОО.ЗАДАЧИ_И_ВИДЫ_ЗАПРЕЩЕНЫ)
    АЕСЛИ прием0.вид.родв # вОРяд ТО
      ОО.Ошибка(ОО.МНОГО_ИСТОЧНИКОВ)
    АЕСЛИ НЕ (f В множЦел) ТО
      ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
    АЕСЛИ (x.роду = Nconst) И (x.пост.цел <= 0) ТО
      ОО.Ошибка(ОО.НЕВЕРНАЯ_ПОСТОЯННАЯ)
    КОН;
    узел:=прием0.право;
    ПОКА узел.след # ПУСТО ВЫП
      узел:=узел.след
    КОН;
    узел.след:=x;
    прием0.вид:=прием0.вид.овид
  АЕСЛИ (нз В {зОбраз,зПоставить}) И (n = 2) ТО
    ЕСЛИ (x.роду = Ntype) ИЛИ (x.роду = Nproc) ТО
      ОО.Ошибка(ОО.ЗАДАЧИ_И_ВИДЫ_ЗАПРЕЩЕНЫ)
    АЕСЛИ НЕ (f В множЦел) ТО
      ОО.Ошибка(ОО.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
    КОН;
    узел:=СоздатьУзел(Nassign);
    узел.подроду:=нз;
    узел.право:=прием0;
    узел.лево:=прием0.след;
    прием0.след:=x;
    прием0:=узел;
    прием0.вид:=ВД.нетвид
  ИНАЧЕ
    ОО.Ошибка(ОО.МНОГО_ИСТОЧНИКОВ)
  КОН
КОН StParN;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       StFct-(прием0+:ПД.ДкУзлу;
              нз,
              всегоПр:ЦЕЛ);      (* Анализ всех приёмников у встроенных задач *)
ПЕР
  размерность:ЦЕЛ;
УКАЗ
  ЕСЛИ
    (всегоПр < 1) ИЛИ
    (всегоПр < 2) И (нз В {зСписать,зИзПамяти,зВПамять,зЗначение}) ИЛИ
    (всегоПр < 3) И (нз В {зОбраз,зПоставить}) ТО
    ОО.Ошибка(ОО.МАЛО_ИСТОЧНИКОВ)
  КОН;
  ВЫБРАТЬ нз ИЗ
    зСоздать:
      ЕСЛИ прием0.вид # ВД.нетвид ТО
        ЕСЛИ прием0.вид.родв = вОРяд ТО
          ОО.Ошибка(ОО.МАЛО_ИСТОЧНИКОВ)
        КОН;
        прием0.вид:=ВД.нетвид
      КОН
  | зУвеличить,зУменьшить:
      ЕСЛИ всегоПр = 1 ТО
        Construct(Nassign,прием0,NewIntConst(1));
        прием0.подроду:=нз;
      КОН
  | зРазмер:
      ЕСЛИ всегоПр = 1 ТО
        ЕСЛИ прием0.вид.родв = вОРяд ТО
          размерность:=0;
          ПОКА прием0.роду = Nindex ВЫП
            прием0:=прием0.лево;
            УВЕЛИЧИТЬ(размерность)
          КОН; (* possible side effect ignored *)
          BindNodes(Ndop,ВД.цел32вид,прием0,NewIntConst(размерность));
          прием0.подроду:=СС.размер
        ИНАЧЕ
          прием0:=NewIntConst(прием0.вид.n)
        КОН
      КОН
  ИНАЧЕ
  КОН
КОН StFct;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       PrepCall-(    x+:ПД.ДкУзлу;
                 приём+:ВД.ДкПонятию);
УКАЗ
  ЕСЛИ (x.пон # ПУСТО) И (x.пон.родп = пЗадача) ТО
    ЕСЛИ прПередаваемая В x.пон.признаки ТО
      ОО.Ошибка(ОО.ВЫЗОВ_ПЕРЕДАВАЕМОЙ)
    КОН;
    приём:=x.пон.след
  АЕСЛИ (x.роду # Ntype) И (x.вид # ПУСТО) И (x.вид.родв = вЗадача) ТО
    ЕСЛИ x.вид.n = 1 ТО
      ОО.Ошибка(ОО.ВЫЗОВ_ПЕРЕДАВАЕМОЙ)
    КОН;
    приём:=x.вид.след
  ИНАЧЕ
    ОО.Ошибка(ОО.ЭТО_НЕ_ЗАДАЧА)
  КОН
КОН PrepCall;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       Param-(иу:ПД.ДкУзлу;
              пп:ВД.ДкПонятию);
(*
 * пп - понятие приёмника 
 * иу - узел источника
 *)
ПЕР
  ив,пв:ВД.ДкВиду;
  пво:ВД.ДкВиду;
  ивр,пвр:ЦЕЛ;
УКАЗ
  ив:=иу.вид;
  ивр:=ив.родв;
  пв:=пп.вид;
  пво:=пв.овид;
  пвр:=пв.родв;
  ЕСЛИ пвр # вНеопр ТО
    ЕСЛИ пп.родп = пПрСсылки ТО
      ЕСЛИ НЕ (прНеизменяемая В пп.признаки) ТО
        ЕСЛИ NotVar(иу) ТО
          ОО.Ошибка(ОО.ЭТО_НЕ_ПЕРЕМЕННАЯ)
        АЕСЛИ иу.толькочт ТО
          ОО.Ошибка(ОО.ПЕР_ДЛЯ_ЧТЕНИЯ)
        КОН
      КОН;
      ЕСЛИ пвр = вОРяд ТО
        ЕСЛИ (прНеизменяемая В пп.признаки) И (иу.роду = Nconst) И (ивр = вЗнак) ТО
          CharToString(иу);
          ив:=иу.вид;
          ивр:=ив.родв
        КОН;
        ЕСЛИ (прНеизменяемая В пп.признаки) И (пво.родв = вЗнак) И (ивр = вПЦепь) ТО
          (* хорошо *)
        АЕСЛИ пво = ВД.оячвид ТО
          ЕСЛИ NotVar(иу) И (ивр # вПЦепь) ТО
            ОО.Ошибка(ОО.ЭТО_НЕ_ПЕРЕМЕННАЯ)
          КОН
        АЕСЛИ ивр В {вРяд,вОРяд} ТО
          ОРядПодобен(пв,ив)
        ИНАЧЕ
          ОО.Ошибка(ОО.ИСТОЧНИК_НЕ_РЯД)
        КОН
      АЕСЛИ (пвр = вНабор) И (ивр = вНабор) ТО
        ВД.НаборРасширен(пв,ив)
      АЕСЛИ (пв = ВД.одоствид) И (ивр = вДоступ) ТО
        (* хорошо *)
      АЕСЛИ ив = пв ТО
        (* хорошо *)
      АЕСЛИ (пвр = вЯчейка) И (ивр = вЦел8) ТО
        (* хорошо *)
      ИНАЧЕ
        ОО.Ошибка(ОО.ВИД_ПРИЕМНИКА)
      КОН
    АЕСЛИ пвр = вОРяд ТО
      ЕСЛИ (иу.роду = Nconst) И (ивр = вЗнак) ТО
        CharToString(иу);
        ив:=иу.вид;
        ивр:=ив.родв
      КОН;
      ЕСЛИ
           (ивр = вПЦепь) И (пво.родв = вЗнак)
      ТО                                       (* хорошо *)
      АЕСЛИ
            иу.роду >= Nconst
      ТО                                       (* не переменная *)
        ОО.Ошибка(ОО.НЕВЕРНЫЙ_ПРИЕМНИК_ОРЯДА)
      АЕСЛИ
            ивр В {вРяд,вОРяд}
      ТО
        ОРядПодобен(пв,ив)
      КОН
    ИНАЧЕ
      CheckAssign(пв,иу)
    КОН
  КОН
КОН Param;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       Call-(    x+,
             исток  :ПД.ДкУзлу;
             приём  :ВД.ДкПонятию);
УКАЗ
  ЕСЛИ x.роду = Nproc ТО
    BindNodes(Ncall,x.вид,x,исток)
  ИНАЧЕ
    BindNodes(Ncall,x.вид.овид,x,исток)
  КОН;
  x.пон:=приём
КОН Call;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       Enter-(procdec+,stat:ПД.ДкУзлу;
                     задача:ВД.ДкПонятию);
ПЕР
  x:ПД.ДкУзлу;
УКАЗ
  x:=СоздатьУзел(Nenter); 
  x.вид:=ВД.нетвид;
  x.пон:=задача;
  x.лево:=procdec;
  x.право:=stat;
  procdec:=x
КОН Enter;
  
(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       Return-(     x+:ПД.ДкУзлу;
               задача :ВД.ДкПонятию);
ПЕР 
  узел:ПД.ДкУзлу;
УКАЗ
  ЕСЛИ задача = ПУСТО ТО (* return from module *)
    ЕСЛИ
         x # ПУСТО
    ТО
      ОО.Ошибка(ОО.ПРИСВАИВАНИЕ_ОТВЕТУ)
    КОН
  ИНАЧЕ
    ЕСЛИ
         x # ПУСТО
    ТО 
      CheckAssign(задача.вид,x)
    АЕСЛИ
          задача.вид # ВД.нетвид
    ТО
      ОО.Ошибка(ОО.ПРИСВАИВАНИЕ_ОТВЕТУ)
    КОН
  КОН;
  узел:=СоздатьУзел(Nreturn); 
  узел.вид:=ВД.нетвид;
  узел.пон:=задача;
  узел.лево:=x;
  x:=узел
КОН Return;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       Assign-(x+,y:ПД.ДкУзлу);
ПЕР 
  z:ПД.ДкУзлу;
УКАЗ
  ЕСЛИ
          x.роду >= Nconst
  ТО
    ОО.Ошибка(ОО.ПРИСВАИВАНИЕ_НЕ_ПЕРЕМЕННОЙ)
  АЕСЛИ
          x.толькочт
  ТО
    ОО.Ошибка(ОО.ПЕР_ДЛЯ_ЧТЕНИЯ)
  КОН;
CheckAssign(x.вид,y);
  ЕСЛИ
          x.вид.родв = вНабор
  ТО
    ЕСЛИ
          x.роду = Nguard
    ТО
       z:=x.лево
    ИНАЧЕ
       z:=x
    КОН;
    ЕСЛИ
         (z.роду = Nderef)
        И
         (z.лево.роду = Nguard)
    ТО
          z.лево:=z.лево.лево        (* пропустить охрану перед dereferencing *)
    КОН;
    ЕСЛИ
         (x.вид.пон # ПУСТО)
        И
         ((z.роду = Nderef) ИЛИ (z.роду = Nvarpar))
    ТО
      BindNodes(Neguard,x.вид,z,ПУСТО);
      x:=z
    КОН
  АЕСЛИ
         (x.вид.родв = вРяд)
        И
         (x.вид.овид = ВД.знаквид)
        И
         (y.вид.родв = вПЦепь)
        И
         (РАЗМЕР(y.пост.цепьД^) = 1)
  ТО                                        (* заменить цепь="" на ряд[0]:=0X *)
    y.вид:=ВД.знаквид;
    y.пост.цел:=0;

    Index(x,NewIntConst(0))
  КОН;
  Construct(Nassign,x,y);
  x.подроду:=assign
КОН Assign;

КОН ПД.

(*
Задумки:
1. Nupto в Ndop
 
deSign  - то, что имеет адрес, то что не вычисляется

выр      = deSign|Nconst|Nupto|Nmop|Ndop|Ncall.
deSign   = Nvar|Nvarpar|Nfield|Nderef|Nindex|Nguard|Neguard|Ntype|Nproc.
следвыр  = ПУСТО|выр.
указЕсли = ПУСТО|Nif.
указВыбр = Ncaselse.
указИз   = ПУСТО|Ncasedo.
указ     = ПУСТО|Nenter|Nassign|NcallTuda|NcallSuda|Ncall|Nifelse|Ncase|
           Nwhile|Nrepeat|Nloop|Nexit|Nreturn|Nwith|Ntrap.

         | роду     подроду    пон      лево      право     след
---------+--------------------------------------------------------- 
         |
deSign   | Nvar                пер                          следвыр
         | Nvarpar             приемпер                     следвыр
         | Nfield              свойство deSign              следвыр
         | Nderef                       deSign              следвыр
         | Nindex                       deSign    выр       следвыр
         | Nguard                       deSign              следвыр  (узел.вид  = охр. вид)
         | Neguard                      deSign              следвыр  (узел.вид  = охр. вид)
         | Ntype               вид                          следвыр  (напр. для МИН(ЦЕЛ) )
         | Nproc               задача                       следвыр
         |
выр      | deSign
         | Nconst              пост                                  (узел.пост = знач)
         | Nupto                        выр       выр       следвыр
         | Nmop      не                 выр                 следвыр
         |           минус              выр                 следвыр
         |           есть      вид      выр                 следвыр
         |           преобр             выр                 следвыр
         |           модуль             выр                 следвыр  МОДУЛЬ
         |           целчасть           выр                 следвыр  ЦЕЛЧАСТЬ
         |           округлить          выр                 следвыр  ОКРУГЛИТЬ
         |           чет                выр                 следвыр  ЧЕТ
         |           элем               выр                 следвыр  {}
         |           длина              выр                 следвыр  ДЛИНА
         |           адрес              выр                 следвыр  ОБХОД.ПолучитьАдрес
         |           значение           выр                 следвыр  ОБХОД.Значение
         | Ndop      умножить           выр       выр       следвыр
         |           косая              выр       выр       следвыр
         |           делить             выр       выр       следвыр
         |           остаток            выр       выр       следвыр
         |           и                  выр       выр       следвыр
         |           плюс               выр       выр       следвыр
         |           минус              выр       выр       следвыр
         |           или                выр       выр       следвыр
         |           равно              выр       выр       следвыр
         |           неравно            выр       выр       следвыр
         |           меньше             выр       выр       следвыр
         |           мравно             выр       выр       следвыр
         |           больше             выр       выр       следвыр
         |           бравно             выр       выр       следвыр
         |           в                  выр       выр       следвыр
         |           сдвиг              выр       выр       следвыр
         |           сбрбиты            выр       Nconst    следвыр
         |           размер             deSign    Nconst    следвыр  РАЗМЕР
         | Ncall               приемн   deSign    источники следвыр
         |
следвыр  | ПУСТО
         | выр
         |
указЕсли | ПУСТО
         | Nif                          выр       указ      указЕсли
         |
указВыбр | Ncaselse                     указИз    указ               (узел.пост = minmax)
         |                                       
указИз   | ПУСТО
         | Ncasedo                      Nconst    указ      указИз
         |
указ     | ПУСТО
         | Nenter              задача   задачи    указ      указ     (задача=ПУСТО для отдела)
         | Nassign   assign             deSign    выр       указ
         |           зСтоп              выр                 указ     СТОП
         |           зСоздать           deSign              указ
         |           зУвеличить         deSign    выр       указ
         |           зУменьшить         deSign    выр       указ
         |           зСписать           deSign    выр       указ
         |           зИзПамяти          deSign    выр       указ     ОБХОД.ИзПамяти
         |           зВПамять           выр       выр       указ     ОБХОД.ВПамять
         |           зОбраз             выр       выр       указ     ОБХОД.Образ
         |           зПоставить         deSign    deSign    указ
         |           зСместить          deSign    выр       указ
         |                                                           (право.след = 3-й парам.)
         | NcallTuda                    пзадача   источники указ
         | NcallSuda                    задача    источники указ
         | Ncall               приемн   deSign    источники указ
         | Nifelse                      указЕсли  указ      указ
         | Ncase                        выр       указВыбр  указ
         | Nwhile                       выр       указ      указ
         | Nrepeat                      указ      выр       указ
         | Nloop                        указ                указ
         | Nexit                                            указ
         | Nreturn             задача   следвыр             указ     (задача = ПУСТО для отдела)
         | Nwith                        указЕсли  указ      указ
         | Ntrap                                  выр       указ
*)
