trailblazer-activity-dsl-linear 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +2 -5
  3. data/CHANGES.md +72 -0
  4. data/Gemfile +6 -3
  5. data/lib/trailblazer/activity/dsl/linear/feature/merge.rb +2 -2
  6. data/lib/trailblazer/activity/dsl/linear/feature/patch.rb +9 -9
  7. data/lib/trailblazer/activity/dsl/linear/feature/variable_mapping/dsl.rb +19 -29
  8. data/lib/trailblazer/activity/dsl/linear/feature/variable_mapping/runtime.rb +6 -8
  9. data/lib/trailblazer/activity/dsl/linear/feature/variable_mapping.rb +25 -35
  10. data/lib/trailblazer/activity/dsl/linear/helper/path.rb +37 -18
  11. data/lib/trailblazer/activity/dsl/linear/helper.rb +27 -18
  12. data/lib/trailblazer/activity/dsl/linear/normalizer/extensions.rb +63 -0
  13. data/lib/trailblazer/activity/dsl/linear/normalizer/inherit.rb +90 -0
  14. data/lib/trailblazer/activity/dsl/linear/normalizer/output_tuples.rb +160 -0
  15. data/lib/trailblazer/activity/dsl/linear/normalizer/terminus.rb +26 -29
  16. data/lib/trailblazer/activity/dsl/linear/normalizer.rb +96 -148
  17. data/lib/trailblazer/activity/dsl/linear/sequence/builder.rb +3 -2
  18. data/lib/trailblazer/activity/dsl/linear/sequence/compiler.rb +21 -17
  19. data/lib/trailblazer/activity/dsl/linear/sequence/search.rb +2 -8
  20. data/lib/trailblazer/activity/dsl/linear/strategy.rb +17 -17
  21. data/lib/trailblazer/activity/dsl/linear/version.rb +1 -1
  22. data/lib/trailblazer/activity/dsl/linear.rb +12 -1
  23. data/lib/trailblazer/activity/fast_track.rb +91 -54
  24. data/lib/trailblazer/activity/path.rb +22 -29
  25. data/lib/trailblazer/activity/railway.rb +60 -54
  26. data/trailblazer-activity-dsl-linear.gemspec +7 -8
  27. metadata +21 -36
  28. data/.github/workflows/ci_jruby.yml +0 -19
  29. data/.github/workflows/ci_legacy.yml +0 -19
  30. data/.github/workflows/ci_truffleruby.yml +0 -19
  31. data/lib/trailblazer/activity/dsl/linear/feature/variable_mapping/inherit.rb +0 -38
@@ -9,12 +9,15 @@ module Trailblazer
9
9
  #
10
10
  # They're usually invoked from {Strategy#invoke_normalizer_for!}, which is called from {Path#step},
11
11
  # {Railway#pass}, etc.
12
+ #
13
+ # Most parts of Normalizer are documented: https://trailblazer.to/2.1/docs/internals.html#internals-dsl-normalizer
12
14
  module Normalizer
13
15
  # Container for all final normalizers of a specific Strategy.
14
16
  class Normalizers
15
17
  def initialize(**options)
16
18
  @normalizers = options
17
19
  end
20
+
18
21
  # Execute the specific normalizer (step, fail, pass) for a particular option set provided
19
22
  # by the DSL user. Usually invoked when you call {#step}.
20
23
  def call(name, ctx)
@@ -57,7 +60,6 @@ module Trailblazer
57
60
  [name, new_normalizer]
58
61
  end.to_h
59
62
 
60
-
61
63
  Normalizers.new(**hsh.merge(new_normalizers))
62
64
  end
63
65
  end
@@ -75,82 +77,125 @@ module Trailblazer
75
77
  end
76
78
 
77
79
  # The generic normalizer not tied to `step` or friends.
