1. Куча / Говнокод #27372

    0

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    -export([parse_transform/2, abstract/2]).
    
    parse_transform(Forms, _Options) ->
      normal(Forms).
    
    normal({call, _Line, {atom, _, '$$'}, [Outer]}) ->
      case Outer of
        {'fun', _, {clauses, Quoted}} ->
          %% Remove outer `fun' and only leave its clauses:
          ok;
        Quoted ->
          %% A plain term has been quoted, leave it as is:
          ok
      end,
      Result = abstract(Quoted),
      %% io:format("Quoted block ~p~n", [Result]),
      Result;
    normal(L) when is_list(L) ->
      lists:map(fun normal/1, L);
    normal(T) when is_tuple(T) ->
      list_to_tuple(lists:map(fun normal/1, tuple_to_list(T)));
    normal(T) ->
      T.
    
    -define(line, 0).
    
    %% @doc Create AST of the AST
    abstract({call, _Line, {atom, _, '$'}, [Splice]}) ->
      normal(Splice);
    abstract(Orig = {var, Line, VarName}) ->
      case lists:suffix("__AST", atom_to_list(VarName)) of
        true ->
          Orig;
        false ->
          {tuple, ?line, [ {atom, ?line, var}
                         , {integer, ?line, Line}
                         , {atom, ?line, VarName}
                         ]}
      end;
    abstract(T) when is_tuple(T) ->
      {tuple, ?line, lists:map(fun abstract/1, tuple_to_list(T))};
    abstract([]) ->
      {nil, ?line};
    abstract([Hd|Tail]) ->
      {cons, ?line, abstract(Hd), abstract(Tail)};
    abstract(A) when is_atom(A) ->
      {atom, ?line, A};
    abstract(I) when is_integer(I) ->
      {integer, ?line, I}.

    Мета-метушня, убогое подобие лисповского квотирования.

    Запостил: CHayT, 23 Апреля 2021

    Комментарии (7) RSS

    • SEO: Квотирование со сплайсами бедного человека
      Ответить
    • P.S. Используется как-то так (берегите глаза):

      {function, Line, Name, Arity,
         [{clause, Line, Vars, []
          , ['$$'(begin
                    ?lazy_self_var = ?typerefl_module:make_lazy( Name__AST
                                                               , Self__AST
                                                               , '$'(mk_literal_list(Line, Vars))
                                                               ),
                    ?typerefl_module:alias( Name__AST
                                          , __AST
                                          , '$'(make_additional_attrs_ast({Name, Arity}, Line, State))
                                          , '$'(mk_literal_list(Line, Vars))
                                          )
                  end)]
          }
         ]}.
      Ответить
    • Ниче не понятно
      Ответить
      • Это же метушня. Если она понятна, значит она недостаточно мета.
        Ответить
      • Это метушня в квадрате: она выдирает из AST модуля (назовём его M) куски, которые превращает в AST AST, который после компиляции M превращаются в терм, содержащий AST, который уже дальше можно метушить.
        Ответить
        • > превращаются в терм, содержащий AST

          Какая гомоиконщина )))
          Ответить
          • Довольно фиговая гомоикона вышла, надо сказать. Есть ограничение в том, что заквотированный кусок должен иметь валидный синтаксис до преобразования его сплайсами... Что довольно глупо.
            Но всё равно лучше, чем крестошаблоны.
            Ответить

    Добавить комментарий