origen_testers 0.5.7 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/config/shared_commands.rb +6 -0
  3. data/config/version.rb +2 -2
  4. data/lib/commands/run.rb +44 -0
  5. data/lib/origen_testers.rb +19 -1
  6. data/lib/origen_testers/flow.rb +382 -0
  7. data/lib/origen_testers/generator.rb +32 -29
  8. data/lib/origen_testers/igxl_based_tester/base/ac_specsets.rb +79 -0
  9. data/lib/origen_testers/igxl_based_tester/base/dc_specsets.rb +98 -0
  10. data/lib/origen_testers/igxl_based_tester/base/edge.rb +60 -0
  11. data/lib/origen_testers/igxl_based_tester/base/edges.rb +24 -0
  12. data/lib/origen_testers/igxl_based_tester/base/edgeset.rb +39 -0
  13. data/lib/origen_testers/igxl_based_tester/base/edgesets.rb +97 -0
  14. data/lib/origen_testers/igxl_based_tester/base/flow.rb +390 -115
  15. data/lib/origen_testers/igxl_based_tester/base/flow_line.rb +4 -54
  16. data/lib/origen_testers/igxl_based_tester/base/generator.rb +257 -11
  17. data/lib/origen_testers/igxl_based_tester/base/level_io_se.rb +59 -0
  18. data/lib/origen_testers/igxl_based_tester/base/level_supply.rb +39 -0
  19. data/lib/origen_testers/igxl_based_tester/base/levels.rb +31 -0
  20. data/lib/origen_testers/igxl_based_tester/base/levelset.rb +109 -0
  21. data/lib/origen_testers/igxl_based_tester/base/pinmap.rb +93 -0
  22. data/lib/origen_testers/igxl_based_tester/base/test_instance.rb +33 -1
  23. data/lib/origen_testers/igxl_based_tester/base/timeset.rb +37 -0
  24. data/lib/origen_testers/igxl_based_tester/base/timesets.rb +47 -0
  25. data/lib/origen_testers/igxl_based_tester/j750/templates/flow.txt.erb +2 -2
  26. data/lib/origen_testers/igxl_based_tester/ultraflex/ac_specsets.rb +10 -0
  27. data/lib/origen_testers/igxl_based_tester/ultraflex/custom_test_instance.rb +4 -0
  28. data/lib/origen_testers/igxl_based_tester/ultraflex/dc_specsets.rb +10 -0
  29. data/lib/origen_testers/igxl_based_tester/ultraflex/edge.rb +9 -0
  30. data/lib/origen_testers/igxl_based_tester/ultraflex/edges.rb +9 -0
  31. data/lib/origen_testers/igxl_based_tester/ultraflex/edgeset.rb +9 -0
  32. data/lib/origen_testers/igxl_based_tester/ultraflex/edgesets.rb +10 -0
  33. data/lib/origen_testers/igxl_based_tester/ultraflex/flow.rb +137 -0
  34. data/lib/origen_testers/igxl_based_tester/ultraflex/level_io_se.rb +9 -0
  35. data/lib/origen_testers/igxl_based_tester/ultraflex/level_supply.rb +9 -0
  36. data/lib/origen_testers/igxl_based_tester/ultraflex/levels.rb +9 -0
  37. data/lib/origen_testers/igxl_based_tester/ultraflex/levelset.rb +10 -0
  38. data/lib/origen_testers/igxl_based_tester/ultraflex/pinmap.rb +10 -0
  39. data/lib/origen_testers/igxl_based_tester/ultraflex/templates/ac_specsets.txt.erb +58 -0
  40. data/lib/origen_testers/igxl_based_tester/ultraflex/templates/dc_specsets.txt.erb +58 -0
  41. data/lib/origen_testers/igxl_based_tester/ultraflex/templates/edgesets.txt.erb +95 -0
  42. data/lib/origen_testers/igxl_based_tester/ultraflex/templates/flow.txt.erb +2 -2
  43. data/lib/origen_testers/igxl_based_tester/ultraflex/templates/levelset.txt.erb +121 -0
  44. data/lib/origen_testers/igxl_based_tester/ultraflex/templates/pinmap.txt.erb +24 -0
  45. data/lib/origen_testers/igxl_based_tester/ultraflex/templates/timesets.txt.erb +137 -0
  46. data/lib/origen_testers/igxl_based_tester/ultraflex/test_instance.rb +4 -0
  47. data/lib/origen_testers/igxl_based_tester/ultraflex/timeset.rb +9 -0
  48. data/lib/origen_testers/igxl_based_tester/ultraflex/timesets.rb +10 -0
  49. data/lib/origen_testers/interface.rb +41 -6
  50. data/lib/origen_testers/no_interface.rb +7 -0
  51. data/lib/origen_testers/origen_ext/application/runner.rb +25 -0
  52. data/lib/origen_testers/origen_ext/generator.rb +37 -0
  53. data/lib/origen_testers/origen_ext/generator/flow.rb +70 -0
  54. data/lib/origen_testers/origen_ext/generator/resources.rb +21 -0
  55. data/lib/origen_testers/program_generators.rb +0 -1
  56. data/lib/origen_testers/smartest_based_tester/base/flow.rb +158 -134
  57. data/lib/origen_testers/smartest_based_tester/base/generator.rb +2 -3
  58. data/lib/origen_testers/smartest_based_tester/base/test_suite.rb +4 -0
  59. data/lib/origen_testers/smartest_based_tester/v93k/templates/template.flow.erb +5 -6
  60. data/lib/origen_testers/test/dut.rb +5 -0
  61. data/lib/origen_testers/test/j750_base_interface.rb +0 -3
  62. data/lib/origen_testers/test/ultraflex_interface.rb +230 -4
  63. data/lib/origen_testers/test/v93k_interface.rb +5 -23
  64. data/program/components/_temp.rb +6 -0
  65. data/program/flow_control.rb +190 -62
  66. data/program/prb1.rb +13 -50
  67. data/program/prb2.rb +0 -16
  68. data/program/test.rb +12 -3
  69. data/program/uflex_resources.rb +159 -0
  70. metadata +66 -16
  71. data/lib/origen_testers/doc.rb +0 -224
  72. data/lib/origen_testers/doc/generator.rb +0 -124
  73. data/lib/origen_testers/doc/generator/flow.rb +0 -69
  74. data/lib/origen_testers/doc/generator/flow_line.rb +0 -201
  75. data/lib/origen_testers/doc/generator/test.rb +0 -66
  76. data/lib/origen_testers/doc/generator/test_group.rb +0 -64
  77. data/lib/origen_testers/doc/generator/tests.rb +0 -45
  78. data/lib/origen_testers/doc/model.rb +0 -160
  79. data/lib/origen_testers/generator/flow_control_api.rb +0 -611
  80. data/lib/origen_testers/smartest_based_tester/base/flow_node.rb +0 -476
  81. data/lib/origen_testers/smartest_based_tester/v93k/flow_node.rb +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6a52647531345037e756ea1413fad9e55af38d5e
