将变量注入引用的表达式

时间:2015-09-06 16:03:20

标签: macros metaprogramming elixir hygiene

我有一个引用的表达式,例如:

ast = quote do
  IO.puts x
end

我希望在表达式中注入一个变量,以便x有一个值,并且由于CompileError被定义为x时表达式不会引发Code.eval_quoted ast, [x: "Hello, world!"] ,如下所示:

ast = quote do
  x = var!(x)
  IO.puts x
end

这个AST传递给我,我无法更改它生成的代码。我通过后可以修改AST。

我想这样做我可以将AST转换为类似于引用的表达式:

{:__block__, [],
[{:=, [],
  [{:x, [], Elixir}, {:var!, [context: Check.Runner], [{:x, [], Elixir}]}]},
  {{:., [], [{:__aliases__, [alias: false], [:IO]}, :puts]}, [],
  [{:x, [], Check.RunnerTest}]}]}

尝试此操作后,我的AST看起来像这样:

var!

这不起作用。我认为这可能是因为{:__block__, [], [{:=, [], [{:x, [], Check.RunnerTest}, {:var!, [context: Check.Runner], [{:x, [], Check.Runner}]}]}, {{:., [], [{:__aliases__, [alias: false], [:IO]}, :puts]}, [], [{:x, [], Check.RunnerTest}]}]} 的上下文值不正确。

解决方案:我现在意识到变量的范围不正确,我需要这样的AST:

var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    var oldValue, newValue;
    if(mutation.type === 'characterData' &&
        mutation.target.parentNode && 
        mutation.target.parentNode.nodeName.toLowerCase() === 'p')
    {
      oldValue = mutation.oldValue;
      newValue = mutation.target.textContent;
    } else if(mutation.target.nodeName.toLowerCase() === 'p' && 
             mutation.addedNodes.length &&
             mutation.removedNodes.length) 
    {
      oldValue = mutation.removedNodes[0].textContent;
      newValue = mutation.addedNodes[0].textContent;
    } else {
      return;
    }
                                        
    // do stuff
    document.write('old: ' + oldValue + ', new: ' + newValue);
  }); 
}); 
  
  observer.observe(document.body, { characterDataOldValue: true, subtree: true, childList: true, characterData: true });

// test
document.querySelector('p').textContent = 'good bye';

1 个答案:

答案 0 :(得分:2)

您的代码应该正常工作。事实上,你写了:

ast = quote do
  x = var!(x)
  IO.puts x
end

但是您展示了其他一些代码的AST,其中一个代码是您将1分配给var!(x)的代码。换句话说,上面的代码没有任何问题。