flor 0.0.1 → 0.9.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 (84) hide show
  1. data/CHANGELOG.md +13 -0
  2. data/LICENSE.txt +1 -1
  3. data/Makefile +66 -0
  4. data/README.md +57 -0
  5. data/fail.txt +7 -0
  6. data/flor.gemspec +12 -9
  7. data/intercepted.txt +123 -0
  8. data/lib/flor/colours.rb +140 -0
  9. data/lib/flor/conf.rb +88 -0
  10. data/lib/flor/core/executor.rb +473 -0
  11. data/lib/flor/core/node.rb +397 -0
  12. data/lib/flor/core/procedure.rb +600 -0
  13. data/lib/flor/core/texecutor.rb +209 -0
  14. data/lib/flor/core.rb +93 -0
  15. data/lib/flor/dollar.rb +248 -0
  16. data/lib/flor/errors.rb +36 -0
  17. data/lib/flor/flor.rb +556 -0
  18. data/lib/flor/log.rb +336 -0
  19. data/lib/flor/migrations/0001_tables.rb +122 -0
  20. data/lib/flor/parser.rb +414 -0
  21. data/lib/flor/pcore/_arr.rb +49 -0
  22. data/lib/flor/pcore/_atom.rb +43 -0
  23. data/lib/flor/pcore/_att.rb +160 -0
  24. data/lib/flor/pcore/_dump.rb +60 -0
  25. data/lib/flor/pcore/_err.rb +30 -0
  26. data/lib/flor/pcore/_happly.rb +73 -0
  27. data/lib/flor/pcore/_obj.rb +65 -0
  28. data/lib/flor/pcore/_skip.rb +63 -0
  29. data/lib/flor/pcore/apply.rb +60 -0
  30. data/lib/flor/pcore/arith.rb +46 -0
  31. data/lib/flor/pcore/break.rb +71 -0
  32. data/lib/flor/pcore/cmp.rb +72 -0
  33. data/lib/flor/pcore/cond.rb +57 -0
  34. data/lib/flor/pcore/cursor.rb +223 -0
  35. data/lib/flor/pcore/define.rb +96 -0
  36. data/lib/flor/pcore/fail.rb +45 -0
  37. data/lib/flor/pcore/ife.rb +56 -0
  38. data/lib/flor/pcore/loop.rb +53 -0
  39. data/lib/flor/pcore/map.rb +75 -0
  40. data/lib/flor/pcore/match.rb +70 -0
  41. data/lib/flor/pcore/move.rb +65 -0
  42. data/lib/flor/pcore/noeval.rb +46 -0
  43. data/lib/flor/pcore/noret.rb +47 -0
  44. data/lib/flor/pcore/push.rb +69 -0
  45. data/lib/flor/pcore/sequence.rb +39 -0
  46. data/lib/flor/pcore/set.rb +76 -0
  47. data/lib/flor/pcore/stall.rb +35 -0
  48. data/lib/flor/pcore/until.rb +122 -0
  49. data/lib/flor/pcore/val.rb +40 -0
  50. data/lib/flor/punit/cancel.rb +69 -0
  51. data/lib/flor/punit/cmap.rb +76 -0
  52. data/lib/flor/punit/concurrence.rb +149 -0
  53. data/lib/flor/punit/every.rb +46 -0
  54. data/lib/flor/punit/on.rb +81 -0
  55. data/lib/flor/punit/schedule.rb +68 -0
  56. data/lib/flor/punit/signal.rb +47 -0
  57. data/lib/flor/punit/sleep.rb +53 -0
  58. data/lib/flor/punit/task.rb +109 -0
  59. data/lib/flor/punit/trace.rb +51 -0
  60. data/lib/flor/punit/trap.rb +100 -0
  61. data/lib/flor/to_string.rb +81 -0
  62. data/lib/flor/tools/env.rb +103 -0
  63. data/lib/flor/tools/repl.rb +231 -0
  64. data/lib/flor/unit/executor.rb +260 -0
  65. data/lib/flor/unit/hooker.rb +186 -0
  66. data/lib/flor/unit/journal.rb +52 -0
  67. data/lib/flor/unit/loader.rb +181 -0
  68. data/lib/flor/unit/logger.rb +181 -0
  69. data/lib/flor/unit/models/execution.rb +105 -0
  70. data/lib/flor/unit/models/pointer.rb +31 -0
  71. data/lib/flor/unit/models/timer.rb +52 -0
  72. data/lib/flor/unit/models/trace.rb +31 -0
  73. data/lib/flor/unit/models/trap.rb +130 -0
  74. data/lib/flor/unit/models.rb +106 -0
  75. data/lib/flor/unit/scheduler.rb +419 -0
  76. data/lib/flor/unit/storage.rb +633 -0
  77. data/lib/flor/unit/tasker.rb +191 -0
  78. data/lib/flor/unit/waiter.rb +146 -0
  79. data/lib/flor/unit/wlist.rb +77 -0
  80. data/lib/flor/unit.rb +50 -0
  81. data/lib/flor.rb +40 -3
  82. metadata +152 -22
  83. checksums.yaml +0 -7
  84. data/Rakefile +0 -52
