flor 0.11.0 → 0.12.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.
Files changed (60) hide show
  1. data/CHANGELOG.md +7 -0
  2. data/Makefile +3 -0
  3. data/lib/flor.rb +1 -1
  4. data/lib/flor/colours.rb +7 -3
  5. data/lib/flor/conf.rb +21 -15
  6. data/lib/flor/core/executor.rb +71 -77
  7. data/lib/flor/core/node.rb +6 -1
  8. data/lib/flor/core/procedure.rb +112 -58
  9. data/lib/flor/core/texecutor.rb +6 -5
  10. data/lib/flor/log.rb +9 -7
  11. data/lib/flor/migrations/0003_timer_onid_bnid.rb +35 -0
  12. data/lib/flor/migrations/0004_trap_bnid.rb +16 -0
  13. data/lib/flor/pcore/_arr.rb +2 -2
  14. data/lib/flor/pcore/_atom.rb +1 -1
  15. data/lib/flor/pcore/_att.rb +59 -13
  16. data/lib/flor/pcore/_happly.rb +3 -3
  17. data/lib/flor/pcore/_obj.rb +22 -2
  18. data/lib/flor/pcore/_skip.rb +2 -2
  19. data/lib/flor/pcore/apply.rb +1 -1
  20. data/lib/flor/pcore/arith.rb +1 -1
  21. data/lib/flor/pcore/break.rb +2 -2
  22. data/lib/flor/pcore/case.rb +1 -1
  23. data/lib/flor/pcore/cmp.rb +1 -1
  24. data/lib/flor/pcore/cond.rb +1 -1
  25. data/lib/flor/pcore/cursor.rb +2 -2
  26. data/lib/flor/pcore/define.rb +1 -1
  27. data/lib/flor/pcore/fail.rb +1 -6
  28. data/lib/flor/pcore/if.rb +2 -2
  29. data/lib/flor/pcore/map.rb +1 -1
  30. data/lib/flor/pcore/matchr.rb +92 -0
  31. data/lib/flor/pcore/move.rb +2 -3
  32. data/lib/flor/pcore/noeval.rb +1 -1
  33. data/lib/flor/pcore/noret.rb +1 -1
  34. data/lib/flor/pcore/push.rb +1 -1
  35. data/lib/flor/pcore/rand.rb +1 -1
  36. data/lib/flor/pcore/set.rb +1 -1
  37. data/lib/flor/pcore/twig.rb +2 -2
  38. data/lib/flor/pcore/until.rb +4 -1
  39. data/lib/flor/pcore/val.rb +1 -1
  40. data/lib/flor/punit/cancel.rb +2 -3
  41. data/lib/flor/punit/cmap.rb +5 -6
  42. data/lib/flor/punit/concurrence.rb +3 -5
  43. data/lib/flor/punit/schedule.rb +20 -5
  44. data/lib/flor/punit/signal.rb +1 -1
  45. data/lib/flor/punit/sleep.rb +2 -2
  46. data/lib/flor/punit/task.rb +3 -3
  47. data/lib/flor/punit/trace.rb +1 -1
  48. data/lib/flor/punit/trap.rb +22 -6
  49. data/lib/flor/to_string.rb +2 -1
  50. data/lib/flor/unit/executor.rb +3 -5
  51. data/lib/flor/unit/hooker.rb +2 -3
  52. data/lib/flor/unit/models/timer.rb +9 -3
  53. data/lib/flor/unit/models/trap.rb +1 -0
  54. data/lib/flor/unit/scheduler.rb +40 -35
  55. data/lib/flor/unit/storage.rb +70 -59
  56. data/lib/flor/unit/waiter.rb +2 -3
  57. data/t.txt +4 -0
  58. metadata +6 -4
  59. data/fail.txt +0 -3
  60. data/lib/flor/pcore/match.rb +0 -46
@@ -31,9 +31,9 @@ module Flor
31
31
  []
32
32
  end
33
33
 
34
- def remove_node(exid, n)
34
+ def archive_node(exid, node)
35
35
 
36
- (@archive[exid] ||= {})[n['nid']] = Flor.dup(n) if @archive
36
+ (@archive[exid] ||= {})[node['nid']] = Flor.dup(node) if @archive
37
37
  end
