flor 0.13.0 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/CHANGELOG.md +8 -0
  2. data/lib/flor.rb +1 -1
  3. data/lib/flor/core.rb +7 -0
  4. data/lib/flor/core/executor.rb +43 -8
  5. data/lib/flor/core/node.rb +84 -54
  6. data/lib/flor/core/procedure.rb +36 -19
  7. data/lib/flor/core/texecutor.rb +4 -1
  8. data/lib/flor/deep.rb +43 -51
  9. data/lib/flor/dollar.rb +2 -3
  10. data/lib/flor/flor.rb +38 -9
  11. data/lib/flor/parser.rb +123 -72
  12. data/lib/flor/pcore/_arr.rb +15 -0
  13. data/lib/flor/pcore/_atom.rb +6 -5
  14. data/lib/flor/pcore/_att.rb +9 -4
  15. data/lib/flor/pcore/_obj.rb +28 -34
  16. data/lib/flor/pcore/_pat_.rb +77 -0
  17. data/lib/flor/pcore/_pat_arr.rb +131 -0
  18. data/lib/flor/pcore/_pat_guard.rb +70 -0
  19. data/lib/flor/pcore/_pat_obj.rb +143 -0
  20. data/lib/flor/pcore/_pat_or.rb +46 -0
  21. data/lib/flor/pcore/_val.rb +20 -0
  22. data/lib/flor/pcore/arith.rb +7 -1
  23. data/lib/flor/pcore/case.rb +46 -69
  24. data/lib/flor/pcore/cursor.rb +24 -24
  25. data/lib/flor/pcore/define.rb +5 -1
  26. data/lib/flor/pcore/do_return.rb +32 -0
  27. data/lib/flor/pcore/length.rb +18 -0
  28. data/lib/flor/pcore/logo.rb +47 -0
  29. data/lib/flor/pcore/map.rb +12 -10
  30. data/lib/flor/pcore/match.rb +276 -0
  31. data/lib/flor/pcore/not.rb +13 -0
  32. data/lib/flor/pcore/push.rb +52 -13
  33. data/lib/flor/pcore/range.rb +69 -0
  34. data/lib/flor/pcore/set.rb +82 -24
  35. data/lib/flor/unit/hook.rb +28 -0
  36. data/lib/flor/unit/hooker.rb +5 -0
  37. data/lib/flor/unit/loader.rb +4 -1
  38. data/lib/flor/unit/storage.rb +5 -3
  39. data/lib/flor/unit/waiter.rb +12 -2
  40. data/lib/flor/unit/wlist.rb +4 -3
  41. data/match.md +22 -0
  42. metadata +15 -5
  43. data/lib/flor/pcore/_happly.rb +0 -49
  44. data/lib/flor/pcore/val.rb +0 -16
  45. data/t.txt +0 -4
@@ -1,28 +1,105 @@
1
1
 
2
2
  class Flor::Pro::Set < Flor::Procedure
