pione 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +12 -1
- data/example/AbstractRule/AbstractRule.pione +40 -0
- data/example/Fib/Fib.pione +12 -5
- data/example/LucasNumber/LucasNumber.pione +1 -1
- data/example/MakePair/MakePair.pione +21 -6
- data/example/OddSelector/OddSelector.pione +17 -0
- data/example/OddSelector/data/1.i +0 -0
- data/example/OddSelector/data/10.i +0 -0
- data/example/OddSelector/data/2.i +0 -0
- data/example/OddSelector/data/3.i +0 -0
- data/example/OddSelector/data/4.i +0 -0
- data/example/OddSelector/data/5.i +0 -0
- data/example/OddSelector/data/6.i +0 -0
- data/example/OddSelector/data/7.i +0 -0
- data/example/OddSelector/data/8.i +0 -0
- data/example/OddSelector/data/9.i +0 -0
- data/example/SequentialParameter/SequentialParameter.pione +4 -0
- data/example/SieveOfEratosthenes/SieveOfEratosthenes.pione +31 -43
- data/example/SingleParticlesWithRef/SingleParticlesWithRef.pione +1 -1
- data/example/Touch/Touch.pione +3 -0
- data/lib/pione/command/pione-syntax-checker.rb +4 -4
- data/lib/pione/model/assignment.rb +6 -1
- data/lib/pione/model/basic-model.rb +92 -278
- data/lib/pione/model/binary-operator.rb +5 -1
- data/lib/pione/model/block.rb +17 -0
- data/lib/pione/model/boolean.rb +54 -22
- data/lib/pione/model/constraints.rb +34 -0
- data/lib/pione/model/data-expr.rb +184 -297
- data/lib/pione/model/feature-expr.rb +13 -4
- data/lib/pione/model/float.rb +24 -41
- data/lib/pione/model/integer.rb +75 -41
- data/lib/pione/model/keyed-sequence.rb +143 -0
- data/lib/pione/model/list.rb +12 -8
- data/lib/pione/model/message.rb +8 -4
- data/lib/pione/model/ordinal-sequence.rb +75 -0
- data/lib/pione/model/package.rb +6 -2
- data/lib/pione/model/parameters.rb +61 -9
- data/lib/pione/model/pione-method.rb +146 -0
- data/lib/pione/model/rule-expr.rb +44 -38
- data/lib/pione/model/rule-io.rb +11 -3
- data/lib/pione/model/rule.rb +105 -155
- data/lib/pione/model/sequence.rb +273 -0
- data/lib/pione/model/string.rb +75 -29
- data/lib/pione/model/ticket-expr.rb +17 -29
- data/lib/pione/model/type.rb +242 -0
- data/lib/pione/model/variable-table.rb +52 -53
- data/lib/pione/model/variable.rb +8 -4
- data/lib/pione/model.rb +34 -0
- data/lib/pione/parser/block-parser.rb +44 -20
- data/lib/pione/parser/common-parser.rb +2 -1
- data/lib/pione/parser/document-parser.rb +6 -1
- data/lib/pione/parser/expr-parser.rb +57 -11
- data/lib/pione/parser/flow-element-parser.rb +2 -2
- data/lib/pione/parser/rule-definition-parser.rb +23 -1
- data/lib/pione/patch/rinda-patch.rb +1 -5
- data/lib/pione/rule-handler/action-handler.rb +5 -5
- data/lib/pione/rule-handler/basic-handler.rb +30 -7
- data/lib/pione/rule-handler/empty-handler.rb +14 -0
- data/lib/pione/rule-handler/flow-handler.rb +132 -115
- data/lib/pione/rule-handler/root-handler.rb +6 -2
- data/lib/pione/rule-handler/update-criteria.rb +152 -0
- data/lib/pione/rule-handler.rb +14 -0
- data/lib/pione/system/identifier.rb +9 -9
- data/lib/pione/transformer/block-transformer.rb +4 -0
- data/lib/pione/transformer/expr-transformer.rb +1 -1
- data/lib/pione/transformer/flow-element-transformer.rb +4 -2
- data/lib/pione/transformer/literal-transformer.rb +14 -3
- data/lib/pione/transformer/rule-definition-transformer.rb +17 -5
- data/lib/pione/tuple-space/data-finder.rb +15 -52
- data/lib/pione/version.rb +1 -1
- data/lib/pione.rb +12 -38
- data/test/agent/spec_task-worker.rb +13 -12
- data/test/model/spec_assignment.rb +2 -2
- data/test/model/spec_binary-operator.rb +10 -10
- data/test/model/spec_block.rb +8 -8
- data/test/model/spec_boolean.rb +1 -72
- data/test/model/spec_boolean.yml +134 -0
- data/test/model/spec_data-expr.rb +50 -237
- data/test/model/spec_data-expr.yml +16 -45
- data/test/model/spec_data-expr_match.yml +45 -0
- data/test/model/spec_feature-expr.rb +2 -43
- data/test/model/spec_feature-expr.yml +0 -28
- data/test/model/spec_feature-expr_decide.yml +28 -0
- data/test/model/spec_float.rb +1 -119
- data/test/model/spec_float.yml +17 -0
- data/test/model/spec_integer.rb +1 -119
- data/test/model/spec_integer.yml +57 -0
- data/test/model/spec_keyed-sequence.rb +5 -0
- data/test/model/spec_keyed-sequence.yml +22 -0
- data/test/model/spec_message.rb +7 -7
- data/test/model/spec_parameters.rb +50 -63
- data/test/model/spec_pione-method.rb +56 -0
- data/test/model/spec_rule-expr.rb +18 -8
- data/test/model/spec_rule.rb +12 -12
- data/test/model/spec_sequence.rb +5 -0
- data/test/model/spec_sequence.yml +60 -0
- data/test/model/spec_string.rb +3 -70
- data/test/model/spec_string.yml +83 -0
- data/test/model/spec_ticket-expr.rb +4 -54
- data/test/model/spec_ticket-expr.yml +11 -0
- data/test/model/spec_variable-table.rb +41 -42
- data/test/model/spec_variable.rb +20 -22
- data/test/parser/spec_block-parser.yml +9 -0
- data/test/parser/spec_expr-parser.yml +0 -17
- data/test/parser/spec_flow-element-parser.yml +1 -1
- data/test/parser/spec_rule-definition-parser.yml +0 -4
- data/test/rule-handler/spec_update-criteria.pione +39 -0
- data/test/rule-handler/spec_update-criteria.rb +53 -0
- data/test/rule-handler/spec_update-criteria.yml +158 -0
- data/test/test-util.rb +25 -0
- data/test/transformer/spec_block-transformer.rb +7 -0
- data/test/transformer/spec_expr-transformer.rb +64 -19
- data/test/transformer/spec_flow-element-transformer.rb +11 -11
- data/test/transformer/spec_literal-transformer.rb +29 -29
- data/test/transformer/spec_rule-definition-transformer.rb +39 -21
- metadata +57 -11
- data/lib/pione/model/undefined-value.rb +0 -24
- data/lib/pione/tuple-space/update-criteria.rb +0 -97
- data/test/model/spec_list.rb +0 -26
- data/test/model/spec_rule-io.rb +0 -32
- 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
|
-
#
|
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
|
-
#
|
102
|
+
# callee parameters inherit caller parameters
|
103
103
|
@variable_table.variables.each do |var|
|
104
104
|
val = @variable_table.get(var)
|
105
|
-
|
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
|
-
#
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
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.
|
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.
|
167
|
-
UpdateCriteria.
|
169
|
+
orders = outputs_combination.map {|outputs|
|
170
|
+
UpdateCriteria.order(rule, inputs, outputs, vtable)
|
168
171
|
}
|
169
|
-
|
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
|
-
|
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
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
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
|
-
|
224
|
-
# ignore
|
225
|
-
end
|
222
|
+
process_log(task_process_record)
|
226
223
|
|
227
|
-
|
228
|
-
|
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
|
-
|
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
|
-
#
|
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
|
279
|
-
def
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
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
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
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
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
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
|
-
|
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
|
-
|
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
|
-
#
|
41
|
-
#
|
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>]
|
44
|
+
# @param inputs [Array<Pione::Tuple::Data>]
|
44
45
|
# input data tuples
|
45
|
-
# @param [
|
46
|
-
# parameters
|
46
|
+
# @param params [Model::Parameters]
|
47
|
+
# parameters
|
47
48
|
# @return [String]
|
48
49
|
# domain string
|
49
|
-
def domain_id3(rule, inputs,
|
50
|
-
package_name = rule.
|
51
|
-
rule_name = rule.
|
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
|
@@ -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 = {
|
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
|
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(
|
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
|