trailblazer-activity-dsl-linear 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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)