<commit_before>-module(reia_bindings).
-export([transform/1]).
-include("reia_nodes.hrl").
-include("reia_bindings.hrl").

% Internal state of the bindings transform
-record(state, {scope=normal, bindings=dict:new()}).

transform(Node) ->
  {Node2, _State} = reia_syntax:mapfold_subtrees(
    fun transform/2,
    #state{},
    Node
  ),
  Node2.

% Walk the LHS of a match expression in match scope
transform(#match{} = Node, State) ->
  {Right, State2} = reia_syntax:mapfold_subtrees(
    fun transform/2,
    State,
    Node#match.right
  ),

  {Left, State3} = reia_syntax:mapfold_subtrees(
    fun transform/2,
    State2#state{scope=match},
    Node#match.left
  ),

  Node2  = Node#match{left=Left, right=Right},
  State4 = State3#state{scope=State#state.scope},
  output(Node2, State4);

% Variables are (re)bound while in match scope
transform(#identifier{name=Name} = Node, #state{scope=match} = State) ->
  NewBindings = case dict:find(Name, State#state.bindings) of
    {ok, Version} -> dict:store(Name, Version + 1);
    error         -> dict:store(Name, 0)
  end,
  output(Node, State#state{bindings=NewBindings});

transform(Node, State) ->
  output(Node, State).

output(Node, State) ->
  {#bindings{node=Node, entries=State#state.bindings}, State}.<commit_msg>Allow the scope given to the bindings annotator to be specifiable<commit_after>-module(reia_bindings).
-export([transform/1, transform/2]).
-include("reia_nodes.hrl").
-include("reia_bindings.hrl").

% Internal state of the bindings annotator
-record(state, {scope=normal, bindings=dict:new()}).

% Annotate the given node with its current bindings
transform(Node) -> transform(Node, normal).

% Annotate the given node, assuming the given scope
transform(Node, Scope) ->
  {Node2, _State} = reia_syntax:mapfold_subtrees(
    fun transform_node/2,
    #state{scope=Scope},
    Node
  ),
  Node2.

% Walk the LHS of a match expression in match scope
transform_node(#match{} = Node, State) ->
  {Right, State2} = reia_syntax:mapfold_subtrees(
    fun transform_node/2,
    State,
    Node#match.right
  ),

  {Left, State3} = reia_syntax:mapfold_subtrees(
    fun transform_node/2,
    State2#state{scope=match},
    Node#match.left
  ),

  Node2  = Node#match{left=Left, right=Right},
  State4 = State3#state{scope=State#state.scope},
  output(Node2, State4);

% Variables are (re)bound while in match scope
transform_node(#identifier{name=Name} = Node, #state{scope=match} = State) ->
  NewBindings = case dict:find(Name, State#state.bindings) of
    {ok, Version} -> dict:store(Name, Version + 1);
    error         -> dict:store(Name, 0)
  end,
  output(Node, State#state{bindings=NewBindings});

transform_node(Node, State) ->
  output(Node, State).

output(Node, State) ->
  {#bindings{node=Node, entries=State#state.bindings}, State}.
{'fraction_non_alphanumeric': 0.14595170454545456, 'fraction_numerical': 0.01171875, 'mean_word_length': 4.512720156555773, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 18, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2338354', 'n_tokens_mistral': 999, 'n_tokens_neox': 962, 'n_words': 214}