78
- def Normalizer
79
- pipeline = TaskWrap::Pipeline.new(
80
+ def Normalizer(prepend_to_default_outputs: [])
81
+ # Adding steps to the output pipeline means they are only called when there
82
+ # are no :outputs set already.
83
+ outputs_pipeline = TaskWrap::Pipeline.new([])
84
+ prepend_to_default_outputs.each do |hsh|
85
+ outputs_pipeline = Linear::Normalizer.prepend_to(outputs_pipeline, nil, hsh) # DISCUSS: does it matter if we prepend FastTrack to Railway, etc?
86
+ end
87
+
88
+ # Call the prepend_to_outputs pipeline only if {:outputs} is not set (by Subprocess).
89
+ # too bad we don't have nesting here, yet.
90
+ defaults_for_outputs = ->(ctx, args) do
91
+ return [ctx, args] if ctx.key?(:outputs)
92
+
93
+ outputs_pipeline.(ctx, args)
94
+ end
95
+
96
+ TaskWrap::Pipeline.new(
80
97
  {
81
- "activity.normalize_step_interface" => Normalizer.Task(method(:normalize_step_interface)), # Makes sure {:options} is always a hash.
98
+ "activity.normalize_step_interface" => Normalizer.Task(method(:normalize_step_interface)), # Makes sure {:options} is always a hash.
99
+ "activity.macro_options_with_symbol_task" => Normalizer.Task(method(:macro_options_with_symbol_task)), # DISCUSS: we might deprecate {task: :instance_method}
100
+
82
101
  "activity.merge_library_options" => Normalizer.Task(method(:merge_library_options)), # Merge "macro"/user options over library options.
83
102
  "activity.normalize_for_macro" => Normalizer.Task(method(:merge_user_options)), # Merge user_options over "macro" options.
84
103
  "activity.normalize_normalizer_options" => Normalizer.Task(method(:merge_normalizer_options)), # Merge user_options over normalizer_options.
85
104
  "activity.normalize_non_symbol_options" => Normalizer.Task(method(:normalize_non_symbol_options)),
86
105
  "activity.path_helper.forward_block" => Normalizer.Task(Helper::Path::Normalizer.method(:forward_block_for_path_branch)), # forward the "global" block
87
106
  "activity.normalize_context" => method(:normalize_context),
107
+ "activity.id_with_inherit_and_replace" => Normalizer.Task(method(:id_with_inherit_and_replace)),
88
108
  "activity.normalize_id" => Normalizer.Task(method(:normalize_id)),
89
- "activity.normalize_override" => Normalizer.Task(method(:normalize_override)),
109
+ "activity.normalize_override" => Normalizer.Task(method(:normalize_override)), # TODO: remove!
90
110
  "activity.wrap_task_with_step_interface" => Normalizer.Task(method(:wrap_task_with_step_interface)),
91
111
 
92
- "activity.inherit_option" => Normalizer.Task(method(:inherit_option)),
112
+ # Nested pipeline:
113
+ "activity.default_outputs" => defaults_for_outputs, # only {if :outputs.nil?}
114
+
115
+ "extensions.convert_extensions_option_to_tuples" => Normalizer.Task(Extensions.method(:convert_extensions_option_to_tuples)),
116
+
117
+ "inherit.recall_recorded_options" => Normalizer.Task(Inherit.method(:recall_recorded_options)),
93
118
  "activity.sequence_insert" => Normalizer.Task(method(:normalize_sequence_insert)),
94
119
  "activity.normalize_duplications" => Normalizer.Task(method(:normalize_duplications)),
95
120
 
96
- "activity.path_helper.path_to_track" => Normalizer.Task(Helper::Path::Normalizer.method(:convert_paths_to_tracks)),
97
- "activity.normalize_outputs_from_dsl" => Normalizer.Task(method(:normalize_outputs_from_dsl)), # Output(Signal, :semantic) => Id()
98
- "activity.normalize_connections_from_dsl" => Normalizer.Task(method(:normalize_connections_from_dsl)),
121
+ "activity.path_helper.path_to_track" => Normalizer.Task(Helper::Path::Normalizer.method(:convert_paths_to_tracks)),
122
+
123
+
124
+ "output_tuples.normalize_output_tuples" => Normalizer.Task(OutputTuples.method(:normalize_output_tuples)), # Output(Signal, :semantic) => Id()
125
+ "output_tuples.remember_custom_output_tuples" => Normalizer.Task(OutputTuples.method(:remember_custom_output_tuples)), # Output(Signal, :semantic) => Id()
126
+ "output_tuples.register_additional_outputs" => Normalizer.Task(OutputTuples.method(:register_additional_outputs)), # Output(Signal, :semantic) => Id()
127
+ "output_tuples.filter_inherited_output_tuples" => Normalizer.Task(OutputTuples.method(:filter_inherited_output_tuples)),
128
+
129
+ "activity.wirings" => Normalizer.Task(OutputTuples::Connections.method(:compile_wirings)),
99
130
 
100
- "activity.wirings" => Normalizer.Task(method(:compile_wirings)),
131
+
132
+ "extensions.compile_extensions" => Normalizer.Task(Extensions.method(:compile_extensions)),
133
+ "extensions.compile_recorded_extensions" => Normalizer.Task(Extensions.method(:compile_recorded_extensions)),
134
+
135
+ # DISCUSS: make this configurable? maybe lots of folks don't want {:inherit}?
136
+ "inherit.compile_recorded_options" => Normalizer.Task(Inherit.method(:compile_recorded_options)),
101
137
 
102
138
  # TODO: make this a "Subprocess":
103
139
  "activity.compile_data" => Normalizer.Task(method(:compile_data)),
104
140
  "activity.create_row" => Normalizer.Task(method(:create_row)),
105
141
  "activity.create_add" => Normalizer.Task(method(:create_add)),
106
142
  "activity.create_adds" => Normalizer.Task(method(:create_adds)),
107
- }.
108
- collect { |id, task| TaskWrap::Pipeline.Row(id, task) }
143
+ }
144
+ .collect { |id, task| TaskWrap::Pipeline.Row(id, task) }
109
145
  )
