flor 0.14.0 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +9 -0
  3. data/CREDITS.md +21 -0
  4. data/LICENSE.txt +4 -1
  5. data/Makefile +4 -0
  6. data/README.md +8 -0
  7. data/flor.gemspec +10 -10
  8. data/lib/flor.rb +2 -2
  9. data/lib/flor/changes.rb +3 -3
  10. data/lib/flor/colours.rb +14 -8
  11. data/lib/flor/conf.rb +63 -58
  12. data/lib/flor/core.rb +4 -4
  13. data/lib/flor/core/executor.rb +65 -29
  14. data/lib/flor/core/node.rb +37 -20
  15. data/lib/flor/core/procedure.rb +182 -40
  16. data/lib/flor/core/texecutor.rb +125 -52
  17. data/lib/flor/djan.rb +111 -82
  18. data/lib/flor/dollar.rb +31 -30
  19. data/lib/flor/flor.rb +314 -237
  20. data/lib/flor/id.rb +7 -2
  21. data/lib/flor/log.rb +250 -245
  22. data/lib/flor/parser.rb +72 -38
  23. data/lib/flor/pcore/_arr.rb +10 -10
  24. data/lib/flor/pcore/_att.rb +49 -14
  25. data/lib/flor/pcore/_coll.rb +18 -0
  26. data/lib/flor/pcore/_obj.rb +23 -7
  27. data/lib/flor/pcore/_pat_.rb +1 -1
  28. data/lib/flor/pcore/_pat_guard.rb +8 -0
  29. data/lib/flor/pcore/_pat_obj.rb +3 -3
  30. data/lib/flor/pcore/_pat_or.rb +4 -0
  31. data/lib/flor/pcore/_pat_regex.rb +24 -0
  32. data/lib/flor/pcore/_skip.rb +4 -0
  33. data/lib/flor/pcore/_val.rb +0 -1
  34. data/lib/flor/pcore/all.rb +111 -0
  35. data/lib/flor/pcore/any.rb +83 -0
  36. data/lib/flor/pcore/arith.rb +35 -6
  37. data/lib/flor/pcore/break.rb +39 -1
  38. data/lib/flor/pcore/case.rb +82 -4
  39. data/lib/flor/pcore/cmp.rb +7 -7
  40. data/lib/flor/pcore/collect.rb +50 -0
  41. data/lib/flor/pcore/cond.rb +17 -3
  42. data/lib/flor/pcore/cursor.rb +8 -2
  43. data/lib/flor/pcore/detect.rb +45 -0
  44. data/lib/flor/pcore/each.rb +52 -0
  45. data/lib/flor/pcore/empty.rb +60 -0
  46. data/lib/flor/pcore/filter.rb +94 -0
  47. data/lib/flor/pcore/find.rb +67 -0
  48. data/lib/flor/pcore/for_each.rb +65 -0
  49. data/lib/flor/pcore/includes.rb +32 -0
  50. data/lib/flor/pcore/inject.rb +55 -0
  51. data/lib/flor/pcore/iterator.rb +151 -0
  52. data/lib/flor/pcore/keys.rb +60 -0
  53. data/lib/flor/pcore/length.rb +34 -7
  54. data/lib/flor/pcore/logo.rb +18 -0
  55. data/lib/flor/pcore/loop.rb +4 -0
  56. data/lib/flor/pcore/map.rb +77 -46
  57. data/lib/flor/pcore/match.rb +8 -2
  58. data/lib/flor/pcore/matchr.rb +4 -5
  59. data/lib/flor/pcore/move.rb +3 -3
  60. data/lib/flor/pcore/noeval.rb +13 -0
  61. data/lib/flor/pcore/not.rb +16 -0
  62. data/lib/flor/pcore/on.rb +172 -0
  63. data/lib/flor/pcore/on_cancel.rb +54 -0
  64. data/lib/flor/pcore/on_error.rb +68 -0
  65. data/lib/flor/pcore/rand.rb +2 -2
  66. data/lib/flor/pcore/range.rb +2 -1
  67. data/lib/flor/pcore/reduce.rb +124 -0
  68. data/lib/flor/pcore/reverse.rb +46 -0
  69. data/lib/flor/pcore/select.rb +72 -0
  70. data/lib/flor/pcore/set.rb +8 -0
  71. data/lib/flor/pcore/stall.rb +10 -0
  72. data/lib/flor/pcore/to_array.rb +61 -0
  73. data/lib/flor/pcore/until.rb +34 -0
  74. data/lib/flor/punit/cancel.rb +30 -5
  75. data/lib/flor/punit/ccollect.rb +11 -0
  76. data/lib/flor/punit/cmap.rb +10 -5
  77. data/lib/flor/punit/concurrence.rb +42 -51
  78. data/lib/flor/punit/cron.rb +33 -0
  79. data/lib/flor/punit/do_trap.rb +42 -0
  80. data/lib/flor/punit/every.rb +48 -13
  81. data/lib/flor/punit/graft.rb +3 -3
  82. data/lib/flor/punit/on_timeout.rb +38 -0
  83. data/lib/flor/punit/schedule.rb +69 -6
  84. data/lib/flor/punit/signal.rb +54 -0
  85. data/lib/flor/punit/sleep.rb +1 -1
  86. data/lib/flor/punit/task.rb +4 -1
  87. data/lib/flor/punit/trap.rb +188 -13
  88. data/lib/flor/tools/shell.rb +408 -62
  89. data/lib/flor/tools/shell_out.rb +31 -0
  90. data/lib/flor/unit.rb +1 -1
  91. data/lib/flor/unit/caller.rb +177 -0
  92. data/lib/flor/unit/executor.rb +1 -0
  93. data/lib/flor/unit/ganger.rb +15 -21
  94. data/lib/flor/unit/hook.rb +1 -1
  95. data/lib/flor/unit/hooker.rb +22 -10
  96. data/lib/flor/unit/loader.rb +22 -22
  97. data/lib/flor/unit/logger.rb +63 -36
  98. data/lib/flor/unit/models.rb +6 -1
  99. data/lib/flor/unit/models/execution.rb +12 -1
  100. data/lib/flor/unit/models/message.rb +7 -0
  101. data/lib/flor/unit/models/trap.rb +31 -17
  102. data/lib/flor/unit/scheduler.rb +18 -10
  103. data/lib/flor/unit/storage.rb +83 -23
  104. data/lib/flor/unit/waiter.rb +1 -2
  105. metadata +96 -52
  106. data/lib/flor/deep.rb +0 -144
  107. data/lib/flor/punit/on.rb +0 -57
  108. data/lib/flor/unit/runner.rb +0 -84
  109. data/match.md +0 -22
