flor 0.0.1 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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
+