38
38
 
39
39
  def has_tasker?(exid, tname)
@@ -59,8 +59,7 @@ module Flor
59
59
 
60
60
  def initialize(conf={})
61
61
 
62
- conf.merge!(Flor::Conf.read_env) unless conf['conf'] == true
63
- # don't read FLOR_DEBUG if this executor is only meant to read the conf
62
+ conf = Flor::Conf.prepare(conf, {})
64
63
 
65
64
  super(
66
65
  TransientUnit.new(conf),
@@ -72,6 +71,8 @@ module Flor
72
71
  #'ashes' => {},
73
72
  'start' => Flor.tstamp
74
73
  })
74
+
75
+ @unit.archive = {} if conf['archive']
75
76
  end
76
77
 
77
78
  def journal; @unit.journal; end
@@ -80,7 +81,7 @@ module Flor
80
81
  def launch(tree, opts={})
81
82
 
82
83
  @unit.opts = opts
83
- @unit.archive = {} if opts[:archive]
84
+ @unit.archive ||= {} if opts[:archive]
84
85
 
85
86
  Flor.print_src(tree, opts) if conf['log_src']
86
87
 
data/lib/flor/log.rb CHANGED
@@ -142,6 +142,8 @@ module Flor
142
142
 
143
143
  def self.print_tree(tree, nid='0', opts={})
144
144
 
145
+ t0, t1, t2 = (tree || [])
146
+
145
147
  o = (opts[:out] ||= $stdout)
146
148
  _c = colours(opts)
147
149
 
@@ -150,14 +152,14 @@ module Flor
150
152
  headers = opts[:headers]; headers = true if headers.nil?
151
153
  headers = true if opts[:title]
152
154
 
153
- h = "#{_c.yl}#{Flor.to_d(tree[0], compact: true)}"
154
- c = tree[1].is_a?(Array) ? '' : " #{_c.yl}#{tree[1]}"
155
- l = " #{_c.dg}L#{tree[2]}"
155
+ h = "#{_c.yl}#{Flor.to_d(t0, compact: true)}"
156
+ c = t1.is_a?(Array) ? '' : " #{_c.yl}#{t1}"
157
+ l = " #{_c.dg}L#{t2}"
156
158
 
157
159
  o.puts "#{ind}#{_c.dg}+--- #{opts[:title]}#{_c.rs}" if headers && nid == '0'
158
160
  o.puts "#{ind}#{_c.dg}| #{nid} #{h}#{c}#{l}#{_c.rs}"
159
- if tree[1].is_a?(Array)
160
- tree[1].each_with_index { |ct, i| print_tree(ct, "#{nid}_#{i}", opts) }
161
+ if t1.is_a?(Array)
162
+ t1.each_with_index { |ct, i| print_tree(ct, Flor.child_nid(nid, i), opts) }
161
163
  end
162
164
  o.puts "#{ind}#{_c.dg}.#{_c.rs}" if headers && nid == '0'
163
165
 
@@ -235,7 +237,7 @@ module Flor
235
237
  t = Flor.truncate_string(t, 42);
236
238
 
237
239
  h = {}
238
- %w[ parent cnid noreply dbg removed ].each do |k|
240
+ %w[ parent cnid noreply dbg ].each do |k|
239
241
  h[k] = n[k] if n.has_key?(k)
240
242
  end
241
243
 
@@ -306,7 +308,7 @@ module Flor
306
308
  o.puts "#{_c.dg}payload:#{_c.yl}"
307
309
  o.puts(Flor.to_pretty_s(m['payload'], 0))
308
310
  o.puts "#{_c.dg}tree:"
309
- print_tree(node.lookup_tree(nid), nid, out: o) if node # FIXME
311
+ print_tree(node.lookup_tree(nid), nid, out: o) if node
310
312
  o.puts "#{_c.dg}node:#{_c.yl}"
311
313
  o.puts(Flor.to_pretty_s(n)) if n
312
314
  o.puts "#{_c.dg}nodes:"
