pione 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. data/History.txt +12 -1
  2. data/example/AbstractRule/AbstractRule.pione +40 -0
  3. data/example/Fib/Fib.pione +12 -5
  4. data/example/LucasNumber/LucasNumber.pione +1 -1
  5. data/example/MakePair/MakePair.pione +21 -6
  6. data/example/OddSelector/OddSelector.pione +17 -0
  7. data/example/OddSelector/data/1.i +0 -0
  8. data/example/OddSelector/data/10.i +0 -0
  9. data/example/OddSelector/data/2.i +0 -0
  10. data/example/OddSelector/data/3.i +0 -0
  11. data/example/OddSelector/data/4.i +0 -0
  12. data/example/OddSelector/data/5.i +0 -0
  13. data/example/OddSelector/data/6.i +0 -0
  14. data/example/OddSelector/data/7.i +0 -0
  15. data/example/OddSelector/data/8.i +0 -0
  16. data/example/OddSelector/data/9.i +0 -0
  17. data/example/SequentialParameter/SequentialParameter.pione +4 -0
  18. data/example/SieveOfEratosthenes/SieveOfEratosthenes.pione +31 -43
  19. data/example/SingleParticlesWithRef/SingleParticlesWithRef.pione +1 -1
  20. data/example/Touch/Touch.pione +3 -0
  21. data/lib/pione/command/pione-syntax-checker.rb +4 -4
  22. data/lib/pione/model/assignment.rb +6 -1
  23. data/lib/pione/model/basic-model.rb +92 -278
  24. data/lib/pione/model/binary-operator.rb +5 -1
  25. data/lib/pione/model/block.rb +17 -0
  26. data/lib/pione/model/boolean.rb +54 -22
  27. data/lib/pione/model/constraints.rb +34 -0
  28. data/lib/pione/model/data-expr.rb +184 -297
  29. data/lib/pione/model/feature-expr.rb +13 -4
  30. data/lib/pione/model/float.rb +24 -41
  31. data/lib/pione/model/integer.rb +75 -41
  32. data/lib/pione/model/keyed-sequence.rb +143 -0
  33. data/lib/pione/model/list.rb +12 -8
  34. data/lib/pione/model/message.rb +8 -4
  35. data/lib/pione/model/ordinal-sequence.rb +75 -0
  36. data/lib/pione/model/package.rb +6 -2
  37. data/lib/pione/model/parameters.rb +61 -9
  38. data/lib/pione/model/pione-method.rb +146 -0
  39. data/lib/pione/model/rule-expr.rb +44 -38
  40. data/lib/pione/model/rule-io.rb +11 -3
  41. data/lib/pione/model/rule.rb +105 -155
  42. data/lib/pione/model/sequence.rb +273 -0
  43. data/lib/pione/model/string.rb +75 -29
  44. data/lib/pione/model/ticket-expr.rb +17 -29
  45. data/lib/pione/model/type.rb +242 -0
  46. data/lib/pione/model/variable-table.rb +52 -53
  47. data/lib/pione/model/variable.rb +8 -4
  48. data/lib/pione/model.rb +34 -0
  49. data/lib/pione/parser/block-parser.rb +44 -20
  50. data/lib/pione/parser/common-parser.rb +2 -1
  51. data/lib/pione/parser/document-parser.rb +6 -1
  52. data/lib/pione/parser/expr-parser.rb +57 -11
  53. data/lib/pione/parser/flow-element-parser.rb +2 -2
  54. data/lib/pione/parser/rule-definition-parser.rb +23 -1
  55. data/lib/pione/patch/rinda-patch.rb +1 -5
  56. data/lib/pione/rule-handler/action-handler.rb +5 -5
  57. data/lib/pione/rule-handler/basic-handler.rb +30 -7
  58. data/lib/pione/rule-handler/empty-handler.rb +14 -0
  59. data/lib/pione/rule-handler/flow-handler.rb +132 -115
  60. data/lib/pione/rule-handler/root-handler.rb +6 -2
  61. data/lib/pione/rule-handler/update-criteria.rb +152 -0
  62. data/lib/pione/rule-handler.rb +14 -0
  63. data/lib/pione/system/identifier.rb +9 -9
  64. data/lib/pione/transformer/block-transformer.rb +4 -0
  65. data/lib/pione/transformer/expr-transformer.rb +1 -1
  66. data/lib/pione/transformer/flow-element-transformer.rb +4 -2
  67. data/lib/pione/transformer/literal-transformer.rb +14 -3
  68. data/lib/pione/transformer/rule-definition-transformer.rb +17 -5
  69. data/lib/pione/tuple-space/data-finder.rb +15 -52
  70. data/lib/pione/version.rb +1 -1
  71. data/lib/pione.rb +12 -38
  72. data/test/agent/spec_task-worker.rb +13 -12
  73. data/test/model/spec_assignment.rb +2 -2
  74. data/test/model/spec_binary-operator.rb +10 -10
  75. data/test/model/spec_block.rb +8 -8
  76. data/test/model/spec_boolean.rb +1 -72
  77. data/test/model/spec_boolean.yml +134 -0
  78. data/test/model/spec_data-expr.rb +50 -237
  79. data/test/model/spec_data-expr.yml +16 -45
  80. data/test/model/spec_data-expr_match.yml +45 -0
  81. data/test/model/spec_feature-expr.rb +2 -43
  82. data/test/model/spec_feature-expr.yml +0 -28
  83. data/test/model/spec_feature-expr_decide.yml +28 -0
  84. data/test/model/spec_float.rb +1 -119
  85. data/test/model/spec_float.yml +17 -0
  86. data/test/model/spec_integer.rb +1 -119
  87. data/test/model/spec_integer.yml +57 -0
  88. data/test/model/spec_keyed-sequence.rb +5 -0
  89. data/test/model/spec_keyed-sequence.yml +22 -0
  90. data/test/model/spec_message.rb +7 -7
  91. data/test/model/spec_parameters.rb +50 -63
  92. data/test/model/spec_pione-method.rb +56 -0
  93. data/test/model/spec_rule-expr.rb +18 -8
  94. data/test/model/spec_rule.rb +12 -12
  95. data/test/model/spec_sequence.rb +5 -0
  96. data/test/model/spec_sequence.yml +60 -0
  97. data/test/model/spec_string.rb +3 -70
  98. data/test/model/spec_string.yml +83 -0
  99. data/test/model/spec_ticket-expr.rb +4 -54
  100. data/test/model/spec_ticket-expr.yml +11 -0
  101. data/test/model/spec_variable-table.rb +41 -42
  102. data/test/model/spec_variable.rb +20 -22
  103. data/test/parser/spec_block-parser.yml +9 -0
  104. data/test/parser/spec_expr-parser.yml +0 -17
  105. data/test/parser/spec_flow-element-parser.yml +1 -1
  106. data/test/parser/spec_rule-definition-parser.yml +0 -4
  107. data/test/rule-handler/spec_update-criteria.pione +39 -0
  108. data/test/rule-handler/spec_update-criteria.rb +53 -0
  109. data/test/rule-handler/spec_update-criteria.yml +158 -0
  110. data/test/test-util.rb +25 -0
  111. data/test/transformer/spec_block-transformer.rb +7 -0
  112. data/test/transformer/spec_expr-transformer.rb +64 -19
  113. data/test/transformer/spec_flow-element-transformer.rb +11 -11
  114. data/test/transformer/spec_literal-transformer.rb +29 -29
  115. data/test/transformer/spec_rule-definition-transformer.rb +39 -21
  116. metadata +57 -11
  117. data/lib/pione/model/undefined-value.rb +0 -24
  118. data/lib/pione/tuple-space/update-criteria.rb +0 -97
  119. data/test/model/spec_list.rb +0 -26
  120. data/test/model/spec_rule-io.rb +0 -32
  121. data/test/spec_update-criteria.rb +0 -83
