1local set = require "util.set";
2
3local known_options = {
4	incremental = set.new { "mode", "threshold", "speed", "step_size" };
5	generational = set.new { "mode", "minor_threshold", "major_threshold" };
6};
7
8if _VERSION ~= "5.4" then
9	known_options.generational = nil;
10	known_options.incremental:remove("step_size");
11end
12
13local function configure(user, defaults)
14	local mode = user.mode or defaults.mode or "incremental";
15	if not known_options[mode] then
16		return nil, "GC mode not supported on ".._VERSION..": "..mode;
17	end
18
19	for k, v in pairs(user) do
20		if not known_options[mode]:contains(k) then
21			return nil, "Unknown GC parameter: "..k;
22		elseif k ~= "mode" and type(v) ~= "number" then
23			return nil, "parameter '"..k.."' should be a number";
24		end
25	end
26
27	if mode == "incremental" then
28		if _VERSION == "Lua 5.4" then
29			collectgarbage(mode,
30				user.threshold or defaults.threshold,
31				user.speed or defaults.speed,
32				user.step_size or defaults.step_size
33			);
34		else
35			collectgarbage("setpause", user.threshold or defaults.threshold);
36			collectgarbage("setstepmul", user.speed or defaults.speed);
37		end
38	elseif mode == "generational" then
39		collectgarbage(mode,
40			user.minor_threshold or defaults.minor_threshold,
41			user.major_threshold or defaults.major_threshold
42		);
43	end
44	return true;
45end
46
47return {
48	configure = configure;
49};
50