summaryrefslogtreecommitdiff
path: root/lua/clever_f
diff options
context:
space:
mode:
Diffstat (limited to 'lua/clever_f')
-rw-r--r--lua/clever_f/sequence_coordinator.lua60
1 files changed, 57 insertions, 3 deletions
diff --git a/lua/clever_f/sequence_coordinator.lua b/lua/clever_f/sequence_coordinator.lua
index 5a05f53..ee50fbd 100644
--- a/lua/clever_f/sequence_coordinator.lua
+++ b/lua/clever_f/sequence_coordinator.lua
@@ -1,6 +1,7 @@
local acquisition_service_factory = require("clever_f.acquisition_service")
local domain = require("clever_f.domain")
local feedback_service_factory = require("clever_f.feedback_service")
+local motion_executor_factory = require("clever_f.motion_executor")
local motion_plan_factory = require("clever_f.motion_plan")
local policy = require("clever_f.policy")
local repeat_resolver_factory = require("clever_f.repeat_resolver")
@@ -100,6 +101,17 @@ function SequenceCoordinator.new(options)
if type(acquisition) ~= "table" or type(acquisition.acquire) ~= "function" then
fail("SequenceCoordinator acquisition service must provide acquire", 2)
end
+ local executor = options.motion_executor
+ or options.executor
+ or motion_executor_factory.new({
+ host = host,
+ state = state,
+ transitions = transitions,
+ feedback = feedback,
+ })
+ if type(executor) ~= "table" or type(executor.execute) ~= "function" then
+ fail("SequenceCoordinator motion executor must provide execute", 2)
+ end
local coordinator = setmetatable({}, SequenceCoordinator)
coordinator_records[coordinator] = {
@@ -112,6 +124,8 @@ function SequenceCoordinator.new(options)
target_factory = target_factory,
motion_factory = motion_factory,
acquisition = acquisition,
+ motion_executor = executor,
+ last_primary_resolution = nil,
}
return coordinator
end
@@ -410,6 +424,36 @@ function SequenceCoordinator:stored_primary_resolution(
return resolution
end
+function SequenceCoordinator:execute_primary_resolution(resolution)
+ if type(resolution) ~= "table"
+ or not domain.ModeContext.is(resolution.invocation.context)
+ or not domain.ResolvedMotionPlan.is(resolution.motion_plan)
+ then
+ fail("primary execution requires a resolved motion", 2)
+ end
+ local record = coordinator_records[self]
+ record.last_primary_resolution = resolution
+ if resolution.skip_destination then
+ return domain.ActionOutcome.empty(resolution.invocation.position)
+ end
+ local view = resolution.text_view or text_topology.from_host(record.host)
+ local outcome = record.motion_executor:execute(
+ view,
+ resolution.invocation.context,
+ resolution.motion_plan,
+ resolution.invocation.count,
+ resolution.first_move
+ )
+ if not domain.ActionOutcome.is(outcome) then
+ fail("MotionExecutor must return an ActionOutcome", 2)
+ end
+ return outcome
+end
+
+function SequenceCoordinator:last_primary_resolution()
+ return coordinator_records[self].last_primary_resolution
+end
+
function SequenceCoordinator:primary(value)
local descriptor = self:validate_primary_descriptor(value)
local invocation = self:read_primary_invocation()
@@ -420,7 +464,11 @@ function SequenceCoordinator:primary(value)
)
invocation.repeat_decision = self:decide_primary(invocation)
if invocation.repeat_decision == repeat_resolver_factory.Decision.ACQUIRE then
- return self:resolve_acquisition(descriptor, invocation)
+ local acquired = self:resolve_acquisition(descriptor, invocation)
+ if domain.ActionOutcome.is(acquired) then
+ return acquired
+ end
+ return self:execute_primary_resolution(acquired)
end
local timeout = self:evaluate_repeat_timeout(invocation)
if timeout.decision == repeat_resolver_factory.Decision.ACQUIRE then
@@ -431,9 +479,15 @@ function SequenceCoordinator:primary(value)
end
record.feedback:release_transition_cleanup(timeout.cleanup)
end
- return self:resolve_acquisition(descriptor, invocation)
+ local acquired = self:resolve_acquisition(descriptor, invocation)
+ if domain.ActionOutcome.is(acquired) then
+ return acquired
+ end
+ return self:execute_primary_resolution(acquired)
end
- return self:stored_primary_resolution(invocation, descriptor, timeout)
+ return self:execute_primary_resolution(
+ self:stored_primary_resolution(invocation, descriptor, timeout)
+ )
end
function M.new(options)