3
+ #
4
+ # sets a field or a variable.
5
+ #
6
+ # ```
7
+ # sequence
8
+ # set f.a 1 # sets the value `1` in the field 'a'
9
+ # set a false # sets the `false` in the variable 'a'
10
+ # set v.b [ 1 2 ] # sets `[ 1, 2 ]` in the variable 'b'
11
+ # set v.c.0 -1 # sets `-1` in first slot of the array in var 'c'
12
+ # ```
13
+ #
14
+ # When set has a single child, it uses as value to copy the content of
15
+ # payload.ret.
16
+ #
17
+ # ```
18
+ # sequence
19
+ # "hello world"
20
+ # set a
21
+ # #
22
+ # # is equivalent to
23
+ # #
24
+ # sequence
25
+ # set a "hello world"
26
+ # ```
27
+ #
28
+ # ## splat
29
+ #
30
+ # ```
31
+ # sequence
32
+ # set a b___ c
33
+ # [ 0 1 2 3 ]
34
+ # # ==> a: 0, b: [ 1, 2 ], c: 3
35
+ # set d e__2 f
36
+ # [ 4 5 6 7 8 ]
37
+ # # ==> d: 4, e: [ 5, 6 ], f: 7
38
+ # set __2 g h
39
+ # [ 9 10 11 12 13 ]
40
+ # # ==> g: 11, h: 12
41
+ # # `__` is not prefixed by a var name, so it justs discard
42
+ # # what it captures
43
+ # set i j___
44
+ # [ 14 15 16 17 18 19 ]
45
+ # # ==> i: 14, j: (15..19).to_a
46
+ # set "k__$(c)" l
47
+ # [ 20 21 22 23 24 ]
48
+ # # ==> k: [ 20, 21, 22 ], l: 23
49
+ # ```
50
+ #
51
+ # ## "setr"
52
+ #
53
+ # "set", before terminating its execution carefully resets the payload.ret
54
+ # value to what it was right before it started executing.
55
+ # "setr" is a version of "set" that doesn't care and leave payload.ret to
56
+ # value set by its last child (usually the value set).
57
+ #
58
+ # ```
59
+ # sequence
60
+ # 123 # payload.ret is set to `123`
61
+ # set a 456 # var 'a' is set to 456, payload.ret is reset to `123`
62
+ # setr b 789 # var 'b' is set to `789`, payload.ret as well
63
+ # ```
3
64
 
4
65
  names %w[ set setr ]
5
66
 
6
67
  def pre_execute
7
68
 
8
69
  unatt_unkeyed_children
9
- stringify_first_child
70
+
71
+ nacn = non_att_children.dup
72
+ sc = @node['single_child'] = nacn.size == 1
73
+ nacn = non_att_children[0..-2] unless sc
74
+
75
+ nacn.each_with_index { |_, i| stringify_child(i) }
76
+
77
+ @node['refs'] = []
10
78
  end
11
79
 
12
80
  def receive_non_att
13
81
 
14
- @node['ref'] ||= payload['ret']
82
+ ret = payload['ret']
83
+ last = ! @node['single_child'] && (@fcid + 1) == children.size
84
+
85
+ @node['refs'] << ret if ! last && ret.is_a?(String)
15
86
 
16
87
  super
17
88
  end
18
89
 
19
90
  def receive_last
20
91
 
21
- set_value(@node['ref'], payload['ret'])
92
+ ret = @node['single_child'] ? node_payload_ret : payload['ret']
93
+
94
+ if @node['refs'].size == 1
95
+ set_value(@node['refs'].first, ret)
96
+ else
97
+ Flor.splat(@node['refs'], ret).each { |k, v| set_value(k, v) }
98
+ end
22
99
 
23
100
  payload['ret'] =
24
- if tree[0] == 'setr' || @node['ref'] == 'f.ret'
25
- payload['ret']
101
+ if tree[0] == 'setr' || @node['refs'].last == 'f.ret'
102
+ ret
26
103
  else
27
104
  node_payload_ret
28
105
  end
@@ -31,22 +108,3 @@ class Flor::Pro::Set < Flor::Procedure
31
108
  end
32
109
  end
33
110
 
34
- # protected
35
- #
36
- # def splat(ks, vs)
37
- #
38
- # ks.inject(0) { |off, k|
39
- # if k[0, 1] == '*'
40
- # #p({ off: off, k: k, ks: ks[off + 1..-1], vs: vs[off..-1] })
41
- # l = vs.length - ks.length + 1
42
- # set_value(k[1..-1], vs[off, l])
43
- # off + l
44
- # else
45
- # set_value(k, vs[off])
46
- # off + 1
47
- # end
48
- # }
49
- # end
50
- #
51
- # TODO need a splat a some point
52
-
@@ -15,10 +15,17 @@ module Flor
15
15
  opts = {}
16
16
  opts[:consumed] = @h['consumed']
17
17
  opts[:point] = Flor.h_fetch_a(@h, 'points', 'point', nil)