@@ -27,6 +27,9 @@ class Flor::Node
27
27
  def copy_current
28
28
  Flor.dup(current)
29
29
  end
30
+ def dup_current
31
+ current ? current.dup : nil
32
+ end
30
33
  def merge(h)
31
34
  current.merge(h)
32
35
  end
@@ -45,9 +48,9 @@ class Flor::Node
45
48
 
46
49
  @executor, @execution =
47
50
  case executor
48
- when nil then [ nil, nil ] # for some tests
49
- when Hash then [ nil, executor ] # from some other tests
50
- else [ executor, executor.execution ] # vanilla case
51
+ when nil then [ nil, nil ] # for some tests
52
+ when Hash then [ nil, executor ] # from some other tests
53
+ else [ executor, executor.execution ] # vanilla case
51
54
  end
52
55
 
53
56
  @node =
@@ -83,6 +86,9 @@ class Flor::Node
83
86
  def node_status
84
87
  @node['status'].last
85
88
  end
89
+ def node_status_flavour
90
+ node_status['flavour']
91
+ end
86
92
  def node_closed?
87
93
  node_status['status'] == 'closed'
88
94
  end
@@ -160,7 +166,7 @@ class Flor::Node
160
166
  lookup_field(mod, key_and_path)
161
167
  end