146
+ end
147
+
148
+ # DISCUSS: should we remove this special case?
149
+ # This handles
150
+ # step task: :instance_method_exposing_circuit_interface
151
+ def macro_options_with_symbol_task(ctx, options:, **)
152
+ return if options[:wrap_task]
153
+ return unless options[:task].is_a?(Symbol)
110
154
 
111
- pipeline
155
+ ctx[:options] = {
156
+ **options,
157
+ wrap_task: true,
158
+ step_interface_builder: ->(task) { Trailblazer::Option(task) } # only wrap in Option, not {TaskAdapter}.
159
+ }
112
160
  end
113
161
 
162
+ # @param {:options} The first argument passed to {#step}
163
+ # After this step, options is always a hash.
164
+ #
114
165
  # Specific to the "step DSL": if the first argument is a callable, wrap it in a {step_interface_builder}
115
166
  # since its interface expects the step interface, but the circuit will call it with circuit interface.
116
167
  def normalize_step_interface(ctx, options:, **)
117
- options = case options
118
- when Hash
119
- # Circuit Interface
120
- task = options.fetch(:task)
121
- id = options[:id]
122
-
123
- if task.is_a?(Symbol)
124
- # step task: :find, id: :load
125
- { **options, id: (id || task), task: Trailblazer::Option(task) }
126
- else
127
- # step task: Callable, ... (Subprocess, Proc, macros etc)
128
- options # NOOP
129
- end
130
- else
131
- # Step Interface
132
- # step :find, ...
133
- # step Callable, ... (Method, Proc etc)
134
- { task: options, wrap_task: true }
135
- end
136
-
137
- ctx[:options] = options
168
+ return if options.is_a?(Hash)
169
+
170
+ # Step Interface
171
+ # step :find, ...
172
+ # step Callable, ... (Method, Proc etc)
173
+ ctx[:options] = {
174
+ task: options,
175
+ wrap_task: true # task exposes step interface.
176
+ }
138
177
  end
139
178
 
140
- def wrap_task_with_step_interface(ctx, wrap_task: false, step_interface_builder:, task:, **)
179
+ # @param :wrap_task If true, the {:task} is wrapped using the step_interface_builder, meaning the
180
+ # task is expecting the step interface.
181
+ def wrap_task_with_step_interface(ctx, step_interface_builder:, task:, wrap_task: false, **)
141
182
  return unless wrap_task
142
183
 
143
184
  ctx[:task] = step_interface_builder.(task)
144
185
  end
145
186
 
146
- def normalize_id(ctx, id: false, task:, **)
187
+ def normalize_id(ctx, task:, id: false, **)
147
188
  ctx[:id] = id || task
148
189
  end
149
190
 
