Class: MilkTea::ControlFlow::DefiniteAssignment

Inherits:
Object
  • Object
show all
Defined in:
lib/milk_tea/core/control_flow/definite_assignment.rb

Defined Under Namespace

Classes: ReadBeforeAssignment, Result

Class Method Summary collapse

Class Method Details

.solve(graph, initially_assigned: Set.new) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/milk_tea/core/control_flow/definite_assignment.rb', line 9

def self.solve(graph, initially_assigned: Set.new)
  initially_assigned = initially_assigned.dup
  universe = initial_universe(graph, initially_assigned)

  result = Dataflow.solve(
    graph,
    direction: :forward,
    initial: -> { universe.dup },
    join: lambda do |states|
      if states.empty?
        universe.dup
      else
        states.reduce(universe.dup) { |acc, state| acc & state }
      end
    end,
    transfer: lambda do |node, in_state|
      in_state | node.writes
    end,
    boundary_in: { graph.entry_id => initially_assigned.dup }
  )

  read_before_assignment = []
  graph.each_node do |node|
    in_state = result.in_states[node.id]
    if node.reads_info.empty?
      node.reads.each do |binding_key|
        next if in_state.include?(binding_key)

        read_before_assignment << ReadBeforeAssignment.new(
          node_id: node.id,
          binding_key:,
          line: node.line,
          column: nil,
          length: nil,
        )
      end
      next
    end

    node.reads_info.each do |read_site|
      next if in_state.include?(read_site.binding_key)

      read_before_assignment << ReadBeforeAssignment.new(
        node_id: node.id,
        binding_key: read_site.binding_key,
        line: read_site.line || node.line,
        column: read_site.column,
        length: read_site.length,
      )
    end
  end

  Result.new(
    definitely_assigned_in: result.in_states,
    definitely_assigned_out: result.out_states,
    read_before_assignment:
  )
end