162
168
 
163
- rescue IndexError
169
+ rescue KeyError, TypeError
164
170
 
165
171
  raise unless silence_index_error
166
172
  nil
@@ -174,6 +180,7 @@ class Flor::Node
174
180
 
175
181
  return @node.nid if k == 'nid'
176
182
  return @node.exid if k == 'exid'
183
+ return Flor.domain(@node.exid) if k == 'domain'
177
184
  return Flor.tstamp if k == 'tstamp'
178
185
 
179
186
  r = @node.lookup(k, true)
@@ -251,7 +258,7 @@ class Flor::Node
251
258
  nil
252
259
  end
253
260
 
254
- def to_procedure
261
+ def to_procedure_node
255
262
 
256
263
  Flor::Procedure.new(@executor, @node, @message)
257
264
  end
@@ -316,12 +323,12 @@ class Flor::Node
316
323
 
317
324
  def lookup_in_node(pth)
318
325
 
319
- Flor.deep_get(@node, pth)
326
+ Dense.fetch(@node, pth)
320
327
  end
321
328
 
322
329
  class PseudoVarContainer < Hash
323
330
  #
324
- # inherit from Hash so that deep.rb is quietly mislead
331
+ # inherit from Hash so that Dense is quietly mislead
325
332
  #
326
333
  def initialize(type); @type = type; end
327
334
  #def has_key?(key); true; end
@@ -331,23 +338,33 @@ class Flor::Node
331
338
  PROC_VAR_CONTAINER = PseudoVarContainer.new('proc')
332
339
  TASKER_VAR_CONTAINER = PseudoVarContainer.new('task')
333
340
 
341
+ def escape(k)
342
+
343
+ case k
344
+ when '*', '.' then "\\#{k}"
345
+ else k
346
+ end
347
+ end
348
+
334
349
  def lookup_var(node, mod, key, pth)
335
350
 
336
351
  c = lookup_var_container(node, mod, key)
337
352
 
338
353
  kp = [ key, pth ].reject { |x| x == nil || x.size < 1 }.join('.')
354
+ kp = escape(kp)
339
355
 
340
- v = Flor.deep_get(c, kp)
341
- #p [ mod, key, pth, '->', v ]
356
+ Dense.fetch(c, kp)
342
357
 
343
- return v unless v.is_a?(Symbol)
358
+ rescue KeyError => ke
344
359
 
345
- vs = v.to_s.split('.')
346
- tail = vs.pop
347
- vs = vs.join('.')
360
+ return nil if ke.miss[4].empty?
348
361
 
349
- fail IndexError.new("variable #{tail.inspect} not found") if vs.empty?
350
- fail IndexError.new("no key #{tail.inspect} in variable #{vs.inspect}")
362
+ m = "variable #{ke.miss[3].inspect} not found"
363
+ m += " at #{Dense::Path.make(ke.miss[1]).to_s.inspect}" if ke.miss[1].any?
364
+
365
+ raise ke.relabel(m)
366
+
367
+ #rescue TypeError => te # leave as is
351
368
  end
352
369
 
353
370
  def lookup_var_container(node, mod, key)
@@ -420,8 +437,11 @@ class Flor::Node
420
437
 
421
438
  def lookup_field(mod, key_and_path)
422
439
 
423
- r = Flor.deep_get(payload.current, key_and_path)
424
- r.is_a?(Symbol) ? nil : r
440
+ Dense.fetch(payload.current, key_and_path)
441
+
442
+ rescue IndexError
443
+
444
+ nil
425
445
  end
426
446
 
427
447
  def key_split(key) # => category, mode, key
@@ -429,9 +449,6 @@ class Flor::Node
429
449
  m = key.match(
430
450
  /\A(?:([lgd]?)((?:v|var|variable)|w|f|fld|field|t|tag)\.)?(.+)\z/)
431
451
 
432
- #fail ArgumentError.new("couldn't split key #{key.inspect}") unless m
433
- # spare that
434
-
435
452
  ca = (m[2] || 'v')[0, 1]