@@ -0,0 +1,35 @@
1
+
2
+ Sequel.migration do
3
+
4
+ up do
5
+
6
+ alter_table :flor_timers do
7
+
8
+ add_column :onid, String
9
+ add_column :bnid, String
10
+ end
11
+
12
+ self[:flor_timers].update(onid: :nid)
13
+ self[:flor_timers].update(bnid: :nid)
14
+
15
+ alter_table :flor_timers do
16
+
17
+ set_column_not_null :onid
18
+ set_column_not_null :bnid
19
+ end
20
+ #
21
+ # Sqlite3, for example, does that by renaming "flor_timers",
22
+ # creating a new table with the "not null" set, then copying the
23
+ # values of the renamed, original, table into the new table...
24
+ end
25
+
26
+ down do
27
+
28
+ alter_table :flor_timers do
29
+
30
+ drop_column :onid
31
+ drop_column :bnid
32
+ end
33
+ end
34
+ end
35
+
@@ -0,0 +1,16 @@
1
+
2
+ Sequel.migration do
3
+
4
+ up do
5
+
6
+ alter_table(:flor_traps) { add_column :bnid, String }
7
+ self[:flor_traps].update(bnid: :nid)
8
+ alter_table(:flor_traps) { set_column_not_null :bnid }
9
+ end
10
+
11
+ down do
12
+
13
+ alter_table(:flor_traps) { drop_column :bnid }
14
+ end
15
+ end
16
+
@@ -10,7 +10,7 @@ class Flor::Pro::Arr < Flor::Procedure
10
10
 
11
11
  def receive
12
12
 
13
- return reply('ret' => []) if children == 0
13
+ return wrap_reply('ret' => []) if children == 0
14
14
 
15
15
  super
16
16
  end
@@ -19,7 +19,7 @@ class Flor::Pro::Arr < Flor::Procedure
19
19
 
20
20
  payload['ret'] = @node['rets']
21
21
 
22
- reply
22
+ wrap_reply
23
23
  end
24
24
  end
25
25
 
@@ -13,7 +13,7 @@ class Flor::Pro::Atom < Flor::Procedure
13
13
  else tree[1]
14
14
  end
15
15
 
16
- reply
16
+ wrap_reply
17
17
  end
18
18
  end
19
19
 
@@ -5,11 +5,14 @@ class Flor::Pro::Att < Flor::Procedure
5
5
 
6
6
  def execute
7
7
 
8
- return reply if children == [ [ '_', [], tree[2] ] ]
8
+ return wrap_reply if children == [ [ '_', [], tree[2] ] ]
9
9
  # spares 1 message
10
10
 
11
11
  pt = parent_node['tree']
12
- return reply if pt && pt[0] == '_apply'
12
+ return wrap_reply if pt && pt[0] == '_apply'
13
+
14
+ m = "pre_execute_#{children[0][0]}"
15
+ send(m) if respond_to?(m, true)
13
16
 
14
17
  execute_child(0, nil, 'accept_symbol' => children.size > 1)
15
18
  end
@@ -25,6 +28,36 @@ class Flor::Pro::Att < Flor::Procedure
25
28
 
26
29
  protected
27
30
 
31
+ #
32
+ # execute phase
33
+
34
+ def pre_execute_boolean_attribute
35
+
36
+ return unless children.size == 1
37
+
38
+ t = @node['tree'] = Flor.dup(tree)
39
+ t[1] << [ '_boo', true, @node['tree'][2] ]
40
+ end
41
+
42
+ alias pre_execute_flank pre_execute_boolean_attribute
43
+
44
+ def pre_execute_vars
45
+
46
+ return unless children.size == 2 && children[1][0] == '_obj'
47
+
48
+ t = tree
49
+
50
+ return if t[1][1][1] == 0 # [ '_obj', 0, 123 ]
51
+
52
+ t = @node['tree'] = Flor.dup(t)
53
+
54
+ t[1][1][1].unshift([
55
+ '_att', [ [ 'quote', [], -1 ], [ '_sqs', 'keys', -1 ] ], -1 ])
56
+ end
57
+
58
+ #
59
+ # receive phase
60
+
28
61
  def receive_unkeyed
29
62
 
30
63
  receive_att(nil)
@@ -71,17 +104,21 @@ class Flor::Pro::Att < Flor::Procedure
71
104
 
