anchor.diff:          }).
   
   -opaque template() :: #?MODULE{}.
  --type data()     :: #{string() => data() | iodata() | fun((data(), function()) -> iodata())}.
  +-type data()       :: #{string() => data() | iodata() | fun((data(), function()) -> iodata())}.
  +-type partial()    :: {partial, {state(), EndTag :: binary(), LastTagSize :: non_neg_integer(), Rest :: binary(), [tag()]}}.
   
   %%----------------------------------------------------------------------------------------------------------------------
   %% Exported Functions
   %%----------------------------------------------------------------------------------------------------------------------
   
   %% @doc
  --spec new(binary()) -> template().
  -new(Bin) when is_binary(Bin) ->
  -    new_impl(#state{}, Bin).
  +-spec render(binary(), data()) -> binary().
  +render(Bin, Map) ->
  +    compile(parse_string(Bin), Map).
  +
  +%% @doc
  +-spec parse_string(binary()) -> template().
  +parse_string(Bin) when is_binary(Bin) ->
  +    parse_string_impl(#state{}, Bin).
   
   %% @doc
   -spec parse_file(file:filename()) -> template().
   parse_file(Filename) ->
       case file:read_file(Filename) of
  -        {ok, Bin} -> new_impl(#state{dirname = filename:dirname(Filename)}, Bin);
  +        {ok, Bin} -> parse_string_impl(#state{dirname = filename:dirname(Filename)}, Bin);
           _         -> error(?FILE_ERROR, [Filename])
       end.
   
   %% @doc
   -spec compile(template(), data()) -> binary().
  -compile(#?MODULE{}, Map) when is_map(Map) ->
  -    hoge.
  +compile(#?MODULE{data = Tags}, Map) when is_map(Map) ->
  +    iolist_to_binary(lists:reverse(compile_impl(Tags, Map, []))).
   
   %%----------------------------------------------------------------------------------------------------------------------
   %% Internal Function
   %%----------------------------------------------------------------------------------------------------------------------
   
  -%% @see new/1
  --spec new_impl(state(), Input :: binary()) -> template().
  -new_impl(State, Input) ->
  +%% @see compile/2
  +%%
  +%% ATTENTION: The result is a list that is inverted.
  +-spec compile_impl(Template :: [tag()], data(), Result :: iodata()) -> iodata().
  +compile_impl([], _, Result) ->
  +    Result;
  +compile_impl([{n, Key} | T], Map, Result) ->
  +    compile_impl(T, Map, [escape(maps:get(Key, Map)) | Result]);
  +compile_impl([{'&', Key} | T], Map, Result) ->
  +    compile_impl(T, Map, [maps:get(Key, Map) | Result]);
  +compile_impl([{'#', Key, Tags, Source} | T], Map, Result) ->
  +    Value = maps:get(Key, Map, undefined),
  +    if
  +        is_list(Value)        -> compile_impl(T, Map, lists:foldl(fun(X, Acc) -> compile_impl(Tags, X, Acc) end,
  +                                                                  Result, Value));
  +        Value =:= false       -> compile_impl(T, Map, Result);
  +        is_function(Value, 2) -> compile_impl(T, Map, Value(Source, fun(Text) -> render(Text, Map) end));
  +        true                  -> compile_impl(T, Map, compile_impl(Tags, Map, Result))
  +    end;
  +compile_impl([{'^', Key, Tags} | T], Map, Result) ->
  +    Value = maps:get(Key, Map, undefined),
  +    case Value =:= undefined orelse Value =:= [] orelse Value =:= false of
  +        true  -> compile_impl(T, Map, compile_impl(Tags, Map, Result));
  +        false -> compile_impl(T, Map, Result)
  +    end;
  +compile_impl([Bin | T], Map, Result) ->
  +    compile_impl(T, Map, [Bin | Result]).
  +
  +%% @see parse_string/1
  +-spec parse_string_impl(state(), Input :: binary()) -> template().
  +parse_string_impl(State, Input) ->
       #?MODULE{data = parse(State, Input)}.
   
   %% @doc
  
positive.code: remove_space_from_tail_impl(_, Size) ->
      Size.
  
  %%----------------------------------------------------------------------------------------------------------------------
  %% Unit Tests
  %%----------------------------------------------------------------------------------------------------------------------
  
  -ifdef(TEST).
  
  -define(NT_S(X, Y), ?_assertEqual(#?MODULE{data=X}, ?MODULE:new(Y))).
  %% new_test generater (success case)
  -define(NT_F(X),    ?_assertError(_,                ?MODULE:new(X))).
  %% new_test generater (failure case)
  
  new_test_() ->
      [
       {"{{tag}}",     ?NT_S([<<"a">>, {n, <<"t">>}, <<"b">>],   <<"a{{t}}b">>)},
       {"{{ tag }}",   ?NT_S([<<>>, {n, <<"t">>}, <<>>],         <<"{{ t }}">>)},
  
negative.code: 
       {"{{#tag}}",    ?NT_F(<<"{{#tag}}">>)},
       {"{{#tag1}}{{#tag2}}{{name}}{{/tag1}}{{/tag2}}",
        ?NT_S([<<"a">>, {'#', <<"t1">>, [<<"b">>,
                                         {'#', <<"t2">>, [<<"c">>, {n, <<"t3">>}, <<"d">>], <<"c{{t3}}d">>},
                                         <<"e">>], <<"b{{#t2}}c{{t3}}d{{/t2}}e">>}, <<"f">>],
              <<"a{{#t1}}b{{#t2}}c{{t3}}d{{/t2}}e{{/t1}}f">>)},
       {"{{#tag1}}{{#tag2}}{{/tag1}}{{/tag2}}", ?NT_F(<<"{{#t1}}{{#t2}}{{/t1}}{{/t2}}">>)},
  
       {"{{# tag}}{{/ tag}}",     ?NT_S([<<>>, {'#', <<"tag">>,  [<<>>], <<>>}, <<>>], <<"{{# tag}}{{/ tag}}">>)},
       {"{{ #tag }}{{ / tag }}",  ?NT_S([<<>>, {'#', <<"tag">>,  [<<>>], <<>>}, <<>>], <<"{{ #tag }}{{ / tag }}">>)},
       {"{{ # tag }}{{ /tag }}",  ?NT_S([<<>>, {'#', <<"tag">>,  [<<>>], <<>>}, <<>>], <<"{{ # tag }}{{ /tag }}">>)},
       {"{{ # ta g}}{{ / ta g}}", ?NT_S([<<>>, {'#', <<"ta g">>, [<<>>], <<>>}, <<>>], <<"{{ # ta g}}{{ / ta g}}">>)},
  
       {"{{!comment}}",           ?NT_S([<<"a">>, <<"c">>], <<"a{{!comment}}c">>)},
       {"{{! comment }}",         ?NT_S([<<>>, <<>>],       <<"{{! comment }}">>)},
  