flor 0.15.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b973449e80aa849aee7d3fade7ab13fe57a0b6a1
|
4
|
+
data.tar.gz: a09d4a0b88d453b42742bb8814d5cee1f957c2c2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 139a8cf68527edcdff12137a9ac831eee6fb9867a49ed9fe24d462efce7f3d53f9396de2302b449f963c1e74fe4e67b5590f04ad5605a6996bb35e6e0f7015ad
|
7
|
+
data.tar.gz: 9de9e3bb4f12f2cb1b48ae0aa4d024ce4ce557b380d5b476c03dae7a7db63480ec041269702102a40165a3ed8ecb290d7b2c77299f999fdf605071976c2f99ea
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
|
2
|
-
#
|
2
|
+
# CHANGELOG.md
|
3
|
+
|
4
|
+
|
5
|
+
## flor 1.0.0 not yet released
|
6
|
+
|
7
|
+
|
8
|
+
## flor 0.16.0 released 2019-02-04
|
9
|
+
|
10
|
+
- Many many improvements
|
11
|
+
- Include "undense" work ("_ref" and friends)
|
12
|
+
- Include "undense" work (killing the dollar subsystem)
|
13
|
+
- Fix dereserving delayed messages
|
14
|
+
- allow for cancel behaviour when "cursor", "sequence", and "until"
|
15
|
+
node_status flavour is "on-error"
|
3
16
|
|
4
17
|
|
5
18
|
## flor 0.15.0 released 2018-06-15
|
data/CREDITS.md
CHANGED
data/LICENSE.txt
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
|
2
|
-
Copyright (c) 2015-
|
2
|
+
Copyright (c) 2015-2019, John Mettraux, jmettraux+flor@gmail.com
|
3
3
|
|
4
4
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
5
|
of this software and associated documentation files (the "Software"), to deal
|
data/Makefile
CHANGED
@@ -13,12 +13,15 @@ cl: count_lines
|
|
13
13
|
|
14
14
|
gemspec_validate:
|
15
15
|
@echo "---"
|
16
|
-
ruby -e "s = eval(File.read(Dir['*.gemspec'].first)); s.validate"
|
16
|
+
ruby -e "s = eval(File.read(Dir['*.gemspec'].first)); p s.validate"
|
17
17
|
@echo "---"
|
18
18
|
|
19
19
|
name: gemspec_validate
|
20
20
|
@echo "$(NAME) $(VERSION)"
|
21
21
|
|
22
|
+
cw:
|
23
|
+
find lib -name "*.rb" -exec ruby -cw {} \; | grep lib
|
24
|
+
|
22
25
|
syncver:
|
23
26
|
sed -E -i '' "s/VERSION = ['0-9.]+/VERSION = '$(shell grep -E "$(NAME) ([0-9.]+)" CHANGELOG.md | head -1 | sed -E 's/[^0-9\.]//g')'/" lib/$(NAME).rb
|
24
27
|
bundle install
|
@@ -81,5 +84,6 @@ cleanshell:
|
|
81
84
|
rm -fR envs/shell/var/tasks/*
|
82
85
|
rm -f .log.txt
|
83
86
|
|
84
|
-
.PHONY:
|
87
|
+
.PHONY: \
|
88
|
+
count_lines gemspec_validate name cw build push spec doc shell cleanshell
|
85
89
|
|
data/README.md
CHANGED
@@ -32,8 +32,9 @@ See [doc/](doc/).
|
|
32
32
|
|
33
33
|
## blog posts and presentations
|
34
34
|
|
35
|
+
* [the flor language](http://jmettraux.skepti.ch/20180927.html?t=the_flor_language) - on the flor workflow definition language itself
|
35
36
|
* [Flor, hubristic interpreter](http://rubykaigi.org/2017/presentations/jmettraux.html) - RubyKaigi 2017, Hiroshima - presentation
|
36
|
-
* [flor design 0](http://jmettraux.skepti.ch/20171021.html?t=flor_design_0) - running a simple execution, what happens - blog post
|
37
|
+
* [flor design 0](http://jmettraux.skepti.ch/20171021.html?t=flor_design_0&f=readme) - running a simple execution, what happens - blog post
|
37
38
|
* [flor, branch to branch](https://speakerdeck.com/jmettraux/flor-branch-to-branch) - q1 2017 - very dry deck
|
38
39
|
* [flor 2017](https://speakerdeck.com/jmettraux/flor-2017) - q1 2017 - very dry deck
|
39
40
|
|
data/flor.gemspec
CHANGED
@@ -15,6 +15,16 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.license = 'MIT'
|
16
16
|
s.summary = 'A Ruby workflow engine'
|
17
17
|
|
18
|
+
s.metadata = {
|
19
|
+
'changelog_uri' => s.homepage + '/flor/blob/master/CHANGELOG.md',
|
20
|
+
'documentation_uri' => s.homepage + '/flor/tree/master/doc',
|
21
|
+
'bug_tracker_uri' => s.homepage + '/flor/issues',
|
22
|
+
'mailing_list_uri' => 'https://groups.google.com/forum/#!forum/floraison',
|
23
|
+
'homepage_uri' => s.homepage + '/flor',
|
24
|
+
'source_code_uri' => s.homepage + '/flor',
|
25
|
+
#'wiki_uri' => s.homepage + '/flor/wiki',
|
26
|
+
}
|
27
|
+
|
18
28
|
s.description = %{
|
19
29
|
A Ruby workflow engine (ruote next generation)
|
20
30
|
}.strip
|
@@ -31,8 +41,8 @@ A Ruby workflow engine (ruote next generation)
|
|
31
41
|
s.add_runtime_dependency 'munemo', '~> 1.0', '>= 1.0.1'
|
32
42
|
s.add_runtime_dependency 'raabro', '~> 1.1', '>= 1.1.5'
|
33
43
|
#s.add_runtime_dependency 'rufus-lru', '~> 1.1'
|
34
|
-
s.add_runtime_dependency 'fugit', '~> 1.1'
|
35
|
-
s.add_runtime_dependency 'dense', '~> 1.1', '>= 1.1.
|
44
|
+
s.add_runtime_dependency 'fugit', '~> 1.1', '>= 1.1.8'
|
45
|
+
s.add_runtime_dependency 'dense', '~> 1.1', '>= 1.1.6'
|
36
46
|
|
37
47
|
s.add_runtime_dependency 'sequel', '~> 4'
|
38
48
|
|
data/lib/flor.rb
CHANGED
@@ -5,6 +5,7 @@ require 'logger'
|
|
5
5
|
require 'thread'
|
6
6
|
require 'digest'
|
7
7
|
require 'socket'
|
8
|
+
require 'forwardable'
|
8
9
|
|
9
10
|
require 'munemo'
|
10
11
|
require 'raabro'
|
@@ -13,7 +14,8 @@ require 'dense'
|
|
13
14
|
|
14
15
|
module Flor
|
15
16
|
|
16
|
-
VERSION = '0.
|
17
|
+
VERSION = '0.16.0'
|
18
|
+
#VERSION = '1.0.0'
|
17
19
|
end
|
18
20
|
|
19
21
|
require 'flor/colours'
|
@@ -22,11 +24,9 @@ require 'flor/djan'
|
|
22
24
|
require 'flor/id'
|
23
25
|
require 'flor/log'
|
24
26
|
require 'flor/flor'
|
25
|
-
require 'flor/dollar'
|
26
27
|
require 'flor/errors'
|
27
28
|
require 'flor/parser'
|
28
29
|
require 'flor/conf'
|
29
|
-
require 'flor/changes'
|
30
30
|
require 'flor/to_string'
|
31
31
|
|
32
32
|
require 'flor/core'
|
data/lib/flor/colours.rb
CHANGED
data/lib/flor/conf.rb
CHANGED
@@ -114,13 +114,12 @@ module Flor
|
|
114
114
|
a = plus - minus
|
115
115
|
|
116
116
|
h =
|
117
|
-
a.inject({}) { |
|
117
|
+
a.inject({}) { |hh, kv|
|
118
118
|
k, v = kv.split(':')
|
119
119
|
k = 'sto' if k == 'db'
|
120
120
|
k = "log_#{k}" if LOG_ALL_KEYS.include?(k)
|
121
|
-
|
122
|
-
|
123
|
-
}
|
121
|
+
hh[k] = v ? JSON.parse(v) : true
|
122
|
+
hh }
|
124
123
|
LOG_ALL_KEYS.each { |k| h["log_#{k}"] = 1 } if h['log_all']
|
125
124
|
LOG_DBG_KEYS.each { |k| h["log_#{k}"] = 1 } if h['log_dbg']
|
126
125
|
|
data/lib/flor/core/executor.rb
CHANGED
@@ -15,6 +15,8 @@ module Flor
|
|
15
15
|
|
16
16
|
@hooks = hooks # raw hooks if any, fresh from the loader
|
17
17
|
@traps = traps # array of Trap instances
|
18
|
+
|
19
|
+
@htraps = nil
|
18
20
|
end
|
19
21
|
|
20
22
|
def conf; @unit.conf; end
|
@@ -144,6 +146,10 @@ module Flor
|
|
144
146
|
# cnid: closure nid
|
145
147
|
# dbg: used to debug messages (useful @node['dbg'] when 'receive')
|
146
148
|
|
149
|
+
if oeh = message['on_error_handler']
|
150
|
+
node['on_error'] = [ [ [ '*' ], oeh ] ]
|
151
|
+
end
|
152
|
+
|
147
153
|
@execution['nodes'][nid] = node
|
148
154
|
end
|
149
155
|
|
@@ -158,9 +164,7 @@ module Flor
|
|
158
164
|
make_node(message) :
|
159
165
|
@execution['nodes'][nid]
|
160
166
|
|
161
|
-
return
|
162
|
-
|
163
|
-
return if node['heat']
|
167
|
+
return if node.nil? || node['heat']
|
164
168
|
|
165
169
|
n = Flor::Node.new(self, node, message)
|
166
170
|
|
@@ -173,34 +177,33 @@ module Flor
|
|
173
177
|
node['tree'] = mt if mt && (mt != nt)
|
174
178
|
tree = node['tree'] || nt
|
175
179
|
|
176
|
-
t0 = tree[0]
|
177
|
-
t0 = (t0.is_a?(Array) && t0[0] == '_dqs') ? n.expand(t0[1]) : t0
|
178
|
-
|
179
|
-
node['heat0'] = tree[0]
|
180
|
+
node['heat0'] = t0 = tree[0]
|
180
181
|
node['heat'] = heat = n.deref(t0)
|
181
|
-
node['heap'] = heap = n.reheap(tree, heat)
|
182
182
|
|
183
|
-
|
183
|
+
if heat == nil && ! message['accept_symbol']
|
184
184
|
|
185
|
-
|
186
|
-
#
|
187
|
-
# a field reference that points to nothing returns null
|
185
|
+
node['heat'] = '(none)'
|
188
186
|
|
189
|
-
|
190
|
-
|
191
|
-
|
187
|
+
fail FlorError.new("cannot find #{t0.inspect}", n) if tree[1].empty?
|
188
|
+
fail FlorError.new("don't know how to apply #{t0.inspect}", n)
|
189
|
+
# TODO how about _ref and letting that procedure fail
|
190
|
+
end
|
192
191
|
|
193
|
-
|
192
|
+
node['heap'] = heap = n.reheap(tree, heat)
|
193
|
+
|
194
|
+
# "exceptions"
|
195
|
+
|
196
|
+
if heat == nil #&& message['accept_symbol']
|
194
197
|
#
|
195
198
|
# tag: et al
|
196
199
|
|
197
|
-
node['tree'] = message['tree'] = t = [ '
|
200
|
+
node['tree'] = message['tree'] = t = [ '_sqs', tree[0], tree[2] ]
|
198
201
|
|
199
202
|
node['heat0'] = t[0]
|
200
203
|
node['heat'] = h = n.deref(t[0])
|
201
204
|
node['heap'] = n.reheap(t, h)
|
202
205
|
|
203
|
-
elsif heap == 'task' && heat[0] == '
|
206
|
+
elsif heap == 'task' && heat[0] == '_tasker'
|
204
207
|
#
|
205
208
|
# rewrite `alpha` into `task alpha`
|
206
209
|
|
@@ -211,7 +214,7 @@ module Flor
|
|
211
214
|
message['tree'][0] =
|
212
215
|
'task'
|
213
216
|
message['tree'][1].unshift(
|
214
|
-
[ '_att', [ [ '_sqs', heat[1]['
|
217
|
+
[ '_att', [ [ '_sqs', heat[1]['tasker'], l ] ], l ])
|
215
218
|
end
|
216
219
|
end
|
217
220
|
|
@@ -222,16 +225,7 @@ module Flor
|
|
222
225
|
|
223
226
|
def apply(node, message)
|
224
227
|
|
225
|
-
heap =
|
226
|
-
if node['heat']
|
227
|
-
node['heap']
|
228
|
-
else
|
229
|
-
node['failure'] ? '_err' : nil
|
230
|
-
end
|
231
|
-
|
232
|
-
return error_reply(
|
233
|
-
node, message, "don't know how to apply #{node['heat0'].inspect}"
|
234
|
-
) if heap == nil
|
228
|
+
heap = node['heap']
|
235
229
|
|
236
230
|
heac = Flor::Procedure[heap]
|
237
231
|
fail NameError.new("unknown procedure #{heap.inspect}") unless heac
|
@@ -283,11 +277,11 @@ module Flor
|
|
283
277
|
|
284
278
|
def leave_node(message)
|
285
279
|
|
280
|
+
return [] if %w[ flank part ].include?(message['flavour'])
|
281
|
+
|
286
282
|
fnid = message['from']; return [] unless fnid
|
287
283
|
fnode = @execution['nodes'][fnid]; return [] unless fnode
|
288
284
|
|
289
|
-
return [] if message['flavour'] == 'flank'
|
290
|
-
|
291
285
|
remove_node(message, fnode) +
|
292
286
|
leave_tags(message, fnode)
|
293
287
|
end
|
@@ -380,36 +374,6 @@ module Flor
|
|
380
374
|
[ m ]
|
381
375
|
end
|
382
376
|
|
383
|
-
def task(message)
|
384
|
-
|
385
|
-
return error_reply(
|
386
|
-
node(message['nid']),
|
387
|
-
message,
|
388
|
-
"don't know how to apply #{message['tasker'].inspect}"
|
389
|
-
) if message['routed'] == false
|
390
|
-
|
391
|
-
@execution['tasks'][message['nid']] =
|
392
|
-
{ 'tasker' => message['tasker'], 'name' => message['taskname'] }
|
393
|
-
#
|
394
|
-
# FIXME is it in use???
|
395
|
-
|
396
|
-
@unit.ganger.task(self, message)
|
397
|
-
end
|
398
|
-
alias detask task
|
399
|
-
|
400
|
-
def return(message)
|
401
|
-
|
402
|
-
@execution['tasks'].delete(message['nid'])
|
403
|
-
#
|
404
|
-
# FIXME is it in use???
|
405
|
-
|
406
|
-
[ { 'point' => 'receive',
|
407
|
-
'exid' => message['exid'],
|
408
|
-
'nid' => message['nid'],
|
409
|
-
'payload' => message['payload'],
|
410
|
-
'tasker' => message['tasker'] } ]
|
411
|
-
end
|
412
|
-
|
413
377
|
def cancel(message)
|
414
378
|
|
415
379
|
n = @execution['nodes'][message['nid']]
|
@@ -444,6 +408,11 @@ module Flor
|
|
444
408
|
|
445
409
|
def process(message)
|
446
410
|
|
411
|
+
fail ArgumentError.new("incoming message has non nil or Hash payload") \
|
412
|
+
unless message['payload'] == nil || message['payload'].is_a?(Hash)
|
413
|
+
#
|
414
|
+
# weed out messages with non-conforming payloads
|
415
|
+
|
447
416
|
begin
|
448
417
|
|
449
418
|
message['m'] = counter_next('msgs') # number messages
|
@@ -516,6 +485,7 @@ module Flor
|
|
516
485
|
# with its 'on_error' turned on.
|
517
486
|
#
|
518
487
|
oep.trigger_on_error
|
488
|
+
#
|
519
489
|
else
|
520
490
|
#
|
521
491
|
# Simply log and don't add further messages ([]) to execute
|
data/lib/flor/core/node.rb
CHANGED
@@ -2,10 +2,12 @@
|
|
2
2
|
class Flor::Node
|
3
3
|
|
4
4
|
class Payload
|
5
|
+
|
5
6
|
def initialize(node, type=:node)
|
6
7
|
@node = node
|
7
8
|
@type = type
|
8
9
|
end
|
10
|
+
|
9
11
|
def has_key?(k)
|
10
12
|
current.has_key?(k)
|
11
13
|
end
|
@@ -33,7 +35,16 @@ class Flor::Node
|
|
33
35
|
def merge(h)
|
34
36
|
current.merge(h)
|
35
37
|
end
|
38
|
+
|
39
|
+
def ret
|
40
|
+
self['ret']
|
41
|
+
end
|
42
|
+
def ret=(v)
|
43
|
+
self['ret'] = v
|
44
|
+
end
|
45
|
+
|
36
46
|
protected
|
47
|
+
|
37
48
|
def container
|
38
49
|
@type == :node ? @node.h : @node.message
|
39
50
|
end
|
@@ -71,6 +82,8 @@ class Flor::Node
|
|
71
82
|
def nid; @node['nid']; end
|
72
83
|
def parent; @node['parent']; end
|
73
84
|
|
85
|
+
def child_id; Flor.child_id(@node['nid']); end
|
86
|
+
|
74
87
|
def domain; Flor.domain(@execution['exid']); end
|
75
88
|
|
76
89
|
def point; @message['point']; end
|
@@ -78,6 +91,7 @@ class Flor::Node
|
|
78
91
|
|
79
92
|
def cnodes; @node['cnodes']; end
|
80
93
|
def cnodes_any?; cnodes && cnodes.any?; end
|
94
|
+
def cnodes_empty?; cnodes.nil? || cnodes.empty?; end
|
81
95
|
|
82
96
|
def payload
|
83
97
|
@message_payload ||= Payload.new(self, :message)
|
@@ -106,6 +120,10 @@ class Flor::Node
|
|
106
120
|
Flor.dup(node_payload['ret'])
|
107
121
|
end
|
108
122
|
|
123
|
+
def payload_ret
|
124
|
+
message['payload']['ret']
|
125
|
+
end
|
126
|
+
|
109
127
|
def message_or_node_payload
|
110
128
|
payload.current ? payload : node_payload
|
111
129
|
end
|
@@ -151,89 +169,86 @@ class Flor::Node
|
|
151
169
|
#
|
152
170
|
# that might be the way...
|
153
171
|
|
154
|
-
def
|
172
|
+
def lookup_value(path)
|
173
|
+
|
174
|
+
original_path = path
|
155
175
|
|
156
|
-
|
157
|
-
|
176
|
+
path =
|
177
|
+
case path
|
178
|
+
when '*' then [ path ]
|
179
|
+
when String then Dense::Path.make(path).to_a
|
180
|
+
else path
|
181
|
+
end
|
158
182
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
183
|
+
path.unshift('v') \
|
184
|
+
if path.length < 2
|
185
|
+
|
186
|
+
case path.first
|
187
|
+
when /\Af(?:ld|ield)?\z/
|
188
|
+
lookup_field(nil, path[1..-1]) # mod -> nil...
|
189
|
+
when /\At(?:ag)?\z/
|
190
|
+
lookup_tag(nil, path[1])
|
191
|
+
when /\A([lgd]?)v(?:ar|ariable)?\z/
|
192
|
+
return @message['__head'][1] if path[1] == '__head'
|
193
|
+
lookup_var(@node, $1, path[1], path[2..-1])
|
194
|
+
when 'node'
|
195
|
+
lookup_in_node(path[1..-1])
|
196
|
+
when 'exe', 'execution'
|
197
|
+
lookup_in_execution(path[1..-1])
|
165
198
|
else
|
166
|
-
|
199
|
+
lookup_var(@node, '', path[0], path[1..-1])
|
167
200
|
end
|
168
201
|
|
169
|
-
rescue KeyError
|
170
|
-
|
171
|
-
raise unless silence_index_error
|
172
|
-
nil
|
173
|
-
end
|
174
|
-
|
175
|
-
class Expander < Flor::Dollar
|
176
|
-
|
177
|
-
def initialize(n); @node = n; end
|
178
|
-
|
179
|
-
def lookup(k)
|
202
|
+
rescue KeyError => ke
|
180
203
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
return Flor.tstamp if k == 'tstamp'
|
204
|
+
class << ke; attr_accessor :original_path, :work_path; end
|
205
|
+
ke.original_path = original_path
|
206
|
+
ke.work_path = path
|
185
207
|
|
186
|
-
|
187
|
-
r.is_a?(Symbol) ? nil : r
|
188
|
-
end
|
208
|
+
raise
|
189
209
|
end
|
190
210
|
|
191
|
-
|
211
|
+
# Returns the referenced tree.
|
212
|
+
# Returns nil if not found.
|
213
|
+
#
|
214
|
+
def deref(s)
|
192
215
|
|
193
|
-
|
216
|
+
v = lookup_value(s)
|
194
217
|
|
195
|
-
|
196
|
-
end
|
218
|
+
if Flor.is_tree?(v)
|
197
219
|
|
198
|
-
|
220
|
+
ref =
|
221
|
+
case v[0]
|
222
|
+
when '_func' then true
|
223
|
+
when '_proc' then v[1]['proc'] != s
|
224
|
+
when '_tasker' then v[1]['tasker'] != s
|
225
|
+
else false
|
226
|
+
end
|
199
227
|
|
200
|
-
|
228
|
+
v[1]['oref'] ||= v[1]['ref'] if ref && v[1]['ref']
|
229
|
+
v[1]['ref'] = s if ref
|
201
230
|
|
202
|
-
|
231
|
+
v
|
203
232
|
|
204
|
-
|
205
|
-
return v unless v[1].is_a?(Hash)
|
206
|
-
|
207
|
-
return v unless %w[ _proc _task _func ].include?(v[0])
|
233
|
+
else
|
208
234
|
|
209
|
-
|
210
|
-
|
211
|
-
when '_func' then true
|
212
|
-
when '_proc' then v[1]['proc'] != o
|
213
|
-
when '_task' then v[1]['task'] != o
|
214
|
-
else false
|
215
|
-
end
|
235
|
+
[ '_val', v, tree[2] ]
|
236
|
+
end
|
216
237
|
|
217
|
-
|
218
|
-
v[1]['ref'] = o if ref
|
238
|
+
rescue KeyError => ke
|
219
239
|
|
220
|
-
|
240
|
+
nil
|
221
241
|
end
|
222
242
|
|
223
243
|
def reheap(tree, heat)
|
224
244
|
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
'apply'
|
233
|
-
elsif heat[0] == '_task'
|
234
|
-
'task'
|
235
|
-
else
|
236
|
-
'_val'
|
245
|
+
case
|
246
|
+
when ! heat.is_a?(Array) then '_val'
|
247
|
+
when tree && tree[1] == [] then '_val'
|
248
|
+
when heat[0] == '_proc' then heat[1]['proc']
|
249
|
+
when heat[0] == '_func' then 'apply'
|
250
|
+
when heat[0] == '_tasker' then 'task'
|
251
|
+
else '_val'
|
237
252
|
end
|
238
253
|
end
|
239
254
|
|
@@ -247,17 +262,6 @@ class Flor::Node
|
|
247
262
|
"#{exid}-#{nid}"
|
248
263
|
end
|
249
264
|
|
250
|
-
def on_error_parent
|
251
|
-
|
252
|
-
oe = @node['on_error']
|
253
|
-
return self if oe && oe.any?
|
254
|
-
|
255
|
-
pn = parent_node
|
256
|
-
return Flor::Node.new(@executor, pn, @message).on_error_parent if pn
|
257
|
-
|
258
|
-
nil
|
259
|
-
end
|
260
|
-
|
261
265
|
def to_procedure_node
|
262
266
|
|
263
267
|
Flor::Procedure.new(@executor, @node, @message)
|
@@ -279,6 +283,24 @@ class Flor::Node
|
|
279
283
|
false
|
280
284
|
end
|
281
285
|
|
286
|
+
def on_error_parent(skip=false)
|
287
|
+
|
288
|
+
if @node['in_on_error'] # prevent loop when error in on_error:
|
289
|
+
skip = true
|
290
|
+
end
|
291
|
+
|
292
|
+
if (@node['on_error'] || []).find { |criteria, _| match_on?(criteria) }
|
293
|
+
return self unless skip
|
294
|
+
skip = false
|
295
|
+
end
|
296
|
+
|
297
|
+
if pn = parent_node
|
298
|
+
return Flor::Node.new(@executor, pn, @message).on_error_parent(skip)
|
299
|
+
end
|
300
|
+
|
301
|
+
nil
|
302
|
+
end
|
303
|
+
|
282
304
|
protected
|
283
305
|
|
284
306
|
def subtree(tree, pnid, nid)
|
@@ -294,7 +316,7 @@ class Flor::Node
|
|
294
316
|
return nil unless cid
|
295
317
|
# maybe failing would be better
|
296
318
|
|
297
|
-
cid.split('_').each { |
|
319
|
+
cid.split('_').each { |id| tree = tree[1][id.to_i] }
|
298
320
|
|
299
321
|
tree
|
300
322
|
end
|
@@ -309,7 +331,21 @@ class Flor::Node
|
|
309
331
|
lookup_tree(node['parent'])
|
310
332
|
end
|
311
333
|
|
312
|
-
def
|
334
|
+
def parent_node_procedure(node=@node)
|
335
|
+
|
336
|
+
Flor::Procedure.make(@executor, parent_node(node), @message)
|
337
|
+
end
|
338
|
+
|
339
|
+
# Returns true if the current node has the node identified with nid as
|
340
|
+
# an ancestor. Returns false else.
|
341
|
+
#
|
342
|
+
def is_ancestor_node?(node_or_nid, node=@node)
|
343
|
+
|
344
|
+
nid = node_or_nid
|
345
|
+
|
346
|
+
return false unless nid
|
347
|
+
|
348
|
+
nid = node_or_nid['nid'] unless nid.is_a?(String)
|
313
349
|
|
314
350
|
return false unless node
|
315
351
|
return true if node['nid'] == nid
|
@@ -321,9 +357,18 @@ class Flor::Node
|
|
321
357
|
# @execution['nodes'][node['cnid']]
|
322
358
|
#end
|
323
359
|
|
324
|
-
def lookup_in_node(
|
360
|
+
def lookup_in_node(path)
|
325
361
|
|
326
|
-
Dense.fetch(@node,
|
362
|
+
Dense.fetch(@node, path)
|
363
|
+
end
|
364
|
+
|
365
|
+
def lookup_in_execution(path)
|
366
|
+
|
367
|
+
if path == %w[ domain ]
|
368
|
+
Flor.domain(@execution['exid'])
|
369
|
+
else
|
370
|
+
Dense.fetch(@execution, path)
|
371
|
+
end
|
327
372
|
end
|
328
373
|
|
329
374
|
class PseudoVarContainer < Hash
|
@@ -336,7 +381,7 @@ class Flor::Node
|
|
336
381
|
end
|
337
382
|
#
|
338
383
|
PROC_VAR_CONTAINER = PseudoVarContainer.new('proc')
|
339
|
-
TASKER_VAR_CONTAINER = PseudoVarContainer.new('
|
384
|
+
TASKER_VAR_CONTAINER = PseudoVarContainer.new('tasker')
|
340
385
|
|
341
386
|
def escape(k)
|
342
387
|
|
@@ -357,19 +402,53 @@ class Flor::Node
|
|
357
402
|
|
358
403
|
rescue KeyError => ke
|
359
404
|
|
360
|
-
return nil if ke.miss[4].empty?
|
361
|
-
|
362
405
|
m = "variable #{ke.miss[3].inspect} not found"
|
363
406
|
m += " at #{Dense::Path.make(ke.miss[1]).to_s.inspect}" if ke.miss[1].any?
|
364
407
|
|
365
408
|
raise ke.relabel(m)
|
366
409
|
|
410
|
+
rescue IndexError => ie
|
411
|
+
|
412
|
+
m =
|
413
|
+
if ie.miss[1] == [ ie.miss[2] ]
|
414
|
+
"variable #{ie.miss[2].inspect} not found"
|
415
|
+
else
|
416
|
+
pa = Dense::Path.make(ie.miss[1]).to_s.inspect
|
417
|
+
ty = Flor.type(ie.miss[2])
|
418
|
+
ke = ie.miss[3].inspect
|
419
|
+
"variable at #{pa} is a #{ty}, it has no key #{ke}"
|
420
|
+
end
|
421
|
+
|
422
|
+
raise ie.relabel(m)
|
423
|
+
|
367
424
|
#rescue TypeError => te # leave as is
|
368
425
|
end
|
369
426
|
|
427
|
+
def var_match?(vs, key)
|
428
|
+
|
429
|
+
vs.each do |v|
|
430
|
+
return true if v == key
|
431
|
+
return true if v.is_a?(Regexp) && v =~ key
|
432
|
+
# TODO fun call
|
433
|
+
end
|
434
|
+
|
435
|
+
false
|
436
|
+
end
|
437
|
+
|
370
438
|
def lookup_var_container(node, mod, key)
|
371
439
|
|
372
|
-
return lookup_dvar_container(mod, key)
|
440
|
+
return lookup_dvar_container(mod, key) \
|
441
|
+
if node == nil || mod == 'd'
|
442
|
+
|
443
|
+
return lookup_arg_container(key) \
|
444
|
+
if mod == '' && %w[ args argv argh ].include?(key)
|
445
|
+
|
446
|
+
if vwl = node['vwlist']
|
447
|
+
return lookup_dvar_container(mod, key) unless var_match?(vwl, key)
|
448
|
+
end
|
449
|
+
if vbl = node['vblist']
|
450
|
+
return lookup_dvar_container(mod, key) if var_match?(vbl, key)
|
451
|
+
end
|
373
452
|
|
374
453
|
pnode = parent_node(node)
|
375
454
|
vars = node['vars']
|
@@ -413,15 +492,21 @@ class Flor::Node
|
|
413
492
|
{}
|
414
493
|
end
|
415
494
|
|
416
|
-
def
|
495
|
+
def lookup_arg_container(key)
|
417
496
|
|
418
|
-
|
497
|
+
vars = lookup_var_container(@node, '', 'arguments')
|
498
|
+
return {} unless vars
|
419
499
|
|
420
|
-
|
421
|
-
|
422
|
-
return k if k
|
500
|
+
args = vars['arguments']
|
501
|
+
return {} unless args
|
423
502
|
|
424
|
-
|
503
|
+
val =
|
504
|
+
case key
|
505
|
+
when 'args', 'argv' then args.collect(&:last)
|
506
|
+
else args.inject({}) { |h, (k, v)| h[k] = v if k; h }
|
507
|
+
end
|
508
|
+
|
509
|
+
{ key => val }
|
425
510
|
end
|
426
511
|
|
427
512
|
def lookup_tag(mod, key)
|
@@ -432,28 +517,60 @@ class Flor::Node
|
|
432
517
|
a
|
433
518
|
end
|
434
519
|
|
435
|
-
nids.
|
520
|
+
nids.any? ? nids : nil
|
436
521
|
end
|
437
522
|
|
438
523
|
def lookup_field(mod, key_and_path)
|
439
524
|
|
440
525
|
Dense.fetch(payload.current, key_and_path)
|
526
|
+
end
|
441
527
|
|
442
|
-
|
528
|
+
# Return true if the current @message matches on the given array of
|
529
|
+
# criteria.
|
530
|
+
#
|
531
|
+
def match_on?(criteria)
|
443
532
|
|
444
|
-
|
533
|
+
# AND, not OR, hence the true at the bottom
|
534
|
+
|
535
|
+
criteria
|
536
|
+
.each { |c|
|
537
|
+
next if c == '*'
|
538
|
+
return false unless send("match_on_#{c[0]}?", c) }
|
539
|
+
|
540
|
+
true
|
445
541
|
end
|
446
542
|
|
447
|
-
def
|
543
|
+
def extract_on_info
|
544
|
+
|
545
|
+
kla = @message['error']['kla']
|
546
|
+
msg = @message['error']['msg']
|
547
|
+
la = kla.split('::').last
|
548
|
+
|
549
|
+
[ kla, la, msg ]
|
550
|
+
end
|
551
|
+
|
552
|
+
def match_on_class?(criterion)
|
553
|
+
|
554
|
+
c1 = criterion[1]
|
555
|
+
kla, la, _ = extract_on_info
|
556
|
+
|
557
|
+
kla == c1 || la == c1
|
558
|
+
end
|
559
|
+
|
560
|
+
def match_on_string?(criterion)
|
561
|
+
|
562
|
+
c1 = criterion[1]
|
563
|
+
kla, la, msg = extract_on_info
|
564
|
+
|
565
|
+
msg == c1 || kla == c1 || la == c1
|
566
|
+
end
|
448
567
|
|
449
|
-
|
450
|
-
/\A(?:([lgd]?)((?:v|var|variable)|w|f|fld|field|t|tag)\.)?(.+)\z/)
|
568
|
+
def match_on_regex?(criterion)
|
451
569
|
|
452
|
-
|
453
|
-
|
454
|
-
ke = m[3]
|
570
|
+
c1 = Flor.to_regex(criterion)
|
571
|
+
kla, _, msg = extract_on_info
|
455
572
|
|
456
|
-
|
573
|
+
msg =~ c1 || kla =~ c1
|
457
574
|
end
|
458
575
|
end
|
459
576
|
|