436
453
  mo = m[1] || ''
437
454
  ke = m[3]
@@ -1,6 +1,11 @@
1
1
 
2
2
  class Flor::Procedure < Flor::Node
3
3
 
4
+ # "Returning vars" variables to pass back to pass upon reply.
5
+ # In the 'receive' messages, it's a hash under the key 'rvars'.
6
+ #
7
+ RVARS = %w[ idx ]
8
+
4
9
  class << self
5
10
 
6
11
  def inherited(subclass)
@@ -50,6 +55,11 @@ class Flor::Procedure < Flor::Node
50
55
  # empty default implementation
51
56
  end
52
57
 
58
+ def prepare_on_receive_last(tree)
59
+
60
+ apply(tree.shift, [ @message ], tree[2])
61
+ end
62
+
53
63
  def trigger_on_error
54
64
 
55
65
  @message['on_error'] = true
@@ -57,7 +67,7 @@ class Flor::Procedure < Flor::Node
57
67
  close_node('on-error')
58
68
 
59
69
  @node['on_receive_last'] =
60
- apply(@node['on_error'].shift, [ @message ], tree[2])
70
+ apply(@node['on_error'].shift, [ @message, @message['error'] ], tree[2])
61
71
 
62
72
  do_wrap_cancel_children ||
63
73
  do_receive # which should trigger 'on_receive_last'
@@ -68,7 +78,7 @@ class Flor::Procedure < Flor::Node
68
78
  nid ||= self.nid
69
79
  tree = lookup_tree(nid)
70
80
 
71
- Flor.print_tree(tree, nid)
81
+ puts Flor.tree_to_s(tree, nid)
72
82
  end
73
83
 
74
84
  def debug_msg(msg=message)
@@ -89,6 +99,8 @@ class Flor::Procedure < Flor::Node
89
99
  wrap('nid' => parent, 'flavour' => 'flank')
90
100
  end
91
101
 
102
+ def heap; @node['heap']; end
103
+
92
104
  protected
93
105
 
94
106
  def counter_next(k)
@@ -136,6 +148,11 @@ class Flor::Procedure < Flor::Node
136
148
  children.select { |c| c[0] != '_att' }
137
149
  end
138
150
 
151
+ def non_att_count
152
+
153
+ non_att_children.size
154
+ end
155
+
139
156
  def unkeyed_children
140
157
 
141
158
  children.select { |c| c[0] != '_att' || c[1].size == 1 }
@@ -171,12 +188,16 @@ class Flor::Procedure < Flor::Node
171
188
 
172
189
  def att_a(*keys)
173
190
 
174
- if keys.last == nil
175
- keys.pop
176
- Flor.to_a(att(*keys))
177
- else
178
- Array(att(*keys))
179
- end
191
+ a =
192
+ if keys.last == nil
193
+ keys.pop
194
+ Flor.to_a(att(*keys))
195
+ else
196
+ Array(att(*keys))
197
+ end
198
+
199
+ return [ a ] if Flor.is_regex_tree?(a)
200
+ a
180
201
  end
181
202
 
182
203
  def tags_to_nids(tags)
@@ -225,7 +246,7 @@ class Flor::Procedure < Flor::Node
225
246
 
226
247
  unkeyed = unkeyed
227
248
  .collect { |c| c[1].first }
228
- .reject { |c| c[0] == '_' && c[1] == [] }
249
+ #.reject { |c| c[0] == '_' && c[1] == [] }
229
250
 
230
251
  cn = keyed + unkeyed + non_att_children
231
252
 
@@ -282,7 +303,8 @@ class Flor::Procedure < Flor::Node
282
303
  from_child = cnodes.delete(from) if cnodes_any? && remove
283
304
 
284
305
  if node_closed?
285
- return receive_from_child_when_closed if from_child
306
+ return receive_from_child_when_closed \
307
+ if from_child || node_status_flavour
286
308
  return receive_when_closed
287
309
  elsif node_ended?
288
310
  return receive_when_ended
