anchor.diff:        end
     end.
   
  +%% @doc Processes a function's ast and modifies all calls to functions
  +%%      in the function's own module for a call to the fun returned by
  +%%      clj_module:fake_fun/3.
  +%% @end
  +-spec replace_calls(erl_parse:abstract_form(), module()) ->
  +  erl_parse:abstract_form().
  +replace_calls( { call, Line
  +               , { remote, _
  +                 , {atom, _, Module}
  +                 , {atom, _, Function}
  +                 } = RemoteOriginal
  +               , Args
  +               }
  +             , CurrentModule) ->
  +  Args1 = replace_calls(Args, CurrentModule),
  +  Arity = length(Args),
  +  %% Only replace the call if the module is loaded. If it is not, then the
  +  %% replacement is happening for the evaluation of an expression where the
  +  %% called function hasn't been declared in the same evaluation.
  +  case is_loaded(Module) of
  +    true  ->
  +      Remote = {remote, Line,
  +                {atom, Line, ?MODULE},
  +                {atom, Line, fake_fun}
  +               },
  +
  +      FunCall = { call, Line, Remote
  +                , [ {atom, Line, Module}
  +                  , {atom, Line, Function}
  +                  , {integer, Line, Arity}
  +                  ]
  +                },
  +      {call, Line, FunCall, Args1};
  +    false ->
  +      {call, Line, RemoteOriginal, Args1}
  +  end;
  +%% Detect non-remote calls done to other functions in the module, so we
  +%% can replace them with fake_funs when necessary.
  +replace_calls({call, Line, {atom, Line2, Function}, Args}, ModuleName) ->
  +  Arity = length(Args),
  +  Args1 = replace_calls(Args, ModuleName),
  +  Remote = {remote, Line,
  +            {atom, Line, ?MODULE},
  +            {atom, Line, fake_fun}
  +           },
  +  FunCall = { call, Line, Remote
  +            , [ {atom, Line2, ModuleName}
  +              , {atom, Line2, Function}
  +              , {integer, Line2, Arity}
  +              ]
  +            },
  +  {call, Line, FunCall, Args1};
  +replace_calls(Ast, Module) when is_tuple(Ast) ->
  +  list_to_tuple(replace_calls(tuple_to_list(Ast), Module));
  +replace_calls(Ast, Module) when is_list(Ast) ->
  +  [replace_calls(Item, Module) || Item <- Ast];
  +replace_calls(Ast, _) ->
  +  Ast.
  +
  +-spec add_vars(module() | clj_module(), ['clojerl.Var':type()]) -> clj_module().
  +add_vars(ModuleName, Vars) when is_atom(ModuleName)  ->
  +  add_vars(get(?MODULE, ModuleName), Vars);
  +add_vars(Module, Vars) ->
  +  AddFun = fun(V) ->
  +               K = clj_core:name(V),
  +               save(Module#module.vars, {K, V})
  +           end,
  +  lists:foreach(AddFun, Vars),
  +  Module.
  +
  +-spec add_attributes(clj_module(), [erl_parse:abstract_form()]) -> clj_module().
  +add_attributes(ModuleName, Attrs) when is_atom(ModuleName)  ->
  +  add_attributes(get(?MODULE, ModuleName), Attrs);
  +add_attributes(Module, []) ->
  +  Module;
  +add_attributes(Module, Attrs) ->
  +  Module1 = Module#module{attrs = Attrs ++ Module#module.attrs},
  +  save(?MODULE, Module1).
  +
  +-spec add_exports(clj_module(), [{atom(), non_neg_integer()}]) ->
  +  clj_module().
  +add_exports(ModuleName, Exports) when is_atom(ModuleName)  ->
  +  add_exports(get(?MODULE, ModuleName), Exports);
  +add_exports(Module, Exports) ->
  +  AddExport = fun(E) ->
  +                  save(Module#module.exports, {E})
  +              end,
  +  ok = lists:foreach(AddExport, Exports),
  +  Module.
  +
  +-spec add_functions(module() | clj_module(), [erl_parse:abstract_form()]) ->
  +  clj_module().
  +add_functions(ModuleName, Funs) when is_atom(ModuleName)  ->
  +  add_functions(get(?MODULE, ModuleName), Funs);
  +add_functions(Module, Funs) ->
  +  SaveFun = fun(F) ->
  +                FunctionId  = function_id(F),
  +                ok          = delete_fake_fun(Module, FunctionId),
  +                save(Module#module.funs, {FunctionId, F})
  +            end,
  +  lists:foreach(SaveFun, Funs),
  +  Module.
  +
  +-spec add_on_load(module() | clj_module(), erl_parse:abstract_expr()) ->
  +  clj_module().
  +add_on_load(ModuleName, Expr) when is_atom(ModuleName) ->
  +  add_on_load(get(?MODULE, ModuleName), Expr);
  +add_on_load(Module, Expr) ->
  +  save(Module#module.on_load, {Expr, Expr}),
  +  Module.
  +
  +-spec is_clojure(module()) -> boolean().
  +is_clojure(Name) ->
  +  Key = {?MODULE, is_clojure, Name},
  +  case clj_cache:get(Key) of
  +    undefined ->
  +      Attrs = Name:module_info(attributes),
  +      IsClojure = lists:keymember(clojure, 1, Attrs),
  +      clj_cache:put(Key, IsClojure),
  +      IsClojure;
  +    {ok, Value} ->
  +      Value
  +  end.
  +
  +%%------------------------------------------------------------------------------
  +%% gen_server callbacks
  +%%------------------------------------------------------------------------------
  +
  +start_link() ->
  +  gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
  +
  +init([]) ->
  +  ets:new(?MODULE, [named_table, set, protected, {keypos, 2}]),
  +  TabId = ets:new(loaded_modules, [set, protected, {keypos, 1}]),
  +  {ok, #{loaded_modules => TabId}}.
  +
  +handle_call({load, Module}, {Pid, _}, #{loaded_modules := TabId} = State) ->
  +  Module = save(?MODULE, Module),
  +  case get(TabId, Pid) of
  +    undefined ->
  +      save(TabId, {Pid, [Module]});
  +    {Pid, Modules}  ->
  +      save(TabId, {Pid, [Module | Modules]})
  +  end,
  +
  +  {reply, ok, State};
  +handle_call(cleanup, {Pid, _}, #{loaded_modules := TabId} = State) ->
  +  Modules = case get(TabId, Pid) of
  +              undefined   -> [];
  +              {Pid, Mods} -> Mods
  +            end,
  +
  +  true = ets:delete(TabId, Pid),
  +  ok   = lists:foreach(fun(M) -> ets:delete(?MODULE, M#module.name) end, Modules),
  +
  +  {reply, Modules, State};
  +handle_call(all, {Pid, _}, #{loaded_modules := TabId} = State) ->
  +  Modules = case get(TabId, Pid) of
  +              undefined   -> [];
  +              {Pid, Mods} -> Mods
  +            end,
  +
  +  {reply, Modules, State}.
  +
  +handle_cast(_Msg, State) ->
  +  {ok, State}.
  +
  +handle_info(_Msg, State) ->
  +  {ok, State}.
  +
  +terminate(_Msg, State) ->
  +  {ok, State}.
  +
  +code_change(_Msg, _From, State) ->
  +  {ok, State}.
  +
  +%%------------------------------------------------------------------------------
  +%% Helper Functions
  +%%------------------------------------------------------------------------------
  +
  +%% @private
  +-spec cleanup() -> ok.
  +cleanup() ->
  +  Modules = gen_server:call(?MODULE, cleanup),
  +  lists:foreach(fun delete_fake_modules/1, Modules).
  +
  +%% @private
  +%% @doc
  +%% Loads the module `Name' into memory. This function assumes it is not
  +%% loaded already, so this check should be done before calling it.
  +%% The value of `Source' is used to set the `file' attribute of the module
  +%% if the module's binary is not found, which is interpreted as if the
  +%% module is new.
  +%% @end
  +-spec load(atom(), string()) -> ok | {error, term()}.
  +load(Name, Source) ->
  +  Module = case code:ensure_loaded(Name) of
  +             {module, Name} ->
  +               new(clj_utils:code_from_binary(Name));
  +             {error, _} ->
  +               new(Name, Source)
  +           end,
  +  ok = gen_server:call(?MODULE, {load, Module}),
  +  Module.
  +
  +-spec is_loaded(module()) -> boolean().
  +is_loaded(Name) ->
  +  ets:member(?MODULE, Name).
  +
   %% @private
   -spec build_fake_fun(clj_module(), atom(), integer()) -> function().
   build_fake_fun(Module, Function, Arity) ->
     {_, FunctionAst} = get(Module#module.funs, {Function, Arity}),
   
     {function, _, _, _, Clauses} =
  -    replace_calls(FunctionAst, Module#module.name, Function),
  +    replace_calls(FunctionAst, Module#module.name),
     Int = erlang:unique_integer([positive]),
     FakeModuleName = list_to_atom("fake_module_" ++ integer_to_list(Int)),
   
  
positive.code:         , is_loaded/1
  
          , fake_fun/3
          , replace_calls/3
  
          , add_vars/2
          , add_attributes/2
  
negative.code:           end,
    Clause = {clause, 0, [], [], Exprs},
    {function, 0, ?ON_LOAD_FUNCTION, 0, [Clause]}.
  
  -spec get(atom(), module()) -> any().
  get(Table, Id) ->
  