anchor.diff:  %%%
   %%% es_gloenv.erl
   %%%
  -%%% Global {Name,Tag} -> Value store for ErlScheme.
  -%%% Used for global variables, and macro and syntax bindings.
  +%%% Global Name -> {Tag, Value} store for ErlScheme.
  +%%%
  +%%% Used for global variables and macros in the repl / user environment.
  +%%% Global variables and macros share name space so that binding an identifier
  +%%% as one kind simultaneously removes its binding as the other kind.
   
   -module(es_gloenv).
   
  --export([init/0,
  -	 destroy/0,
  -	 get_var/1,
  -	 enter_var/2,
  -	 lookup/2,
  -	 insert/3]).
  +-export([ destroy/0
  +        , enter_var/2
  +        , get_var/1
  +        , init/0
  +        , insert/3
  +        , lookup/2
  +        ]).
   
   -define(es_gloenv_tab, es_gloenv_tab).
   -define(es_gloenv_pid, es_gloenv_pid).
  +-define(tag_var, '%var').
   
  +%% API -------------------------------------------------------------------------
  +
  +-spec init() -> ok.
   init() ->
     case ets:info(?es_gloenv_tab, type) of
       set ->
         ok;
       undefined ->
         Self = self(),
  -      %% XXX: monitoring here?
  +      %% FIXME: monitoring here?
         P = spawn(fun () -> do_init(Self) end),
         receive {ok, P} -> ok end
     end.
  +
  +-spec destroy() -> ok.
  +destroy() ->
  +  case whereis(?es_gloenv_pid) of
  +    Pid when is_pid(Pid) ->
  +      Pid ! {destroy, self()},
  +      receive {ok, Pid} -> ok end;
  +    undefined ->
  +      ok
  +  end.
  +
  +-spec get_var(term()) -> term().
  +get_var(Name) ->
  +  case lookup(Name, ?tag_var) of
  +    {value, Value} -> Value;
  +    none -> throw({unbound_variable, Name})
  +  end.
  +
  +-spec enter_var(term(), term()) -> true.
  +enter_var(Name, Value) -> insert(Name, ?tag_var, Value).
  +
  +-spec lookup(term(), atom()) -> {value, term()} | none.
  +lookup(Name, Tag) ->
  +  case lookup(Name) of
  +    {Tag, Value} -> {value, Value};
  +    {_OtherTag, _Value} -> none;
  +    none -> none
  +  end.
  +
  +-spec insert(term(), atom(), term()) -> true.
  +insert(Name, Tag, Val) ->
  +  ets:insert(?es_gloenv_tab, {Name, {Tag, Val}}).
  +
  +%% Internals -------------------------------------------------------------------
   
   do_init(Pid) ->
     erlang:register(?es_gloenv_pid, self()),
  
positive.code:       wait_for_destroy()
    end.
  
  destroy() ->
    case whereis(?es_gloenv_pid) of
      Pid when is_pid(Pid) ->
        Pid ! {destroy, self()},
        receive {ok, Pid} -> ok end;
      undefined ->
        ok
    end.
  
  -define(tag_var, '%var').
  
  get_var(Name) ->
    case lookup(Name, ?tag_var) of
      {value, Value} -> Value;
      none -> throw({unbound_variable, Name})
    end.
  
  enter_var(Name, Value) -> insert(Name, ?tag_var, Value).
  
  lookup(Name, Tag) ->
    try
      {value, ets:lookup_element(?es_gloenv_tab, {Name, Tag}, 2)}
    catch
      error:badarg -> none
    end.
  
  insert(Name, Tag, Val) ->
    ets:insert(?es_gloenv_tab, {{Name, Tag}, Val}).
  
negative.code: %%% -*- erlang-indent-level: 2 -*-
  %%%
  %%%   Copyright 2014-2022 Mikael Pettersson
  %%%
  %%%   Licensed under the Apache License, Version 2.0 (the "License");
  %%%   you may not use this file except in compliance with the License.
  