72
105
  payload['ret'] = @node['ret'] if key
73
106
 
74
- reply
107
+ wrap_reply
75
108
  end
76
109
 
77
110
  # vars: { ... }, inits a scope for the parent node
78
111
  #
79
112
  def receive_vars
80
113
 
81
- parent_node['vars'] = payload['ret']
114
+ vars = payload['ret']
115
+ vars = @executor.vars(nid) if vars == 'copy' || vars == '*'
116
+
117
+ (parent_node['vars'] ||= {}).merge!(vars)
118
+
82
119
  payload['ret'] = @node['ret']
83
120
 
84
- reply
121
+ wrap_reply
85
122
  end
86
123
 
87
124
  def receive_tag
@@ -96,13 +133,13 @@ class Flor::Pro::Att < Flor::Procedure
96
133
 
97
134
  tags = Array(ret)
98
135
 
99
- return reply if tags.empty?
136
+ return wrap_reply if tags.empty?
100
137
 
101
138
  (parent_node['tags'] ||= []).concat(tags)
102
139
  parent_node['tags'].uniq!
103
140
 
104
- reply('point' => 'entered', 'tags' => tags) +
105
- reply
141
+ wrap('point' => 'entered', 'tags' => tags) +
142
+ wrap_reply
106
143
  end
107
144
  alias receive_tags receive_tag
108
145
 
@@ -112,17 +149,17 @@ class Flor::Pro::Att < Flor::Procedure
112
149
  pn['aret'] = Flor.dup(payload['ret'])
113
150
  end
114
151
 
115
- reply
152
+ wrap_reply
116
153
  end
117
154
 
118
155
  def receive_timeout
119
156
 
120
157
  n = parent
121
- m = reply('point' => 'cancel', 'nid' => n, 'flavour' => 'timeout').first
158
+ m = wrap_cancel('nid' => n, 'flavour' => 'timeout').first
122
159
  t = payload['ret']
123
160
 
124
- schedule('type' => 'in', 'string' => t, 'nid' => n, 'message' => m) +
125
- reply
161
+ wrap_schedule('type' => 'in', 'string' => t, 'nid' => n, 'message' => m) +
162
+ wrap_reply
126
163
  end
127
164
 
128
165
  def receive_on_error
@@ -132,7 +169,16 @@ class Flor::Pro::Att < Flor::Procedure
132
169
 
133
170
  (parent_node['on_error'] ||= []) << oe
134
171
 
135
- reply
172
+ wrap_reply
173
+ end
174
+
175
+ def receive_flank
176
+
177
+ return wrap_reply unless Flor.true?(payload['ret'])
178
+ return wrap_reply unless parent_node
179
+
180
+ Flor::Procedure.make(@executor, parent_node, @message).flank +
181
+ wrap_reply
136
182
  end
137
183
  end
138
184
 
@@ -10,7 +10,7 @@ class Flor::Pro::Happly < Flor::Procedure
10
10
 
11
11
  def execute
12
12
 