@@ -291,6 +313,12 @@ class Flor::Procedure < Flor::Node
291
313
  receive
292
314
  end
293
315
 
316
+ def message_cause
317
+
318
+ (@message['cause'] || [])
319
+ .find { |c| c['nid'] == nid }
320
+ end
321
+
294
322
  def pop_on_receive_last
295
323
 
296
324
  orl = @node['on_receive_last']
@@ -298,7 +326,22 @@ class Flor::Procedure < Flor::Node
298
326
  return nil unless orl
299
327
  return nil if orl.empty?
300
328
 
301
- open_node unless node_status['flavour'] == 'on-error'
329
+ c = message_cause
330
+
331
+ #puts "<<<"
332
+ ##p @message
333
+ ##p @message['cause']
334
+ #p node_status
335
+ ##p @node['on_error']
336
+ #p c
337
+ ##puts caller[0, 3]
338
+ #puts ">>>"
339
+ open_node \
340
+ unless
341
+ (node_status_flavour == 'on-error') || # TODO use the cause ???
342
+ (c && c['cause'] == 'cancel' && @node['on_cancel']) ||
343
+ (c && c['cause'] == 'timeout' && @node['on_timeout'])
344
+
302
345
  @node['on_receive_last'] = []
303
346
 
304
347
  @node['mtime'] = Flor.tstamp
@@ -340,6 +383,11 @@ class Flor::Procedure < Flor::Node
340
383
  @fcid && (c = children[@fcid]) && c[0] == '_att'
341
384
  end
342
385
 
386
+ def last_receive?
387
+
388
+ children[@ncid] == nil
389
+ end
390
+
343
391
  def receive
344
392
 
345
393
  determine_fcid_and_ncid
@@ -369,10 +417,21 @@ class Flor::Procedure < Flor::Node
369
417
  execute_child(@ncid)
370
418
  end
371
419
 
420
+ # Prepare incoming ret for storage in @node['ret'] or @node['rets']
421
+ #
422
+ def receive_payload_ret
423
+
424
+ Flor.dup(payload['ret'])
425
+ end
426
+
372
427
  def receive_non_att
373
428
 
429
+ if @node.has_key?('ret')
430
+ @node['ret'] = receive_payload_ret
431
+ @node['mtime'] = Flor.tstamp
432
+ end
374
433
  if @node['rets']
375
- @node['rets'] << Flor.dup(payload['ret'])
434
+ @node['rets'] << receive_payload_ret
376
435
  @node['mtime'] = Flor.tstamp
377
436
  end
378
437
 
@@ -385,6 +444,25 @@ class Flor::Procedure < Flor::Node
385
444
  wrap_reply
386
445
  end
387
446
 
447
+ # Grab on_error proc from incoming payload and stores it into parent node.
448
+ #
449
+ # Has no effect if there is no parent node.
450
+ #
451
+ def store_on(key, prc=nil)
452
+
453
+ pnode = parent_node; return unless pnode
454
+
455
+ prc ||= payload['ret']
456
+
457
+ return unless Flor.is_func_tree?(prc)
458
+
459
+ flavour = "on_#{key}"
460
+
461
+ prc[1][flavour] = true
462
+
463
+ (pnode[flavour] ||= []) << prc
464
+ end
465
+
388
466
  # Used by 'cursor' (and 'loop') when
389
467
  # ```
390
468
  # cursor 'main'
@@ -418,6 +496,8 @@ class Flor::Procedure < Flor::Node
418
496
 
419
497
  m['sm'] = @message['m']
420
498
 
499
+ m['cause'] = @message['cause'] if @message.has_key?('cause')
500
+
421
501
  ret =
422
502
  if @node.has_key?('aret') # from the 'ret' common attribute
423
503
  @node['aret']
@@ -427,12 +507,21 @@ class Flor::Procedure < Flor::Node
427
507
  :no
428
508
  end
429
509
 
430
- m['payload'] = payload.current
510
+ m['payload'] = payload.dup_current
431
511
 
