flor 0.13.0 → 0.14.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.
- data/CHANGELOG.md +8 -0
- data/lib/flor.rb +1 -1
- data/lib/flor/core.rb +7 -0
- data/lib/flor/core/executor.rb +43 -8
- data/lib/flor/core/node.rb +84 -54
- data/lib/flor/core/procedure.rb +36 -19
- data/lib/flor/core/texecutor.rb +4 -1
- data/lib/flor/deep.rb +43 -51
- data/lib/flor/dollar.rb +2 -3
- data/lib/flor/flor.rb +38 -9
- data/lib/flor/parser.rb +123 -72
- data/lib/flor/pcore/_arr.rb +15 -0
- data/lib/flor/pcore/_atom.rb +6 -5
- data/lib/flor/pcore/_att.rb +9 -4
- data/lib/flor/pcore/_obj.rb +28 -34
- data/lib/flor/pcore/_pat_.rb +77 -0
- data/lib/flor/pcore/_pat_arr.rb +131 -0
- data/lib/flor/pcore/_pat_guard.rb +70 -0
- data/lib/flor/pcore/_pat_obj.rb +143 -0
- data/lib/flor/pcore/_pat_or.rb +46 -0
- data/lib/flor/pcore/_val.rb +20 -0
- data/lib/flor/pcore/arith.rb +7 -1
- data/lib/flor/pcore/case.rb +46 -69
- data/lib/flor/pcore/cursor.rb +24 -24
- data/lib/flor/pcore/define.rb +5 -1
- data/lib/flor/pcore/do_return.rb +32 -0
- data/lib/flor/pcore/length.rb +18 -0
- data/lib/flor/pcore/logo.rb +47 -0
- data/lib/flor/pcore/map.rb +12 -10
- data/lib/flor/pcore/match.rb +276 -0
- data/lib/flor/pcore/not.rb +13 -0
- data/lib/flor/pcore/push.rb +52 -13
- data/lib/flor/pcore/range.rb +69 -0
- data/lib/flor/pcore/set.rb +82 -24
- data/lib/flor/unit/hook.rb +28 -0
- data/lib/flor/unit/hooker.rb +5 -0
- data/lib/flor/unit/loader.rb +4 -1
- data/lib/flor/unit/storage.rb +5 -3
- data/lib/flor/unit/waiter.rb +12 -2
- data/lib/flor/unit/wlist.rb +4 -3
- data/match.md +22 -0
- metadata +15 -5
- data/lib/flor/pcore/_happly.rb +0 -49
- data/lib/flor/pcore/val.rb +0 -16
- data/t.txt +0 -4
data/CHANGELOG.md
CHANGED
data/lib/flor.rb
CHANGED
data/lib/flor/core.rb
CHANGED
@@ -44,6 +44,13 @@ module Flor
|
|
44
44
|
pl = opts[:payload] || opts[:fields] || {}
|
45
45
|
vs = opts[:variables] || opts[:vars] || {}
|
46
46
|
|
47
|
+
fail ArgumentError.new(
|
48
|
+
"given launch payload should be a Hash, but it's a #{pl.class}"
|
49
|
+
) unless pl.is_a?(Hash)
|
50
|
+
fail ArgumentError.new(
|
51
|
+
"given launch variables should come in a Hash, but it's a #{vs.class}"
|
52
|
+
) unless vs.is_a?(Hash)
|
53
|
+
|
47
54
|
msg =
|
48
55
|
{ 'point' => 'execute',
|
49
56
|
'exid' => exid,
|
data/lib/flor/core/executor.rb
CHANGED
@@ -182,18 +182,23 @@ module Flor
|
|
182
182
|
|
183
183
|
# "exceptions"
|
184
184
|
|
185
|
-
|
186
|
-
#
|
187
|
-
#
|
188
|
-
|
185
|
+
if heat == nil && tree[0].index('.') && tree[1].empty?
|
186
|
+
#
|
187
|
+
# a field reference that points to nothing returns null
|
188
|
+
|
189
|
+
node['heat0'] = '_nul'
|
190
|
+
node['heat'] = '_nul'
|
191
|
+
node['heap'] = '_nul'
|
192
|
+
|
193
|
+
elsif message['accept_symbol'] && heat == nil
|
189
194
|
#
|
190
195
|
# tag: et al
|
191
196
|
|
192
|
-
|
197
|
+
node['tree'] = message['tree'] = t = [ '_dqs', tree[0], tree[2] ]
|
193
198
|
|
194
|
-
node['heat0'] =
|
195
|
-
node['heat'] =
|
196
|
-
node['heap'] =
|
199
|
+
node['heat0'] = t[0]
|
200
|
+
node['heat'] = h = n.deref(t[0])
|
201
|
+
node['heap'] = n.reheap(t, h)
|
197
202
|
|
198
203
|
elsif heap == 'task' && heat[0] == '_task'
|
199
204
|
#
|
@@ -296,11 +301,41 @@ module Flor
|
|
296
301
|
@unit.archive_node(message['exid'], node)
|
297
302
|
# archiving is only active during testing
|
298
303
|
|
304
|
+
#update_parent_node_tree(node)
|
305
|
+
|
299
306
|
@execution['nodes'].delete(nid)
|
300
307
|
|
301
308
|
cancels
|
302
309
|
end
|
303
310
|
|
311
|
+
# This saves the modified trees in the parent when the node is removed
|
312
|
+
# it works ok except for 3 (2017-05-9) failing specs.
|
313
|
+
#
|
314
|
+
# Introducing 3 exceptions for this is not interesting.
|
315
|
+
#
|
316
|
+
# def update_parent_node_tree(node)
|
317
|
+
#
|
318
|
+
# t = node['tree']; return unless t
|
319
|
+
##return if t[0] == '_apply'
|
320
|
+
# pnode = @execution['nodes'][node['parent']]; return unless pnode
|
321
|
+
#
|
322
|
+
# pt =
|
323
|
+
# pnode['tree'] ||
|
324
|
+
# Flor::Node.new(self, pnode, nil).lookup_tree(pnode['nid'])
|
325
|
+
# cid =
|
326
|
+
# Flor.child_id(node['nid'])
|
327
|
+
#
|
328
|
+
# if cid == pt[1].size # head "exception"
|
329
|
+
# return if pt[0] == t
|
330
|
+
# pt[0] = t
|
331
|
+
# pnode['tree'] = pt
|
332
|
+
# return
|
333
|
+
# end
|
334
|
+
#
|
335
|
+
# pt[1][cid] = t
|
336
|
+
# pnode['tree'] = pt
|
337
|
+
# end
|
338
|
+
|
304
339
|
def leave_tags(message, node)
|
305
340
|
|
306
341
|
ts = node['tags']; return [] unless ts && ts.any?
|
data/lib/flor/core/node.rb
CHANGED
@@ -145,27 +145,25 @@ class Flor::Node
|
|
145
145
|
#
|
146
146
|
# that might be the way...
|
147
147
|
|
148
|
-
def lookup(name)
|
149
|
-
|
150
|
-
cat, mod,
|
151
|
-
key, pth =
|
152
|
-
|
153
|
-
val =
|
154
|
-
if [ cat, mod, key ] == [ 'v', '', 'node' ]
|
155
|
-
@node
|
156
|
-
elsif cat == 'v'
|
157
|
-
lookup_var(@node, mod, key)
|
158
|
-
elsif cat == 't'
|
159
|
-
lookup_tag(mod, key)
|
160
|
-
else
|
161
|
-
lookup_field(mod, key)
|
162
|
-
end
|
148
|
+
def lookup(name, silence_index_error=false)
|
149
|
+
|
150
|
+
cat, mod, key_and_path = key_split(name)
|
151
|
+
key, pth = key_and_path.split('.', 2)
|
163
152
|
|
164
|
-
if
|
165
|
-
|
153
|
+
if [ cat, mod, key ] == [ 'v', '', 'node' ]
|
154
|
+
lookup_in_node(pth)
|
155
|
+
elsif cat == 'v'
|
156
|
+
lookup_var(@node, mod, key, pth)
|
157
|
+
elsif cat == 't'
|
158
|
+
lookup_tag(mod, key)
|
166
159
|
else
|
167
|
-
|
160
|
+
lookup_field(mod, key_and_path)
|
168
161
|
end
|
162
|
+
|
163
|
+
rescue IndexError
|
164
|
+
|
165
|
+
raise unless silence_index_error
|
166
|
+
nil
|
169
167
|
end
|
170
168
|
|
171
169
|
class Expander < Flor::Dollar
|
@@ -178,7 +176,8 @@ class Flor::Node
|
|
178
176
|
return @node.exid if k == 'exid'
|
179
177
|
return Flor.tstamp if k == 'tstamp'
|
180
178
|
|
181
|
-
@node.lookup(k)
|
179
|
+
r = @node.lookup(k, true)
|
180
|
+
r.is_a?(Symbol) ? nil : r
|
182
181
|
end
|
183
182
|
end
|
184
183
|
|
@@ -202,10 +201,10 @@ class Flor::Node
|
|
202
201
|
|
203
202
|
ref =
|
204
203
|
case v[0]
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
204
|
+
when '_func' then true
|
205
|
+
when '_proc' then v[1]['proc'] != o
|
206
|
+
when '_task' then v[1]['task'] != o
|
207
|
+
else false
|
209
208
|
end
|
210
209
|
|
211
210
|
v[1]['oref'] ||= v[1]['ref'] if ref && v[1]['ref']
|
@@ -226,8 +225,6 @@ class Flor::Node
|
|
226
225
|
'apply'
|
227
226
|
elsif heat[0] == '_task'
|
228
227
|
'task'
|
229
|
-
elsif Flor.is_tree_head_tree?(tree)
|
230
|
-
'_happly'
|
231
228
|
else
|
232
229
|
'_val'
|
233
230
|
end
|
@@ -317,54 +314,86 @@ class Flor::Node
|
|
317
314
|
# @execution['nodes'][node['cnid']]
|
318
315
|
#end
|
319
316
|
|
320
|
-
def
|
317
|
+
def lookup_in_node(pth)
|
321
318
|
|
322
|
-
|
323
|
-
|
324
|
-
end
|
319
|
+
Flor.deep_get(@node, pth)
|
320
|
+
end
|
325
321
|
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
end
|
322
|
+
class PseudoVarContainer < Hash
|
323
|
+
#
|
324
|
+
# inherit from Hash so that deep.rb is quietly mislead
|
325
|
+
#
|
326
|
+
def initialize(type); @type = type; end
|
327
|
+
#def has_key?(key); true; end
|
328
|
+
def [](key); [ "_#{@type}", { @type => key }, -1 ]; end
|
329
|
+
end
|
330
|
+
#
|
331
|
+
PROC_VAR_CONTAINER = PseudoVarContainer.new('proc')
|
332
|
+
TASKER_VAR_CONTAINER = PseudoVarContainer.new('task')
|
333
333
|
|
334
|
-
|
335
|
-
return [ '_task', { 'task' => key }, -1 ]
|
336
|
-
end
|
334
|
+
def lookup_var(node, mod, key, pth)
|
337
335
|
|
338
|
-
|
336
|
+
c = lookup_var_container(node, mod, key)
|
337
|
+
|
338
|
+
kp = [ key, pth ].reject { |x| x == nil || x.size < 1 }.join('.')
|
339
|
+
|
340
|
+
v = Flor.deep_get(c, kp)
|
341
|
+
#p [ mod, key, pth, '->', v ]
|
342
|
+
|
343
|
+
return v unless v.is_a?(Symbol)
|
344
|
+
|
345
|
+
vs = v.to_s.split('.')
|
346
|
+
tail = vs.pop
|
347
|
+
vs = vs.join('.')
|
348
|
+
|
349
|
+
fail IndexError.new("variable #{tail.inspect} not found") if vs.empty?
|
350
|
+
fail IndexError.new("no key #{tail.inspect} in variable #{vs.inspect}")
|
339
351
|
end
|
340
352
|
|
341
|
-
def
|
353
|
+
def lookup_var_container(node, mod, key)
|
342
354
|
|
343
|
-
return
|
355
|
+
return lookup_dvar_container(mod, key) if node == nil || mod == 'd'
|
344
356
|
|
345
357
|
pnode = parent_node(node)
|
346
|
-
|
358
|
+
vars = node['vars']
|
347
359
|
|
348
360
|
if mod == 'g'
|
349
|
-
|
350
|
-
return
|
351
|
-
return vars[key] if vars
|
352
|
-
#return lookup_var(cnode, mod, key) if cnode
|
361
|
+
return lookup_var_container(pnode, mod, key) if pnode
|
362
|
+
return vars if vars
|
353
363
|
fail "node #{node['nid']} has no vars and no parent"
|
354
364
|
end
|
355
365
|
|
356
|
-
vars
|
357
|
-
|
358
|
-
return vars[key] if vars && vars.has_key?(key)
|
366
|
+
return vars if vars && vars.has_key?(key)
|
359
367
|
|
360
368
|
if cnid = node['cnid']
|
361
369
|
cvars = (@execution['nodes'][cnid] || {})['vars']
|
362
|
-
return cvars
|
370
|
+
return cvars if cvars && cvars.has_key?(key)
|
363
371
|
end
|
364
372
|
#
|
365
373
|
# look into closure, just one level deep...
|
366
374
|
|
367
|
-
|
375
|
+
lookup_var_container(pnode, mod, key)
|
376
|
+
end
|
377
|
+
|
378
|
+
def lookup_dvar_container(mod, key)
|
379
|
+
|
380
|
+
if mod != 'd' && Flor::Procedure[key]
|
381
|
+
return PROC_VAR_CONTAINER
|
382
|
+
end
|
383
|
+
|
384
|
+
l = @executor.unit.loader
|
385
|
+
vdomain = @node['vdomain']
|
386
|
+
#
|
387
|
+
if l && vdomain != false
|
388
|
+
vars = l.variables(vdomain || domain)
|
389
|
+
return vars if vars.has_key?(key)
|
390
|
+
end
|
391
|
+
|
392
|
+
if mod != 'd' && @executor.unit.has_tasker?(@executor.exid, key)
|
393
|
+
return TASKER_VAR_CONTAINER
|
394
|
+
end
|
395
|
+
|
396
|
+
{}
|
368
397
|
end
|
369
398
|
|
370
399
|
def lookup_var_name(node, val)
|
@@ -389,9 +418,10 @@ class Flor::Node
|
|
389
418
|
nids.empty? ? [ '_nul', nil, -1 ] : nids
|
390
419
|
end
|
391
420
|
|
392
|
-
def lookup_field(mod,
|
421
|
+
def lookup_field(mod, key_and_path)
|
393
422
|
|
394
|
-
Flor.deep_get(payload.current,
|
423
|
+
r = Flor.deep_get(payload.current, key_and_path)
|
424
|
+
r.is_a?(Symbol) ? nil : r
|
395
425
|
end
|
396
426
|
|
397
427
|
def key_split(key) # => category, mode, key
|
data/lib/flor/core/procedure.rb
CHANGED
@@ -17,12 +17,15 @@ class Flor::Procedure < Flor::Node
|
|
17
17
|
|
18
18
|
names = names.flatten
|
19
19
|
@names = names if names.any?
|
20
|
+
@core = !! caller.find { |l| l.match(/flor\/pcore/) } if names.any?
|
20
21
|
|
21
22
|
@names
|
22
23
|
end
|
23
24
|
|
24
25
|
alias :name :names
|
25
26
|
|
27
|
+
def core?; @core; end
|
28
|
+
|
26
29
|
def make(executor, node, message)
|
27
30
|
|
28
31
|
heap = node['heat'] ? node['heap'] : nil
|
@@ -234,9 +237,9 @@ class Flor::Procedure < Flor::Node
|
|
234
237
|
unatt_unkeyed_children(true)
|
235
238
|
end
|
236
239
|
|
237
|
-
def
|
240
|
+
def stringify_child(non_att_index)
|
238
241
|
|
239
|
-
c = non_att_children
|
242
|
+
c = non_att_children[non_att_index]
|
240
243
|
return unless c
|
241
244
|
return unless c[1] == [] && c[0].is_a?(String)
|
242
245
|
|
@@ -247,6 +250,11 @@ class Flor::Procedure < Flor::Node
|
|
247
250
|
@node['tree'] = [ tree[0], cn, tree[2] ]
|
248
251
|
end
|
249
252
|
|
253
|
+
def stringify_first_child
|
254
|
+
|
255
|
+
stringify_child(0)
|
256
|
+
end
|
257
|
+
|
250
258
|
def do_execute
|
251
259
|
|
252
260
|
pre_execute
|
@@ -321,31 +329,37 @@ class Flor::Procedure < Flor::Node
|
|
321
329
|
[]
|
322
330
|
end
|
323
331
|
|
324
|
-
def
|
332
|
+
def determine_fcid_and_ncid
|
325
333
|
|
326
334
|
@fcid = point == 'receive' ? Flor.child_id(from) : nil
|
327
335
|
@ncid = (@fcid || -1) + 1
|
336
|
+
end
|
328
337
|
|
329
|
-
|
338
|
+
def from_att?
|
339
|
+
|
340
|
+
@fcid && (c = children[@fcid]) && c[0] == '_att'
|
341
|
+
end
|
330
342
|
|
331
|
-
|
343
|
+
def receive
|
332
344
|
|
333
|
-
|
345
|
+
determine_fcid_and_ncid
|
334
346
|
|
347
|
+
return receive_first if @fcid == nil
|
348
|
+
return receive_att if from_att?
|
335
349
|
receive_non_att
|
336
350
|
end
|
337
351
|
|
338
352
|
def receive_first
|
339
353
|
|
340
|
-
return receive_last_att if children[0] &&
|
354
|
+
return receive_last_att if (c = children[0]) && c[0] != '_att'
|
341
355
|
execute_child(@ncid)
|
342
356
|
end
|
343
357
|
|
344
358
|
def receive_att
|
345
359
|
|
346
|
-
|
360
|
+
nt = children[@ncid]
|
347
361
|
|
348
|
-
return receive_last_att if
|
362
|
+
return receive_last_att if nt == nil || nt[0] != '_att'
|
349
363
|
execute_child(@ncid)
|
350
364
|
end
|
351
365
|
|
@@ -477,9 +491,9 @@ class Flor::Procedure < Flor::Node
|
|
477
491
|
|
478
492
|
if node
|
479
493
|
|
480
|
-
|
494
|
+
v = Flor.deep_set(node['vars'], k, v)
|
481
495
|
|
482
|
-
return v
|
496
|
+
return v unless v.is_a?(Symbol)
|
483
497
|
end
|
484
498
|
|
485
499
|
fail IndexError.new("couldn't set var #{mode}v.#{k}")
|
@@ -487,9 +501,9 @@ class Flor::Procedure < Flor::Node
|
|
487
501
|
|
488
502
|
def set_field(k, v)
|
489
503
|
|
490
|
-
|
504
|
+
value = Flor.deep_set(payload.copy, k, v)
|
491
505
|
|
492
|
-
fail IndexError.new("couldn't set field #{k}")
|
506
|
+
fail IndexError.new("couldn't set field #{k}") if value.is_a?(Symbol)
|
493
507
|
|
494
508
|
value
|
495
509
|
end
|
@@ -501,10 +515,10 @@ class Flor::Procedure < Flor::Node
|
|
501
515
|
cat, mod, key = key_split(k)
|
502
516
|
|
503
517
|
case cat[0, 1]
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
518
|
+
when 'f' then set_field(key, v)
|
519
|
+
when 'v' then set_var(mod, key, v)
|
520
|
+
#when 'w' then set_war(key, v)
|
521
|
+
else fail IndexError.new("don't know how to set #{k.inspect}")
|
508
522
|
end
|
509
523
|
end
|
510
524
|
|
@@ -516,10 +530,12 @@ class Flor::Procedure < Flor::Node
|
|
516
530
|
|
517
531
|
cni = fun[1]['cnid'] # closure nid
|
518
532
|
|
519
|
-
t =
|
533
|
+
t = fun[1]['tree']
|
534
|
+
t = t || lookup_tree(fni) # TODO when fun[1]['tree'] is settled, drop me
|
520
535
|
fail ArgumentError.new("couldn't find function at #{fni}") unless t
|
521
536
|
|
522
|
-
t = t[0] if
|
537
|
+
t = t[0] if t[0].is_a?(Array)
|
538
|
+
t = t[1][0] if t[0] == '_att'
|
523
539
|
|
524
540
|
sig = t[1].select { |c| c[0] == '_att' }
|
525
541
|
sig = sig.drop(1) if t[0] == 'define'
|
@@ -629,6 +645,7 @@ class Flor::Macro < Flor::Procedure
|
|
629
645
|
def rewrite
|
630
646
|
|
631
647
|
t = rewrite_tree
|
648
|
+
#Flor.print_tree(t, nid)
|
632
649
|
|
633
650
|
m = @message.dup
|
634
651
|
m['tree'] = t
|