let InstOf = ref (\x,y.failwith `InstOf`);

let {type TopValEnvCell' = (| VarName: SynBindIde'; VarType: TypTerm';
                              VarValue: object; OverLoad: OverLoad' |)}
ins type TopValEnv' <=> (TopValEnvCell') Dictionary
with {
    defaultVal x = failwith `notinhash`
and
    keyPrint = PrintAtom o absAtom'
and
    valPrint x = (outtok `-`; newline(1))
and
    UpdateCheck(key,old: TopValEnvCell', new: TopValEnvCell') =
  let key = absAtom'(key) in
  let (|VarName; VarType; VarValue; OverLoad|) = old 
  enc OverLoad' = if !Debug.InhibitNewOverloadings then [|None|]
                  else if OverLoad is None then OverLoad
                  else if (!InstOf)(VarType,new.VarType) then OverLoad 
                  else [|None|]
   in case OverLoad' of
    [| Some=l. (|VarName; VarType; VarValue;
                 OverLoad=[|Some=(new.VarType,new.VarName)::l|] |);
       None.
         if (!Debug.InhibitUpdates) And Not(EqAtom(key, AtomIt)) 
         then (outtok `An attempt was made to redefine `;
               PrintAtom(key);
               outtok(` while InhibitUpdates switch active.`); newline(1);
               old)
         else new
    |]
} ins {
   ResetTopValEnv():TopValEnv' =
     absTopValEnv'(NewDictionary(1000,defaultVal,UpdateCheck,keyPrint,valPrint))

 and UpdateTopValEnv(e: TopValEnv',
                  VarName:SynBindIde',VarType:TypTerm',VarValue:object):void =
%AM 22/8/84, remove this from VarValue field of env now duplicated%
     (VarName.StkPosn := [|Global=VarValue|];
      let (OverLoad: OverLoad') =
        if VarName.SMorUser is OverLoaded then [|Some=[]|] else [|None|]
      in AddToDictionary(repTopValEnv'(e),
                         repAtom'(VarName.Ide),
                         (|VarName; VarType; VarValue; OverLoad|)))

 and RetrieveValFromTop(Ide: Atom', e: TopValEnv', ErrorFunc%: Atom' -> 'a%)
                       :(TypTerm' # SynBindIde' # bool # OverLoad') =
     (let x = FetchFromDictionary(repTopValEnv'(e), repAtom'(Ide)) in
       %AM: VarValue now in StkPosn field%
       (x.VarType, x.VarName, %LambdaBound=%false, x.OverLoad))
     ?? [`notinhash`] ErrorFunc(Ide)

 and IterTopValEnv(e: TopValEnv', 
                iterFunc: ((SynBindIde' # TypTerm' # object) -> void)):void =
     AppDictionary
        (\(key,el).iterFunc(el.VarName, el.VarType, el.VarValue))
        (repTopValEnv'(e))

 and CopyTopValEnv(e: TopValEnv'): TopValEnv' =
     absTopValEnv'(
       CopyFromDictionary( repTopValEnv'(e), [], 1000, defaultVal,
                           UpdateCheck, keyPrint, valPrint) )

 and CopyFromTopValEnv(e: TopValEnv', EntriesReq): TopValEnv' =
     absTopValEnv'(
       CopyFromDictionary( repTopValEnv'(e), EntriesReq, 1000, defaultVal,
                           UpdateCheck, keyPrint, valPrint) )
} ;
%------------------------------------------------------------%
let type TopTypEnvCell' =
   (| TypNam: Atom'; Multiadic: bool; TypIde: TypTerm' |)
ins type TopTypEnv' <=> TopTypEnvCell' Dictionary

with TypUpdateCheck(key,old,new) = new
and defaultVal x = failwith `notinhash`
and keyPrint = PrintAtom o absAtom'
and valPrint x = (outtok `-`; newline(1))
ins
   ResetTopTypEnv():TopTypEnv' =
     absTopTypEnv'(NewDictionary(100,defaultVal,TypUpdateCheck,
                                 keyPrint,valPrint))

and UpdateTopTypEnv(TypNam: Atom', TypIde: TypTerm', Multiadic: bool,
                    Env: TopTypEnv'): void =
      AddToDictionary(repTopTypEnv'(Env), repAtom'(TypNam),
                      (| TypNam; TypIde; Multiadic |))

and RetrieveTypFromTop(Ide: Atom', e: TopTypEnv', ErrorFunc%: Atom' -> 'a%)
                      :TypTerm' # bool =
     (let x = FetchFromDictionary(repTopTypEnv'(e), repAtom'(Ide))
      in (x.TypIde, x.Multiadic))
     ?? [`notinhash`] ErrorFunc(Ide)

and IterTopTypEnv(e: TopTypEnv', 
                  iterFunc: ((Atom' # TypTerm' # bool) -> void)):void =
     AppDictionary
        (\(key,el).iterFunc(el.TypNam, el.TypIde, el.Multiadic))
        (repTopTypEnv'(e))

and CopyTopTypEnv(e: TopTypEnv'): TopTypEnv' =
     absTopTypEnv'(
       CopyFromDictionary( repTopTypEnv'(e), [], 100, defaultVal,
                           TypUpdateCheck, keyPrint, valPrint) )

and CopyFromTopTypEnv(e: TopTypEnv', EntriesReq): TopTypEnv' =
     absTopTypEnv'(
       CopyFromDictionary( repTopTypEnv'(e), EntriesReq, 100, defaultVal,
                           TypUpdateCheck, keyPrint, valPrint) );
%------------------------------------------------------------%
%RJGDELlet type TopExcEnvCell' = (| ExcIde:SynBindIde'; ExcTyp:TypTerm'|)%
%RJGDELins type TopExcEnv' <=> TopExcEnvCell' Dictionary%

%RJGDEL with ExcUpdateCheck(key,old,new) = new%
%RJGDEL and defaultVal x = failwith `notinhash`%
%RJGDEL and keyPrint = PrintAtom o absAtom'%
%RJGDEL and valPrint x = (outtok `-`; newline(1))%
%RJGDEL ins%
%RJGDEL    ResetTopExcEnv():TopExcEnv' =%
%RJGDEL      absTopExcEnv'(NewDictionary(100,defaultVal,ExcUpdateCheck,%
%RJGDEL                                  keyPrint,valPrint))%

%RJGDEL and UpdateTopExcEnv(Env: TopExcEnv', ExcIde: SynBindIde', ExcTyp: TypTerm',%
%RJGDEL                     ExcValue: object): void =%
%RJGDEL      (ExcIde.StkPosn := [|Global=ExcValue|];%
%RJGDEL       AddToDictionary(repTopExcEnv'(Env), repAtom'(ExcIde.Ide),%
%RJGDEL                       (| ExcIde; ExcTyp |)))%

%RJGDEL and RetrieveExcFromTop(Ide: Atom', e: TopExcEnv', ErrorFunc: Atom' -> 'a)%
%RJGDEL                       :TypTerm' # SynBindIde' =%
%RJGDEL      (let x = FetchFromDictionary(repTopExcEnv'(e), repAtom'(Ide))%
%RJGDEL       in (x.ExcTyp, x.ExcIde))%
%RJGDEL      ?? [`notinhash`] ErrorFunc(Ide)%

%RJGDEL and IterTopExcEnv(Env: TopExcEnv', iterFunc: (SynBindIde' # TypTerm') -> void):void =%
%RJGDEL     AppDictionary(\(key,el).iterFunc(el.ExcIde,el.ExcTyp))(repTopExcEnv'(Env))%

%RJGDEL and CopyTopExcEnv(e: TopExcEnv'): TopExcEnv' =%
%RJGDEL      absTopExcEnv'(%
%RJGDEL        CopyFromDictionary( repTopExcEnv'(e), [], 100, defaultVal,%
%RJGDEL                            ExcUpdateCheck, keyPrint, valPrint) )%

%RJGDEL and CopyFromTopExcEnv( e: TopExcEnv', Entries ): TopExcEnv' =%
%RJGDEL      absTopExcEnv'(%
%RJGDEL        CopyFromDictionary( repTopExcEnv'(e), Entries, 100, defaultVal,%
%RJGDEL                            ExcUpdateCheck, keyPrint,valPrint ) );%
%------------------------------------------------------------%

let type TopAllEnv' =
    (| 
       Val: TopValEnv'; Typ: TopTypEnv' %RJGDEL Exc: TopExcEnv'%
    |);

let ResetTopEnv() =
     (| 
        Val = ResetTopValEnv();
        Typ = ResetTopTypEnv()
%RJGDEL         Exc = ResetTopExcEnv()%
     |);

let NilTopEnv = ResetTopEnv();

let CopyTopEnv(| Val; Typ |) =
    (| 
       Val = CopyTopValEnv(Val);
       Typ = CopyTopTypEnv(Typ)
%RJGDEL        Exc = CopyTopExcEnv(Exc)%
    |);

let CopyFromTopEnv( (| Val;Typ |),
                    ValIdes, TypIdes ) =
   (| 
      Val = CopyFromTopValEnv(Val,ValIdes);
      Typ = CopyFromTopTypEnv(Typ,TypIdes)
%RJGDEL       Exc = CopyFromTopExcEnv(Exc,ExcIdes)%
   |);