13
- queue(
13
+ wrap(
14
14
  'point' => 'execute',
15
15
  'nid' => Flor.child_nid(nid, tree[1].size),
16
16
  'tree' => tree[0])
@@ -20,7 +20,7 @@ class Flor::Pro::Happly < Flor::Procedure
20
20
 
21
21
  fcid = Flor.child_id(message['from'])
22
22
 
23
- return reply if @node['applied']
23
+ return wrap_reply if @node['applied']
24
24
  return super unless fcid == tree[1].size
25
25
 
26
26
  ret = payload['ret']
@@ -33,7 +33,7 @@ class Flor::Pro::Happly < Flor::Procedure
33
33
 
34
34
  hret = @node['hret']
35
35
 
36
- return reply('ret' => hret) unless Flor.is_func_tree?(hret)
36
+ return wrap_reply('ret' => hret) unless Flor.is_func_tree?(hret)
37
37
 
38
38
  args = @node['atts'].collect(&:last)
39
39
 
@@ -6,11 +6,31 @@ class Flor::Pro::Obj < Flor::Procedure
6
6
  def pre_execute
7
7
 
8
8
  @node['rets'] = []
9
+ @node['atts'] = []
10
+ end
11
+
12
+ def receive_last_att
13
+
14
+ return super unless att('quote') == 'keys'
15
+
16
+ t0 = tree
17
+ t1 = Flor.dup(t0)
18
+
19
+ (@ncid..t1[1].length - 1).step(2) do |i|
20
+
21
+ c = t1[1][i]
22
+
23
+ t1[1][i] = [ '_sqs', c[0], *c[2..-1] ] if c[0].is_a?(String) && c[1] == []
24
+ end
25
+
26
+ @node['tree'] = t1 if t1 != t0
27
+
28
+ super
9
29
  end
10
30
 
11
31
  def receive_first
12
32
 
13
- return reply('ret' => {}) if children == 0
33
+ return wrap_reply('ret' => {}) if children == 0
14
34
 
15
35
  cn = children
16
36
  .inject([]) { |a, e| a << (a.size.even? ? stringify(e) : e); a }
@@ -27,7 +47,7 @@ class Flor::Pro::Obj < Flor::Procedure
27
47
  .each_slice(2)
28
48
  .inject({}) { |h, (k, v)| h[k.to_s] = v; h }
29
49
 
30
- reply
50
+ wrap_reply
31
51
  end
32
52
 
33
53
  protected
@@ -23,9 +23,9 @@ class Flor::Pro::Skip < Flor::Procedure
23
23
 
24
24
  @node['count'] -= 1
25
25
 
26
- return reply if @node['count'] < 1
26
+ return wrap_reply if @node['count'] < 1
27
27
 
28
- reply('nid' => nid, 'from' => Flor.child_nid(nid, children.size))
28
+ wrap_reply('nid' => nid, 'from' => Flor.child_nid(nid, children.size))
29
29
  end
30
30
 
31
31
  def receive_last
@@ -33,7 +33,7 @@ class Flor::Pro::Apply < Flor::Procedure
33
33
 
34
34
  def receive
35
35
 
36
- return reply if from && from == @node['applied']
36
+ return wrap_reply if from && from == @node['applied']
37
37
 
38
38
  super
39
39
  end
@@ -16,7 +16,7 @@ class Flor::Pro::Arith < Flor::Procedure
16
16
 
17
17
  payload['ret'] = @node['rets'].reduce(&sign) || DEFAULTS[sign]
18
18
 
19
- reply
19
+ wrap_reply
20
20
  end
21
21
  end
22
22
 
@@ -30,7 +30,7 @@ class Flor::Pro::Break < Flor::Procedure
30
30
 
31
31
  if nid
32
32
 
33
- ms += reply('point' => 'cancel', 'nid' => nid, 'flavour' => @node['heap'])
33
+ ms += wrap_cancel('nid' => nid, 'flavour' => @node['heap'])
34
34
  end
35
35
 
36
36
  unless is_ancestor_node?(nid)
@@ -38,7 +38,7 @@ class Flor::Pro::Break < Flor::Procedure
38
38
  pl = ms.any? ? payload.copy_current : payload.current
39
39
  pl['ret'] = node_payload_ret
40
40
 
41
- ms += reply('payload' => pl)
41
+ ms += wrap_reply('payload' => pl)
42
42
  end
43
43
 
44
44
  ms
@@ -42,7 +42,7 @@ class Flor::Pro::Case < Flor::Procedure
42
42
 
43
43
  def receive_non_att
44
44
 
45
- return reply if @node['found']
45
+ return wrap_reply if @node['found']
46
46
 
47
47
  return receive_array if @node.has_key?('key')
48
48
 
@@ -21,7 +21,7 @@ class Flor::Pro::Cmp < Flor::Procedure
21
21
  true
22
22
  end
23
23
 
24
- reply
24
+ wrap_reply
25
25
  end
26
26
 
27
27
  protected
@@ -30,7 +30,7 @@ class Flor::Pro::Cond < Flor::Procedure
30
30
  def receive_non_att
31
31
 
32
32
  return execute_child(0) if @message['point'] == 'execute'
33
- return reply if @node['found']
33
+ return wrap_reply if @node['found']
34
34
 
35
35
  tf2 = tree[1][@fcid + 2]
36
36