18
+ opts[:nid] = Flor.h_fetch_a(@h, 'nids', 'nid', nil)
18
19
  opts[:heap] = Flor.h_fetch_a(@h, 'heaps', 'heap', nil)
19
20
  opts[:heat] = Flor.h_fetch_a(@h, 'heats', 'heat', nil)
20
21
  #opts[:name] = data['names']
21
22
 
23
+ #correct_points(opts)
24
+ #
25
+ # Necessary since "cancel" gets interpreted as
26
+ # [ '_proc', { 'proc' => 'cancel' }, @line ]
27
+ # ...
28
+
22
29
  [ "hook#{object_id}", opts, self, nil ]
23
30
  end
24
31
 
@@ -27,6 +34,27 @@ module Flor
27
34
 
28
35
  @unit.runner.run(executor, @h, message)
29
36
  end
37
+
38
+ # Avoid the proc/cancel problem upstreams in ConfExecutor, by ignoring
39
+ # non-core procedures, keeping this around for now
40
+ #
41
+ # protected
42
+ #
43
+ # def correct_points(opts)
44
+ #
45
+ # pts = opts[:point]; return unless pts
46
+ #
47
+ # opts[:point] =
48
+ # Flor.is_tree?(pts) ?
49
+ # correct_point(pts) :
50
+ # pts.collect { |pt| correct_point(pt) }
51
+ # end
52
+ #
53
+ # def correct_point(point)
54
+ #
55
+ # return point[1]['proc'] if point.is_a?(Array) && point[0] == '_proc'
56
+ # point
57
+ # end
30
58
  end
31
59
  end
32
60
 
@@ -102,6 +102,11 @@ module Flor
102
102
  ps = o(opts, :point, :p, [])
103
103
  return false if ps && ! ps.include?(message['point'])
104
104
 
105
+ if nid = o(opts, :nid)
106
+ return false \
107
+ unless nid.include?(message['nid'])
108
+ end
109
+
105
110
  if exi = o(opts, :exid)
106
111
  return false \
107
112
  unless message['exid'] == exi
@@ -94,6 +94,9 @@ module Flor
94
94
 
95
95
  def hooks(domain, name=nil)
96
96
 
97
+ # NB: do not relativize path, because Ruby load path != cwd,
98
+ # stay absolute for `require` and `load`
99
+
97
100
  Dir[File.join(@root, '**/*.json')]
98
101
  .select { |f| f.index('/lib/hooks/') }
99
102
  .collect { |pa| [ pa, expose_d(pa, {}) ] }
@@ -101,7 +104,7 @@ module Flor
101
104
  .sort_by { |pa, d| d.count('.') }
102
105
  .collect { |pa, d|
103
106
  interpret(pa).each_with_index { |h, i|
104
- h['_path'] = Flor.relativize_path(pa) + ":#{i}" } }
107
+ h['_path'] = pa + ":#{i}" } }
105
108
  .flatten(1)
106
109
  end
107
110
 
@@ -625,9 +625,11 @@ module Flor
625
625
  }.compact
626
626
 
627
627
  pointers +=
628
- exe['tasks'].collect { |nid, v|
629
- [ dom, exid, nid, 'tasker', v['tasker'], v['name'], now, u ]
630
- }
628
+ exe['tasks']
629
+ .reject { |_, v|
630
+ v['tasker'] == nil }
631
+ .collect { |nid, v|
632
+ [ dom, exid, nid, 'tasker', v['tasker'], v['name'], now, u ] }
631
633
 
632
634
  cps = @db[:flor_pointers] # current pointers
633
635
  .where(exid: exid)
@@ -5,12 +5,14 @@ module Flor
5
5
 
6
6
  def initialize(exid, opts)
7
7
 
8
- serie, timeout, repeat = expand_args(opts)
8
+ serie, timeout, on_timeout, repeat =
9
+ expand_args(opts)
9
10
 
10
11
  @exid = exid
