class Core::Pipeline::Compiler
- public
-
Compiles a pipeline into evalable code.
Public Class Methods
compile(callable, object)
click to toggle source
- public
-
Compiles a callable pipeline in context of an object.
# File lib/core/pipeline/compiler.rb, line 14 def compile(callable, object) <<~CODE def call(object, ...) #{compile_call(callable, object)} rescue Core::Pipeline::Signals::Halted => error error.value end CODE end
Private Class Methods
build_finalized_actions(callable, object)
click to toggle source
# File lib/core/pipeline/compiler.rb, line 56 def build_finalized_actions(callable, object) ordered_actions(callable).reject { |action| callable.skipped.include?(action.name) }.map { |action| action.finalize(object) }.each_with_object({}) { |action, lookup| lookup[action.object_id] = action } end
compile_call(callable, object)
click to toggle source
# File lib/core/pipeline/compiler.rb, line 24 def compile_call(callable, object) compiled = +"" finalized_actions(callable, object).each_pair do |object_id, action| compiled << "begin; " compiled << case action when Symbol "object.#{action}(...); " else "@__finalized_actions[#{object_id}].call(...); " end compiled << "rescue Core::Pipeline::Signals::Rejected; end\n" end compiled end
finalized_actions(callable, object)
click to toggle source
# File lib/core/pipeline/compiler.rb, line 42 def finalized_actions(callable, object) validate_skipped_actions(callable) finalized_actions = build_finalized_actions(callable, object) callable.instance_variable_set(:@__finalized_actions, finalized_actions) end
ordered_actions(callable)
click to toggle source
# File lib/core/pipeline/compiler.rb, line 66 def ordered_actions(callable) return callable.actions if callable.actions.empty? marked = [] ordered = [] working = callable.actions.dup callable.actions.each do |action| unless action.before || action.after ordered << action working.delete(action) end end raise "pipeline cannot be finalized because all actions have dependencies" if ordered.empty? until working.empty? action = working[0] anchor_action_name = action.before || action.after anchor_action = ordered.find { |ordered_action| ordered_action.name == anchor_action_name } if anchor_action insertion_index = if action.before ordered.index(anchor_action) else ordered.index(anchor_action) + 1 end ordered.insert(insertion_index, action) working.delete(action) marked.delete(action) elsif working.find { |working_action| working_action.name == anchor_action_name } if marked.include?(action) raise "pipeline has one or more recursive dependencies" else marked << action working.delete(action) working << action end else raise "unknown action `#{anchor_action_name}`" end end ordered end
validate_skipped_actions(callable)
click to toggle source
# File lib/core/pipeline/compiler.rb, line 48 def validate_skipped_actions(callable) callable.skipped.each do |skipped| unless callable.actions.any? { |action| action.name == skipped } raise "cannot skip unknown action `#{skipped}`" end end end