anchor.diff:    Expected =
       {wheredim,
        {wheredim,
  -      {'#',{'?',{dim,"t"}}},
  -      [ {{dim,"t"},58} ]},
  -     [ {{dim,"t"},46} ]},
  -  ?assertEqual(Expected, transform1(R, [])).
  +      {'#',{dim,{[0],1},"t"}},
  +      [ {{dim,{[0],1},"t"},58} ]},
  +     [ {{dim,{[],1},"t"},46} ]},
  +  ?assertEqual(Expected, transform1(R)).
  +
  +wheredim_with_string_dim_id_test() ->
  +  T =
  +    {where,
  +     "t",
  +     [{dim,"t",46},{var,"t",58}]},
  +  R = ttransform0:transform0(T),
  +  Expected =
  +    {wheredim,
  +     {wherevar,
  +      {dim,{[],1},"t"}, %% FIXME var id shall not be replaced
  +      [ {"t",58} ]},
  +     [ {{dim,{[],1},"t"},46} ]},
  +  ?assertEqual(Expected, transform1(R)).
  
positive.code: -export([test/0]).
  
  %%------------------------------------------------------------------------------
  %% This transformation module transforms wheredim identifiers into hidden 
  %% dimensions (e.g: t -> {dim, t}) and references to these identifiers as 
  %% constant queries to the context ({'?', {dim, t}}).
  %%
  %% Transformed expressions are wheredim, wherevar, intension abstractions, 
  %% intension applications, base and value abstractions / applications.
  %%------------------------------------------------------------------------------
  
  %%------------------------------------------------------------------------------
  %% Constants
  %%------------------------------------------------------------------------------
  transform1(Const, _H) when is_number(Const) orelse is_boolean(Const) ->
    Const;
  
  transform1({string, Str}, _H) ->
    {string, Str};
  
  %%------------------------------------------------------------------------------
  %% Primop
  %%------------------------------------------------------------------------------
  transform1({primop, F, Eis}, H) ->
    {primop, F, lists:map(fun (Ei) -> transform1(Ei, H) end, Eis)};
  
  %%------------------------------------------------------------------------------
  %% Tuple Expression
  %%------------------------------------------------------------------------------
  transform1({t, E0E1is}, H) ->
    {t, lists:map(fun ({E0,E1}) -> {transform1(E0,H),transform1(E1,H)} end, E0E1is)};
  
  %%------------------------------------------------------------------------------
  %% Context Perturbation
  %%------------------------------------------------------------------------------
  transform1({'@', E0, E1}, H) ->
    {'@', transform1(E0, H), transform1(E1, H)};
  
  %%------------------------------------------------------------------------------
  %% Conditional
  %%------------------------------------------------------------------------------
  transform1({'if', E0, E1, E2}, H) ->
    {'if', transform1(E0, H), transform1(E1, H), transform1(E2, H)};
  
  %%------------------------------------------------------------------------------
  %% Dimensional Query
  %%------------------------------------------------------------------------------
  transform1({'#', E0}, H) ->
    {'#', transform1(E0, H)};
  
  %%------------------------------------------------------------------------------
  %% Base Abstraction
  %%------------------------------------------------------------------------------
  transform1({b_abs, Is, Params, E, P}, H) ->
    Dims = [{dim, Param} || Param <- Params],
    %% Here we expect P to be a runtime assigned constant
    {b_abs, tset:union(H, [transform1(I, H) || I <- Is]),
     Dims,
     transform1(E, tset:union(H, Dims)),
     P};
  
  transform1({b_apply, E0, E1}, H) ->
    {b_apply, transform1(E0, H), transform1(E1, H)};
  
  %%------------------------------------------------------------------------------
  %% Value Abstraction
  %%------------------------------------------------------------------------------
  transform1({v_abs, Is, Params, E}, H) ->
    Dims = [{dim, Param} || Param <- Params],
    {v_abs, tset:union(H, [transform1(I, H) || I <- Is]),
     Dims,
     transform1(E, tset:union(H, Dims))};
  
  transform1({v_apply, E0, E1}, H) ->
    {v_apply, transform1(E0, H), transform1(E1, H)};
  
  %%------------------------------------------------------------------------------
  %% Intension Abstraction
  %%------------------------------------------------------------------------------
  transform1({i_abs, Is, E}, H) ->
    {i_abs, tset:union(H, [transform1(I, H) || I <- Is]),
     transform1(E, H)};
  
  transform1({i_apply, E}, H) ->
    {i_apply, transform1(E, H)};
  
  %%------------------------------------------------------------------------------
  %% Wherevar
  %%------------------------------------------------------------------------------
  transform1({wherevar, E0, XiEis}, H) ->
    {wherevar, transform1(E0, H),
     [{Xi, transform1(Ei, H)} || {Xi, Ei} <- XiEis]};
  
  %%------------------------------------------------------------------------------
  %% Wheredim
  %%------------------------------------------------------------------------------
  transform1({wheredim, E0, XiEis}, H) ->
    DimsEis = [{{dim, Xi}, transform1(Ei, H)} || {Xi, Ei} <- XiEis],
    Dims = [Dim || {Dim, _} <- DimsEis],
    {wheredim, transform1(E0, tset:union(H, Dims)),
     DimsEis};
  
  %%------------------------------------------------------------------------------
  %% Identifiers
  %%------------------------------------------------------------------------------
  transform1(Xi, H) when is_list(Xi) orelse is_atom(Xi) ->
    case lists:keyfind(Xi, 2, H) of
      {dim, Xi} ->
        {'?', {dim, Xi}};
      _ ->
        Xi
    end.
  
  %%------------------------------------------------------------------------------
  %% Insta-test
  