4
- data.tar.gz: d2f632b5f8fc173a407a367e44f76f11bff71a9a
3
+ metadata.gz: e3d1a042fabeba96ae6e0c3e49a4448412f5e086
4
+ data.tar.gz: 8afd5f06c2fdded1afb0158c10e416d39e5c1d17
5
5
  SHA512:
6
- metadata.gz: 37665c194131cff9784e4eb867750aa1d44dc1f50fe899348696f6872ed5f3d8d096ca1b636ade17aaaf5a268af3be0380e4be7882b51d915c9123982581e4fe
7
- data.tar.gz: 74af03290ef3057d9347294c75a028ff18d3784f9b1d9585e7c9ab5de6d93e6d508aa51b7e5a799ea5183aaf8d7d82bcfbd3eaf67ef12638fb68fc8a2ee8f747
6
+ metadata.gz: 854aaa61e835e0ef0753cac4572a0851cc036273fd7f9e7c7c246b6cf3ac3862a1c08f2416fd03b5d561589e112d39ce47e52d19898c559e5cef141bb648f1cb
7
+ data.tar.gz: 7087d2fcb8ffc06b0680bab06b20c7daa45329894573895630758377792f5686aaa30d5c542afab5a4f7ec4df104b37a2d2f491f4d73f266497e8c5c8b7661d1
@@ -41,7 +41,13 @@ case @command
41
41
  require "#{Origen.root!}/lib/commands/build"
42
42
  exit 0
43
43
 