@@ -80,7 +80,7 @@ module Pione
80
80
  list + callee.eval(@variable_table).expr.to_set.to_a.map{|expr| CallRule.new(expr)}
81
81
  end
82
82
 
83
- # ticket check
83
+ # check input tickets
84
84
  callees = callees.inject([]) do |list, callee|
85
85
  target = nil
86
86
  # check if tickets exist in the domain
@@ -99,28 +99,37 @@ module Pione
99
99
  # find callee rule
100
100
  rule = find_callee_rule_tuple(callee).content
101
101
 
102
- # update callee parameters
102
+ # callee parameters inherit caller parameters
103
103
  @variable_table.variables.each do |var|
104
104
  val = @variable_table.get(var)
105
- unless val == UndefinedValue.new
105
+ if val.kind_of?(Callable) or val.kind_of?(Variable) or val.void?
106
106
  if rule.params.keys.include?(var)
107
107
  callee.expr.params.set_safety!(var, val)
108
108
  end
109
109
  end
110
110
  end
111
111
 
112
- # eval callee rule by the context
113
- vtable = callee.expr.params.eval(@variable_table).as_variable_table
114
- rule = rule.eval(vtable)
115
-
116
- # check rule status and find combinations
117
- @data_finder.find(:input, rule.inputs, vtable).each do |res|
118
- combinations << [
119
- callee,
120
- rule,
121
- res.combination,
122
- res.variable_table
123
- ]
112
+ # build callee parameter from rule definition
113
+ callee_params = rule.params.merge(callee.expr.params)
114
+
115
+ # expand parameters
116
+ callee_params.eval(@variable_table).each do |atomic_params|
117
+
118
+ # eval callee rule by the context
119
+ vtable = atomic_params.eval(@variable_table).as_variable_table
120
+ rule = rule.eval(vtable)
121
+
122
+ # check rule status and find combinations
123
+ @data_finder.find(:input, rule.inputs, vtable).each do |res|
124
+ combinations << [
125
+ callee,
126
+ atomic_params,
127
+ rule,
128
+ res.combination,
129
+ res.variable_table,
130
+ ID.domain_id3(rule, res.combination, atomic_params)
131
+ ] if rule.constraints.satisfy?(res.variable_table)
132
+ end
124
133
  end