432
512
  m.merge!(h)
433
513
 
434
514
  m['payload']['ret'] = ret if ret != :no
435
515
 
516
+ if vs = @node['vars']
517
+ (RVARS & vs.keys).each { |k| (m['rvars'] ||= {})[k] = vs[k] }
518
+ end
519
+ #
520
+ # initially for "cmap"
521
+ #
522
+ # was considering passing the whole vars back (as 'varz'), but
523
+ # it got in the way... and it might be heavy
524
+
436
525
  [ m ]
437
526
  end
438
527
 
@@ -467,11 +556,11 @@ class Flor::Procedure < Flor::Node
467
556
 
468
557
  if vars
469
558
  return node if mode == 'l'
470
- return node if mode == '' && Flor.deep_has_key?(vars, k)
559
+ return node if mode == '' && Dense.has_key?(vars, k)
471
560
  end
472
561
 
473
562
  if cnode = mode == '' && @execution['nodes'][node['cnid']]
474
- return cnode if Flor.deep_has_key?(cnode['vars'], k)
563
+ return cnode if Dense.has_key?(cnode['vars'], k)
475
564
  end
476
565
 
477
566
  par = parent_node(node)
@@ -482,18 +571,34 @@ class Flor::Procedure < Flor::Node
482
571
  nil
483
572
  end
484
573
 
574
+ # List all the tags the current node is "included" in.
575
+ #
576
+ def list_tags
577
+
578
+ r = []
579
+ n = @node
580
+
581
+ while n
582
+ ts = n['tags']
583
+ r.concat(ts) if ts
584
+ n = @execution['nodes'][n['parent']]
585
+ end
586
+
587
+ r
588
+ end
589
+
485
590
  def set_var(mode, k, v)
486
591
 
487
592
  fail IndexError.new("cannot set domain variables") if mode == 'd'
488
593
 
489
- node = lookup_var_node(@node, mode, k)
490
- node = lookup_var_node(@node, 'l', k) if node.nil? && mode == ''
594
+ begin
491
595
 
492
- if node
596
+ node = lookup_var_node(@node, mode, k)
597
+ node = lookup_var_node(@node, 'l', k) if node.nil? && mode == ''
493
598
 
494
- v = Flor.deep_set(node['vars'], k, v)
599
+ return Dense.set(node['vars'], k, v) if node
495
600
 
496
- return v unless v.is_a?(Symbol)
601
+ rescue IndexError
497
602
  end
498
603
 
499
604
  fail IndexError.new("couldn't set var #{mode}v.#{k}")
@@ -501,11 +606,11 @@ class Flor::Procedure < Flor::Node
501
606
 
502
607
  def set_field(k, v)
503
608
 
504
- value = Flor.deep_set(payload.copy, k, v)
609
+ Dense.set(payload.copy, k, v)
505
610
 
506
- fail IndexError.new("couldn't set field #{k}") if value.is_a?(Symbol)
611
+ rescue IndexError
507
612
 
508
- value
613
+ fail IndexError.new("couldn't set field #{k}")
509
614
  end
510
615
 
511
616
  def set_value(k, v)
@@ -522,7 +627,10 @@ class Flor::Procedure < Flor::Node
522
627
  end
523
628
  end
524
629
 
525
- def apply(fun, args, line, anid=true)
630
+ def apply(fun, args, line, opts={})
631
+
632
+ anid = opts.has_key?(:anid) ? opts[:anid] : true
633
+ # true => generate sub_nid
526
634
 
527
635
  fni = fun[1]['nid'] # fun nid
528
636
  ani = anid ? Flor.sub_nid(fni, counter_next('subs')) : fni
@@ -540,8 +648,10 @@ class Flor::Procedure < Flor::Node
540
648
  sig = t[1].select { |c| c[0] == '_att' }
541
649
  sig = sig.drop(1) if t[0] == 'define'
542
650
 
543
- vars = {}
651
+ vars = opts[:vars] || {}
652
+ #
544
653
  vars['arguments'] = args # should I dup?