44
+ when "testers:run"
45
+ require "#{Origen.root!}/lib/commands/run"
46
+ exit 0
47
+
48
+
44
49
  else
45
50
  @plugin_commands << " testers:build Build a test program from a collection of sub-programs"
51
+ @plugin_commands << " testers:run Run the last test program generated for the current target"
46
52
 
47
53
  end
data/config/version.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  module OrigenTesters
2
2
  MAJOR = 0
3
- MINOR = 5
4
- BUGFIX = 7
3
+ MINOR = 6
4
+ BUGFIX = 0
5
5
  DEV = nil
6
6
 
7
7
  VERSION = [MAJOR, MINOR, BUGFIX].join(".") + (DEV ? ".pre#{DEV}" : '')
@@ -0,0 +1,44 @@
1
+ require 'optparse'
2
+ require 'pathname'
3
+
4
+ options = {}
5
+
6
+ opt_parser = OptionParser.new do |opts|
7
+ opts.banner = <<-EOT
8
+ Run (execute a flow) of the last test program generated for the given target.
9
+
10
+ Usage: origen testers:run FLOW [options]
11
+ EOT
12
+ opts.on('--enable FLAG,FLAG', Array, 'Comma-separated list of flow flags to enable') { |flags| options[:flow_flags] = flags }
13
+ opts.on('--job NAME', String, 'Job name to enable') { |job| options[:job] = job }
14
+ opts.on('--fail ID,ID', Array, 'Comma-separated list of test IDs to fail') { |ids| options[:failed_test_ids] = ids }
15
+ opts.on('-e', '--environment NAME', String, 'Override the default environment, NAME can be a full path or a fragment of an environment file name') { |e| options[:environment] = e }
16
+ opts.on('-t', '--target NAME', String, 'Override the default target, NAME can be a full path or a fragment of a target file name') { |t| options[:target] = t }
17
+ opts.on('-d', '--debugger', 'Enable the debugger') { options[:debugger] = true }
18
+ opts.on('-m', '--mode MODE', Origen::Mode::MODES, 'Force the Origen operating mode:', ' ' + Origen::Mode::MODES.join(', ')) { |_m| }
19
+ opts.separator ''
20
+ opts.on('-h', '--help', 'Show this message') { puts opts; exit 0 }
21
+ end
22
+
23
+ opt_parser.parse! ARGV
24
+
25
+ Origen.environment.temporary = options[:environment] if options[:environment]
26
+ Origen.target.temporary = options[:target] if options[:target]
27
+ # Origen.app.load_target!
28
+
29
+ program = OrigenTesters.program
30
+
31
+ unless program
32
+ puts 'Sorry, but there is no program model available for the current target, generate the program then retry'
33
+ exit 1
34
+ end
35
+
36
+ flow = ARGV.first
37
+
38
+ unless flow
39
+ puts 'You must supply the name of the flow to execute, the current program has these flows'
40
+ puts OrigenTesters.program.flows.keys
41
+ exit 1
42
+ end
43
+
44
+ OrigenTesters.program.flows[flow.to_sym].run(options)
@@ -1,9 +1,13 @@
1
1
  require 'origen'
2
2
  require 'active_support/concern'
3
3
  require 'require_all'
4
+ require 'atp'
5
+ require 'origen_testers/origen_ext/generator/flow'
6
+ require 'origen_testers/origen_ext/generator/resources'
7
+ require 'origen_testers/origen_ext/application/runner'
8
+ require 'origen_testers/origen_ext/generator'
4
9
 
5
10
  module OrigenTesters
6
- autoload :Doc, 'origen_testers/doc'
7
11
  autoload :CommandBasedTester, 'origen_testers/command_based_tester'
8
12
  autoload :VectorBasedTester, 'origen_testers/vector_based_tester'
9
13
  autoload :Vector, 'origen_testers/vector'
@@ -13,8 +17,22 @@ module OrigenTesters
13
17
  autoload :Parser, 'origen_testers/parser'
14
18
  autoload :BasicTestSetups, 'origen_testers/basic_test_setups'
15
19
  autoload :ProgramGenerators, 'origen_testers/program_generators'
20
+ autoload :Flow, 'origen_testers/flow'
21
+ autoload :NoInterface, 'origen_testers/no_interface'
16
22
 
17
23
  # not yet autoload :Time, 'origen_testers/time'