191
+ # TODO: remove {#normalize_override} in 1.2.0 (Used in macro-contract tests).
150
192
  # {:override} really only makes sense for {step Macro(), {override: true}} where the {user_options}
151
193
  # dictate the overriding.
152
194
  def normalize_override(ctx, id:, override: false, **)
153
195
  return unless override
196
+
197
+ Activity::Deprecate.warn Linear::Deprecate.dsl_caller_location, "The :override option is deprecated and will be removed. Please use :replace instead."
198
+
154
199
  ctx[:replace] = (id || raise)
155
200
  end
156
201
 
@@ -176,20 +221,6 @@ module Trailblazer
176
221
  return ctx, flow_options
177
222
  end
178
223
 
179
- # Compile the actual {Seq::Row}'s {wiring}.
180
- # This combines {:connections} and {:outputs}
181
- def compile_wirings(ctx, connections:, outputs:, id:, **)
182
- ctx[:wirings] =
183
- connections.collect do |semantic, (search_strategy_builder, *search_args)|
184
- output = outputs[semantic] || raise("No `#{semantic}` output found for #{id.inspect} and outputs #{outputs.inspect}")
185
-
186
- search_strategy_builder.( # return proc to be called when compiling Seq, e.g. {ById(output, :id)}
187
- output,
188
- *search_args
189
- )
190
- end
191
- end
192
-
193
224
  # Processes {:before,:after,:replace,:delete} options and
194
225
  # defaults to {before: "End.success"} which, yeah.
195
226
  def normalize_sequence_insert(ctx, end_id:, **)
@@ -205,10 +236,10 @@ module Trailblazer
205
236
  # @private
206
237
  def sequence_insert_options
207
238
  {
208
- :before => :Prepend,
209
- :after => :Append,
210
- :replace => :Replace,
211
- :delete => :Delete,
239
+ before: :Prepend,
240
+ after: :Append,
241
+ replace: :Replace,
242
+ delete: :Delete
212
243
  }
213
244
  end
214
245
 
@@ -231,7 +262,6 @@ module Trailblazer
231
262
  ctx[:task] = task.clone if sequence.find { |row| row[1] == task }
232
263
  end
233
264
 
234
-
235
265
  # Move DSL user options such as {Output(:success) => Track(:found)} to
236
266
  # a new key {options[:non_symbol_options]}.
237
267
  # This allows using {options} as a {**ctx}-able hash in Ruby 2.6 and 3.0.
@@ -243,97 +273,14 @@ module Trailblazer
243
273
  ctx[:options] = symbol_options.merge(non_symbol_options: non_symbol_options)
244
274
  end
245
275
 
246
- # Process {Output(:semantic) => target} and make them {:connections}.
247
- def normalize_connections_from_dsl(ctx, connections:, adds:, non_symbol_options:, sequence:, normalizers:, **)
248
- # Find all {Output() => Track()/Id()/End()}
249
- output_configs = non_symbol_options.find_all{ |k,v| k.kind_of?(Linear::OutputSemantic) }
250
- return unless output_configs.any?
251
-
252
- # DISCUSS: how could we add another magnetic_to to an end?
253
- output_configs.each do |output, cfg|
254
- new_connections, add =
255
- if cfg.is_a?(Linear::Track)
256
- [output_to_track(ctx, output, cfg), cfg.adds] # FIXME: why does Track have a {adds} field? we don't use it anywhere.
257
- elsif cfg.is_a?(Linear::Id)
258
- [output_to_id(ctx, output, cfg.value), []]
259
- elsif cfg.is_a?(Activity::End)
260
- end_id = Activity::Railway.end_id(**cfg.to_h)
261
- end_exists = Activity::Adds::Insert.find_index(ctx[:sequence], end_id)
262
-
263
- _adds = end_exists ? [] : add_terminus(cfg, id: end_id, sequence: sequence, normalizers: normalizers)
264
-
265
- [output_to_id(ctx, output, end_id), _adds]
266
- else
267
- raise cfg.inspect
268
- end
269
-
270
- connections = connections.merge(new_connections)
271
- adds += add
272
- end
273
-
274
- ctx[:connections] = connections
275
- ctx[:adds] = adds
276
- end
277
-
278
- def output_to_track(ctx, output, track)
279
- search_strategy = track.options[:wrap_around] ? :WrapAround : :Forward
280
-
281
- {output.value => [Linear::Sequence::Search.method(search_strategy), track.color]}
282
- end
283
-
284
- def output_to_id(ctx, output, target)
285
- {output.value => [Linear::Sequence::Search.method(:ById), target]}
286
- end
287
-
288
- # Returns ADDS for the new terminus.
289
- def add_terminus(end_event, id:, sequence:, normalizers:)
290
- step_options = Linear::Sequence::Builder.invoke_normalizer_for(:terminus, end_event, {id: id}, sequence: sequence, normalizer_options: {}, normalizers: normalizers)
276
+ # Whenever {:replace} and {:inherit} are passed, automatically assign {:id}.
277
+ # DISCUSS: this step could be nested in {inherit_option}.
278
+ def id_with_inherit_and_replace(ctx, id: nil, replace: nil, inherit: nil, **)
279
+ return if id
280
+ return unless inherit # inherit: true and inherit: [] both work.
281
+ return unless replace
291
282
 