125
134
 
126
135
  # find next
@@ -145,13 +154,7 @@ module Pione
145
154
 
146
155
  # Find inputs and variables for flow element rules.
147
156
  def select_updatables(combinations)
148
- combinations.select do |callee, rule, inputs, vtable|
149
- # task domain
150
- task_domain = ID.domain_id3(rule, inputs, callee)
151
-
152
- # import finished tuples's data
153
- import_finished_outputs(task_domain)
154
-
157
+ combinations.map do |callee, params, rule, inputs, vtable, task_domain|
155
158
  # find outputs combination
156
159
  outputs_combination = @data_finder.find(
157
160
  :output,
@@ -163,10 +166,14 @@ module Pione
163
166
  outputs_combination = [[]] if outputs_combination.empty?
164
167
 
165
168
  # check update criterias
166
- outputs_combination.any?{|outputs|
167
- UpdateCriteria.satisfy?(rule, inputs, outputs, vtable)
169
+ orders = outputs_combination.map {|outputs|
170
+ UpdateCriteria.order(rule, inputs, outputs, vtable)
168
171
  }
169
- end
172
+ order = nil
173
+ order = :weak if orders.include?(:weak)
174
+ order = :force if orders.include?(:force)
175
+ [callee, params, rule, inputs, vtable, task_domain, order]
176
+ end.select {|_, _, _, _, _, _, order| not(order.nil?)}
170
177
  end
171
178
 
172
179
  # Distribute tasks.
@@ -181,58 +188,51 @@ module Pione
181
188
  process_log(@task_process_record.merge(transition: "suspend"))
182
189
  process_log(@rule_process_record.merge(transition: "suspend"))
183
190
 
184
- applications.uniq.each do |callee, rule, inputs, vtable|
185
- # task domain
186
- task_domain = ID.domain_id3(rule, inputs, callee)
187
-
191
+ applications.uniq.each do |callee, params, rule, inputs, vtable, task_domain, order|
188
192
  # make a task tuple
189
193
  task = Tuple[:task].new(
190
194
  rule.rule_path,
191
195
  inputs,
192
- callee.expr.params,
196
+ params,
193
197
  rule.features,
194
198
  task_domain,
195
199
  @call_stack + [@domain] # current call stack + caller
196
200
  )
197
201
 
198
- # check if same task exists
199
- begin
200
- if need_to_process_task?(task)
201
- # copy input data from the handler domain to task domain
202
- copy_data_into_domain(inputs, task_domain)
203
-
204
- # write the task
205
- write(task)
206
-
207
- # put task schedule process log
208
- task_process_record = Log::TaskProcessRecord.new.tap do |record|
209
- record.name = task.digest
210
- record.rule_name = rule.rule_path
211
- record.rule_type = rule.rule_type
212
- record.inputs = inputs.flatten.map{|input| input.name}.join(",")
213
- record.parameters = callee.expr.params.textize
214
- record.transition = "schedule"
215
- end
216
- process_log(task_process_record)
217
-
218
- msg = "distributed task %s on %s" % [task.digest, handler_digest]
219
- user_message(msg, 1)
220
-
221
- next
202
+ # check if the same task exists or finished already
203
+ if need_to_process_task?(task, order)
204
+ # clear finished tuple
205
+ remove_finished_tuple(task.domain)
206
+
207
+ # copy input data from this domain to the task domain
208
+ inputs.flatten.each {|input| copy_data_into_domain(input, task_domain)}
209
+
210
+ # write the task
211
+ write(task)
212
+
213
+ # put task schedule process log
214
+ task_process_record = Log::TaskProcessRecord.new.tap do |record|
215
+ record.name = task.digest
216
+ record.rule_name = rule.rule_path
217
+ record.rule_type = rule.rule_type
218
+ record.inputs = inputs.flatten.map{|input| input.name}.join(",")
219
+ record.parameters = params.textize
220
+ record.transition = "schedule"
222
221
  end
223
- rescue Rinda::RedundantTupleError
224
- # ignore
225
- end
222
+ process_log(task_process_record)
226
223
 
227
- show "cancel task %s on %s" % [task.digest, handler_digest]
228
- canceled << task_domain
224
+ # message
225
+ msg = "distributed task %s on %s" % [task.digest, handler_digest]
226
+ user_message(msg, 1)
227
+ else
228
+ # cancel the task
229
+ show "cancel task %s on %s" % [task.digest, handler_digest]
230
+ canceled << task_domain
231
+ end
229
232
  end
230
233
 
231
234
  # wait to finish threads
232
- applications.uniq.each do |callee, rule, inputs, vtable|
233
- # task domain
234
- task_domain = ID.domain_id3(rule, inputs, callee)
235
-
235
+ applications.uniq.each do |callee, params, rule, inputs, vtable, task_domain, order|
236
236
  # wait to finish the work
237
237
  template = Tuple[:finished].new(
238
238
  domain: task_domain,
@@ -240,16 +240,16 @@ module Pione
240
240
  )
241
241
  finished = read(template)
242
242
 
243
+ # show message about canceled tasks
243
244
  unless canceled.include?(task_domain)
244
245
  msg = "finished task %s on %s" % [finished.domain, handler_digest]
245
246
  user_message(msg, 1)
246
247
  end
247
248
 
248
- # copy data from task domain to this domain
249
- @finished << finished
250
- copy_data_into_domain(finished.outputs, @domain)
249
+ # copy write operation data tuple from the task domain to this domain
250
+ update_by_finished_tuple(rule, finished, vtable)
251
251
 
252
- # output ticket
252
+ # publish tickets into the domain
253
253
  callee.expr.output_ticket_expr.names.each do |name|
254
254
  write(Tuple[:ticket].new(@domain, name))
255
255
  end
@@ -262,39 +262,21 @@ module Pione
262
262
 
263
263
  # Return true if we need to write the task into the tuple space.
264
264
  #
265
- # @param [TaskTuple] task
266
- # task tuple
267
- # @return [Boolean]
268
- # true if we need to write the task into the tuple space
269
- def need_to_process_task?(task)
270
- not(read!(task) or working?(task))
271
- end
272
-
273
- # Return true if any task worker is working on the task.
274
- #
275
265
  # @param task [TaskTuple]
276
266
  # task tuple
267
+ # @param order [Symbol]
268
+ # update order type
277
269
  # @return [Boolean]
278
- # true if any task worker is working on the task
279
- def working?(task)
280
- read!(Tuple[:working].new(domain: task.domain))
281
- end
282
-
283
- # Find outputs from the domain.
284
- #
285
- # @return [void]
286
- def find_outputs
287
- tuples = read_all(Tuple[:data].new(domain: @domain))
288
- @rule.outputs.each_with_index do |output, i|
289
- output = output.eval(@variable_table)
290
- case output.modifier
291
- when :all
292
- @outputs[i] = tuples.find_all {|data| output.match(data.name)}
293
- when :each
294
- # FIXME
295
- @outputs[i] = tuples.find {|data| output.match(data.name)}
270
+ # true if we need to write the task into the tuple space
271
+ def need_to_process_task?(task, order)
272
+ # reuse task finished result if order is weak update
273
+ if order == :weak
274
+ if read!(Tuple[:finished].new(domain: task.domain, status: :succeeded))
275
+ return false
296
276
  end
297
277
  end
278
+ # check task status
279
+ not(read!(task) or read!(Tuple[:working].new(domain: task.domain)))
298
280
  end
299
281
 
300
282
  # Lift output data from child domains to this domain.
@@ -339,36 +321,71 @@ module Pione
339
321
  end
340
322
  end
341
323
 
324
+ # Remove finished tuple.
325
+ #
326
+ # @param domain [String]
327
+ # domain of the finished tuple
328
+ # @return [void]
329
+ def remove_finished_tuple(domain)
330
+ take!(Tuple[:finished].new(domain: domain))
331
+ end
332
+
342
333
  # Import finished tuple's outputs from the domain.
343
334
  #
344
335
  # @param [String] task_domain
345
336
  # target task domain
346
337
  # @return [void]
347
- def import_finished_outputs(task_domain)
348
- return if @finished.any?{|t| t.domain == task_domain}
349
- if task_domain != @domain
350
- template = Tuple[:finished].new(
351
- domain: task_domain,
352
- status: :succeeded
353
- )
354
- if finished = read!(template)
355
- copy_data_into_domain(finished.outputs, @domain)
338
+ def update_by_finished_tuple(rule, finished, vtable)
339
+ finished.outputs.each_with_index do |output, i|
340
+ data_expr = rule.outputs[i].eval(vtable)
341
+ case data_expr.operation
342
+ when :write
343
+ if output.kind_of?(Array)
344
+ output.each {|o| copy_data_into_domain(o, @domain)}
345
+ else
346
+ copy_data_into_domain(output, @domain)
347
+ end
348
+ when :remove
349
+ if output.kind_of?(Array)
350
+ output.each {|o| remove_data_from_domain(o, @domain)}
351
+ else
352
+ remove_data_from_domain(output, @domain)
353
+ end
354
+ when :touch
355
+ if output.kind_of?(Array)
356
+ output.each {|o| touch_data_in_domain(o, @domain)}
357
+ else
358
+ touch_data_in_domain(output, @domain)
359
+ end
356
360
  end
357
361
  end
358
362
  end
359
363
 
360
- # Copy data into specified domain and return the tuple list
361
- def copy_data_into_domain(src_data, dest_domain)
362
- src_data.flatten.compact.map do |d|
363
- new_data = d.clone
364
- new_data.domain = dest_domain
365
- begin
366
- write(new_data)
367
- rescue Rinda::RedundantTupleError
368
- # ignore
369
- end
370
- new_data
364
+ # Copy the data tuple with the specified domain and return the tuple list.
365
+ #
366
+ # @param data [DataTuple]
367
+ # target data tuple
368
+ # @param domain [String]
369
+ # new domain of the copied data tuple
370
+ # @return [DataTuple]
371
+ # new data tuple with the domain
372
+ def copy_data_into_domain(data, domain)
373
+ new_data = data.clone.tap {|x| x.domain = domain}
374
+ write(new_data)
375
+ return new_data
376
+ end
377
+
378
+ # Remove the data from the domain.
379
+ def remove_data_from_domain(data, domain)
380
+ take!(Tuple[:data].new(name: data.name, domain: domain))
381
+ end
382
+
383
+ def touch_data_in_domain(data, domain)
384
+ if target = read!(Tuple[:data].new(name: data.name, domain: domain))
385
+ data = target
371
386
  end
387
+ new_data = data.clone.tap {|x| x.domain = domain; x.time = Time.now}
388
+ write(new_data)
372
389
  end
373
390
  end
374
391
  end
@@ -9,11 +9,15 @@ module Pione
9
9
  # @api private
10
10
  def execute
11
11
  # import initial input tuples from input domain
12
- copy_data_into_domain(@inputs.flatten, @domain)
12
+ @inputs.flatten.each do |input|
13
+ copy_data_into_domain(input, @domain)
14
+ end
13
15
  # execute the rule
14
16
  result = super
15
17
  # export outputs to output domain
16
- copy_data_into_domain(@outputs.flatten, '/output')
18
+ @outputs.flatten.each do |output|
19
+ copy_data_into_domain(output, '/output')
20
+ end
17
21
  # substantiate symbolic links
18
22
  # substantiate_date
19
23
 
@@ -0,0 +1,152 @@
1
+ # UpdateCriteria repesents rule application criteria.
2
+ module Pione
3
+ module RuleHandler
4
+ module UpdateCriteria
5
+ class << self
6
+ # Return true if the rule has no output conditions.
7
+ #
8
+ # @param rule [Rule]
9
+ # rule
10
+ # @param inputs [Tuple::Data]
11
+ # input data tuples
12
+ # @param outputs [Tuple::Data]
13
+ # output data tuples
14
+ # @param vtable [VariableTable]
15
+ # variable table
16
+ # @return [Boolean]
17
+ # true if the rule has no output conditions
18
+ def no_output_conditions?(rule, inputs, outputs, vtable)
19
+ rule.outputs.empty?
20
+ end
21
+
22
+ # Return true if data tuples don't exist against output conditions with
23
+ # write operation.
24
+ #
25
+ # @param rule [Rule]
26
+ # rule
27
+ # @param inputs [Tuple::Data]
28
+ # input data tuples
29
+ # @param outputs [Tuple::Data]
30
+ # output data tuples
31
+ # @param vtable [VariableTable]
32
+ # variable table
33
+ # @return [Boolean]
34
+ # true if data tuples don't exist against output conditions with write
35
+ # operation
36
+ def not_exist_output_data?(rule, inputs, outputs, vtable)
37
+ result = false
38
+ rule.outputs.each_with_index do |data_expr, i|
39
+ data_expr = data_expr.eval(vtable)
40
+ if data_expr.write? or data_expr.touch?
41
+ case data_expr.distribution
42
+ when :all
43
+ if outputs[i].nil? or outputs[i].select{|data| data_expr.match(data.name)}.empty?
44
+ result = true
45
+ end
46
+ when :each
47
+ if outputs[i].nil? or not(data_expr.match(outputs[i].name))
48
+ result = true
49
+ end
50
+ end
51
+ end
52
+ break if result
53
+ end
54
+ return result
55
+ end
56
+
57
+
58
+ # Return true if data tuples exist against output conditions with remove
59
+ # or touch operation.
60
+ #
61
+ # @param rule [Rule]
62
+ # rule
63
+ # @param inputs [Tuple::Data]
64
+ # input data tuples
65
+ # @param outputs [Tuple::Data]
66
+ # output data tuples
67
+ # @param vtable [VariableTable]
68
+ # variable table
69
+ # @return [Boolean]
70
+ # if data tuples exist against output conditions with remove or touch
71
+ # operation
72
+ def exist_output_data?(rule, inputs, outputs, vtable)
73
+ result = false
74
+ rule.outputs.each_with_index do |data_expr, i|
75
+ data_expr = data_expr.eval(vtable)
76
+ if data_expr.remove?
77
+ case data_expr.distribution
78
+ when :all
79
+ if not(outputs[i].nil? or outputs[i].select{|data| data_expr.match(data.name)}.empty?)
80
+ result = true
81
+ end
82
+ when :each
83
+ if not(outputs[i].nil?) and data_expr.match(outputs[i].name)
84
+ result = true
85
+ end
86
+ end
87
+ end
88
+ break if result
89
+ end
90
+ return result
91
+ end
92
+
93
+ # Return true if newer input data exist.
94
+ #
95
+ # @param rule [Rule]
96
+ # rule
97
+ # @param inputs [Tuple::Data]
98
+ # input data tuples
99
+ # @param outputs [Tuple::Data]
100
+ # output data tuples
101
+ # @param vtable [VariableTable]
102
+ # variable table
103
+ # @return [Boolean]
104
+ # true if newer input data exist
105
+ def exist_newer_input_data?(rule, inputs, outputs, vtable)
106
+ # get output oldest time
107
+ outputs = outputs.select.with_index{|output, i| rule.outputs[i].eval(vtable).care?}
108
+ output_oldest_time = outputs.flatten.map{|output| output.time}.sort.first
109
+
110
+ # get input last time
111
+ inputs = inputs.select.with_index{|input, i| rule.inputs[i].eval(vtable).care?}
112
+ input_last_time = inputs.flatten.map{|input| input.time}.sort.last
113
+
114
+ #p output_oldest_time
115
+ #p input_last_time
116
+
117
+ # criteria
118
+ return false unless output_oldest_time
119
+ return false unless input_last_time
120
+ return output_oldest_time < input_last_time
121
+ end
122
+
123
+ # Return update order name if we need to update.
124
+ #
125
+ # @param [Rule] rule
126
+ # rule
127
+ # @param [Tuple::DataTuple] inputs
128
+ # input tuples
129
+ # @param [Tuple::DataTuple] outputs
130
+ # output tuples
131
+ # @param [VariableTable] vtable
132
+ # variable table
133
+ # @return [Symbol,nil]
134
+ # update order or nil
135
+ def order(rule, inputs, outputs, vtable)
136
+ if FORCE_UPDATE.any? {|name| self.send(name, rule, inputs, outputs, vtable)}
137
+ return :force
138
+ end
139
+ if WEAK_UPDATE.any? {|name| self.send(name, rule, inputs, outputs, vtable)}
140
+ return :weak
141
+ end
142
+ end
143
+
144
+ # force update criteria
145
+ FORCE_UPDATE = [:no_output_conditions?, :exist_newer_input_data?]
146
+
147
+ # update criteria
148
+ WEAK_UPDATE = [:not_exist_output_data?, :exist_output_data?]
149
+ end
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,14 @@
1
+ module Pione
2
+ # RuleHandler is a name space for rule handling classes.
3
+ module RuleHandler
4
+ end
5
+ end
6
+
7
+ require 'pione/rule-handler/basic-handler'
8
+ require 'pione/rule-handler/update-criteria'
9
+ require 'pione/rule-handler/flow-handler'
10
+ require 'pione/rule-handler/action-handler'
11
+ require 'pione/rule-handler/root-handler'
12
+ require 'pione/rule-handler/system-handler'
13
+ require 'pione/rule-handler/empty-handler'
14
+
@@ -37,19 +37,19 @@ module Pione
37
37
  end
38
38
  module_function :domain_id
39
39
 
40
- # Makes target domain name by module name, inputs, and outputs.
41
- # @param [String] rule
40
+ # Make a domain name by rule path, inputs, and parameters.
41
+ #
42
+ # @param rule [String]
42
43
  # package name
43
- # @param [Array<Pione::Tuple::Data>] inputs
44
+ # @param inputs [Array<Pione::Tuple::Data>]
44
45
  # input data tuples
45
- # @param [Pione::Model::] callee
46
- # parameters object
46
+ # @param params [Model::Parameters]
47
+ # parameters
47
48
  # @return [String]
48
49
  # domain string
49
- def domain_id3(rule, inputs, callee)
50
- package_name = rule.expr.package.name
51
- rule_name = rule.expr.name
52
- params = callee.expr.params
50
+ def domain_id3(rule, inputs, params)
51
+ package_name = rule.rule_expr.package.name
52
+ rule_name = rule.rule_expr.name
53
53
  return domain_id(package_name, rule_name, inputs, params)
54
54
  end
55
55
  module_function :domain_id3
@@ -19,6 +19,10 @@ module Pione
19
19
  x.set_line_and_column(keyword_Action.line_and_column)
20
20
  end
21
21
  }
22
+
23
+ rule(:empty_block => simple(:any)) {
24
+ EmptyBlock.instance
25
+ }
22
26
  end
23
27
  end
24
28
  end
@@ -67,7 +67,7 @@ module Pione
67
67
 
68
68
  # data null
69
69
  rule(:data_null => simple(:obj)) {
70
- Model::DataExprNull.instance
70
+ Model::DataExprNull.instance.to_seq
71
71
  }
72
72
 
73
73
  # Extract the content of +:rule_expr+.
@@ -11,7 +11,6 @@ module Pione
11
11
 
12
12
  # Transform +:call_rule: as Model::CallRule.
13
13
  rule(:call_rule => subtree(:rule_expr)) {
14
- TypeRuleExpr.check(rule_expr)
15
14
  CallRule.new(rule_expr)
16
15
  }
17
16
 
@@ -21,7 +20,10 @@ module Pione
21
20
  :if_true_elements => sequence(:if_true),
22
21
  :if_else_block => simple(:if_false)
23
22
  }) {
24
- block = { Model::PioneBoolean.true => Model::FlowBlock.new(*if_true) }
23
+ block = {
24
+ Model::BooleanSequence.new([Model::PioneBoolean.true]) =>
25
+ Model::FlowBlock.new(*if_true)
26
+ }
25
27
  block[:else] = if_false if if_false
26
28
  Model::ConditionalBlock.new(condition, block)
27
29
  }