11
12
  @original_serie = repeat ? Flor.dup(serie) : nil
12
13
  @serie = serie
13
14
  @timeout = timeout
15
+ @on_timeout = on_timeout
14
16
 
15
17
  @queue = []
16
18
  @mutex = Mutex.new
@@ -59,7 +61,11 @@ module Flor
59
61
  @var.wait(@mutex, @timeout)
60
62
  # will wait "in aeternum" if @timeout is nil
61
63
 
62
- fail(RuntimeError, "timeout for #{self.to_s}") if @queue.empty?
64
+ if @queue.empty?
65
+ fail RuntimeError.new(
66
+ "timeout for #{self.to_s}") if @on_timeout == 'fail'
67
+ return { 'exid' => @exid, 'timed_out' => @on_timeout }
68
+ end
63
69
  end
64
70
 
65
71
  #executor, message = @queue.shift
@@ -89,19 +95,23 @@ module Flor
89
95
  owait = opts[:wait]
90
96
  orepeat = opts[:repeat] || false
91
97
  otimeout = opts[:timeout]
98
+ oontimeout = opts[:on_timeout] || opts[:ontimeout] || 'fail'
92
99
 
93
100
  case owait
94
101
  when true
95
102
  [ [ [ nil, %w[ failed terminated ] ] ], # serie
96
103
  otimeout,
104
+ oontimeout,
97
105
  orepeat ]
98
106
  when Numeric
99
107
  [ [ [ nil, %w[ failed terminated ] ] ], # serie
100
108
  owait, # timeout
109
+ oontimeout,
101
110
  orepeat ]
102
111
  when String, Array
103
112
  [ parse_serie(owait), # serie
104
113
  otimeout,
114
+ oontimeout,
105
115
  orepeat ]
106
116
  else
