Module: SyntaxTree::WithEnvironment

Defined in:
lib/syntax_tree/visitor/with_environment.rb

Overview

WithEnvironment is a module intended to be included in classes inheriting from Visitor. The module overrides a few visit methods to automatically keep track of local variables and arguments defined in the current environment. Example usage:

class MyVisitor < Visitor
  include WithEnvironment

  def visit_ident(node)
    # Check if we're visiting an identifier for an argument, a local
    variable or something else
    local = current_environment.find_local(node)

    if local.type == :argument
      # handle identifiers for arguments
    elsif local.type == :variable
      # handle identifiers for variables
    else
      # handle other identifiers, such as method names
    end
end

Instance Method Summary collapse

Instance Method Details

#current_environmentObject



25
26
27
# File 'lib/syntax_tree/visitor/with_environment.rb', line 25

def current_environment
  @current_environment ||= Environment.new
end

#visit_blockarg(node) ⇒ Object



101
102
103
104
105
106
# File 'lib/syntax_tree/visitor/with_environment.rb', line 101

def visit_blockarg(node)
  name = node.name
  current_environment.add_local_definition(name, :argument) if name

  super
end

#visit_class(node) ⇒ Object

Visits for nodes that create new environments, such as classes, modules and method definitions



39
40
41
# File 'lib/syntax_tree/visitor/with_environment.rb', line 39

def visit_class(node)
  with_new_environment { super }
end

#visit_def(node) ⇒ Object



55
56
57
# File 'lib/syntax_tree/visitor/with_environment.rb', line 55

def visit_def(node)
  with_new_environment { super }
end

#visit_def_endless(node) ⇒ Object



63
64
65
# File 'lib/syntax_tree/visitor/with_environment.rb', line 63

def visit_def_endless(node)
  with_new_environment { super }
end

#visit_defs(node) ⇒ Object



59
60
61
# File 'lib/syntax_tree/visitor/with_environment.rb', line 59

def visit_defs(node)
  with_new_environment { super }
end

#visit_kwrest_param(node) ⇒ Object



94
95
96
97
98
99
# File 'lib/syntax_tree/visitor/with_environment.rb', line 94

def visit_kwrest_param(node)
  name = node.name
  current_environment.add_local_definition(name, :argument) if name

  super
end

#visit_method_add_block(node) ⇒ Object

When we find a method invocation with a block, only the code that happens inside of the block needs a fresh environment. The method invocation itself happens in the same environment



50
51
52
53
# File 'lib/syntax_tree/visitor/with_environment.rb', line 50

def visit_method_add_block(node)
  visit(node.call)
  with_new_environment { visit(node.block) }
end

#visit_module(node) ⇒ Object



43
44
45
# File 'lib/syntax_tree/visitor/with_environment.rb', line 43

def visit_module(node)
  with_new_environment { super }
end

#visit_params(node) ⇒ Object

Visit for keeping track of local arguments, such as method and block arguments



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/syntax_tree/visitor/with_environment.rb', line 69

def visit_params(node)
  add_argument_definitions(node.requireds)

  node.posts.each do |param|
    current_environment.add_local_definition(param, :argument)
  end

  node.keywords.each do |param|
    current_environment.add_local_definition(param.first, :argument)
  end

  node.optionals.each do |param|
    current_environment.add_local_definition(param.first, :argument)
  end

  super
end

#visit_rest_param(node) ⇒ Object



87
88
89
90
91
92
# File 'lib/syntax_tree/visitor/with_environment.rb', line 87

def visit_rest_param(node)
  name = node.name
  current_environment.add_local_definition(name, :argument) if name

  super
end

#visit_var_field(node) ⇒ Object Also known as: visit_pinned_var_ref

Visit for keeping track of local variable definitions



109
110
111
112
113
114
115
116
117
# File 'lib/syntax_tree/visitor/with_environment.rb', line 109

def visit_var_field(node)
  value = node.value

  if value.is_a?(SyntaxTree::Ident)
    current_environment.add_local_definition(value, :variable)
  end

  super
end

#visit_var_ref(node) ⇒ Object

Visits for keeping track of variable and argument usages



122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/syntax_tree/visitor/with_environment.rb', line 122

def visit_var_ref(node)
  value = node.value

  if value.is_a?(SyntaxTree::Ident)
    definition = current_environment.find_local(value.value)

    if definition
      current_environment.add_local_usage(value, definition.type)
    end
  end

  super
end

#with_new_environmentObject



29
30
31
32
33
34
35
# File 'lib/syntax_tree/visitor/with_environment.rb', line 29

def with_new_environment
  previous_environment = @current_environment
  @current_environment = Environment.new(previous_environment)
  yield
ensure
  @current_environment = previous_environment
end