negative.code: 
  test() ->
    R = ttransform0:transform0(d1_tournament()),
    transform1(R).
  
  
  rules_test_() ->
    Consts = [46,
              false,
              {string,"ciao"}],
    ConstTests = lists:zip(Consts, Consts),
    WheredimTest = {WheredimTree, WheredimExpected} =
      { {where,    {'#',            "t" }, [{ dim,       "t", 46}]} ,
        {wheredim, {'#',{dim,{[],1},"t"}}, [{{dim,{[],1},"t"},46}]} },
    WheredimTreeF =
      fun(DimName) when is_list(DimName) ->
          {where, {'#',DimName}, [{dim,DimName,46}]}
      end,
    WheredimExpectedF =
      fun(DimName, Pos) when is_list(DimName), is_list(Pos) ->
          {wheredim, {'#',{dim,{Pos,1},DimName}}, [{{dim,{Pos,1},DimName},46}]}
      end,
    WheredimTree     = WheredimTreeF(    "t"),
    WheredimExpected = WheredimExpectedF("t", []),
    WherevarTest =
      { {where,    WheredimTree,
         [{var,"X",WheredimTree              },
          {var,"Y",WheredimTree              }]},
        {wherevar, WheredimExpectedF("t",[0]),
         [{    "X",WheredimExpectedF("t",[1])},
          {    "Y",WheredimExpectedF("t",[2])}]} },
    %% Testing expression in dimensional query, even if it does not make
    %% sense as dims are not ground values atm
    DimQueryTest =
      { {'#', WheredimTree    },
        {'#', WheredimExpected} },
    TupleTests =
      [{ {t, [{"lhs",46}]},
         {t, [{"lhs",46}]} },
       %% XXX How can lhs of tuple be expression if dims cannot be ground values atm? Not testing it.
       { {t, [{"lhs1",WheredimTree              },
              {"lhs2",WheredimTree              }]},
         {t, [{"lhs1",WheredimExpectedF("t",[3])},
              {"lhs2",WheredimExpectedF("t",[5])}]} }
      ],
    %% TODO (not important) test perturbation, primop, if-then-else
    TreeExpectedTuples =
      ConstTests ++ [WheredimTest, WherevarTest, DimQueryTest] ++ TupleTests,
    [?_test(begin
              AstAfterT0 = ttransform0:transform0(Tree),
              Actual = transform1(AstAfterT0),
              %io:format(user, "AstAfterT0: ~1000p~nActual: ~1000p~n", [AstAfterT0, Actual]),
              ?assertEqual(Expected, Actual)
            end)
     || {Tree, Expected} <- TreeExpectedTuples].
  
  
  nested_wheredims_test() ->
  