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
@@ -0,0 +1,134 @@
|
|
1
|
+
|
2
|
+
class Flor::Pro::Merge < Flor::Procedure
|
3
|
+
#
|
4
|
+
# Merges objects or arrays.
|
5
|
+
#
|
6
|
+
# With objects:
|
7
|
+
# ```
|
8
|
+
# merge {} # => {}
|
9
|
+
# merge { a: 0 } # => { 'a' => 0 }
|
10
|
+
# {}; merge _ # => {}
|
11
|
+
# { a: 0 }; merge _ # => { 'a' => 0 }
|
12
|
+
#
|
13
|
+
# merge { a: 0 b: 1 } { b: 'B' c: 'C' }
|
14
|
+
# # => { 'a' => 0, 'b' => 'B', 'c' => 'C' }
|
15
|
+
# merge { b: 'B' c: 'C' } { a: 0 b: 1 }
|
16
|
+
# # => { 'a' => 0, 'b' => 1, 'c' => 'C' },
|
17
|
+
# ```
|
18
|
+
#
|
19
|
+
# With arrays:
|
20
|
+
# ```
|
21
|
+
# merge [ 0 1 2 3 ] [ 'a' 'b' 'c' ]
|
22
|
+
# # => [ 'a', 'b', 'c', 3 ],
|
23
|
+
#
|
24
|
+
# merge [] # => []
|
25
|
+
# merge [ 0 1 2 ] # => [ 0, 1, 2 ]
|
26
|
+
# []; merge _ # => []
|
27
|
+
# [ 0 1 2 ]; merge _ # => [ 0, 1, 2 ]
|
28
|
+
# ```
|
29
|
+
#
|
30
|
+
# It determines if it has to deal with arrays or objects by looking at its
|
31
|
+
# first argument (not the incoming ret).
|
32
|
+
#
|
33
|
+
# It fails if the arguments are not all objects or not all arrays.
|
34
|
+
#
|
35
|
+
# If the attribute `lax:` (or `loose:`) is set to `true`, it doesn't care
|
36
|
+
# about non matching arguments and merges anyway:
|
37
|
+
# ```
|
38
|
+
# merge { a: 0 } { b: 1 } 'nada' { c: 2 } lax: true
|
39
|
+
# # => { 'a' => 0, 'b' => 1, 'c' => 2 }
|
40
|
+
# merge { a: 0 } { b: 1 } { c: 2 }
|
41
|
+
# # => { 'a' => 0, 'b' => 1, 'c' => 2 }
|
42
|
+
# merge { a: 0 } { b: 1 } 'nada' { c: 2 } tags: 'xxx' loose: true
|
43
|
+
# # => { 'a' => 0, 'b' => 1, 'c' => 2 }
|
44
|
+
# ```
|
45
|
+
#
|
46
|
+
# `strict: false` is OK as well:
|
47
|
+
# ```
|
48
|
+
# merge { a: 0 } { b: 1 } 'nada' { c: 2 } strict: false
|
49
|
+
# # => { 'a' => 0, 'b' => 1, 'c' => 2 }
|
50
|
+
# ```
|
51
|
+
#
|
52
|
+
# ## incoming ret
|
53
|
+
#
|
54
|
+
# "merge" only draws in the incoming ret if necessary. If there are
|
55
|
+
# enough arguments to perform a merge, the incoming ret will not be taken
|
56
|
+
# into account.
|
57
|
+
# You can add the incoming to the merge simply with `f.ret`.
|
58
|
+
#
|
59
|
+
# ```
|
60
|
+
# [ 0 1 2 ]; merge [ 0 1 'deux' 3 ] # => [ 0 1 'deux' 3 ]
|
61
|
+
# [ 0 1 2 3 4 ]; merge [ 0 1 2 3 ] [ 0 'un' 2 ] # => [ 0 'un' 2 3 ]
|
62
|
+
# [ 0 1 2 3 4 ]; merge f.ret [ 0 1 2 3 ] [ 0 'un' 2 ] # => [ 0 'un' 2 3 ]
|
63
|
+
# [ 0 1 2 3 4 ]; merge [ 0 1 2 3 ] [ 0 'un' 2 ] f.ret # => [ 0 1 2 3 4 ]
|
64
|
+
# [ 0 ]; merge { a: 1 } { a: 'one' } # => { a: 'one' }
|
65
|
+
# ```
|
66
|
+
#
|
67
|
+
# ## see also
|
68
|
+
#
|
69
|
+
# reverse, length, keys
|
70
|
+
|
71
|
+
name 'merge'
|
72
|
+
|
73
|
+
def pre_execute
|
74
|
+
|
75
|
+
@node['atts'] = []
|
76
|
+
@node['rets'] = []
|
77
|
+
|
78
|
+
unatt_unkeyed_children
|
79
|
+
end
|
80
|
+
|
81
|
+
def receive_last
|
82
|
+
|
83
|
+
indexes = @node['rets']
|
84
|
+
.each_with_index
|
85
|
+
.inject({ array: [], object: [], other: [] }) { |is, (e, i)|
|
86
|
+
case e
|
87
|
+
when Array then is[:array]
|
88
|
+
when Hash then is[:object]
|
89
|
+
else is[:other]
|
90
|
+
end << i
|
91
|
+
is }
|
92
|
+
|
93
|
+
a0 = indexes[:array].first || @node['rets'].length
|
94
|
+
o0 = indexes[:object].first || @node['rets'].length
|
95
|
+
|
96
|
+
kln = a0 < o0 ? :array : :object
|
97
|
+
okln = kln == :array ? :object : :array
|
98
|
+
|
99
|
+
cols = indexes[kln].collect { |i| @node['rets'][i] }
|
100
|
+
|
101
|
+
cols.unshift(node_payload_ret) \
|
102
|
+
if cols.length == 1 && Flor.type(node_payload_ret) == kln
|
103
|
+
|
104
|
+
fail Flor::FlorError.new('found no array or object to merge', self) \
|
105
|
+
if cols.empty?
|
106
|
+
|
107
|
+
unless att('lax', 'loose') == true || att('strict') == false
|
108
|
+
|
109
|
+
others = (indexes[:other] + indexes[okln]).sort
|
110
|
+
|
111
|
+
fail Flor::FlorError.new(
|
112
|
+
"found a non-#{kln} item (#{Flor.type(@node['rets'][others[0]])} item)",
|
113
|
+
self
|
114
|
+
) if others.any?
|
115
|
+
end
|
116
|
+
|
117
|
+
wrap('ret' => send(kln == :array ? :merge_arrays : :merge_objects, cols))
|
118
|
+
end
|
119
|
+
|
120
|
+
protected
|
121
|
+
|
122
|
+
def merge_arrays(as)
|
123
|
+
|
124
|
+
as
|
125
|
+
.inject([]) { |r, a| a.each_with_index { |e, i| r[i] = e }; r }
|
126
|
+
end
|
127
|
+
|
128
|
+
def merge_objects(os)
|
129
|
+
|
130
|
+
os
|
131
|
+
.inject({}) { |r, o| r.merge(o) }
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
data/lib/flor/pcore/move.rb
CHANGED
data/lib/flor/pcore/noret.rb
CHANGED
data/lib/flor/pcore/not.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|
class Flor::Pro::Not < Flor::Procedure
|
3
3
|
#
|
4
|
-
#
|
4
|
+
# Negates its last child (or its last unkeyed attribute)
|
5
5
|
#
|
6
6
|
# ```
|
7
7
|
# not _ # --> true
|
@@ -16,6 +16,20 @@ class Flor::Pro::Not < Flor::Procedure
|
|
16
16
|
# true
|
17
17
|
# false # --> true
|
18
18
|
# ```
|
19
|
+
#
|
20
|
+
# ```
|
21
|
+
# not true false # --> true
|
22
|
+
# ```
|
23
|
+
#
|
24
|
+
# ## Warning
|
25
|
+
#
|
26
|
+
# ```
|
27
|
+
# and not(false) not(false) # --> false
|
28
|
+
# ```
|
29
|
+
# It is recommended to use:
|
30
|
+
# ```
|
31
|
+
# and (not false) (not false) # --> true
|
32
|
+
# ```
|
19
33
|
|
20
34
|
name 'not'
|
21
35
|
|
data/lib/flor/pcore/on.rb
CHANGED
@@ -44,6 +44,17 @@ class Flor::Pro::On < Flor::Macro
|
|
44
44
|
# Please note that "error" in `on error` is not quoted, nor double quoted.
|
45
45
|
# If it were, it would trap the signal named "error".
|
46
46
|
#
|
47
|
+
# `on error` accepts the same criteria as [on_error](on_error.md), as in:
|
48
|
+
# ```
|
49
|
+
# sequence
|
50
|
+
# on error (/timeout/)
|
51
|
+
# charly "it timed out"
|
52
|
+
# on error
|
53
|
+
# charly "it failed", err
|
54
|
+
# alice 'do this'
|
55
|
+
# bob 'do that'
|
56
|
+
# ```
|
57
|
+
#
|
47
58
|
#
|
48
59
|
# ## cancel
|
49
60
|
#
|
data/lib/flor/pcore/on_cancel.rb
CHANGED
data/lib/flor/pcore/on_error.rb
CHANGED
@@ -16,7 +16,7 @@ class Flor::Pro::OnError < Flor::Procedure
|
|
16
16
|
# push f.l 1
|
17
17
|
# ```
|
18
18
|
# Where the field `l` ends up containing
|
19
|
-
# `[ 0, "
|
19
|
+
# `[ 0, "cannot find \"x\"" ]`.
|
20
20
|
#
|
21
21
|
# ```
|
22
22
|
# set f.l []
|
@@ -47,6 +47,48 @@ class Flor::Pro::OnError < Flor::Procedure
|
|
47
47
|
# # ...
|
48
48
|
# ```
|
49
49
|
#
|
50
|
+
# ## on_error kriteria
|
51
|
+
#
|
52
|
+
# Similarly to Ruby, one may catch certain types of errors.
|
53
|
+
#
|
54
|
+
# In the follow example, Charly is tasked with "it failed" and the err
|
55
|
+
# if there is a Ruby error of class `RuntimeError` happens in the sequence:
|
56
|
+
# ```
|
57
|
+
# sequence
|
58
|
+
# on_error class: 'RuntimeError' (def err \ charly "it failed", err)
|
59
|
+
# alice 'do this'
|
60
|
+
# bob 'do that'
|
61
|
+
# ```
|
62
|
+
#
|
63
|
+
# One can shorten it to:
|
64
|
+
# ```
|
65
|
+
# sequence
|
66
|
+
# on_error 'RuntimeError' (def err \ charly "it failed", err)
|
67
|
+
# alice 'do this'
|
68
|
+
# bob 'do that'
|
69
|
+
# ```
|
70
|
+
# But this short version will check the Ruby class name and then the error
|
71
|
+
# message.
|
72
|
+
#
|
73
|
+
# In the next example, Charly is tasked with "it timed out" if the error
|
74
|
+
# class or the error message match the regex `/timeout/`:
|
75
|
+
# ```
|
76
|
+
# sequence
|
77
|
+
# on_error (/timeout/) (def err \ charly "it timed out")
|
78
|
+
# on_error (def err \ charly "it failed", err)
|
79
|
+
# alice 'do this'
|
80
|
+
# bob 'do that'
|
81
|
+
# ```
|
82
|
+
# Order matters.
|
83
|
+
#
|
84
|
+
# Please note that you can't set a criteria when you're using the `on_error:`
|
85
|
+
# attribute, as in:
|
86
|
+
# ```
|
87
|
+
# sequence on_error: (def err \ charly "it failed", err)
|
88
|
+
# alice 'do this'
|
89
|
+
# bob 'do that'
|
90
|
+
# ```
|
91
|
+
#
|
50
92
|
# ## see also
|
51
93
|
#
|
52
94
|
# On, on_cancel.
|
@@ -56,13 +98,36 @@ class Flor::Pro::OnError < Flor::Procedure
|
|
56
98
|
def pre_execute
|
57
99
|
|
58
100
|
unatt_unkeyed_children
|
101
|
+
|
102
|
+
@node['atts'] = []
|
103
|
+
@node['rets'] = []
|
59
104
|
end
|
60
105
|
|
61
|
-
def
|
106
|
+
def receive_last
|
107
|
+
|
108
|
+
prc = @node['rets'].find { |r| Flor.is_func_tree?(r) }
|
109
|
+
|
110
|
+
line = tree[2]
|
111
|
+
|
112
|
+
cri = []
|
113
|
+
if cla = att('class', 'klass')
|
114
|
+
cri << [ 'class', cla, line ]
|
115
|
+
end
|
116
|
+
if str = @node['rets'].find { |r| r.is_a?(String) }
|
117
|
+
cri << [ 'string', str, line ]
|
118
|
+
end
|
119
|
+
if rex = @node['rets'].find { |r| Flor.is_regex_tree?(r) }
|
120
|
+
cri << [ 'regex', *rex[1..-1] ]
|
121
|
+
end
|
122
|
+
cri << '*' if cri.empty?
|
123
|
+
|
124
|
+
store_on(:error, prc, cri)
|
125
|
+
|
126
|
+
ms = super
|
62
127
|
|
63
|
-
|
128
|
+
ms.first['from_on'] = 'error'
|
64
129
|
|
65
|
-
|
130
|
+
ms
|
66
131
|
end
|
67
132
|
end
|
68
133
|
|
data/lib/flor/pcore/push.rb
CHANGED
@@ -39,7 +39,7 @@ class Flor::Pro::Push < Flor::Procedure
|
|
39
39
|
def pre_execute
|
40
40
|
|
41
41
|
unatt_unkeyed_children
|
42
|
-
|
42
|
+
rep_first_child
|
43
43
|
end
|
44
44
|
|
45
45
|
def receive_non_att
|
@@ -47,7 +47,7 @@ class Flor::Pro::Push < Flor::Procedure
|
|
47
47
|
if ! @node['arr']
|
48
48
|
@node['arr'] = payload['ret']
|
49
49
|
else
|
50
|
-
@node['
|
50
|
+
@node['val'] = payload['ret']
|
51
51
|
end
|
52
52
|
|
53
53
|
super
|
@@ -55,7 +55,7 @@ class Flor::Pro::Push < Flor::Procedure
|
|
55
55
|
|
56
56
|
def receive_last
|
57
57
|
|
58
|
-
push(@node.has_key?('
|
58
|
+
push(@node.has_key?('val') ? @node['val'] : node_payload_ret)
|
59
59
|
|
60
60
|
payload['ret'] = node_payload_ret \
|
61
61
|
unless tree[0] == 'pushr'
|
@@ -67,12 +67,7 @@ class Flor::Pro::Push < Flor::Procedure
|
|
67
67
|
|
68
68
|
def push(val)
|
69
69
|
|
70
|
-
arr = @node['arr']
|
71
|
-
|
72
|
-
if arr.is_a?(String)
|
73
|
-
payload.copy if arr[0, 1] == 'f'
|
74
|
-
arr = lookup(arr)
|
75
|
-
end
|
70
|
+
arr = lookup_value(@node['arr']) rescue nil
|
76
71
|
|
77
72
|
fail Flor::FlorError.new(
|
78
73
|
"cannot push to given target (#{arr.class})", self
|
data/lib/flor/pcore/range.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|
class Flor::Pro::Range < Flor::Procedure
|
3
3
|
#
|
4
|
-
#
|
4
|
+
# Generates ranges of integers.
|
5
5
|
#
|
6
6
|
# ```
|
7
7
|
# # range {end}
|
@@ -41,15 +41,15 @@ class Flor::Pro::Range < Flor::Procedure
|
|
41
41
|
edn = rets[1] || rets[0] || 0
|
42
42
|
ste = rets[2] || ((sta > edn) ? -1 : 1)
|
43
43
|
|
44
|
-
asta = att('start'
|
45
|
-
aedn = att('end'
|
46
|
-
aste = att('step'
|
44
|
+
asta = att('start', 'from')
|
45
|
+
aedn = att('end', 'to')
|
46
|
+
aste = att('step', 'by', 'inc')
|
47
47
|
|
48
48
|
sta = asta if asta
|
49
49
|
edn = aedn if aedn
|
50
50
|
ste = aste if aste
|
51
51
|
|
52
|
-
fail Flor::FlorError.new("#{
|
52
|
+
fail Flor::FlorError.new("#{heap} step is 0", self) \
|
53
53
|
if ste == 0
|
54
54
|
|
55
55
|
#payload['ret'] = (sta..edn - 1).step(ste).to_a
|
data/lib/flor/pcore/reduce.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|
class Flor::Pro::Reduce < Flor::Pro::Iterator
|
3
3
|
#
|
4
|
-
#
|
4
|
+
# Takes a collection and a function, reduces the collection
|
5
5
|
# to a single result thanks to the function.
|
6
6
|
#
|
7
7
|
# ```
|
@@ -54,7 +54,7 @@ class Flor::Pro::Reduce < Flor::Pro::Iterator
|
|
54
54
|
@node['fun'] ||= a
|
55
55
|
elsif Flor.is_proc_tree?(a)
|
56
56
|
@node['fun'] ||= proc_to_fun(a)
|
57
|
-
elsif
|
57
|
+
elsif Flor.is_collection?(a)
|
58
58
|
@node['ocol'] ||= a
|
59
59
|
else
|
60
60
|
@node['res'] ||= a
|
@@ -68,29 +68,16 @@ class Flor::Pro::Reduce < Flor::Pro::Iterator
|
|
68
68
|
) unless @node['fun']
|
69
69
|
fail Flor::FlorError.new(
|
70
70
|
"collection not given to #{heap.inspect}", self
|
71
|
-
) unless
|
71
|
+
) unless Flor.is_collection?(ocol)
|
72
72
|
|
73
73
|
@node['col'] = Flor.to_coll(@node['ocol'])
|
74
|
-
|
75
74
|
@node['res'] ||= @node['col'].shift
|
76
|
-
|
77
75
|
@node['args'] = nil
|
78
76
|
end
|
79
77
|
|
80
|
-
def
|
81
|
-
|
82
|
-
res = @node['res']
|
83
|
-
idx = @node['idx']
|
84
|
-
elt = @node['col'][idx]
|
85
|
-
len = @node['col'].length
|
78
|
+
def determine_iteration_args
|
86
79
|
|
87
|
-
|
88
|
-
{ 'res' => res, 'elt' => elt,
|
89
|
-
'idx' => idx, 'len' => len }
|
90
|
-
else
|
91
|
-
{ 'res' => res, 'key' => elt[0], 'val' => elt[1],
|
92
|
-
'idx' => idx, 'len' => len }
|
93
|
-
end
|
80
|
+
super.unshift([ 'res', @node['res'] ])
|
94
81
|
end
|
95
82
|
|
96
83
|
def receive_iteration
|
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
class Flor::Pro::Return < Flor::Procedure
|
3
|
+
|
4
|
+
name 'return'
|
5
|
+
|
6
|
+
def receive_last
|
7
|
+
|
8
|
+
si = Flor.sub_nid(nid)
|
9
|
+
n = @node
|
10
|
+
|
11
|
+
target =
|
12
|
+
loop do
|
13
|
+
pn = parent_node(n)
|
14
|
+
break nil unless pn
|
15
|
+
psi = Flor.sub_nid(pn['nid'])
|
16
|
+
break n['nid'] if psi != si
|
17
|
+
n = pn
|
18
|
+
end
|
19
|
+
|
20
|
+
fail Flor::FlorError.new('"return" outside of function', self) \
|
21
|
+
unless target
|
22
|
+
|
23
|
+
wrap_cancel('nid' => target, 'flavour' => 'return')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|