24
+
25
+ # The documentation tester model has been removed, but this keeps some
26
+ # legacy code working e.g. $tester.is_a?(OrigenTesters::Doc)
27
+ class Doc
28
+ end
29
+
30
+ def self.program
31
+ f = "#{Flow::PROGRAM_MODELS_DIR}/#{Origen.target.name}"
32
+ if File.exist?(f)
33
+ ATP::Program.load(f)
34
+ end
35
+ end
18
36
  end
19
37
 
20
38
  require 'origen_testers/igxl_based_tester'
@@ -0,0 +1,382 @@
1
+ require 'digest/md5'
2
+ module OrigenTesters
3
+ # Provides a common API to add tests to a flow that is supported by all testers.
4
+ #
5
+ # This builds up a flow model using the Abstract Test Program (ATP) gem, which
6
+ # now deals with implementing the flow control API.
7
+ #
8
+ # Individual tester drivers in this plugin are then responsible at the end to
9
+ # render the abstract flow to their specific format and conventions.
10
+ module Flow
11
+ include OrigenTesters::Generator
12
+
13
+ PROGRAM_MODELS_DIR = "#{Origen.root}/tmp/program_models"
14
+
15
+ def self.callstack
16
+ @callstack ||= []
17
+ end
18
+
19
+ def self.comment_stack
20
+ @comment_stack ||= []
21
+ end
22
+
23
+ def self.flow_comments
24
+ @flow_comments
25
+ end
26
+
27
+ def self.flow_comments=(val)
28
+ @flow_comments = val
29
+ end
30
+
31
+ def self.unique_ids
32
+ @unique_ids
33
+ end
34
+
35
+ def self.unique_ids=(val)
36
+ @unique_ids = val
37
+ end
38
+
39
+ def lines
40
+ @lines
41
+ end
42
+
43
+ # Returns the abstract test program model, this is shared by all
44
+ # flow created together in a generation run
45
+ def program
46
+ @@program ||= ATP::Program.new
47
+ end
48
+
49
+ def save_program
50
+ FileUtils.mkdir_p(PROGRAM_MODELS_DIR) unless File.exist?(PROGRAM_MODELS_DIR)
51
+ program.save("#{PROGRAM_MODELS_DIR}/#{Origen.target.name}")
52
+ end
53
+
54
+ def model
55
+ if Origen.interface.resources_mode?
56
+ @throwaway ||= ATP::Flow.new(self)
57
+ else
58
+ @model ||= begin
59
+ f = program.flow(id, description: OrigenTesters::Flow.flow_comments)
60
+ @sig = flow_sig(id)
61
+ f.id = @sig if OrigenTesters::Flow.unique_ids
62
+ f
63
+ end
64
+ end
65
+ end
66
+
67
+ def enable(var, options = {})
68
+ add_meta!(options)
69
+ model.enable(var, clean_options(options))
70
+ end
71
+
72
+ def disable(var, options = {})
73
+ add_meta!(options)
74
+ model.disable(var, clean_options(options))
75
+ end
76
+
77
+ def bin(number, options = {})
78
+ options[:bin_description] ||= options.delete(:description)
79
+ if number.is_a?(Hash)
80
+ fail 'The bin number must be passed as the first argument'
81
+ end
82
+ add_meta!(options)
83
+ options[:type] ||= :fail
84
+ model.bin(number, clean_options(options))
85
+ end
86
+
87
+ def pass(number, options = {})
88
+ if number.is_a?(Hash)
89
+ fail 'The bin number must be passed as the first argument'
90
+ end
91
+ options[:type] = :pass
92
+ bin(number, clean_options(options))
93
+ end
94
+
95
+ def test(instance, options = {})
96
+ add_meta_and_description!(options)
97
+ model.test(instance, clean_options(options))
98
+ end
99
+
100
+ def render(file, options = {})
101
+ add_meta!(options)
102
+ begin
103
+ text = super
104
+ rescue
105
+ text = file
106
+ end
107
+ model.render(text)
108
+ end
109
+
110
+ def cz(instance, cz_setup, options = {})
111
+ add_meta_and_description!(options)
112
+ model.cz(instance, cz_setup, clean_options(options))
113
+ end
114
+ alias_method :characterize, :cz
115
+
116
+ def log(message, options = {})
117
+ add_meta!(options)
118
+ model.log(message, clean_options(options))
119
+ end
120
+ alias_method :logprint, :log
121
+
122
+ def group(name, options = {})
123
+ add_meta!(options)
124
+ model.group(name, clean_options(options)) do
125
+ yield
126
+ end
127
+ end
128
+
129
+ def nop(options = {})
130
+ end
131
+
132
+ # @api private
133
+ # This fires between target loads
134
+ def at_run_start
135
+ @@program = nil
136
+ end
137
+
138
+ # @api private
139
+ # This fires between flows
140
+ def at_flow_start
141
+ @labels = {}
142
+ end
143
+
144
+ def if_job(*jobs)
145
+ options = jobs.last.is_a?(Hash) ? jobs.pop : {}
146
+ options[:if_job] = jobs.flatten
147
+ add_meta!(options)
148
+ model.with_conditions(options) do
149
+ yield
150
+ end
151
+ end
152
+ alias_method :if_jobs, :if_job
153
+
154
+ def unless_job(*jobs)
155
+ options = jobs.last.is_a?(Hash) ? jobs.pop : {}
156
+ options[:unless_job] = jobs.flatten
157
+ add_meta!(options)
158
+ model.with_conditions(options) do
159
+ yield
160
+ end
161
+ end
162
+ alias_method :unless_jobs, :unless_job
163
+
164
+ def if_enable(word, options = {})
165
+ if options[:or]
166
+ yield
167
+ else
168
+ options = { enable: word }
169
+ add_meta!(options)
170
+ model.with_conditions(options) do
171
+ yield
172
+ end
173
+ end
174
+ end
175
+ alias_method :if_enabled, :if_enable
176
+
177
+ def unless_enable(word, options = {})
178
+ if options[:or]
179
+ yield
180
+ else
181
+ options = { unless_enable: word }
182
+ add_meta!(options)
183
+ model.with_conditions(options) do
184
+ yield
185
+ end
186
+ end
187
+ end
188
+ alias_method :unless_enabled, :unless_enable
189
+
190
+ def if_passed(test_id, options = {})
191
+ if test_id.is_a?(Array)
192
+ fail 'if_passed only accepts one ID, use if_any_passed or if_all_passed for multiple IDs'
193
+ end
194
+ options = { if_passed: test_id }
195
+ add_meta!(options)
196
+ model.with_conditions(options) do
197
+ yield
198
+ end
199
+ end
200
+ alias_method :unless_failed, :if_passed
201
+
202
+ def if_failed(test_id, options = {})
203
+ if test_id.is_a?(Array)
204
+ fail 'if_failed only accepts one ID, use if_any_failed or if_all_failed for multiple IDs'
205
+ end
206
+ options = { if_failed: test_id }
207
+ add_meta!(options)
208
+ model.with_conditions(options) do
209
+ yield
210
+ end
211
+ end
212
+ alias_method :unless_passed, :if_failed
213
+
214
+ def if_ran(test_id, options = {})
215
+ options = { if_ran: test_id }
216
+ add_meta!(options)
217
+ model.with_conditions(options) do
218
+ yield
219
+ end
220
+ end
221
+
222
+ def unless_ran(test_id, options = {})
223
+ options = { unless_ran: test_id }
224
+ add_meta!(options)
225
+ model.with_conditions(options) do
226
+ yield
227
+ end
228
+ end
229
+
230
+ def if_any_failed(*ids)
231
+ options = ids.last.is_a?(Hash) ? ids.pop : {}
232
+ options[:if_any_failed] = ids.flatten
233
+ add_meta!(options)
234
+ model.with_conditions(options) do
235
+ yield
236
+ end
237
+ end
238
+
239
+ def if_all_failed(*ids)
240
+ options = ids.last.is_a?(Hash) ? ids.pop : {}
241
+ options[:if_all_failed] = ids.flatten
242
+ add_meta!(options)
243
+ model.with_conditions(options) do
244
+ yield
245
+ end
246
+ end
247
+
248
+ def if_any_passed(*ids)
249
+ options = ids.last.is_a?(Hash) ? ids.pop : {}
250
+ options[:if_any_passed] = ids.flatten
251
+ add_meta!(options)
252
+ model.with_conditions(options) do
253
+ yield
254
+ end
255
+ end
256
+
257
+ def if_all_passed(*ids)
258
+ options = ids.last.is_a?(Hash) ? ids.pop : {}
259
+ options[:if_all_passed] = ids.flatten
260
+ add_meta!(options)
261
+ model.with_conditions(options) do
262
+ yield
263
+ end
264
+ end
265
+
266
+ def if_flag(flag, options = {})
267
+ options = { if_flag: flag }
268
+ add_meta!(options)
269
+ model.with_conditions(options) do
270
+ yield
271
+ end
272
+ end
273
+
274
+ def unless_flag(flag, options = {})
275
+ options = { unless_flag: flag }
276
+ add_meta!(options)
277
+ model.with_conditions(options) do
278
+ yield
279
+ end
280
+ end
281
+
282
+ # @api private
283
+ def is_the_flow?
284
+ true
285
+ end
286
+
287
+ # Returns true if the test context generated from the supplied options + existing condition
288
+ # wrappers is different from that which was applied to the previous test.
289
+ def context_changed?(options)
290
+ options = clean_options(options)
291
+ model.context_changed?(options)
292
+ end
293
+
294
+ def generate_unique_label(name = nil)
295
+ name = 'label' if !name || name == ''
296
+ name.gsub!(' ', '_')
297
+ name.upcase!
298
+ @labels ||= {}
299
+ @labels[name] ||= 0
300
+ @labels[name] += 1
301
+ "#{name}_#{@labels[name]}_#{sig}"
302
+ end
303
+
304
+ # Returns a unique signature that has been generated for the current flow, this can be appended
305
+ # to named references to avoid naming collisions with any other flow
306
+ def sig
307
+ @sig
308
+ end
309
+ alias_method :signature, :sig
310
+
311
+ private
312
+
313
+ # Make a unique signature for the flow based on the flow name and the name of
314
+ # the plugin/app that owns it
315
+ def flow_sig(id)
316
+ s = Digest::MD5.new
317
+ # These guarantee uniqueness within a plugin/app
318
+ s << id.to_s
319
+ s << filename
320
+ # This will add the required plugin uniqueness in the case of a top-level app
321
+ # that has multiple plugins that can generate test program snippets
322
+ if file = OrigenTesters::Flow.callstack.first
323
+ s << get_app(file).name.to_s
324
+ end
325
+ s.to_s[0..6].upcase
326
+ end
327
+
328
+ def get_app(file)
329
+ path = Pathname.new(file).dirname
330
+ until File.exist?(File.join(path, 'config/application.rb')) || path.root?
331
+ path = path.parent
332
+ end
333
+ if path.root?
334
+ fail 'Something went wrong resoving the app root in OrigenTesters'
335
+ end
336
+ Origen.find_app_by_root(path)
337
+ end
338
+
339
+ def add_meta!(options)
340
+ flow_file = OrigenTesters::Flow.callstack.last
341
+ called_from = caller.find { |l| l =~ /^#{flow_file}:.*/ }
342
+ if called_from
343
+ called_from = called_from.split(':')
344
+ options[:source_file] = called_from[0]
345
+ options[:source_line_number] = called_from[1].to_i
346
+ end
347
+ end
348
+
349
+ def add_meta_and_description!(options)
350
+ add_meta!(options)
351
+ # Can be useful if an app generates additional tests on the fly for a single test in the flow,
352
+ # e.g. a POR, in that case they will not want the description to be attached to the POR, but to
353
+ # the test that follows it
354
+ unless options[:inhibit_description_consumption]
355
+ comments = OrigenTesters::Flow.comment_stack.last
356
+ if options[:source_line_number]
357
+ while comments.first && comments.first.first < options[:source_line_number]
358
+ options[:description] ||= []
359
+ c = comments.shift
360
+ if c[0] + c[1].size == options[:source_line_number]
361
+ options[:description] += c[1]
362
+ end
363
+ end
364
+ end
365
+ end
366
+ end
367
+
368
+ def clean_options(options)
369
+ ATP::AST::Builder::CONDITION_KEYS.each do |key|
370
+ if v = options.delete(key)
371
+ options[:conditions] ||= {}
372
+ if options[:conditions][key]
373
+ fail "Multiple values assigned to flow condition #{key}"
374
+ else
375
+ options[:conditions][key] = v
376
+ end
377
+ end
378
+ end
379
+ options
380
+ end
381
+ end
382
+ end