Module: Kernel

Defined in:
lib/adsl/util/general.rb,
lib/adsl/extract/instrumenter.rb,
lib/adsl/extract/rails/action_instrumenter.rb

Instance Method Summary collapse

Instance Method Details

#ins_branch_choice(condition, branch_id) ⇒ Object



87
88
89
90
# File 'lib/adsl/extract/rails/action_instrumenter.rb', line 87

def ins_branch_choice(condition, branch_id)
  ins_stmt condition
  ::ADSL::Extract::Instrumenter.get_instance.abb.branch_choice branch_id 
end

#ins_call(object, method_name, *args, &block) ⇒ Object



10
11
12
# File 'lib/adsl/extract/instrumenter.rb', line 10

def ins_call(object, method_name, *args, &block)
  ::ADSL::Extract::Instrumenter.get_instance.execute_instrumented object, method_name, *args, &block
end

#ins_do_raise(*args) ⇒ Object



83
84
85
# File 'lib/adsl/extract/rails/action_instrumenter.rb', line 83

def ins_do_raise(*args)
  ::ADSL::Extract::Instrumenter.get_instance.abb.do_raise *args
end

#ins_do_return(*return_values) ⇒ Object



79
80
81
# File 'lib/adsl/extract/rails/action_instrumenter.rb', line 79

def ins_do_return(*return_values)
  ::ADSL::Extract::Instrumenter.get_instance.abb.do_return *return_values
end

#ins_explore_all(method_name, &block) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/adsl/extract/rails/action_instrumenter.rb', line 92

def ins_explore_all(method_name, &block)
  instrumenter = ::ADSL::Extract::Instrumenter.get_instance

  return_value = instrumenter.abb.explore_all_choices &block

  block_adsl_ast = instrumenter.abb.adsl_ast

  instrumenter.prev_abb << block_adsl_ast

  # are we at the root level? if so, wrap everything around in an action/callback
  if instrumenter.stack_depth == 2
    Array.wrap(return_value).each do |final_return|
      adsl_ast = ::ADSL::Extract::Rails::ActionInstrumenter.extract_stmt_from_expr final_return
      block_adsl_ast.statements << adsl_ast if !adsl_ast.nil? and adsl_ast.class.is_statement?
    end
    instrumenter.prev_abb << ::ADSL::Parser::ASTDummyStmt.new(:type => method_name)
  end
  
  return_value
end

#ins_if(condition, arg1, arg2) ⇒ Object



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/adsl/extract/rails/action_instrumenter.rb', line 123

def ins_if(condition, arg1, arg2)
  ins_stmt condition
  push_frame_expr1, frame1_ret_value, frame1_stmts = arg1
  push_frame_expr2, frame2_ret_value, frame2_stmts = arg2
  if frame1_stmts.length <= 1 && frame2_stmts.length <= 1 &&
      frame1_ret_value.respond_to?(:adsl_ast) && frame1_ret_value.adsl_ast.class.is_objset? &&
      frame2_ret_value.respond_to?(:adsl_ast) && frame2_ret_value.adsl_ast.class.is_objset? &&
      !frame1_ret_value.adsl_ast.objset_has_side_effects? && !frame2_ret_value.adsl_ast.objset_has_side_effects?

    return nil if frame1_ret_value.nil? && frame2_ret_value.nil?
    
    result_type = if frame1_ret_value.nil?
      frame2_ret_value.class
    elsif frame2_ret_value.nil?
      frame1_ret_value.class
    elsif frame1_ret_value.class <= frame2_ret_value.class
      frame2_ret_value.class
    elsif frame2_ret_value.class <= frame1_ret_value.class
      frame1_ret_value.class
    else
      # objset types are incompatible
      # but MRI cannot parse return statements inside an if that's being assigned
      nil
    end

    if result_type.nil?
      block1 = ::ADSL::Parser::ASTBlock.new :statements => frame1_stmts
      block2 = ::ADSL::Parser::ASTBlock.new :statements => frame2_stmts
      return ::ADSL::Parser::ASTEither.new :blocks => [block1, block2]
    end

    result_type.new(:adsl_ast => ::ADSL::Parser::ASTOneOfObjset.new(
      :objsets => [frame1_ret_value.adsl_ast, frame2_ret_value.adsl_ast]
    ))
  else
    block1 = ::ADSL::Parser::ASTBlock.new :statements => frame1_stmts
    block2 = ::ADSL::Parser::ASTBlock.new :statements => frame2_stmts
    ::ADSL::Parser::ASTEither.new :blocks => [block1, block2]
  end
end

#ins_mark_render_statementObject



25
26
27
# File 'lib/adsl/extract/rails/action_instrumenter.rb', line 25

