Class: FastRuby::ScopeModeHelper

Inherits:
Object
  • Object
show all
Defined in:
lib/fastruby/translator/scope_mode_helper.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.get_scope_mode(tree_) ⇒ Object



25
26
27
# File 'lib/fastruby/translator/scope_mode_helper.rb', line 25

def self.get_scope_mode(tree_)
  new.get_scope_mode(tree_)
end

Instance Method Details

#get_scope_mode(tree_) ⇒ Object



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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/fastruby/translator/scope_mode_helper.rb', line 29

def get_scope_mode(tree_)
  tree = FastRuby::FastRubySexp.from_sexp(tree_)

  if tree.node_type == :defn
    args_tree = tree[2]
    impl_tree = tree[3]
  elsif tree.node_type == :defs
    args_tree = tree[3]
    impl_tree = tree[4]
  end

  graph = impl_tree.to_graph

  args_tree[1..-1].each do |subtree|
    return :dag if subtree.to_s =~ /^\&/
  end

  tree.walk_tree do |subtree|
    if subtree.node_type == :iter
      iter_impl = subtree[3]
      
      return :dag if has_local_variable_access?(subtree[3])
      return :dag if subtree[2]

      if iter_impl
        return_node = iter_impl.find_tree{|st2| st2.node_type == :return}

        if return_node
          return :dag
        end
      end
    elsif subtree.node_type == :block_pass
      return :dag
    end
  end

  impl_tree.walk_tree do |subtree|
    graph.each_path_from(subtree) do |path|
      # verify path prohibitive for :linear scope (local variable read after call)
      has_call = false
      writes = Set.new

      path.each do |st2|
        next unless st2 
        if st2.node_type == :call
          if has_call and st2[1] == nil
            return :dag
          end

          writes.clear
          has_call = true
        elsif st2.node_type == :iter
          if has_call and st2[1][1] == nil
            return :dag
          end

          writes.clear
          has_call = true
        elsif st2.node_type == :lasgn
          writes << st2[1] # record local writes
        elsif st2.node_type == :lvar or st2.node_type == :self or 
              st2.node_type == :return or st2.node_type == :yield

          if has_call
            if st2.node_type == :lvar
              if writes.include? st2[1]
                # no problem
              else
                # read after call, the scope of this function must be implemented on heap
                return :dag
              end
            else
              return :dag
            end              
          end
        end
      end
    end
  end

  :linear
end