Class: Mxrb::Semantic::Inliner
- Inherits:
-
Object
- Object
- Mxrb::Semantic::Inliner
- Defined in:
- lib/mxrb/semantic/inliner.rb
Overview
Inlines a called microflow back into its caller, replacing the call_microflow activity with the callee's activities.
Constant Summary collapse
- FLOW_KINDS =
%i[microflow nanoflow].freeze
Instance Method Summary collapse
-
#initialize(project) ⇒ Inliner
constructor
A new instance of Inliner.
- #plan(source_name, calling:) ⇒ Object
Constructor Details
#initialize(project) ⇒ Inliner
Returns a new instance of Inliner.
117 118 119 |
# File 'lib/mxrb/semantic/inliner.rb', line 117 def initialize(project) @project = project end |
Instance Method Details
#plan(source_name, calling:) ⇒ 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 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/mxrb/semantic/inliner.rb', line 123 def plan(source_name, calling:) source = resolve(source_name) raise ArgumentError, "#{source.qualified_name} is not a microflow or nanoflow" \ unless FLOW_KINDS.include?(source.kind) called = resolve(calling) raise ArgumentError, "#{called.qualified_name} is not a microflow or nanoflow" \ unless FLOW_KINDS.include?(called.kind) source_raw = @project.raw_unit(source.unit_id) source_doc = @project.parse_bson(source_raw) all_objects = normalize_all(parse_array(source_doc["ObjectCollection"]["Objects"])) all_flows = normalize_all(parse_array(source_doc["Flows"])) call_activity = all_objects.find do |obj| obj["$Type"] == "Microflows$ActionActivity" && obj.dig("Action", "MicroflowCall", "Microflow") == calling end raise ArgumentError, "no call to #{calling.inspect} found in #{source_name.inspect}" \ unless call_activity call_id = call_activity["$ID"] entry_flow = all_flows.find { _1["DestinationPointer"] == call_id } exit_flow = all_flows.find { _1["OriginPointer"] == call_id } raise ArgumentError, "cannot find entry flow for call activity" unless entry_flow raise ArgumentError, "cannot find exit flow for call activity" unless exit_flow called_raw = @project.raw_unit(called.unit_id) called_doc = @project.parse_bson(called_raw) called_objects = normalize_all(parse_array(called_doc["ObjectCollection"]["Objects"])) called_flows = normalize_all(parse_array(called_doc["Flows"])) start_event = called_objects.find { _1["$Type"] == "Microflows$StartEvent" } end_event = called_objects.find { _1["$Type"] == "Microflows$EndEvent" } raise ArgumentError, "#{calling.inspect} has no start event" unless start_event raise ArgumentError, "#{calling.inspect} has no end event" unless end_event start_id = start_event["$ID"] end_id = end_event["$ID"] inner_objects = called_objects.reject { [start_id, end_id].include?(_1["$ID"]) } raise ArgumentError, "#{calling.inspect} has no activities to inline" if inner_objects.empty? inner_flows = called_flows.reject do |f| [start_id, end_id].include?(f["OriginPointer"]) || [start_id, end_id].include?(f["DestinationPointer"]) end start_to_first = called_flows.find { _1["OriginPointer"] == start_id } last_to_end = called_flows.find { _1["DestinationPointer"] == end_id } raise ArgumentError, "cannot resolve first activity in #{calling.inspect}" unless start_to_first raise ArgumentError, "cannot resolve last activity in #{calling.inspect}" unless last_to_end # Synthesise entry/exit flows that point at the actual first/last inlined objects synthetic_entry = entry_flow.merge("DestinationPointer" => start_to_first["DestinationPointer"]) synthetic_exit = exit_flow.merge("OriginPointer" => last_to_end["OriginPointer"]) InlinePlan.new( project: @project, source: source, called_name: calling, call_id: call_id, inner_objects: inner_objects, inner_flows: inner_flows, entry_flow: synthetic_entry, exit_flow: synthetic_exit, source_doc: source_doc, source_raw: source_raw ) end |