292
- step_options[:adds]
293
- end
294
-
295
- # Output(Signal, :semantic) => Id()
296
- def normalize_outputs_from_dsl(ctx, non_symbol_options:, outputs:, **)
297
- output_configs = non_symbol_options.find_all{ |k,v| k.kind_of?(Activity::Output) }
298
- return unless output_configs.any?
299
-
300
- dsl_options = {}
301
-
302
- output_configs.collect do |output, cfg| # {cfg} = Track(:success)
303
- outputs = outputs.merge(output.semantic => output)
304
- dsl_options = dsl_options.merge(Linear::Strategy.Output(output.semantic) => cfg)
305
- end
306
-
307
- ctx[:outputs] = outputs
308
- ctx[:non_symbol_options] = non_symbol_options.merge(dsl_options)
309
- end
310
-
311
- # Currently, the {:inherit} option copies over {:connections} from the original step
312
- # and merges them with the (prolly) connections passed from the user.
313
- def inherit_option(ctx, inherit: false, sequence:, id:, extensions: [], **)
314
- return unless inherit === true
315
-
316
- row = InheritOption.find_row(sequence, id) # from this row we're inheriting options.
317
-
318
- inherited_connections = row.data[:connections]
319
- inherited_extensions = row.data[:extensions]
320
-
321
- ctx[:connections] = get_inheritable_connections(ctx, inherited_connections)
322
- ctx[:extensions] = Array(inherited_extensions) + Array(extensions)
323
- end
324
-
325
- module InheritOption # TODO: move all inherit methods in here!
326
- def self.find_row(sequence, id)
327
- index = Activity::Adds::Insert.find_index(sequence, id)
328
- sequence[index]
329
- end
330
- end
331
-
332
- # return connections from {parent} step which are supported by current step
333
- private def get_inheritable_connections(ctx, parent_connections)
334
- return parent_connections unless ctx[:outputs]
335
-
336
- parent_connections.slice(*ctx[:outputs].keys)
283
+ ctx[:id] = replace
337
284
  end
338
285
 
339
286
  def create_row(ctx, task:, wirings:, magnetic_to:, data:, **)
@@ -350,13 +297,14 @@ module Trailblazer
350
297
 
351
298
  # TODO: document DataVariable() => :name
352
299
  # Compile data that goes into the sequence row.
353
- def compile_data(ctx, default_variables_for_data: [:id, :dsl_track, :connections, :extensions, :stop_event], non_symbol_options:, **)
354
- variables_for_data = non_symbol_options.find_all { |k,v| k.instance_of?(Linear::DataVariableName) }.collect { |k,v| Array(v) }.flatten
300
+ def compile_data(ctx, non_symbol_options:, default_variables_for_data: [:id, :dsl_track, :extensions], **)
301
+ variables_for_data = non_symbol_options
302
+ .find_all { |k, v| k.instance_of?(Linear::DataVariableName) }
303
+ .flat_map { |k, v| Array(v) }
355
304
 
356
305
  ctx[:data] = (default_variables_for_data + variables_for_data).collect { |key| [key, ctx[key]] }.to_h
357
306
  end
358
307
  end
359
-
360
308
  end # Normalizer