@@ -9,6 +9,7 @@ module Pione
9
9
  val = (s == "true")
10
10
  Model::PioneBoolean.new(val).tap do |x|
11
11
  x.set_line_and_column(s.line_and_column)
12
+ break Model::BooleanSequence.new([x])
12
13
  end
13
14
  end
14
15
 
@@ -18,13 +19,21 @@ module Pione
18
19
  val = s.str.gsub(/\\(.)/){$1}
19
20
  Model::PioneString.new(val).tap do |x|
20
21
  x.set_line_and_column(s.line_and_column)
22
+ break Model::StringSequence.new([x])
21
23
  end
22
24
  end
23
25
 
26
+ # NOTE: how do we get the position of empty string?
27
+ rule(:string => sequence(:empty)) do
28
+ # convert backslash notations
29
+ Model::StringSequence.new([Model::PioneString.new("")])
30
+ end
31
+
24
32
  # Transform +:integer+ as Model::PioneInteger.
25
33
  rule(:integer => simple(:i)) do
26
34
  Model::PioneInteger.new(i.to_i).tap do |x|
27
35
  x.set_line_and_column(i.line_and_column)
36
+ break Model::IntegerSequence.new([x])
28
37
  end
29
38
  end
30
39
 
@@ -32,6 +41,7 @@ module Pione
32
41
  rule(:float => simple(:f)) do
