You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
3.8 KiB
Lua
105 lines
3.8 KiB
Lua
--- Module for representing a command internally in a 'declarative' way
|
|
-- @module lqc.fsm.command
|
|
-- @alias command
|
|
local Gen = require 'lqc.generator'
|
|
local random = require 'lqc.random'
|
|
local deep_copy = require 'lqc.helpers.deep_copy'
|
|
|
|
--- Returns a string representation of the command.
|
|
-- @param cmd Command to transform into a string
|
|
-- @return string representation of the command
|
|
local function stringify(cmd)
|
|
local result = {'{ call, ', cmd.state_name}
|
|
|
|
local size_result = #result
|
|
for i = 1, #cmd.args do
|
|
-- TODO allow printing of table etc..
|
|
result[i + size_result] = ', ' .. cmd.args[i]
|
|
end
|
|
|
|
result[#result + 1] = ' }'
|
|
return table.concat(result)
|
|
end
|
|
|
|
--- Creates a function that picks a random value for each of the generators
|
|
-- specified in the argument list.
|
|
-- @param state_name Name of the state this command is associated with
|
|
-- @param command_func Function to be called when this command is selected
|
|
-- @param args_generators List of generators that generate the arguments for command_func
|
|
-- @return table with keys { state_name, func, args }
|
|
local function pick(state_name, command_func, args_generators)
|
|
local function do_pick(num_tests)
|
|
local args = {}
|
|
for i = 1, #args_generators do
|
|
args[i] = args_generators[i]:pick(num_tests)
|
|
end
|
|
return {
|
|
state_name = state_name,
|
|
func = command_func,
|
|
args = args,
|
|
to_string = stringify,
|
|
}
|
|
end
|
|
return do_pick
|
|
end
|
|
|
|
--- Does the actual shrinking of the args
|
|
-- Randomly picks 1 of the arguments and shrinks it, rest stays the same
|
|
-- @param prev_args Previously generated args for the command
|
|
-- @param args_generators Generators used to generate and shrink the args
|
|
-- @return shrunk down argument list
|
|
local function shrink_args(prev_args, args_generators)
|
|
local idx = random.between(1, #prev_args)
|
|
local shrunk_arg = args_generators[idx]:shrink(prev_args[idx])
|
|
local args_copy = deep_copy(prev_args)
|
|
args_copy[idx] = shrunk_arg
|
|
return args_copy
|
|
end
|
|
|
|
--- Shrinks the command to a simpler form.
|
|
-- Only args are shrunk, state_name and func are unmodified.
|
|
-- @param state_name Name of the state this command is associated with
|
|
-- @param command_func Function to be called when this command is selected
|
|
-- @param args_generators Generators used to generate and shrink the args
|
|
-- @return function that does the actual shrinking for this command
|
|
local function shrink(state_name, command_func, args_generators)
|
|
local function do_shrink(previous)
|
|
if #previous.args == 0 then
|
|
return previous
|
|
end
|
|
return {
|
|
state_name = state_name,
|
|
func = command_func,
|
|
args = shrink_args(previous.args, args_generators),
|
|
to_string = stringify,
|
|
}
|
|
end
|
|
return do_shrink
|
|
end
|
|
|
|
--- Creates a new command generator with a state_name, command function
|
|
-- and a list of generators (args will be passed into the command_func in the FSM)
|
|
-- @param state_name Name of the state this command is associated with
|
|
-- @param command_func Function to be called when this command is selected
|
|
-- @param args_generators Generators used to generate and shrink the args
|
|
-- @return generator for randomly creating a command
|
|
local function new(state_name, command_func, args_generators)
|
|
local generator = Gen.new(pick(state_name, command_func, args_generators),
|
|
shrink(state_name, command_func, args_generators))
|
|
generator.state_name = state_name
|
|
return generator
|
|
end
|
|
|
|
local command = {}
|
|
local command_mt = {
|
|
__call = function(_, command_tbl)
|
|
return new(command_tbl[1], command_tbl[2], command_tbl[3])
|
|
end,
|
|
}
|
|
|
|
command.stop = new('stop', function()
|
|
end, {})
|
|
|
|
return setmetatable(command, command_mt)
|
|
|