107
117
  fail ArgumentError.new(
@@ -19,8 +19,8 @@ module Flor
19
19
  @waiters = []
20
20
 
21
21
  @unit.instance_eval do
22
- def wait(exid, opts=true)
23
- @hooker['wlist'].wait(exid, opts)
22
+ def wait(exid, opts=true, more=nil)
23
+ @hooker['wlist'].wait(exid, opts, more)
24
24
  end
25
25
  end
26
26
  end
@@ -46,7 +46,7 @@ module Flor
46
46
  [] # no new messages
47
47
  end
48
48
 
49
- def wait(exid, opts)
49
+ def wait(exid, opts, more)
50
50
 
51
51
  exid, opts =
52
52
  if opts == true && exid == 'idle'
@@ -56,6 +56,7 @@ module Flor
56
56
  else
57
57
  [ exid, opts ]
58
58
  end
59
+ opts.merge!(more) if more.is_a?(Hash)
59
60
 
60
61
  opts[:timeout] =
61
62
  nil if opts[:timeout] == true
@@ -0,0 +1,22 @@
1
+
2
+ ```
3
+ match f.data
4
+ { temperature: t }; register_temperature t
5
+ { humidity: h }; register_humidity h
6
+ { luminosity: l, period: 'am' }; register_morning_luminosity l
7
+ { luminosity: l }; register_pm_luminosity l
8
+ ```
9
+
10
+ or
11
+
12
+ ```
13
+ cond
14
+ f.data.temperature; register_temperature f.data.temperature
15
+ f.data.humidity; register_humidity f.data.humidity
16
+ and \
17
+ luminosity
18
+ == period 'am'
19
+ register_morning_luminosity f.data.luminosity
20
+ f.data.luminosity; register_pm_luminosity f.data.luminosity
21
+ ```
22
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.0
4
+ version: 0.14.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-04-24 00:00:00.000000000 Z
12
+ date: 2017-06-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: munemo
@@ -140,9 +140,14 @@ files:
140
140
  - lib/flor/pcore/_att.rb
141
141
  - lib/flor/pcore/_dump.rb
142
142
  - lib/flor/pcore/_err.rb
143
- - lib/flor/pcore/_happly.rb
144
143
  - lib/flor/pcore/_obj.rb
144
+ - lib/flor/pcore/_pat_.rb
145
+ - lib/flor/pcore/_pat_arr.rb
146
+ - lib/flor/pcore/_pat_guard.rb
147
+ - lib/flor/pcore/_pat_obj.rb
148
+ - lib/flor/pcore/_pat_or.rb
145
149
  - lib/flor/pcore/_skip.rb
150
+ - lib/flor/pcore/_val.rb
146
151
  - lib/flor/pcore/apply.rb
147
152
  - lib/flor/pcore/arith.rb
148
153
  - lib/flor/pcore/break.rb
@@ -151,23 +156,28 @@ files:
151
156
  - lib/flor/pcore/cond.rb
152
157
  - lib/flor/pcore/cursor.rb
153
158
  - lib/flor/pcore/define.rb
159
+ - lib/flor/pcore/do_return.rb
154
160
  - lib/flor/pcore/echo.rb
155
161
  - lib/flor/pcore/fail.rb
156
162
  - lib/flor/pcore/if.rb
163
+ - lib/flor/pcore/length.rb
164
+ - lib/flor/pcore/logo.rb
157
165
  - lib/flor/pcore/loop.rb
158
166
  - lib/flor/pcore/map.rb
167
+ - lib/flor/pcore/match.rb
159
168
  - lib/flor/pcore/matchr.rb
160
169
  - lib/flor/pcore/move.rb
161
170
  - lib/flor/pcore/noeval.rb
162
171
  - lib/flor/pcore/noret.rb
172
+ - lib/flor/pcore/not.rb
163
173
  - lib/flor/pcore/push.rb
164
174
  - lib/flor/pcore/rand.rb
175
+ - lib/flor/pcore/range.rb
165
176
  - lib/flor/pcore/sequence.rb
166
177
  - lib/flor/pcore/set.rb
167
178
  - lib/flor/pcore/stall.rb
168
179
  - lib/flor/pcore/twig.rb
169
180
  - lib/flor/pcore/until.rb
170
- - lib/flor/pcore/val.rb
171
181
  - lib/flor/punit/cancel.rb
172
182
  - lib/flor/punit/cmap.rb
173
183
  - lib/flor/punit/concurrence.rb
@@ -208,8 +218,8 @@ files:
208
218
  - lib/flor.rb
209
219
  - flor.gemspec
210
220
  - LICENSE.txt
211
- - t.txt
212
221
  - CHANGELOG.md
222
+ - match.md
213
223
  - README.md
214
224
  homepage: http://github.com/floraison
215
225
  licenses:
@@ -1,49 +0,0 @@
1
-
2
- class Flor::Pro::Happly < Flor::Procedure
3
-
4
- name '_happly'
5
-
6
- def pre_execute
7
-
8
- @node['atts'] = []
9
- end
10
-
11
- def execute
12
-
13
- wrap(
14
- 'point' => 'execute',
15
- 'nid' => Flor.child_nid(nid, tree[1].size),
16
- 'tree' => tree[0])
17
- end
18
-
19
- def receive
20
-
21
- fcid = Flor.child_id(message['from'])
22
-
23
- return wrap_reply if @node['applied']
24
- return super unless fcid == tree[1].size
25
-
26
- ret = payload['ret']
27
-
28
- @node['hret'] = payload['ret']
29
- execute_child(0)
30
- end
31
-
32
- def receive_last
33
-
34
- hret = @node['hret']
35
-
36
- return wrap_reply('ret' => hret) unless Flor.is_func_tree?(hret)
37
-
38
- args = @node['atts'].collect(&:last)
39
-
40
- hret[1].merge!('head' => true, 'nid' => nid)
41
-
42
- msgs = apply(hret, args, tree[2])
43
-
44
- @node['applied'] = msgs.first['nid']
45
-
46
- msgs
47
- end
48
- end
49
-