33
42
  Model::PioneFloat.new(f.to_f).tap do |x|
34
43
  x.set_line_and_column(f.line_and_column)
44
+ break Model::FloatSequence.new([x])
35
45
  end
36
46
  end
37
47
 
@@ -48,6 +58,7 @@ module Pione
48
58
  val = name.str.gsub(/\\(.)/){$1}
49
59
  Model::DataExpr.new(val).tap do |x|
50
60
  x.set_line_and_column(name.line_and_column)
61
+ break Model::DataExprSequence.new([x])
51
62
  end
52
63
  end
53
64
 
@@ -63,7 +74,7 @@ module Pione
63
74
  rule(:rule_name => simple(:name)) do
64
75
  package = Package.new(Thread.current[:current_package_name])
65
76
  val = name.str
66
- RuleExpr.new(package, val, Parameters.empty, TicketExpr.empty, TicketExpr.empty).tap do |x|
77
+ RuleExpr.new(package, val).tap do |x|
67
78
  x.set_line_and_column(name.line_and_column)
68
79
  end
69
80
  end
@@ -71,9 +82,9 @@ module Pione
71
82
  # ticket
72
83
  rule(:ticket => simple(:name)) do
73
84
  line_and_column = name.line_and_column
74
- TicketExpr.new([name.to_s]) do
85
+ TicketExpr.new(name.to_s) do
75
86
  set_line_and_column(line_and_column)
76
- end
87
+ end.to_seq
77
88
  end
78
89
  end
79
90
  end