flor 0.15.0 → 0.16.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +14 -1
- data/CREDITS.md +1 -0
- data/LICENSE.txt +1 -1
- data/Makefile +6 -2
- data/README.md +2 -1
- data/flor.gemspec +12 -2
- data/lib/flor.rb +3 -3
- data/lib/flor/colours.rb +1 -1
- data/lib/flor/conf.rb +3 -4
- data/lib/flor/core/executor.rb +31 -61
- data/lib/flor/core/node.rb +213 -96
- data/lib/flor/core/procedure.rb +194 -75
- data/lib/flor/core/texecutor.rb +6 -7
- data/lib/flor/djan.rb +41 -22
- data/lib/flor/flor.rb +137 -42
- data/lib/flor/id.rb +77 -59
- data/lib/flor/log.rb +43 -22
- data/lib/flor/migrations/0001_tables.rb +7 -7
- data/lib/flor/parser.rb +271 -74
- data/lib/flor/pcore/_apply.rb +108 -0
- data/lib/flor/pcore/_atom.rb +2 -4
- data/lib/flor/pcore/_att.rb +54 -37
- data/lib/flor/pcore/_dmute.rb +18 -0
- data/lib/flor/pcore/_dol.rb +17 -0
- data/lib/flor/pcore/_dqs.rb +35 -0
- data/lib/flor/pcore/_head.rb +25 -0
- data/lib/flor/pcore/_obj.rb +1 -3
- data/lib/flor/pcore/_pat_guard.rb +1 -1
- data/lib/flor/pcore/_pat_obj.rb +11 -3
- data/lib/flor/pcore/_pat_regex.rb +16 -2
- data/lib/flor/pcore/_ref.rb +51 -0
- data/lib/flor/pcore/_rxs.rb +27 -0
- data/lib/flor/pcore/_val.rb +11 -6
- data/lib/flor/pcore/{logo.rb → andor.rb} +4 -6
- data/lib/flor/pcore/apply.rb +72 -2
- data/lib/flor/pcore/arith.rb +16 -4
- data/lib/flor/pcore/array_qmark.rb +100 -0
- data/lib/flor/pcore/break.rb +1 -2
- data/lib/flor/pcore/case.rb +1 -1
- data/lib/flor/pcore/cmp.rb +3 -2
- data/lib/flor/pcore/collect.rb +2 -2
- data/lib/flor/pcore/cond.rb +19 -1
- data/lib/flor/pcore/cursor.rb +12 -11
- data/lib/flor/pcore/define.rb +30 -4
- data/lib/flor/pcore/do_return.rb +3 -0
- data/lib/flor/pcore/flatten.rb +39 -0
- data/lib/flor/pcore/if.rb +15 -5
- data/lib/flor/pcore/includes.rb +5 -2
- data/lib/flor/pcore/inject.rb +1 -1
- data/lib/flor/pcore/iterator.rb +28 -18
- data/lib/flor/pcore/keys.rb +2 -2
- data/lib/flor/pcore/map.rb +19 -1
- data/lib/flor/pcore/match.rb +2 -2
- data/lib/flor/pcore/matchr.rb +18 -5
- data/lib/flor/pcore/max.rb +51 -0
- data/lib/flor/pcore/merge.rb +134 -0
- data/lib/flor/pcore/move.rb +1 -1
- data/lib/flor/pcore/noret.rb +1 -1
- data/lib/flor/pcore/not.rb +15 -1
- data/lib/flor/pcore/on.rb +11 -0
- data/lib/flor/pcore/on_cancel.rb +5 -1
- data/lib/flor/pcore/on_error.rb +69 -4
- data/lib/flor/pcore/push.rb +4 -9
- data/lib/flor/pcore/range.rb +5 -5
- data/lib/flor/pcore/reduce.rb +5 -18
- data/lib/flor/pcore/return.rb +26 -0
- data/lib/flor/pcore/reverse.rb +4 -0
- data/lib/flor/pcore/sequence.rb +8 -1
- data/lib/flor/pcore/set.rb +74 -15
- data/lib/flor/pcore/shuffle.rb +71 -0
- data/lib/flor/pcore/slice.rb +137 -0
- data/lib/flor/pcore/sort.rb +244 -0
- data/lib/flor/pcore/sort_by.rb +67 -0
- data/lib/flor/pcore/split.rb +39 -0
- data/lib/flor/pcore/stall.rb +1 -1
- data/lib/flor/pcore/strings.rb +123 -0
- data/lib/flor/pcore/timestamp.rb +34 -0
- data/lib/flor/pcore/to_array.rb +2 -3
- data/lib/flor/pcore/twig.rb +1 -1
- data/lib/flor/pcore/type_of.rb +37 -0
- data/lib/flor/pcore/until.rb +3 -3
- data/lib/flor/punit/cancel.rb +3 -3
- data/lib/flor/punit/ccollect.rb +29 -0
- data/lib/flor/punit/cmap.rb +76 -20
- data/lib/flor/punit/concurrence.rb +440 -33
- data/lib/flor/punit/cron.rb +1 -1
- data/lib/flor/punit/every.rb +1 -1
- data/lib/flor/punit/graft.rb +2 -3
- data/lib/flor/punit/on_timeout.rb +5 -1
- data/lib/flor/punit/part.rb +63 -0
- data/lib/flor/punit/schedule.rb +1 -1
- data/lib/flor/punit/task.rb +52 -10
- data/lib/flor/punit/trap.rb +4 -5
- data/lib/flor/tools/shell.rb +37 -18
- data/lib/flor/unit/caller.rb +23 -11
- data/lib/flor/unit/executor.rb +33 -12
- data/lib/flor/unit/ganger.rb +10 -1
- data/lib/flor/unit/hook.rb +2 -1
- data/lib/flor/unit/hooker.rb +13 -2
- data/lib/flor/unit/loader.rb +7 -7
- data/lib/flor/unit/logger.rb +15 -17
- data/lib/flor/unit/models.rb +4 -2
- data/lib/flor/unit/models/execution.rb +83 -38
- data/lib/flor/unit/models/message.rb +16 -0
- data/lib/flor/unit/models/pointer.rb +24 -0
- data/lib/flor/unit/models/timer.rb +25 -4
- data/lib/flor/unit/models/trace.rb +14 -0
- data/lib/flor/unit/models/trap.rb +39 -14
- data/lib/flor/unit/scheduler.rb +11 -7
- data/lib/flor/unit/storage.rb +55 -39
- data/lib/flor/unit/taskers.rb +17 -14
- data/lib/flor/unit/waiter.rb +4 -3
- metadata +40 -10
- data/lib/flor/changes.rb +0 -26
- data/lib/flor/dollar.rb +0 -224
- data/lib/flor/unit/hooks.rb +0 -37
data/lib/flor/pcore/cursor.rb
CHANGED
@@ -57,16 +57,16 @@ class Flor::Pro::Cursor < Flor::Procedure
|
|
57
57
|
|
58
58
|
def receive_first
|
59
59
|
|
60
|
-
|
61
|
-
|
60
|
+
# break/continue/move are set as variables so that they can
|
61
|
+
# be aliases, it's useful in nested loops
|
62
62
|
|
63
|
-
@node['vars']
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
63
|
+
@node['vars'] = {
|
64
|
+
'break' =>
|
65
|
+
[ '_proc', { 'proc' => 'break', 'nid' => nid }, tree[-1] ],
|
66
|
+
'continue' =>
|
67
|
+
[ '_proc', { 'proc' => 'continue', 'nid' => nid }, tree[-1] ],
|
68
|
+
'move' =>
|
69
|
+
[ '_proc', { 'proc' => 'move', 'nid' => nid }, tree[-1] ] }
|
70
70
|
|
71
71
|
super
|
72
72
|
end
|
@@ -92,7 +92,8 @@ class Flor::Pro::Cursor < Flor::Procedure
|
|
92
92
|
|
93
93
|
def cancel_when_closed
|
94
94
|
|
95
|
-
return
|
95
|
+
return cancel if node_status_flavour == 'on-error'
|
96
|
+
return [] if @message['flavour'] != 'break'
|
96
97
|
|
97
98
|
cancel
|
98
99
|
end
|
@@ -117,7 +118,7 @@ class Flor::Pro::Cursor < Flor::Procedure
|
|
117
118
|
@node['on_receive_last'] = nil
|
118
119
|
end
|
119
120
|
|
120
|
-
super
|
121
|
+
super
|
121
122
|
end
|
122
123
|
|
123
124
|
protected
|
data/lib/flor/pcore/define.rb
CHANGED
@@ -32,6 +32,10 @@ class Flor::Pro::Define < Flor::Procedure
|
|
32
32
|
# define "$(prefix)-sum" a b
|
33
33
|
# + a b
|
34
34
|
# ```
|
35
|
+
#
|
36
|
+
# ## see also
|
37
|
+
#
|
38
|
+
# apply.
|
35
39
|
|
36
40
|
names %w[ def fun define ]
|
37
41
|
|
@@ -46,7 +50,7 @@ class Flor::Pro::Define < Flor::Procedure
|
|
46
50
|
|
47
51
|
def receive_att
|
48
52
|
|
49
|
-
t =
|
53
|
+
t = flatten_tree
|
50
54
|
cnode = lookup_var_node(@node, 'l')
|
51
55
|
cnid = cnode['nid']
|
52
56
|
fun = counter_next('funs') - 1
|
@@ -58,7 +62,7 @@ class Flor::Pro::Define < Flor::Procedure
|
|
58
62
|
{ 'nid' => nid, 'tree' => t, 'cnid' => cnid, 'fun' => fun },
|
59
63
|
t[2] ]
|
60
64
|
|
61
|
-
if
|
65
|
+
if heap == 'define'
|
62
66
|
name =
|
63
67
|
if @message['point'] == 'execute'
|
64
68
|
t[1].first[1].first[0]
|
@@ -68,9 +72,31 @@ class Flor::Pro::Define < Flor::Procedure
|
|
68
72
|
set_var('', name, val)
|
69
73
|
end
|
70
74
|
|
71
|
-
|
75
|
+
wrap('ret' => val)
|
76
|
+
end
|
77
|
+
|
78
|
+
protected
|
79
|
+
|
80
|
+
def flatten_tree
|
81
|
+
|
82
|
+
off = heap == 'define' ? 1 : 0
|
83
|
+
sig = tree[1][off..-1].select { |t| t[0] == '_att' }
|
84
|
+
|
85
|
+
return tree if sig.all? { |a| a[1][0][1] == [] }
|
86
|
+
|
87
|
+
# There is a parenthese around the parameters, let's unwrap that...
|
88
|
+
|
89
|
+
hed = Flor.dup(tree[1][0, off])
|
90
|
+
sig = Flor.dup(sig)
|
91
|
+
bdy = Flor.dup(tree[1][(off + sig.length)..-1])
|
92
|
+
|
93
|
+
att0 = sig[0][1][0]
|
94
|
+
att0atts = att0[1]
|
95
|
+
att0[1] = []
|
96
|
+
|
97
|
+
sig = sig + att0atts
|
72
98
|
|
73
|
-
|
99
|
+
[ heap, hed + sig + bdy, *tree[2..-1] ]
|
74
100
|
end
|
75
101
|
end
|
76
102
|
|
data/lib/flor/pcore/do_return.rb
CHANGED
@@ -0,0 +1,39 @@
|
|
1
|
+
|
2
|
+
class Flor::Pro::Flatten < Flor::Procedure
|
3
|
+
#
|
4
|
+
# Flattens the given array
|
5
|
+
#
|
6
|
+
# ```
|
7
|
+
# flatten [ 1, [ 2, [ 3 ], 4 ] ] # ==> [ 1, 2, 3, 4 ]
|
8
|
+
# flatten [ 1, [ 2, [ 3 ], 4 ] ], 1 # ==> [ 1, 2, [ 3 ], 4 ]
|
9
|
+
#
|
10
|
+
# [ 1, [ 2, [ 3 ], 4 ] ]
|
11
|
+
# flatten 1 # ==> [ 1, 2, [ 3 ], 4 ]
|
12
|
+
#
|
13
|
+
# [ 1, [ 2, [ 3 ], 4 ] ]
|
14
|
+
# flatten _ # ==> [ 1, 2, 3, 4 ]
|
15
|
+
# ```
|
16
|
+
|
17
|
+
name 'flatten'
|
18
|
+
|
19
|
+
def pre_execute
|
20
|
+
|
21
|
+
@node['rets'] = []
|
22
|
+
|
23
|
+
unatt_unkeyed_children
|
24
|
+
end
|
25
|
+
|
26
|
+
def receive_last
|
27
|
+
|
28
|
+
col = (@node['rets'] + [ node_payload_ret ])
|
29
|
+
.find { |r| r.is_a?(Array) }
|
30
|
+
|
31
|
+
lvl = @node['rets']
|
32
|
+
.find { |r| r.is_a?(Integer) } || -1
|
33
|
+
|
34
|
+
fail Flor::FlorError.new('missing collection', self) if col == nil
|
35
|
+
|
36
|
+
wrap('ret' => col.flatten(lvl))
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
data/lib/flor/pcore/if.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|
class Flor::Pro::If < Flor::Procedure
|
3
3
|
#
|
4
|
-
# The classical "if" (and its "unless"
|
4
|
+
# The classical "if" (and its "unless" sidekick)
|
5
5
|
#
|
6
6
|
# ```
|
7
7
|
# if
|
@@ -14,7 +14,7 @@ class Flor::Pro::If < Flor::Procedure
|
|
14
14
|
# set f.designation 'child'
|
15
15
|
# sequence # else
|
16
16
|
# set f.designation 'baby'
|
17
|
-
# order_baby_food
|
17
|
+
# order_baby_food _
|
18
18
|
# ```
|
19
19
|
#
|
20
20
|
# Warning, the direct children are relevant. In the following snip,
|
@@ -22,7 +22,7 @@ class Flor::Pro::If < Flor::Procedure
|
|
22
22
|
# ```
|
23
23
|
# if (f.age > 3)
|
24
24
|
# set f.designation 'child'
|
25
|
-
# order_child_seat
|
25
|
+
# order_child_seat _
|
26
26
|
# ```
|
27
27
|
#
|
28
28
|
# ## postfix `if` and `unless`
|
@@ -37,8 +37,17 @@ class Flor::Pro::If < Flor::Procedure
|
|
37
37
|
# a > b
|
38
38
|
# task 'bob'
|
39
39
|
# ```
|
40
|
+
#
|
41
|
+
# ## else-if
|
42
|
+
#
|
43
|
+
# Currently, if an "else if" is needed, it's better to use [cond](cond.md).
|
44
|
+
#
|
45
|
+
#
|
46
|
+
# ## see also
|
47
|
+
#
|
48
|
+
# Cond, case, match.
|
40
49
|
|
41
|
-
names %w[ if unless ife unlesse ]
|
50
|
+
names %w[ if unless ife unlesse _if _unless ]
|
42
51
|
#
|
43
52
|
# removing "ife" and "unlesse" leads to
|
44
53
|
# LoadError: cannot load such file -- sequel/adapters/
|
@@ -56,7 +65,8 @@ class Flor::Pro::If < Flor::Procedure
|
|
56
65
|
# "else" or "then" answered, replying to parent...
|
57
66
|
|
58
67
|
off =
|
59
|
-
|
68
|
+
case heap
|
69
|
+
when 'unless', 'unlesse', '_unless'
|
60
70
|
Flor.false?(payload['ret']) ? 1 : 2
|
61
71
|
else # 'if' or 'ife'
|
62
72
|
Flor.true?(payload['ret']) ? 1 : 2
|
data/lib/flor/pcore/includes.rb
CHANGED
@@ -16,17 +16,20 @@ class Flor::Pro::Includes < Flor::Procedure
|
|
16
16
|
elt = :nil
|
17
17
|
|
18
18
|
@node['rets'].each do |ret|
|
19
|
-
if col == nil &&
|
19
|
+
if col == nil && Flor.is_collection?(ret)
|
20
20
|
col = ret
|
21
21
|
elsif elt == :nil
|
22
22
|
elt = ret
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
+
ret = (col == nil) && node_payload_ret
|
27
|
+
col = ret if Flor.is_collection?(ret)
|
28
|
+
|
26
29
|
fail Flor::FlorError.new('missing collection', self) if col == nil
|
27
30
|
fail Flor::FlorError.new('missing element', self) if elt == :nil
|
28
31
|
|
29
|
-
|
32
|
+
wrap('ret' => col.include?(elt))
|
30
33
|
end
|
31
34
|
end
|
32
35
|
|
data/lib/flor/pcore/inject.rb
CHANGED
@@ -4,7 +4,7 @@ require 'flor/pcore/iterator'
|
|
4
4
|
|
5
5
|
class Flor::Pro::Inject < Flor::Macro::Iterator
|
6
6
|
#
|
7
|
-
#
|
7
|
+
# A simplified version of [reduce](reduce.md).
|
8
8
|
#
|
9
9
|
# Inject takes a collection and a block. It reduces the collection
|
10
10
|
# to a single result thanks to the block.
|
data/lib/flor/pcore/iterator.rb
CHANGED
@@ -66,21 +66,20 @@ class Flor::Pro::Iterator < Flor::Procedure
|
|
66
66
|
.each { |a|
|
67
67
|
if Flor.is_func_tree?(a)
|
68
68
|
@node['fun'] ||= a
|
69
|
-
elsif
|
69
|
+
elsif Flor.is_collection?(a)
|
70
70
|
@node['ocol'] ||= a
|
71
71
|
end }
|
72
72
|
|
73
|
-
@node['ocol'] ||= node_payload_ret
|
74
|
-
ocol = @node['ocol']
|
73
|
+
ocol = (@node['ocol'] ||= node_payload_ret)
|
75
74
|
|
76
75
|
fail Flor::FlorError.new(
|
77
76
|
"function not given to #{heap.inspect}", self
|
78
77
|
) if function_mandatory? && ( ! @node['fun'])
|
79
78
|
fail Flor::FlorError.new(
|
80
79
|
"collection not given to #{heap.inspect}", self
|
81
|
-
) unless
|
80
|
+
) unless Flor.is_collection?(ocol)
|
82
81
|
|
83
|
-
@node['col'] = Flor.to_coll(
|
82
|
+
@node['col'] = Flor.to_coll(ocol) if @node['fun']
|
84
83
|
@node['args'] = nil
|
85
84
|
end
|
86
85
|
|
@@ -91,25 +90,31 @@ class Flor::Pro::Iterator < Flor::Procedure
|
|
91
90
|
|
92
91
|
def apply_iteration
|
93
92
|
|
94
|
-
vars = determine_iteration_vars
|
93
|
+
#vars = determine_iteration_vars
|
94
|
+
#args = vars.values
|
95
|
+
#vars.each { |k, v| @node['vars'][k] = v }
|
96
|
+
#
|
97
|
+
#apply(@node['fun'], args, tree[2])
|
95
98
|
|
96
|
-
|
97
|
-
vars.each { |k, v| @node['vars'][k] = v }
|
98
|
-
|
99
|
-
apply(@node['fun'], args, tree[2])
|
99
|
+
apply(@node['fun'], determine_iteration_args, tree[2])
|
100
100
|
end
|
101
101
|
|
102
|
-
def
|
102
|
+
def determine_iteration_args
|
103
103
|
|
104
104
|
idx = @node['idx']
|
105
105
|
elt = @node['col'][idx]
|
106
106
|
len = @node['col'].length
|
107
107
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
108
|
+
args =
|
109
|
+
if @node['ocol'].is_a?(Array)
|
110
|
+
[ [ 'elt', elt ] ]
|
111
|
+
else
|
112
|
+
[ [ 'key', elt[0] ], [ 'val', elt[1] ] ]
|
113
|
+
end
|
114
|
+
args << [ 'idx', idx ]
|
115
|
+
args << [ 'len', len ]
|
116
|
+
|
117
|
+
args
|
113
118
|
end
|
114
119
|
|
115
120
|
def iterator_over?
|
@@ -138,8 +143,13 @@ class Flor::Macro::Iterator < Flor::Macro
|
|
138
143
|
if non_att_children.any?
|
139
144
|
|
140
145
|
td = [ 'def', [], l ]
|
141
|
-
|
142
|
-
td[1] << [ '_att', [ [ '
|
146
|
+
|
147
|
+
#td[1] << [ '_att', [ [ 'res', [], l ] ], l ] \
|
148
|
+
# if procedure_name == 'reduce'
|
149
|
+
#td[1] << [ '_att', [ [ 'elt', [], l ] ], l ]
|
150
|
+
#
|
151
|
+
# the "_apply" does that work now and it distinguishes elt vs key/val
|
152
|
+
|
143
153
|
non_att_children.each { |nac| td[1] << Flor.dup(nac) }
|
144
154
|
|
145
155
|
th[1] << td
|
data/lib/flor/pcore/keys.rb
CHANGED
@@ -27,7 +27,7 @@ class Flor::Pro::Keys < Flor::Procedure
|
|
27
27
|
#
|
28
28
|
# length
|
29
29
|
|
30
|
-
names %w
|
30
|
+
names %w[ keys values ]
|
31
31
|
|
32
32
|
def pre_execute
|
33
33
|
|
@@ -45,7 +45,7 @@ class Flor::Pro::Keys < Flor::Procedure
|
|
45
45
|
) if ret.nil?
|
46
46
|
fail Flor::FlorError.new(
|
47
47
|
"received argument of class #{ret.class}, no #{heap}", self
|
48
|
-
) unless
|
48
|
+
) unless Flor.is_collection?(ret)
|
49
49
|
|
50
50
|
r =
|
51
51
|
if ret.is_a?(Hash)
|
data/lib/flor/pcore/map.rb
CHANGED
@@ -63,9 +63,17 @@ class Flor::Pro::Map < Flor::Pro::Iterator
|
|
63
63
|
# The corresponding `key`, `val`, `idx` and `len` variables are also
|
64
64
|
# set in the closure for the function call.
|
65
65
|
#
|
66
|
+
# ## missing collection
|
67
|
+
#
|
68
|
+
# "map" fails if it is not given a collection.
|
69
|
+
#
|
70
|
+
# ## missing function
|
71
|
+
#
|
72
|
+
# "map" returns the collection as is if it is not given a function.
|
73
|
+
#
|
66
74
|
# ## see also
|
67
75
|
#
|
68
|
-
# Collect.
|
76
|
+
# Collect, cmap.
|
69
77
|
|
70
78
|
name 'map'
|
71
79
|
|
@@ -80,5 +88,15 @@ class Flor::Pro::Map < Flor::Pro::Iterator
|
|
80
88
|
|
81
89
|
@node['res']
|
82
90
|
end
|
91
|
+
|
92
|
+
def function_mandatory?
|
93
|
+
|
94
|
+
false
|
95
|
+
end
|
96
|
+
|
97
|
+
def no_iterate
|
98
|
+
|
99
|
+
wrap('ret' => @node['ocol'])
|
100
|
+
end
|
83
101
|
end
|
84
102
|
|
data/lib/flor/pcore/match.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|
class Flor::Pro::Match < Flor::Pro::Case
|
3
3
|
#
|
4
|
-
#
|
4
|
+
# A kind of "destructuring [case](case.md)".
|
5
5
|
#
|
6
6
|
# "match", like "case", matches its first argument or the incoming `f.ret`.
|
7
7
|
#
|
@@ -187,7 +187,7 @@ class Flor::Pro::Match < Flor::Pro::Case
|
|
187
187
|
#
|
188
188
|
# ## see also
|
189
189
|
#
|
190
|
-
# Case.
|
190
|
+
# Case, if, cond.
|
191
191
|
|
192
192
|
name 'match'
|
193
193
|
|
data/lib/flor/pcore/matchr.rb
CHANGED
@@ -9,6 +9,10 @@ class Flor::Pro::Matchr < Flor::Procedure
|
|
9
9
|
# `match? s r` will return true if string `s` matches regular expression `r`.
|
10
10
|
# It returns false else.
|
11
11
|
#
|
12
|
+
# `pmatch s r` will return false it it doesn't match, it will return the
|
13
|
+
# string matched else. If there is a capture group (parentheses) in the
|
14
|
+
# pattern, it will return its content instead of the whole match.
|
15
|
+
#
|
12
16
|
# ```
|
13
17
|
# matchr "alpha", /bravo/
|
14
18
|
# # yields an empty array []
|
@@ -42,8 +46,17 @@ class Flor::Pro::Matchr < Flor::Procedure
|
|
42
46
|
# match? (/black/)
|
43
47
|
# # => false
|
44
48
|
# ```
|
49
|
+
#
|
50
|
+
# ```
|
51
|
+
# # pmatch
|
52
|
+
# pmatch 'string', /^str/ # ==> 'str'
|
53
|
+
# pmatch 'string', /^str(.+)$/ # ==> 'ing'
|
54
|
+
# pmatch 'string', /^str(?:.+)$/ # ==> 'string'
|
55
|
+
# pmatch 'strogonoff', /^str(?:.{0,3})(.*)$/ # ==> 'noff'
|
56
|
+
# pmatch 'sutoringu', /^str/ # ==> ''
|
57
|
+
# ```
|
45
58
|
|
46
|
-
names %w[ matchr match? ]
|
59
|
+
names %w[ matchr match? pmatch ]
|
47
60
|
|
48
61
|
def pre_execute
|
49
62
|
|
@@ -57,10 +70,10 @@ class Flor::Pro::Matchr < Flor::Procedure
|
|
57
70
|
m = rex.match(str)
|
58
71
|
|
59
72
|
payload['ret'] =
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
73
|
+
case heap
|
74
|
+
when 'match?' then !! m
|
75
|
+
when 'pmatch' then (m && (m[1] || m[0])) || ''
|
76
|
+
else m ? m.to_a : []
|
64
77
|
end
|
65
78
|
|
66
79
|
wrap_reply
|
@@ -0,0 +1,51 @@
|
|
1
|
+
|
2
|
+
class Flor::Pro::Max < Flor::Procedure
|
3
|
+
|
4
|
+
names %w[ max min ]
|
5
|
+
|
6
|
+
def pre_execute
|
7
|
+
|
8
|
+
@node['atts'] = []
|
9
|
+
@node['ret'] ||= receive_payload_ret
|
10
|
+
|
11
|
+
unatt_unkeyed_children
|
12
|
+
end
|
13
|
+
|
14
|
+
def receive_payload_ret
|
15
|
+
|
16
|
+
case ret = payload['ret']
|
17
|
+
when Array then ret
|
18
|
+
when Hash then ret.values
|
19
|
+
else false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def receive_last
|
24
|
+
|
25
|
+
ret = @node['ret']
|
26
|
+
|
27
|
+
fail Flor::FlorError.new(
|
28
|
+
"found no argument that can #{@node['heap']}", self
|
29
|
+
) unless ret
|
30
|
+
|
31
|
+
lax = att('lax', 'loose') == true
|
32
|
+
types = ret.collect { |e| Flor.type(e) }
|
33
|
+
|
34
|
+
ret = ret.collect { |x| JSON.dump(x) } if lax && types != [ 'number' ]
|
35
|
+
|
36
|
+
r =
|
37
|
+
begin
|
38
|
+
ret.send(@node['heap'])
|
39
|
+
rescue
|
40
|
+
fail unless lax
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
res =
|
44
|
+
r ?
|
45
|
+
@node['ret'][ret.index { |e| e == r }] :
|
46
|
+
nil
|
47
|
+
|
48
|
+
wrap_reply('ret' => res)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|