@@ -0,0 +1,397 @@
1
+ #--
2
+ # Copyright (c) 2015-2017, John Mettraux, jmettraux+flor@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+ #
22
+ # Made in Japan.
23
+ #++
24
+
25
+
26
+ class Flor::Node
27
+
28
+ class Payload
29
+ def initialize(node, type=:node)
30
+ @node = node
31
+ @type = type
32
+ end
33
+ def has_key?(k)
34
+ current.has_key?(k)
35
+ end
36
+ def [](k)
37
+ current[k]
38
+ end
39
+ def []=(k, v)
40
+ copy[k] = v
41
+ end
42
+ def delete(k)
43
+ copy.delete(k)
44
+ end
45
+ def copy
46
+ container['pld'] ||= Flor.dup(original)
47
+ end
48
+ def current
49
+ container['pld'] || container['payload']
50
+ end
51
+ def copy_current
52
+ Flor.dup(current)
53
+ end
54
+ def merge(h)
55
+ current.merge(h)
56
+ end
57
+ protected
58
+ def container
59
+ @type == :node ? @node.h : @node.message
60
+ end
61
+ def original
62
+ container['payload']
63
+ end
64
+ end
65
+
66
+ attr_reader :message
67
+
68
+ def initialize(executor, node, message)
69
+
70
+ @executor, @execution =
71
+ case executor
72
+ when nil then [ nil, nil ] # for some tests
73
+ when Hash then [ nil, executor ] # from some other tests
74
+ else [ executor, executor.execution ] # vanilla case
75
+ end
76
+
77
+ @node =
78
+ if node
79
+ node
80
+ elsif message
81
+ @execution['nodes'][message['nid']]
82
+ else
83
+ nil
84
+ end
85
+
86
+ @message = message
87
+ end
88
+
89
+ def h; @node; end
90
+
91
+ def exid; @execution['exid']; end
92
+ def nid; @node['nid']; end
93
+ def parent; @node['parent']; end
94
+
95
+ def domain; Flor.domain(@execution['exid']); end
96
+
97
+ def point; @message['point']; end
98
+ def from; @message['from']; end
99
+
100
+ def payload
101
+ @message_payload ||= Payload.new(self, :message)
102
+ end
103
+
104
+ def node_status
105
+ @node['status'].last
106
+ end
107
+ def node_closed?
108
+ node_status['status'] == 'closed'
109
+ end
110
+ def node_ended?
111
+ node_status['status'] == 'ended'
112
+ end
113
+ def node_open?
114
+ node_status['status'] == nil
115
+ end
116
+
117
+ def node_payload
118
+ @node_payload ||= Payload.new(self)
119
+ end
120
+ def node_payload_ret
121
+ Flor.dup(node_payload['ret'])
122
+ end
123
+
124
+ def message_or_node_payload
125
+ payload.current ? payload : node_payload
126
+ end
127
+
128
+ def lookup_tree(nid)
129
+
130
+ return nil unless nid
131
+
132
+ node = @execution['nodes'][nid]
133
+
134
+ tree = node && node['tree']
135
+ return tree if tree
136
+
137
+ par = node && node['parent']
138
+ cid = Flor.child_id(nid)
139
+
140
+ tree = par && lookup_tree(par)
141
+ return subtree(tree, par, nid) if tree
142
+
143
+ return nil if node
144
+
145
+ tree = lookup_tree(Flor.parent_nid(nid))
146
+ return tree[1][cid] if tree
147
+
148
+ #tree = lookup_tree(Flor.parent_nid(nid, true))
149
+ #return tree[1][cid] if tree
150
+ #
151
+ # might become necessary at some point
152
+
153
+ nil
154
+ end
155
+
156
+ #def lookup_tree(nid)
157
+ # climb_down_for_tree(nid) ||
158
+ # climb_up_for_tree(nid) ||
159
+ #end
160
+ #def climb_up_for_tree(nid)
161
+ # # ...
162
+ #end
163
+ #def climb_down_for_tree(nid)
164
+ # # ...
165
+ #end
166
+ #
167
+ # that might be the way...
168
+
169
+ def lookup(name)
170
+
171
+ cat, mod, key = key_split(name)
172
+ key, pth = key.split('.', 2)
173
+
174
+ val =
175
+ if [ cat, mod, key ] == [ 'v', '', 'node' ]
176
+ @node
177
+ elsif cat == 'v'
178
+ lookup_var(@node, mod, key)
179
+ else
180
+ lookup_field(mod, key)
181
+ end
182
+
183
+ if pth
184
+ Flor.deep_get(val, pth)[1]
185
+ else
186
+ val
187
+ end
188
+ end
189
+
190
+ class Expander < Flor::Dollar
191
+
192
+ def initialize(n); @node = n; end
193
+
194
+ def lookup(k)
195
+
196
+ return @node.nid if k == 'nid'
197
+ return @node.exid if k == 'exid'
198
+ return Flor.tstamp if k == 'tstamp'
199
+
200
+ @node.lookup(k)
201
+ end
202
+ end
203
+
204
+ def expand(s)
205
+
206
+ return s unless s.is_a?(String)
207
+
208
+ Expander.new(self).expand(s)
209
+ end
210
+
211
+ def deref(o)
212
+
213
+ return o unless o.is_a?(String)
214
+
215
+ v = lookup(o)
216
+
217
+ return v unless Flor.is_tree?(v)
218
+ return v unless v[1].is_a?(Hash)
219
+
220
+ return v unless %w[ _proc _task _func ].include?(v[0])
221
+
222
+ ref =
223
+ case v[0]
224
+ when '_func' then true
225
+ when '_proc' then v[1]['proc'] != o
226
+ when '_task' then v[1]['task'] != o
227
+ else false
228
+ end
229
+
230
+ v[1]['oref'] ||= v[1]['ref'] if ref && v[1]['ref']
231
+ v[1]['ref'] = o if ref
232
+
233
+ v
234
+ end
235
+
236
+ def tree
237
+
238
+ lookup_tree(nid)
239
+ end
240
+
241
+ def fei
242
+
243
+ "#{exid}-#{nid}"
244
+ end
245
+
246
+ def on_error_parent
247
+
248
+ oe = @node['on_error']
249
+ return self if oe && oe.any?
250
+
251
+ pn = parent_node
252
+ return Flor::Node.new(@executor, pn, @message).on_error_parent if pn
253
+
254
+ nil
255
+ end
256
+
257
+ def to_procedure
258
+
259
+ Flor::Procedure.new(@executor, @node, @message)
260
+ end
261
+
262
+ def descendant_of?(nid, on_self=true)
263
+
264
+ return on_self if self.nid == nid && on_self != nil
265
+
266
+ i = self.nid
267
+
268
+ loop do
269
+ node = @executor.node(i)
270
+ break unless node
271
+ i = node['parent']
272
+ return true if i == nid
273
+ end
274
+
275
+ false
276
+ end
277
+
278
+ protected
279
+
280
+ def subtree(tree, pnid, nid)
281
+
282
+ pnid = Flor.master_nid(pnid)
283
+ nid = Flor.master_nid(nid)
284
+
285
+ return nil unless nid[0, pnid.length] == pnid
286
+ # maybe failing would be better
287
+
288
+ cid = nid[pnid.length + 1..-1]
289
+
290
+ return nil unless cid
291
+ # maybe failing would be better
292
+
293
+ cid.split('_').each { |cid| tree = tree[1][cid.to_i] }
294
+
295
+ tree
296
+ end
297
+
298
+ def parent_node(node=@node)
299
+
300
+ @execution['nodes'][node['parent']]
301
+ end
302
+
303
+ def parent_node_tree(node=@node)
304
+
305
+ lookup_tree(node['parent'])
306
+ end
307
+
308
+ def is_ancestor_node?(nid, node=@node)
309
+
310
+ return false unless node
311
+ return true if node['nid'] == nid
312
+
313
+ is_ancestor_node?(nid, parent_node(node))
314
+ end
315
+
316
+ #def closure_node(node=@node)
317
+ # @execution['nodes'][node['cnid']]
318
+ #end
319
+
320
+ def lookup_dvar(mod, key)
321
+
322
+ if mod != 'd' && Flor::Procedure[key]
323
+ return [ '_proc', { 'proc' => key }, -1 ]
324
+ end
325
+
326
+ if mod != 'd' && @executor.unit.tasker.has_tasker?(@executor.exid, key)
327
+ return [ '_task', { 'task' => key }, -1 ]
328
+ end
329
+
330
+ l = @executor.unit.loader
331
+ vdomain = @node['vdomain']
332
+ #
333
+ if l && vdomain != false
334
+ return l.variables(vdomain || domain)[key]
335
+ end
336
+
337
+ nil
338
+ end
339
+
340
+ def lookup_var(node, mod, key)
341
+
342
+ return lookup_dvar(mod, key) if node == nil || mod == 'd'
343
+
344
+ pnode = parent_node(node)
345
+ #cnode = closure_node(node)
346
+
347
+ if mod == 'g'
348
+ vars = node['vars']
349
+ return lookup_var(pnode, mod, key) if pnode
350
+ return vars[key] if vars
351
+ #return lookup_var(cnode, mod, key) if cnode
352
+ fail "node #{node['nid']} has no vars and no parent"
353
+ end
354
+
355
+ vars = node['vars']
356
+
357
+ return vars[key] if vars && vars.has_key?(key)
358
+
359
+ if cnid = node['cnid'] # look into closure
360
+ cvars = (@execution['nodes'][cnid] || {})['vars']
361
+ return cvars[key] if cvars && cvars.has_key?(key)
362
+ end
363
+
364
+ lookup_var(pnode, mod, key)
365
+ end
366
+
367
+ def lookup_var_name(node, val)
368
+
369
+ return nil unless node
370
+
371
+ vars = node['vars']
372
+ k, _ = vars && vars.find { |k, v| v == val }
373
+ return k if k
374
+
375
+ lookup_var_name(parent_node(node), val)
376
+ end
377
+
378
+ def lookup_field(mod, key)
379
+
380
+ Flor.deep_get(payload.current, key)[1]
381
+ end
382
+
383
+ def key_split(key) # => category, mode, key
384
+
385
+ m = key.match(/\A(?:([lgd]?)((?:v|var|variable)|w|f|fld|field)\.)?(.+)\z/)
386
+
387
+ #fail ArgumentError.new("couldn't split key #{key.inspect}") unless m
388
+ # spare that
389
+
390
+ ca = (m[2] || 'v')[0, 1]
391
+ mo = m[1] || ''
392
+ ke = m[3]
393
+
394
+ [ ca, mo, ke ]
395
+ end
396
+ end
397
+