flor 0.16.1 → 0.16.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/CREDITS.md +1 -0
- data/Makefile +1 -1
- data/README.md +82 -6
- data/lib/flor.rb +1 -1
- data/lib/flor/conf.rb +19 -6
- data/lib/flor/core/executor.rb +45 -16
- data/lib/flor/core/node.rb +4 -4
- data/lib/flor/core/procedure.rb +40 -0
- data/lib/flor/djan.rb +5 -2
- data/lib/flor/flor.rb +92 -7
- data/lib/flor/id.rb +19 -0
- data/lib/flor/migrations/0001_tables.rb +6 -6
- data/lib/flor/migrations/0005_pointer_content.rb +20 -0
- data/lib/flor/pcore/_apply.rb +103 -57
- data/lib/flor/pcore/_att.rb +15 -1
- data/lib/flor/pcore/_ref.rb +2 -1
- data/lib/flor/pcore/arith.rb +46 -9
- data/lib/flor/pcore/break.rb +1 -1
- data/lib/flor/pcore/case.rb +41 -0
- data/lib/flor/pcore/collect.rb +1 -1
- data/lib/flor/pcore/cursor.rb +1 -1
- data/lib/flor/pcore/define.rb +32 -6
- data/lib/flor/pcore/iterator.rb +12 -0
- data/lib/flor/pcore/on_cancel.rb +1 -1
- data/lib/flor/pcore/set.rb +14 -4
- data/lib/flor/punit/{ccollect.rb → c_collect.rb} +2 -2
- data/lib/flor/punit/c_each.rb +11 -0
- data/lib/flor/punit/c_for_each.rb +41 -0
- data/lib/flor/punit/c_iterator.rb +160 -0
- data/lib/flor/punit/c_map.rb +43 -0
- data/lib/flor/punit/concurrence.rb +43 -200
- data/lib/flor/punit/graft.rb +3 -2
- data/lib/flor/punit/m_ram.rb +281 -0
- data/lib/flor/unit.rb +1 -0
- data/lib/flor/unit/caller.rb +6 -1
- data/lib/flor/unit/executor.rb +17 -4
- data/lib/flor/unit/ganger.rb +12 -1
- data/lib/flor/unit/hloader.rb +251 -0
- data/lib/flor/unit/hook.rb +74 -15
- data/lib/flor/unit/hooker.rb +9 -12
- data/lib/flor/unit/loader.rb +41 -17
- data/lib/flor/unit/models.rb +54 -18
- data/lib/flor/unit/models/execution.rb +15 -4
- data/lib/flor/unit/models/pointer.rb +11 -0
- data/lib/flor/unit/scheduler.rb +126 -30
- data/lib/flor/unit/spooler.rb +5 -3
- data/lib/flor/unit/storage.rb +40 -13
- data/lib/flor/unit/waiter.rb +165 -26
- data/lib/flor/unit/wlist.rb +98 -5
- metadata +10 -4
- data/lib/flor/punit/cmap.rb +0 -112
data/lib/flor/id.rb
CHANGED
@@ -76,6 +76,7 @@ module Flor
|
|
76
76
|
|
77
77
|
"#{nid}_#{i}#{subnid ? "-#{subnid}" : ''}"
|
78
78
|
end
|
79
|
+
alias make_child_nid child_nid
|
79
80
|
|
80
81
|
def parent_id(nid)
|
81
82
|
|
@@ -100,6 +101,24 @@ module Flor
|
|
100
101
|
!! (s.is_a?(String) && s.match(/\A[0-9]+(?:_[0-9]+)*(?:-[0-9]+)?\z/))
|
101
102
|
end
|
102
103
|
|
104
|
+
def split_exid(s)
|
105
|
+
|
106
|
+
return nil unless s.is_a?(String)
|
107
|
+
|
108
|
+
_, d, u, t = s
|
109
|
+
.match(/\A([^-\s]+)-([^-\s]+)-(\d{8,9}\.\d{4}\.[a-z]+)\z/)
|
110
|
+
.to_a
|
111
|
+
|
112
|
+
return nil unless d && u && t
|
113
|
+
|
114
|
+
[ d, u, t ]
|
115
|
+
end
|
116
|
+
|
117
|
+
def is_exid?(s)
|
118
|
+
|
119
|
+
!! split_exid(s)
|
120
|
+
end
|
121
|
+
|
103
122
|
# Returns [ exid, nid ]
|
104
123
|
#
|
105
124
|
def extract_exid_and_nid(s)
|
@@ -5,7 +5,7 @@ Sequel.migration do
|
|
5
5
|
|
6
6
|
create_table :flor_messages do
|
7
7
|
|
8
|
-
primary_key :id
|
8
|
+
primary_key :id
|
9
9
|
String :domain, null: false
|
10
10
|
String :exid, null: false
|
11
11
|
String :point, null: false # 'execute', 'task', 'receive', 'schedule', ...
|
@@ -19,7 +19,7 @@ Sequel.migration do
|
|
19
19
|
|
20
20
|
create_table :flor_executions do
|
21
21
|
|
22
|
-
primary_key :id
|
22
|
+
primary_key :id
|
23
23
|
String :domain, null: false
|
24
24
|
String :exid, null: false
|
25
25
|
File :content # JSON
|
@@ -32,7 +32,7 @@ Sequel.migration do
|
|
32
32
|
|
33
33
|
create_table :flor_timers do
|
34
34
|
|
35
|
-
primary_key :id
|
35
|
+
primary_key :id
|
36
36
|
String :domain, null: false
|
37
37
|
String :exid, null: false
|
38
38
|
String :nid, null: false
|
@@ -51,7 +51,7 @@ Sequel.migration do
|
|
51
51
|
|
52
52
|
create_table :flor_traps do
|
53
53
|
|
54
|
-
primary_key :id
|
54
|
+
primary_key :id
|
55
55
|
String :domain, null: false
|
56
56
|
String :exid, null: false
|
57
57
|
String :onid, null: false
|
@@ -76,7 +76,7 @@ Sequel.migration do
|
|
76
76
|
|
77
77
|
create_table :flor_pointers do
|
78
78
|
|
79
|
-
primary_key :id
|
79
|
+
primary_key :id
|
80
80
|
String :domain, null: false
|
81
81
|
String :exid, null: false
|
82
82
|
String :nid, null: false
|
@@ -97,7 +97,7 @@ Sequel.migration do
|
|
97
97
|
|
98
98
|
create_table :flor_traces do
|
99
99
|
|
100
|
-
primary_key :id
|
100
|
+
primary_key :id
|
101
101
|
String :domain, null: false
|
102
102
|
String :exid, null: false
|
103
103
|
String :nid, null: true
|
data/lib/flor/pcore/_apply.rb
CHANGED
@@ -16,63 +16,7 @@ class Flor::Pro::UnderscoreApply < Flor::Procedure
|
|
16
16
|
@node['in_on_error'] = from
|
17
17
|
end
|
18
18
|
|
19
|
-
|
20
|
-
args = message['arguments']
|
21
|
-
|
22
|
-
vars['arguments'] = args
|
23
|
-
|
24
|
-
tr = tree
|
25
|
-
retree = nil
|
26
|
-
|
27
|
-
atts = tr[1].inject([]) { |a, t| a << t[1] if t[0] == '_att'; a }
|
28
|
-
args = args.dup
|
29
|
-
#puts "\n---"
|
30
|
-
#puts "== atts (sig):"; pp atts; # signature
|
31
|
-
#puts "== args (given):"; pp args # passed arguments
|
32
|
-
#puts
|
33
|
-
|
34
|
-
# first, make 2 passes on atts
|
35
|
-
# 1). grab named args
|
36
|
-
# 2). grab remaining args
|
37
|
-
# then make 1 pass on still remaining args
|
38
|
-
# 1). set vars if not yet set
|
39
|
-
|
40
|
-
seen = []
|
41
|
-
|
42
|
-
atts
|
43
|
-
.each { |(att_key, _), _|
|
44
|
-
arg_i = args.index { |arg_key, arg_val| arg_key == att_key }
|
45
|
-
next unless arg_i
|
46
|
-
arg_key, arg_val = args.delete_at(arg_i)
|
47
|
-
seen << arg_key
|
48
|
-
vars[att_key] = arg_val }
|
49
|
-
#puts "== 0 vars:"; pp vars
|
50
|
-
atts
|
51
|
-
.each_with_index { |((att_key, _), att_val), att_i|
|
52
|
-
next if vars.has_key?(att_key)
|
53
|
-
seen << att_key
|
54
|
-
if att_i < args.length
|
55
|
-
arg_key, arg_val = args[att_i]
|
56
|
-
seen << arg_key
|
57
|
-
vars[att_key] = arg_val
|
58
|
-
elsif att_val
|
59
|
-
l = tree[2]
|
60
|
-
retree ||= Flor.dup(tr)
|
61
|
-
retree[1][att_i] = [ 'set', [ [ att_key, [], l ], att_val ], l ]
|
62
|
-
else
|
63
|
-
vars[att_key] = nil
|
64
|
-
end }
|
65
|
-
#puts "== seen:"; p seen
|
66
|
-
args
|
67
|
-
.each { |arg_key, arg_val|
|
68
|
-
vars[arg_key] = arg_val unless seen.include?(arg_key) }
|
69
|
-
|
70
|
-
#puts "\n== 1 vars: "; pp vars
|
71
|
-
#print "vars: "; pp vars.collect { |k, v| [ k, JSON.dump(v)[0, 20] + "..." ] }
|
72
|
-
#print "vars: "; vars.each { |k, v| print "#{k.inspect} --> "; pp v }
|
73
|
-
|
74
|
-
@node['tree'] = retree if retree
|
75
|
-
#puts "== retree:"; pp retree
|
19
|
+
map_arguments_to_parameters
|
76
20
|
|
77
21
|
super
|
78
22
|
end
|
@@ -104,5 +48,107 @@ class Flor::Pro::UnderscoreApply < Flor::Procedure
|
|
104
48
|
|
105
49
|
ms
|
106
50
|
end
|
51
|
+
|
52
|
+
protected
|
53
|
+
|
54
|
+
def compute_param_key(t)
|
55
|
+
|
56
|
+
t0 = t[0]
|
57
|
+
k = t0[0]
|
58
|
+
|
59
|
+
if k == '_ref' && t0[1].is_a?(Array) && t0[1].length > 0
|
60
|
+
t[0][1].collect { |tt| tt[1].to_s }.join('.')
|
61
|
+
else
|
62
|
+
k
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def map_arguments_to_parameters
|
67
|
+
|
68
|
+
@node['vars'] = {}
|
69
|
+
|
70
|
+
args = message['arguments']
|
71
|
+
|
72
|
+
@node['vars']['arguments'] = args
|
73
|
+
|
74
|
+
tr = tree
|
75
|
+
retree = nil
|
76
|
+
|
77
|
+
params = tr[1]
|
78
|
+
.select { |t| t[0] == '_att' }
|
79
|
+
.inject([]) { |a, t|
|
80
|
+
t1 = t[1]
|
81
|
+
a << [ compute_param_key(t1), t[1][0], t[1][1] ]
|
82
|
+
a }
|
83
|
+
args = args.dup
|
84
|
+
#puts "\n---"
|
85
|
+
#puts "== params:"
|
86
|
+
#params.each_with_index { |a, i| printf "%2d: %s\n", i, a.inspect }
|
87
|
+
#puts "== args:"
|
88
|
+
#args.each_with_index { |a, i| printf "%2d: %s\n", i, a.inspect }
|
89
|
+
#puts
|
90
|
+
|
91
|
+
# first, make 2 passes on params
|
92
|
+
# 1). grab named args
|
93
|
+
# 2). grab remaining args
|
94
|
+
# then make 1 pass on still remaining args
|
95
|
+
# 1). set vars if not yet set
|
96
|
+
|
97
|
+
seen = []
|
98
|
+
|
99
|
+
params.each do |param_key, param_tree|
|
100
|
+
next if param_tree[0] == '_ref'
|
101
|
+
arg_i = args.index { |arg_key, arg_val| arg_key == param_key }
|
102
|
+
next unless arg_i
|
103
|
+
arg_key, arg_val = args.delete_at(arg_i)
|
104
|
+
seen << arg_key
|
105
|
+
set_param(param_key, arg_val)
|
106
|
+
end
|
107
|
+
#puts "== 0 vars:"; pp @node['vars']
|
108
|
+
params.each_with_index do |(param_key, param_tree, param_val), param_i|
|
109
|
+
ref = param_tree[0] == '_ref'
|
110
|
+
next if ! ref && @node['vars'].has_key?(param_key)
|
111
|
+
seen << param_key
|
112
|
+
if param_i < args.length
|
113
|
+
arg_key, arg_val = args[param_i]
|
114
|
+
seen << arg_key
|
115
|
+
set_param(param_key, arg_val)
|
116
|
+
elsif param_val
|
117
|
+
l = tree[2]
|
118
|
+
retree ||= Flor.dup(tr)
|
119
|
+
retree[1][param_i] = [ 'set', [ [ param_key, [], l ], param_val ], l ]
|
120
|
+
else
|
121
|
+
set_param(param_key, nil) unless ref
|
122
|
+
end
|
123
|
+
end
|
124
|
+
#puts "== seen:"; p seen
|
125
|
+
args.each do |arg_key, arg_val|
|
126
|
+
set_param(arg_key, arg_val) unless seen.include?(arg_key)
|
127
|
+
end
|
128
|
+
|
129
|
+
#puts "\n== 1 vars: "; pp @node['vars']
|
130
|
+
#puts "\n== 1 fields: "; pp payload.current
|
131
|
+
#
|
132
|
+
#print "vars: "
|
133
|
+
#pp @node['vars'].collect { |k, v| [ k, JSON.dump(v)[0, 20] + "..." ] }
|
134
|
+
#print "vars: "
|
135
|
+
#@node['vars'].each { |k, v| print "#{k.inspect} --> "; pp v }
|
136
|
+
|
137
|
+
#puts "== retree:"; pp retree; puts
|
138
|
+
@node['tree'] = retree if retree
|
139
|
+
end
|
140
|
+
|
141
|
+
def set_param(key, val)
|
142
|
+
|
143
|
+
return unless key
|
144
|
+
|
145
|
+
if m = key.match(/\A(?:field|fld|f)\.(.+)\z/)
|
146
|
+
Dense.set(payload.copy, m[1], val)
|
147
|
+
elsif m = key.match(/\A(?:variable|var|v)\.(.+)\z/)
|
148
|
+
Dense.set(@node['vars'], m[1], val)
|
149
|
+
else
|
150
|
+
Dense.set(@node['vars'], key, val)
|
151
|
+
end
|
152
|
+
end
|
107
153
|
end
|
108
154
|
|
data/lib/flor/pcore/_att.rb
CHANGED
@@ -234,8 +234,22 @@ class Flor::Pro::Att < Flor::Procedure
|
|
234
234
|
|
235
235
|
wrap_reply('disable' => Flor.true?(payload['ret']))
|
236
236
|
end
|
237
|
-
|
237
|
+
#
|
238
238
|
alias receive_off receive_disabled
|
239
239
|
alias receive_disable receive_disabled
|
240
|
+
|
241
|
+
def receive_child_on_error
|
242
|
+
if pn = parent_node; pn['child_on_error'] = payload_ret; end; wrap_reply
|
243
|
+
end
|
244
|
+
def receive_child_on_cancel
|
245
|
+
if pn = parent_node; pn['child_on_cancel'] = payload_ret; end; wrap_reply
|
246
|
+
end
|
247
|
+
def receive_child_on_timeout
|
248
|
+
if pn = parent_node; pn['child_on_timeout'] = payload_ret; end; wrap_reply
|
249
|
+
end
|
250
|
+
#
|
251
|
+
alias receive_children_on_error receive_child_on_error
|
252
|
+
alias receive_children_on_cancel receive_child_on_cancel
|
253
|
+
alias receive_children_on_timeout receive_child_on_timeout
|
240
254
|
end
|
241
255
|
|
data/lib/flor/pcore/_ref.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|
class Flor::Pro::Ref < Flor::Procedure
|
3
3
|
|
4
|
-
names %w[ _ref _rep ]
|
4
|
+
names %w[ _ref _rep _reff ]
|
5
5
|
|
6
6
|
def pre_execute
|
7
7
|
|
@@ -44,6 +44,7 @@ class Flor::Pro::Ref < Flor::Procedure
|
|
44
44
|
return nil if field?(ke.work_path)
|
45
45
|
return nil if child_id == 1 && (n = parent_node) && n['heat0'] == '_head'
|
46
46
|
return nil if ke.miss[1].any? && ke.miss[4].empty?
|
47
|
+
return nil if tree[0] == '_reff'
|
47
48
|
|
48
49
|
raise
|
49
50
|
end
|
data/lib/flor/pcore/arith.rb
CHANGED
@@ -23,7 +23,19 @@ class Flor::Pro::Arith < Flor::Procedure
|
|
23
23
|
# 3 # ==> -4
|
24
24
|
# ```
|
25
25
|
#
|
26
|
-
#
|
26
|
+
# ```
|
27
|
+
# [ 1 2 3 ]
|
28
|
+
# + _ # ==> 6
|
29
|
+
#
|
30
|
+
# [ 2 3 4 ]
|
31
|
+
# * _ # ==> 24
|
32
|
+
# ```
|
33
|
+
#
|
34
|
+
# ```
|
35
|
+
# + "hell" "o"
|
36
|
+
# "hel" + "lo"
|
37
|
+
# # both yield "hello"
|
38
|
+
# ```
|
27
39
|
|
28
40
|
names %w[ + - * / % ]
|
29
41
|
|
@@ -32,26 +44,41 @@ class Flor::Pro::Arith < Flor::Procedure
|
|
32
44
|
def pre_execute
|
33
45
|
|
34
46
|
@node['rets'] = []
|
47
|
+
@node['atts'] = []
|
48
|
+
|
49
|
+
unatt_unkeyed_children
|
35
50
|
end
|
36
51
|
|
37
52
|
def receive_last
|
38
53
|
|
39
54
|
sign = tree.first.to_sym
|
40
|
-
|
55
|
+
|
56
|
+
rets = @node['rets']
|
57
|
+
rets << node_payload_ret \
|
58
|
+
if rets.empty? && node_payload_ret.is_a?(Array)
|
59
|
+
rets = rets[0] \
|
60
|
+
if rets.size == 1 && rets[0].is_a?(Array)
|
41
61
|
|
42
62
|
fail Flor::FlorError.new('modulo % requires at least 2 arguments', self) \
|
43
|
-
if sign == :% &&
|
63
|
+
if sign == :% && rets.size < 2
|
64
|
+
|
65
|
+
if j = att('join')
|
66
|
+
max = rets.size - 1
|
67
|
+
rets = rets.each_with_index.inject([]) { |a, (e, i)|
|
68
|
+
a << e
|
69
|
+
a << j if i < max
|
70
|
+
a }
|
71
|
+
rets[0] = stringify(rets[0]) \
|
72
|
+
if rets.any? && j.is_a?(String)
|
73
|
+
end
|
44
74
|
|
45
75
|
ret =
|
46
|
-
if
|
76
|
+
if rets.compact.empty?
|
47
77
|
DEFAULTS[sign]
|
48
78
|
elsif sign == :+
|
49
|
-
|
50
|
-
|
51
|
-
# TODO use JSON instead of #to_s or djan?
|
52
|
-
r + (r.is_a?(String) ? e.to_s : e) }
|
79
|
+
rets.reduce { |r, e|
|
80
|
+
r + (r.is_a?(String) ? stringify(e) : e) }
|
53
81
|
else
|
54
|
-
rets = @node['rets']
|
55
82
|
rets = rets.collect(&:to_f) \
|
56
83
|
if sign == :/ || rets.find { |r| r.is_a?(Float) }
|
57
84
|
rets.reduce(&sign)
|
@@ -65,5 +92,15 @@ class Flor::Pro::Arith < Flor::Procedure
|
|
65
92
|
|
66
93
|
wrap_reply('ret' => ret)
|
67
94
|
end
|
95
|
+
|
96
|
+
protected
|
97
|
+
|
98
|
+
def stringify(o)
|
99
|
+
|
100
|
+
# TODO use djan instead of #to_s?
|
101
|
+
# TODO use JSON instead of #to_s or djan?
|
102
|
+
|
103
|
+
o.to_s
|
104
|
+
end
|
68
105
|
end
|
69
106
|
|
data/lib/flor/pcore/break.rb
CHANGED
data/lib/flor/pcore/case.rb
CHANGED
@@ -85,6 +85,47 @@ class Flor::Pro::Case < Flor::Procedure
|
|
85
85
|
# # yields "matched:molzin"
|
86
86
|
# ```
|
87
87
|
#
|
88
|
+
# ### defaulting to f.ret
|
89
|
+
#
|
90
|
+
# When nothing is explicitely provided for consideration by "case", the
|
91
|
+
# incoming `f.ret` is used.
|
92
|
+
#
|
93
|
+
# ```
|
94
|
+
# 2
|
95
|
+
# case
|
96
|
+
# [ 0 1 2 ]; 'low'
|
97
|
+
# 6; 'high'
|
98
|
+
# else; 'over'
|
99
|
+
# # yields 'low'
|
100
|
+
# ```
|
101
|
+
#
|
102
|
+
# ### incoming f.ret is preserved
|
103
|
+
#
|
104
|
+
# "case" makes sure `f.ret` gets to its upon-entering-"case" value
|
105
|
+
# when considered inside:
|
106
|
+
#
|
107
|
+
# ```
|
108
|
+
# 7
|
109
|
+
# case (+ 3 4)
|
110
|
+
# 5; 'cinq'
|
111
|
+
# [ f.ret ]; 'sept'
|
112
|
+
# 6; 'six'
|
113
|
+
# else; 'whatever...'
|
114
|
+
#
|
115
|
+
# # yields 'sept'
|
116
|
+
# ```
|
117
|
+
#
|
118
|
+
# ```
|
119
|
+
# "six"
|
120
|
+
# case 6
|
121
|
+
# 5; 'cinq'
|
122
|
+
# 7; 'sept'
|
123
|
+
# 6; "six $( f.ret | upcase _ )"
|
124
|
+
# else; 'je ne sais pas'
|
125
|
+
#
|
126
|
+
# # yields "six SIX"
|
127
|
+
# ```
|
128
|
+
#
|
88
129
|
# ## see also
|
89
130
|
#
|
90
131
|
# Match, cond, if.
|