361
309
  end
362
310
  end
@@ -13,7 +13,7 @@ module Trailblazer
13
13
  # @private
14
14
  # Run a specific normalizer (e.g. for `#step`), apply the adds to the sequence and return the latter.
15
15
  # DISCUSS: where does this method belong? Sequence + Normalizers?
16
- def self.update_sequence_for(type, task, options={}, sequence:, **kws, &block)
16
+ def self.update_sequence_for(type, task, options = {}, sequence:, **kws, &block)
17
17
  step_options = invoke_normalizer_for(type, task, options, sequence: sequence, **kws, &block)
18
18
 
19
19
  _sequence = Activity::Adds.apply_adds(sequence, step_options[:adds])
@@ -32,7 +32,8 @@ module Trailblazer
32
32
  sequence: sequence,
33
33
  }
34
34
 
35
- _step_options = normalizers.(type,
35
+ _step_options = normalizers.(
36
+ type,
36
37
  normalizer_options: normalizer_options, # class-level Strategy configuration, such as :step_interface_builder
37
38
  options: task, # macro-options
38
39
  user_options: options, # user-specified options from the DSL method
@@ -8,16 +8,19 @@ module Trailblazer
8
8
  module_function
9
9
 
10
10
  # Default strategy to find out what's a stop event is to inspect the TaskRef's {data[:stop_event]}.
11
- def find_stop_task_ids(intermediate_wiring)
12
- intermediate_wiring.collect { |task_ref, outs| task_ref.data[:stop_event] ? task_ref.id : nil }.compact
11
+ def find_termini(intermediate_wiring)
12
+ intermediate_wiring
13
+ .find_all { |task_ref, _| task_ref.data[:stop_event] }
14
+ .collect { |task_ref, _| [task_ref.id, task_ref.data.fetch(:semantic)] }
15
+ .to_h
13
16
  end
14
17
 
15
18
  # The first task in the wiring is the default start task.
16
- def find_start_task_ids(intermediate_wiring)
17
- [intermediate_wiring.first.first.id]
19
+ def find_start_task_id(intermediate_wiring) # FIXME: shouldn't we use sequence here? and Row#id?
20
+ intermediate_wiring.first.first.id
18
21
  end
19
22
 
20
- def call(sequence, find_stops: method(:find_stop_task_ids), find_start: method(:find_start_task_ids))
23
+ def call(sequence, find_stops: method(:find_termini), find_start: method(:find_start_task_id))
21
24
  _implementations, intermediate_wiring =
22
25
  sequence.inject([[], []]) do |(implementations, intermediates), seq_row|
23
26
  _magnetic_to, task, connections, data = seq_row
@@ -27,7 +30,7 @@ module Trailblazer
27
30
  connections = find_connections(seq_row, connections, sequence)
28
31
 
29
32
  # FIXME: {:extensions} should be initialized
30
- implementations += [[id, Schema::Implementation::Task(task, connections.collect { |output, _| output }, data[:extensions] || []) ]]
33
+ implementations += [[id, Schema::Implementation::Task(task, connections.collect { |output, _| output }, data[:extensions] || [])]]
31
34
 
32
35
  intermediates += [
33
36
  [
@@ -40,29 +43,30 @@ module Trailblazer
40
43
  [implementations, intermediates]
41
44
  end
42
45
 
43
- start_task_ids = find_start.(intermediate_wiring)
44
- stop_task_refs = find_stops.(intermediate_wiring)
46
+ start_task_id = find_start.(intermediate_wiring)
47
+ terminus_to_semantic = find_stops.(intermediate_wiring)
45
48
 
46
- intermediate = Schema::Intermediate.new(Hash[intermediate_wiring], stop_task_refs, start_task_ids)
47
- implementation = Hash[_implementations]
49
+ intermediate = Schema::Intermediate.new(intermediate_wiring.to_h, terminus_to_semantic, start_task_id)
50
+ implementation = _implementations.to_h
48
51
 
49
- Schema::Intermediate.(intermediate, implementation) # implemented in the generic {trailblazer-activity} gem.
52
+ Schema::Intermediate::Compiler.(intermediate, implementation) # implemented in the generic {trailblazer-activity} gem.
50
53
  end
51
54
 
52
55
  # private
53
56
 
54
- def find_connections(seq_row, strategies, sequence)
55
- strategies.collect do |search|
57
+ # Execute all search strategies for a row, retrieve outputs and
58
+ # their respective target IDs.
59
+ def find_connections(seq_row, searches, sequence)
60
+ searches.collect do |search|
56
61
  output, target_seq_row = search.(sequence, seq_row) # invoke the node's "connection search" strategy.
57
62
 
58
63
  target_seq_row = sequence[-1] if target_seq_row.nil? # connect to an End if target unknown. # DISCUSS: make this configurable, maybe?
59
64
 
60
65
  [
61
- output, # implementation
62
- target_seq_row[3][:id], # intermediate # FIXME. this sucks.
63
- target_seq_row # DISCUSS: needed?
66
+ output,
67
+ target_seq_row.id
64
68
  ]
65
- end.compact
69
+ end
66
70
  end
67
71
  end # Compiler
68
72
  end # Sequence
@@ -11,7 +11,7 @@ class Trailblazer::Activity
11
11
  # Note that we only go forward, no back-references are done here.
12
12
  def Forward(output, target_color)
13
13
  ->(sequence, me) do
14
- target_seq_row = find_in_range(sequence[sequence.index(me)+1..-1], target_color)
14
+ target_seq_row = find_in_range(sequence[sequence.index(me) + 1..-1], target_color)
15
15
 
16
16
  return output, target_seq_row
17
17
  end
@@ -23,7 +23,7 @@ class Trailblazer::Activity
23
23
  ->(sequence, me) do
24
24
  my_index = sequence.index(me)
25
25
  # First, try all elements after me, then go through the elements preceding myself.
26
- wrapped_range = sequence[my_index+1..-1] + sequence[0..my_index-1]
26
+ wrapped_range = sequence[my_index + 1..-1] + sequence[0..my_index - 1]
27
27
 
28
28
  target_seq_row = find_in_range(wrapped_range, target_color)
29
29
 
@@ -31,12 +31,6 @@ class Trailblazer::Activity
31
31
  end
32
32
  end
33
33
 
34
- def Noop(output)
35
- ->(sequence, me) do
36
- return output, [nil,nil,nil,{}] # FIXME
37
- end
38
- end
39
-
40
34
  # Find the seq_row with {id} and connect the current node to it.
41
35
  def ById(output, id)
42
36
  ->(sequence, me) do
@@ -28,10 +28,15 @@ module Trailblazer
28
28
  end
29
29
 
30
30
  # @public
31
- # We forward `step` to the Dsl (State) object.
32
- # Recompiling the activity/sequence is a matter specific to Strategy (Railway etc).
33
- def step(*args, &block); recompile_activity_for(:step, *args, &block); end
34
- def terminus(*args); recompile_activity_for(:terminus, *args); end
31
+ # We forward `step` to the Dsl (State) object.
32
+ # Recompiling the activity/sequence is a matter specific to Strategy (Railway etc).
33
+ def step(*args, &block)
34
+ recompile_activity_for(:step, *args, &block)
35
+ end
36
+
37
+ def terminus(*args)
38
+ recompile_activity_for(:terminus, *args)
39
+ end
35
40
 
36
41
  private def recompile_activity_for(type, *args, &block)
37
42
  sequence = apply_step_on_sequence_builder(type, *args, &block)
@@ -41,16 +46,14 @@ module Trailblazer
41
46
 
42
47
  # TODO: make {rescue} optional, only in dev mode.
43
48
  # @return Sequence
44
- private def apply_step_on_sequence_builder(type, arg, options={}, &block)
45
- return Sequence::Builder.(type, arg, options,
49
+ private def apply_step_on_sequence_builder(type, arg, options = {}, &block)
50
+ Sequence::Builder.(type, arg, options,
46
51
  sequence: @state.get(:sequence),
47
52
  normalizers: @state.get(:normalizers),
48
53
 
49
54
  normalizer_options: @state.get(:normalizer_options),
50
55
 
51
- &block
52
- )
53
-
56
+ &block)
54
57
  rescue Activity::Adds::IndexError
55
58
  # re-raise this exception with activity class prepended
56
59
  # to the message this time.
@@ -90,7 +93,7 @@ module Trailblazer
90
93
 
91
94
  activity.to_h.to_h.merge(
92
95
  activity: activity,
93
- sequence: @state.get(:sequence),
96
+ sequence: @state.get(:sequence)
94
97
  )
95
98
  end
96
99
 
@@ -105,8 +108,8 @@ module Trailblazer
105
108
  )
106
109
  end
107
110
 
108
- def invoke(*args)
109
- TaskWrap.invoke(self, *args)
111
+ def invoke(*args, **kws)
112
+ TaskWrap.invoke(self, *args, **kws)
110
113
  end
111
114
  end # class << self
112
115
  # FIXME: do we want class << self?!
@@ -124,7 +127,7 @@ module Trailblazer
124
127
  Class.new(strategy) do
125
128
  compile_strategy!(strategy::DSL, normalizers: @state.get(:normalizers), **options)
126
129
 
127
- class_exec(&block) if block_given?
130
+ class_exec(&block) if block
128
131
  end
129
132
  end
130
133
 
@@ -153,7 +156,7 @@ module Trailblazer
153
156
  sequence = append_terminus(sequence, task, **options_for_append_terminus, **terminus_options)
154
157
  end
155
158
 
156
- return sequence
159
+ sequence
157
160
  end
158
161
 
159
162
  def append_terminus(sequence, task, normalizers:, **options)
@@ -167,7 +170,6 @@ module Trailblazer
167
170
  end
168
171
  end # DSL
169
172
 
170
-
171
173
  # FIXME: move to State#dup
172
174
  def self.copy(value, **) # DISCUSS: should that be here?
173
175
  value.copy
@@ -195,5 +197,3 @@ module Trailblazer
195
197
  end
196
198
  end
197
199
  end
198
-
199
-
@@ -3,7 +3,7 @@ module Trailblazer
3
3
  module Activity
4
4
  module DSL
5
5
  module Linear
6
- VERSION = "1.1.0"
6
+ VERSION = "1.2.0"
7
7
  end
8
8
  end
9
9
  end
@@ -16,6 +16,15 @@ class Trailblazer::Activity
16
16
  Trailblazer::Activity::Adds::Insert.method(name)
17
17
  end
18
18
  end
19
+
20
+ module Deprecate
21
+ # Used in combination with `Activity::Deprecate.warn`. Guesses the location
22
+ # of the method call from the stacktrace.
23
+ def self.dsl_caller_location
24
+ caller_index = caller_locations.find_index { |location| location.to_s =~ /recompile_activity_for/ }
25
+ caller_index ? caller_locations[caller_index + 2] : caller_locations[0]
26
+ end
27
+ end
19
28
  end # Linear
20
29
  end
21
30
  end
@@ -24,6 +33,9 @@ require "trailblazer/activity/dsl/linear/sequence"
24
33
  require "trailblazer/activity/dsl/linear/sequence/builder"
25
34
  require "trailblazer/activity/dsl/linear/sequence/search"
26
35
  require "trailblazer/activity/dsl/linear/sequence/compiler"
36
+ require "trailblazer/activity/dsl/linear/normalizer/inherit" # DISCUSS. should we add normalizer/options/... or something?
37
+ require "trailblazer/activity/dsl/linear/normalizer/extensions"
38
+ require "trailblazer/activity/dsl/linear/normalizer/output_tuples"
27
39
  require "trailblazer/activity/dsl/linear/normalizer"
28
40
  require "trailblazer/activity/dsl/linear/normalizer/terminus"
29
41
  require "trailblazer/activity/dsl/linear/helper"
@@ -36,7 +48,6 @@ require "trailblazer/activity/dsl/linear/feature/variable_mapping"
36
48
  require "trailblazer/activity/dsl/linear/feature/variable_mapping/dsl"
37
49
  require "trailblazer/activity/dsl/linear/feature/variable_mapping/runtime"
38
50
  require "trailblazer/activity/dsl/linear/feature/patch"
39
- require "trailblazer/activity/dsl/linear/feature/variable_mapping/inherit"
40
51
 
41
52
  # feature/variable_mapping
42
53
  Trailblazer::Activity::DSL::Linear::VariableMapping.extend!(Trailblazer::Activity::Path, :step)