-
Notifications
You must be signed in to change notification settings - Fork 72
/
Copy pathloop.lua
86 lines (81 loc) · 1.92 KB
/
loop.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
local parser = require("overseer.parser")
local util = require("overseer.parser.util")
local Loop = {
desc = "A decorator that repeats the child",
doc_args = {
{
name = "opts",
type = "object",
desc = "Configuration options",
position_optional = true,
fields = {
{
name = "ignore_failure",
type = "boolean",
desc = "Keep looping even when the child fails",
default = false,
},
{
name = "repetitions",
type = "integer",
desc = "When set, loop a set number of times then return SUCCESS",
},
},
},
{
name = "child",
type = "parser",
desc = "The child parser node",
},
},
}
local MAX_LOOP = 2
function Loop.new(opts, child)
if child == nil then
child = opts
opts = {}
end
vim.validate({
ignore_failure = { opts.ignore_failure, "b", true },
repetitions = { opts.repetitions, "n", true },
})
return setmetatable({
ignore_failure = opts.ignore_failure,
repetitions = opts.repetitions,
count = 0,
done = nil,
child = util.hydrate(child),
}, { __index = Loop })
end
function Loop:reset()
self.count = 0
self.done = nil
self.child:reset()
end
function Loop:ingest(...)
if self.done then
return self.done
end
local loop_count = 0
local st
repeat
if self.repetitions and self.count >= self.repetitions then
return parser.STATUS.SUCCESS
end
st = self.child:ingest(...)
if st == parser.STATUS.SUCCESS then
self.child:reset()
self.count = self.count + 1
elseif st == parser.STATUS.FAILURE then
self.child:reset()
self.count = self.count + 1
if not self.ignore_failure then
self.done = st
return st
end
end
loop_count = loop_count + 1
until st == parser.STATUS.RUNNING or loop_count >= MAX_LOOP
return parser.STATUS.RUNNING
end
return Loop