def ins_mark_render_statement()
  ::ADSL::Parser::ASTDummyStmt.new :type => :render
end

#ins_multi_assignment(outer_binding, names, values, operator = '=') ⇒ 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
# File 'lib/adsl/extract/rails/action_instrumenter.rb', line 29

def ins_multi_assignment(outer_binding, names, values, operator = '=')
  values_to_be_returned = []
  names.length.times do |index|
    name = names[index]
    value = values[index]

    adsl_ast_name = if /^@@[^@]+$/ =~ name.to_s
      "atat__#{ name.to_s[2..-1] }"
    elsif /^@[^@]+$/ =~ name.to_s
      "at__#{ name.to_s[1..-1] }"
    elsif /^\$.*$/ =~ name.to_s
      "global__#{ name.to_s[1..-1] }"
    else
      name.to_s
    end
    
    if value.respond_to?(:adsl_ast) && value.adsl_ast.class.is_objset?
      assignment = ::ADSL::Parser::ASTAssignment.new(
        :var_name => ::ADSL::Parser::ASTIdent.new(:text => adsl_ast_name),
        :objset => value.adsl_ast
      )
      if operator == '||='
        old_value = outer_binding.eval name rescue nil
        if old_value.respond_to?(:adsl_ast) &&
            old_value.adsl_ast.class.is_objset?
          assignment = [
            ::ADSL::Parser::ASTDeclareVar.new(:var_name => ::ADSL::Parser::ASTIdent.new(:text => adsl_ast_name.dup)),
            ::ADSL::Parser::ASTEither.new(:blocks => [
              ::ADSL::Parser::ASTBlock.new(:statements => []),
              ::ADSL::Parser::ASTBlock.new(:statements => [assignment])
            ])
          ]
        end
      end
      ins_stmt assignment

      variable = value.nil? ? nil : value.class.new(
        :adsl_ast => ::ADSL::Parser::ASTVariable.new(:var_name => ::ADSL::Parser::ASTIdent.new(:text => adsl_ast_name)
      ))
      outer_binding.eval "#{name} #{operator} ObjectSpace._id2ref(#{variable.object_id})"
      
      values_to_be_returned << variable
    else
      outer_binding.eval "#{name} #{operator} ObjectSpace._id2ref(#{value.object_id})"
      values_to_be_returned << value
    end
  end
  names.length == 1 ? values_to_be_returned.first : values_to_be_returned
end

#ins_pop_frameObject



118
119
120
121
# File 'lib/adsl/extract/rails/action_instrumenter.rb', line 118

def ins_pop_frame
  instrumenter = ::ADSL::Extract::Instrumenter.get_instance
  instrumenter.abb.pop_frame
end

#ins_push_frameObject



113
114
115
116
# File 'lib/adsl/extract/rails/action_instrumenter.rb', line 113

def ins_push_frame
  instrumenter = ::ADSL::Extract::Instrumenter.get_instance
  instrumenter.abb.push_frame
end

#ins_stmt(expr = nil, options = {}) ⇒ Object



11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/adsl/extract/rails/action_instrumenter.rb', line 11

def ins_stmt(expr = nil, options = {})
  if expr.is_a? Array
    expr.each do |subexpr|
      ins_stmt subexpr, options
    end
  else
    stmt = ::ADSL::Extract::Rails::ActionInstrumenter.extract_stmt_from_expr expr
    if stmt.is_a? ::ADSL::Parser::ASTNode and stmt.class.is_statement?
      ::ADSL::Extract::Instrumenter.get_instance.abb.append_stmt stmt, options
    end
  end
  expr
end

#process_race(*commands) ⇒ Object

returns stdout of the process that terminates first not completely thread safe; cannot be with 1.8.7



186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/adsl/util/general.rb', line 186

def process_race(*commands)
  parent_thread = Thread.current
  mutex = Mutex.new
  children_threads = []
  spawned_pids = []
  result = nil
  mutex.synchronize do
    commands.each do |command|
      children_threads << Thread.new do
        begin
          sleep 0.1
          pipe = IO.popen command, 'r'
          spawned_pids << pipe.pid
          output = pipe.read
          mutex.synchronize do
            result = output if result.nil?
            parent_thread.run
          end
        rescue => e
          parent_thread.raise e unless e.message == 'die!'
        end
      end
    end
  end
  Thread.stop
  return result
ensure
  children_threads.each do |child|
    child.raise 'die!'
  end
  spawned_pids.each do |pid|
    Process.kill 'HUP', pid
  end
end

#until_no_change(object) ⇒ Object



221
222
223
224
225
226
227
# File 'lib/adsl/util/general.rb', line 221

def until_no_change(object)
  loop do
    old_object = object
    object = yield object
    return object if old_object == object
  end
end