654
+ #
545
655
  sig.each_with_index do |att, i|
546
656
  key = att[1].first[0]
547
657
  vars[key] = args[i]
@@ -570,9 +680,7 @@ class Flor::Procedure < Flor::Node
570
680
 
571
681
  def wrap_cancelled
572
682
 
573
- wrap(
574
- 'cause' => 'cancel',
575
- 'payload' => @message['payload'] || @node['payload'])
683
+ wrap('payload' => @message['payload'] || @node['payload'])
576
684
  end
577
685
 
578
686
  def wrap_cancel_children(h={})
@@ -585,37 +693,68 @@ class Flor::Procedure < Flor::Node
585
693
  wrap_cancel_children(h).instance_eval { |ms| ms.any? ? ms : nil }
586
694
  end
587
695
 
588
- # The executor calls #do_cancel, while most procedure implementations
589
- # override #cancel...
696
+ # Called by the executor, in turns call cancel and cancel_when_ methods
697
+ # which may be overriden.
590
698
  #
591
699
  def do_cancel
592
700
 
593
- if @message['flavour'] == 'kill'
701
+ if orl = @message['on_receive_last']
702
+ #
703
+ # the message on_receive_last is used by the re_apply feature
704
+
705
+ @node['on_receive_last'] = orl
594
706
 
595
- return [] if node_ended?
596
- kill
707
+ elsif @message['flavour'] == 'timeout' && ot = @node['on_timeout']
597
708
 
598
- else
709
+ @node['on_receive_last'] = prepare_on_receive_last(ot)
599
710
 
600
- orl = @message['on_receive_last']
601
- @node['on_receive_last'] = orl if orl
711
+ elsif oc = @node['on_cancel']
602
712
 
603
- return cancel_when_ended if node_ended?
604
- return cancel_when_closed if node_closed?
605
- cancel
713
+ @node['on_receive_last'] = prepare_on_receive_last(oc)
606
714
  end
715
+
716
+ return cancel_when_ended if node_ended?
717
+ return cancel_when_closed if node_closed?
718
+
719
+ cancel
720
+ end
721
+
722
+ # Called by the executor, in turns call kill and kill_when_ methods
723
+ # which may be overriden.
724
+ #
725
+ def do_kill
726
+
727
+ return kill_when_ended if node_ended?
728
+ #return kill_when_closed if node_closed? # nothing of the sort
729
+
730
+ kill
607
731
  end
608
732
 
733
+ # Handle an incoming cancel message when the node has ended.
734
+ # Open for override.
735
+ #
609
736
  def cancel_when_ended
610
737
 
611
738
  [] # node has already emitted reply to parent, ignore any later request
612
739
  end
613
740
 
741
+ # Handle an incoming cancel message when the node has closed.
742
+ # Open for override (overridden by "cursor" and "until")
743
+ #
614
744
  def cancel_when_closed
615
745
 
616
746
  [] # by default, no effect
617
747
  end
618
748
 
749
+ # When the node has ended, incoming kill messages are silenced ([] return).
750
+ #
751
+ def kill_when_ended
752
+
753
+ [] # no effect
754
+ end
755
+
756
+ # The core cancel work, is overriden by some procedure implementations.
757
+ #
619
758
  def cancel
620
759
 
621
760
  close_node
@@ -625,6 +764,9 @@ class Flor::Procedure < Flor::Node
625
764
  wrap_cancelled
626
765
  end
627
766
 
767
+ # The core kill work, open for override, but actually no procedure
768
+ # provides a custom implementation. Kill is kill for every of the procs.
769
+ #
628
770
  def kill
629
771
 
630
772
  close_node
@@ -645,7 +787,7 @@ class Flor::Macro < Flor::Procedure
645
787
  def rewrite
646
788
 
647
789
  t = rewrite_tree
648
- #Flor.print_tree(t, nid)
790
+ #puts Flor.tree_to_s(t, nid)
649
791
 
650
792
  m = @message.dup
651
793
  m['tree'] = t