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
data/lib/pione/model/rule.rb
CHANGED
@@ -2,65 +2,40 @@ module Pione
|
|
2
2
|
module Model
|
3
3
|
# RuleCondition represents rule condition.
|
4
4
|
class RuleCondition < BasicModel
|
5
|
-
# the value of attribute inputs
|
6
|
-
#
|
7
5
|
# @return [Array<DataExpr, Array<DataExpr>>]
|
8
|
-
#
|
6
|
+
# input data condition
|
9
7
|
attr_reader :inputs
|
10
8
|
|
11
|
-
# the value of attribute outputs
|
12
|
-
#
|
13
9
|
# @return [Array<DataExpr, Array<DataExpr>>]
|
14
|
-
#
|
10
|
+
# output data condition
|
15
11
|
attr_reader :outputs
|
16
12
|
|
17
|
-
|
18
|
-
#
|
19
|
-
# @return [Parameters]
|
20
|
-
# rule parameters table
|
21
|
-
attr_reader :params
|
22
|
-
|
23
|
-
# the value of attribute features
|
24
|
-
#
|
25
|
-
# @return [Feature]
|
26
|
-
# rule feature condition
|
27
|
-
attr_reader :features
|
28
|
-
|
29
|
-
# input ticket expression
|
30
|
-
#
|
31
|
-
# @return [TicketExpr]
|
32
|
-
# input ticket expression
|
33
|
-
attr_reader :input_ticket_expr
|
34
|
-
|
35
|
-
# output ticket expression
|
36
|
-
#
|
37
|
-
# @return [TicketExpr]
|
38
|
-
# output ticket
|
39
|
-
attr_reader :output_ticket_expr
|
13
|
+
forward_as_key! :@condition, :params, :features, :constraints, :input_ticket_expr, :output_ticket_expr
|
40
14
|
|
41
15
|
# Create a rule condition.
|
42
16
|
#
|
43
|
-
# @param inputs [Array<DataExpr
|
44
|
-
#
|
45
|
-
# @param outputs [Array<DataExpr
|
46
|
-
#
|
47
|
-
# @param
|
17
|
+
# @param inputs [Array<DataExpr>]
|
18
|
+
# input conditions
|
19
|
+
# @param outputs [Array<DataExpr>]
|
20
|
+
# output conditions
|
21
|
+
# @param condition [Hash]
|
22
|
+
# @option condition [Parameters] params
|
48
23
|
# rule parameters
|
49
|
-
# @
|
24
|
+
# @option condition [Feature] features
|
50
25
|
# rule features
|
51
|
-
# @
|
52
|
-
# input ticket
|
53
|
-
# @
|
54
|
-
# output ticket
|
55
|
-
def initialize(inputs, outputs,
|
56
|
-
check_argument_type(params, Parameters)
|
57
|
-
check_argument_type(features, Feature::Expr)
|
26
|
+
# @option condition [TicketExpr] input_ticket_expr
|
27
|
+
# input ticket
|
28
|
+
# @option condition [TicketExpr] output_ticket_expr
|
29
|
+
# output ticket
|
30
|
+
def initialize(inputs, outputs, condition={})
|
58
31
|
@inputs = inputs
|
59
32
|
@outputs = outputs
|
60
|
-
@
|
61
|
-
@
|
62
|
-
@
|
63
|
-
@
|
33
|
+
@condition = {}
|
34
|
+
@condition[:params] = condition[:params] || Parameters.empty
|
35
|
+
@condition[:features] = condition[:features] || Feature.empty
|
36
|
+
@condition[:constraints] = condition[:constraints] || Constraints.empty
|
37
|
+
@condition[:input_ticket_expr] = condition[:input_ticket_expr] || TicketExprSequence.empty
|
38
|
+
@condition[:output_ticket_expr] = condition[:output_ticket_expr] || TicketExprSequence.empty
|
64
39
|
super()
|
65
40
|
end
|
66
41
|
|
@@ -69,81 +44,90 @@ module Pione
|
|
69
44
|
# @return [Boolean]
|
70
45
|
# true if the condition includes variable, or false
|
71
46
|
def include_variable?
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
47
|
+
return true if @inputs.any? {|input| input.include_variable?}
|
48
|
+
return true if @outputs.any? {|output| output.include_variable?}
|
49
|
+
return true if @condition.any? {|key, val| val.include_variable?}
|
50
|
+
return false
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_hash
|
54
|
+
@condition.merge(inputs: @inputs, outputs: @outputs)
|
79
55
|
end
|
80
56
|
|
81
57
|
# @api private
|
82
58
|
def ==(other)
|
83
|
-
|
84
|
-
return false unless @outputs == other.outputs
|
85
|
-
return false unless @params == other.params
|
86
|
-
return false unless @features == other.features
|
87
|
-
return true
|
59
|
+
to_hash == other.to_hash
|
88
60
|
end
|
89
61
|
alias :eql? :"=="
|
90
62
|
|
91
63
|
# @api private
|
92
64
|
def hash
|
93
|
-
@inputs.hash + @outputs.hash + @
|
65
|
+
@inputs.hash + @outputs.hash + @condition.hash
|
94
66
|
end
|
95
67
|
end
|
96
68
|
|
97
69
|
# Rule is a class for PIONE rule model.
|
98
70
|
class Rule < BasicModel
|
99
|
-
|
71
|
+
class << self
|
72
|
+
attr_reader :rule_type
|
73
|
+
attr_reader :handler_class
|
74
|
+
|
75
|
+
# Declare rule type of the class.
|
76
|
+
#
|
77
|
+
# @param rule_type [Symbol]
|
78
|
+
# rule type
|
79
|
+
# @return [void]
|
80
|
+
def set_rule_type(rule_type)
|
81
|
+
@rule_type = rule_type
|
82
|
+
end
|
100
83
|
|
101
|
-
|
102
|
-
|
103
|
-
@
|
84
|
+
# Declare rule handler class of the class.
|
85
|
+
#
|
86
|
+
# @param handler_class [Class]
|
87
|
+
# handler class
|
88
|
+
# @return [void]
|
89
|
+
def set_handler_class(handler_class)
|
90
|
+
@handler_class = handler_class
|
91
|
+
end
|
104
92
|
end
|
105
93
|
|
106
|
-
#
|
107
|
-
#
|
108
|
-
|
109
|
-
# rule inputs condition
|
110
|
-
attr_reader :expr
|
94
|
+
# @return [RuleExpr]
|
95
|
+
# rule expression
|
96
|
+
attr_reader :rule_expr
|
111
97
|
|
98
|
+
# @return [RuleCondition]
|
99
|
+
# rule condition
|
112
100
|
attr_reader :condition
|
101
|
+
|
102
|
+
# @return [Object]
|
103
|
+
# rule body
|
113
104
|
attr_reader :body
|
114
105
|
|
115
|
-
forward! :@condition, :inputs, :outputs, :params, :features
|
106
|
+
forward! :@condition, :inputs, :outputs, :params, :features, :constraints
|
116
107
|
forward! :@condition, :input_ticket_expr, :output_ticket_expr
|
117
|
-
forward :class, :rule_type
|
108
|
+
forward! :class, :rule_type, :handler_class
|
109
|
+
forward! :@rule_expr, :rule_path
|
118
110
|
|
119
111
|
# Create a rule.
|
120
112
|
#
|
121
|
-
# @param
|
113
|
+
# @param rule_expr [RuleExpr]
|
122
114
|
# rule expression
|
123
115
|
# @param condition [RuleCondition]
|
124
116
|
# rule condition
|
125
117
|
# @param [Block] body
|
126
118
|
# rule body block
|
127
|
-
def initialize(
|
128
|
-
@
|
119
|
+
def initialize(rule_expr, condition, body)
|
120
|
+
@rule_expr = rule_expr
|
129
121
|
@condition = condition
|
130
122
|
@body = body
|
131
123
|
end
|
132
124
|
|
133
|
-
# Return the rule path.
|
134
|
-
#
|
135
|
-
# @return [String]
|
136
|
-
# rule path
|
137
|
-
def rule_path
|
138
|
-
@expr.rule_path
|
139
|
-
end
|
140
|
-
|
141
125
|
# Return true if expression, condition, or body include variables.
|
142
126
|
#
|
143
127
|
# @return [Boolean]
|
144
128
|
# true if expression, condition, or body include variables
|
145
129
|
def include_variable?
|
146
|
-
return true if @
|
130
|
+
return true if @rule_expr.include_variable?
|
147
131
|
return true if @condition.include_variable?
|
148
132
|
return true if @body.include_variable?
|
149
133
|
return false
|
@@ -169,7 +153,7 @@ module Pione
|
|
169
153
|
#
|
170
154
|
# @param ts_server [TupleSpaceServer]
|
171
155
|
# tuple space server
|
172
|
-
# @param inputs [Array<
|
156
|
+
# @param inputs [Array<DataTuple, Array<DataTuple>>]
|
173
157
|
# input tuples
|
174
158
|
# @param params [Parameters]
|
175
159
|
# rule parameters
|
@@ -181,17 +165,10 @@ module Pione
|
|
181
165
|
handler_class.new(ts_server, self, inputs, params, call_stack, opts)
|
182
166
|
end
|
183
167
|
|
184
|
-
# Return a rule handler class.
|
185
|
-
#
|
186
|
-
# @api private
|
187
|
-
def handler_class
|
188
|
-
raise NotImplementedError
|
189
|
-
end
|
190
|
-
|
191
168
|
# @api private
|
192
169
|
def ==(other)
|
193
170
|
return false unless other.kind_of?(self.class)
|
194
|
-
return false unless @
|
171
|
+
return false unless @rule_expr == other.rule_expr
|
195
172
|
return false unless @condition == other.condition
|
196
173
|
return false unless @body == other.body
|
197
174
|
return true
|
@@ -201,39 +178,42 @@ module Pione
|
|
201
178
|
|
202
179
|
# @api private
|
203
180
|
def hash
|
204
|
-
@
|
181
|
+
@rule_expr.hash + @condition.hash + @body.hash
|
205
182
|
end
|
206
183
|
end
|
207
184
|
|
208
|
-
# ActionRule is a rule
|
185
|
+
# ActionRule is a rule that have some actions. This rule makes data
|
186
|
+
# processing.
|
209
187
|
class ActionRule < Rule
|
210
|
-
|
211
|
-
|
212
|
-
# @api private
|
213
|
-
def handler_class
|
214
|
-
RuleHandler::ActionHandler
|
215
|
-
end
|
188
|
+
set_rule_type :action
|
189
|
+
set_handler_class RuleHandler::ActionHandler
|
216
190
|
end
|
217
191
|
|
218
|
-
# FlowRule
|
219
|
-
#
|
192
|
+
# FlowRule is a rule that have flow elements. This rule makes flows of PIONE
|
193
|
+
# processing.
|
220
194
|
class FlowRule < Rule
|
221
|
-
|
195
|
+
set_rule_type :flow
|
196
|
+
set_handler_class RuleHandler::FlowHandler
|
197
|
+
end
|
222
198
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
199
|
+
# EmptyRule is a rule that have no body. This rule is useful when you need
|
200
|
+
# no flows and no actions.
|
201
|
+
class EmptyRule < Rule
|
202
|
+
set_rule_type :action
|
203
|
+
set_handler_class RuleHandler::EmptyHandler
|
227
204
|
end
|
228
205
|
|
229
|
-
# RootRule is a hidden toplevel
|
206
|
+
# RootRule is a hidden toplevel rule. This rule has same flow as the follow:
|
230
207
|
# Rule Root
|
231
208
|
# input '*'.all
|
232
209
|
# output '*'.all.except('{$INPUT[1]}')
|
233
210
|
# Flow
|
234
211
|
# rule &main:Main
|
235
212
|
# End
|
236
|
-
class RootRule <
|
213
|
+
class RootRule < Rule
|
214
|
+
set_rule_type :flow
|
215
|
+
set_handler_class RuleHandler::RootHandler
|
216
|
+
|
237
217
|
INPUT_DOMAIN = 'input'
|
238
218
|
|
239
219
|
# root domain has no digest and no package
|
@@ -250,56 +230,45 @@ module Pione
|
|
250
230
|
def initialize(main, params=Parameters.empty)
|
251
231
|
@main = main
|
252
232
|
@params = params
|
253
|
-
condition = make_condition
|
254
233
|
super(
|
255
|
-
RuleExpr.new(Package.new("root"), "Root"
|
256
|
-
|
257
|
-
FlowBlock.new(CallRule.new(@main.
|
234
|
+
RuleExpr.new(Package.new("root"), "Root"),
|
235
|
+
RuleCondition.new(@main.inputs, @main.outputs),
|
236
|
+
FlowBlock.new(CallRule.new(@main.rule_expr.set_params(@params)))
|
258
237
|
)
|
259
238
|
@domain = ROOT_DOMAIN
|
260
239
|
end
|
261
240
|
|
262
241
|
# @api private
|
263
242
|
def make_handler(ts_server)
|
243
|
+
# build parameter
|
244
|
+
params = @main.params.merge(@params)
|
245
|
+
|
246
|
+
# find inputs
|
264
247
|
finder = DataFinder.new(ts_server, INPUT_DOMAIN)
|
265
|
-
results = finder.find(:input, inputs,
|
248
|
+
results = finder.find(:input, inputs, params.as_variable_table)
|
266
249
|
if results.empty? and not(@main.inputs.empty?)
|
267
250
|
return nil
|
268
251
|
end
|
269
252
|
inputs = @main.inputs.empty? ? [] : results.first.combination
|
253
|
+
|
254
|
+
# make handler
|
270
255
|
handler_class.new(
|
271
256
|
ts_server,
|
272
257
|
self,
|
273
258
|
inputs,
|
274
|
-
|
259
|
+
params,
|
275
260
|
[],
|
276
261
|
{:domain => @domain}
|
277
262
|
)
|
278
263
|
end
|
279
|
-
|
280
|
-
private
|
281
|
-
|
282
|
-
# @api private
|
283
|
-
def make_condition
|
284
|
-
RuleCondition.new(
|
285
|
-
@main.inputs,
|
286
|
-
@main.outputs,
|
287
|
-
Parameters.empty,
|
288
|
-
Feature.empty,
|
289
|
-
TicketExpr.empty,
|
290
|
-
TicketExpr.empty
|
291
|
-
)
|
292
|
-
end
|
293
|
-
|
294
|
-
# @api private
|
295
|
-
def handler_class
|
296
|
-
RuleHandler::RootHandler
|
297
|
-
end
|
298
264
|
end
|
299
265
|
|
300
266
|
# SystemRule represents built-in rule definition. System rules belong to
|
301
267
|
# 'system' package.
|
302
|
-
class SystemRule <
|
268
|
+
class SystemRule < Rule
|
269
|
+
set_rule_type :action
|
270
|
+
set_handler_class RuleHandler::SystemHandler
|
271
|
+
|
303
272
|
# Create a system rule model.
|
304
273
|
#
|
305
274
|
# @param name [String]
|
@@ -307,29 +276,10 @@ module Pione
|
|
307
276
|
# @param [Proc] b
|
308
277
|
# rule process
|
309
278
|
def initialize(name, &b)
|
310
|
-
expr = RuleExpr.new(
|
311
|
-
|
312
|
-
name,
|
313
|
-
Parameters.empty,
|
314
|
-
TicketExpr.empty,
|
315
|
-
TicketExpr.empty
|
316
|
-
)
|
317
|
-
condition = make_condition
|
279
|
+
expr = RuleExpr.new(Package.new('system'), name)
|
280
|
+
condition = RuleCondition.new([DataExpr.new('*').to_seq.set_all], [])
|
318
281
|
super(expr, condition, b)
|
319
282
|
end
|
320
|
-
|
321
|
-
private
|
322
|
-
|
323
|
-
# @api private
|
324
|
-
def make_condition
|
325
|
-
inputs = [DataExpr.new('*')]
|
326
|
-
RuleCondition.new(inputs, [], Parameters.empty, Feature::EmptyFeature.new, TicketExpr.empty, TicketExpr.empty)
|
327
|
-
end
|
328
|
-
|
329
|
-
# @api private
|
330
|
-
def handler_class
|
331
|
-
RuleHandler::SystemHandler
|
332
|
-
end
|
333
283
|
end
|
334
284
|
|
335
285
|
# &System:Terminate rule
|
@@ -0,0 +1,273 @@
|
|
1
|
+
module Pione
|
2
|
+
module Model
|
3
|
+
# SequenceAttributeError is an exception for attribute mismatching.
|
4
|
+
class SequenceAttributeError < StandardError
|
5
|
+
def initialize(attribute)
|
6
|
+
@attribute = attribute
|
7
|
+
end
|
8
|
+
|
9
|
+
def message
|
10
|
+
"attribute mismatched: %s" % @attribute
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Sequence is a base class for all expressions.
|
15
|
+
class Sequence < Callable
|
16
|
+
include Enumerable
|
17
|
+
|
18
|
+
class << self
|
19
|
+
# Copy sequence attribute to subclass.
|
20
|
+
def inherited(subclass)
|
21
|
+
@sequence_attribute.each do |name, vals|
|
22
|
+
subclass.define_sequence_attribute(name, *vals)
|
23
|
+
end
|
24
|
+
subclass.set_index_type index_type
|
25
|
+
end
|
26
|
+
|
27
|
+
# Define sequence attribute.
|
28
|
+
#
|
29
|
+
# @param name [Symbol]
|
30
|
+
# attribute name
|
31
|
+
# @param default_value [Symbol]
|
32
|
+
# default value of the attribute
|
33
|
+
# @param other_values [Array<Symbol>]
|
34
|
+
# other values of the attribute
|
35
|
+
# @return [void]
|
36
|
+
def define_sequence_attribute(name, default_value, *other_values)
|
37
|
+
@sequence_attribute ||= {}
|
38
|
+
@sequence_attribute[name] = [default_value] + other_values
|
39
|
+
|
40
|
+
define_method(name) do
|
41
|
+
@attribute[name]
|
42
|
+
end
|
43
|
+
|
44
|
+
define_method("set_%s" % name) do |value|
|
45
|
+
self.class.new(@elements, @attribute.merge({name => value}))
|
46
|
+
end
|
47
|
+
|
48
|
+
# define additional methods when values are symbols
|
49
|
+
if default_value.kind_of?(Symbol)
|
50
|
+
([default_value] + other_values).each do |value|
|
51
|
+
define_method("%s?" % value) do
|
52
|
+
@attribute[name] == value
|
53
|
+
end
|
54
|
+
|
55
|
+
define_method("set_%s" % value) do
|
56
|
+
self.class.new(@elements, @attribute.merge({name => value}))
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
attr_reader :element_class
|
63
|
+
attr_reader :sequence_attribute
|
64
|
+
attr_reader :shortname
|
65
|
+
attr_reader :index_type
|
66
|
+
|
67
|
+
# Set element class.
|
68
|
+
#
|
69
|
+
# @param klass [Class]
|
70
|
+
# element class
|
71
|
+
# @return [void]
|
72
|
+
def set_element_class(klass)
|
73
|
+
@element_class = klass
|
74
|
+
klass.set_sequence_class(self)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Set the shortname.
|
78
|
+
#
|
79
|
+
# @param name [String]
|
80
|
+
# shortname
|
81
|
+
# @return [void]
|
82
|
+
def set_shortname(name)
|
83
|
+
@shortname = name
|
84
|
+
end
|
85
|
+
|
86
|
+
# Set the index type.
|
87
|
+
#
|
88
|
+
# @param index_type [Type]
|
89
|
+
# index type
|
90
|
+
# @return [void]
|
91
|
+
def set_index_type(index_type)
|
92
|
+
@index_type = index_type
|
93
|
+
end
|
94
|
+
|
95
|
+
# Make an empty sequence.
|
96
|
+
def empty(attributes={})
|
97
|
+
new([], attributes)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Make a void sequence.
|
102
|
+
def Sequence.void
|
103
|
+
Sequence.new([])
|
104
|
+
end
|
105
|
+
|
106
|
+
define_sequence_attribute :distribution, :each, :all
|
107
|
+
forward! :class, :sequence_attribute, :shortname, :index_type
|
108
|
+
forward! :@elements, :first, :[], :empty?
|
109
|
+
attr_reader :elements
|
110
|
+
attr_reader :attribute
|
111
|
+
|
112
|
+
# @param elements [Array]
|
113
|
+
# sequence elements
|
114
|
+
# @param attribute [Hash]
|
115
|
+
# sequence attribute
|
116
|
+
def initialize(elements, attribute={})
|
117
|
+
@elements = elements
|
118
|
+
@attribute = Hash.new.merge(attribute)
|
119
|
+
|
120
|
+
# clear unneeded keys
|
121
|
+
(attribute.keys - sequence_attribute.keys).each do |key|
|
122
|
+
@attribute.delete(key)
|
123
|
+
end
|
124
|
+
|
125
|
+
# fill default value
|
126
|
+
sequence_attribute.each do |name, values|
|
127
|
+
@attribute[name] ||= values.first
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
# Return true if the sequence is void.
|
133
|
+
#
|
134
|
+
# @return [Boolean]
|
135
|
+
# true if the sequence is void
|
136
|
+
def void?
|
137
|
+
self.class == Sequence and empty?
|
138
|
+
end
|
139
|
+
|
140
|
+
# Concatenate another sequence.
|
141
|
+
#
|
142
|
+
# @param other [Sequence]
|
143
|
+
# other sequence
|
144
|
+
# @return [Sequence]
|
145
|
+
# a new sequence that have members of self and other
|
146
|
+
def concat(other)
|
147
|
+
raise SequenceAttributeError.new(other) unless @attribute == other.attribute
|
148
|
+
self.class.new(@elements + other.elements, @attribute)
|
149
|
+
end
|
150
|
+
|
151
|
+
# Push the element to the sequecence.
|
152
|
+
#
|
153
|
+
# @param element [Element]
|
154
|
+
# the element
|
155
|
+
# @return [Sequence]
|
156
|
+
# a new sequence that have member self and the element.
|
157
|
+
def push(element)
|
158
|
+
self.class.new(@elements + [element], @attribute)
|
159
|
+
end
|
160
|
+
|
161
|
+
# Iterate each elements.
|
162
|
+
#
|
163
|
+
# @return [Enumerator]
|
164
|
+
# return an enumerator if the block is not given
|
165
|
+
def each
|
166
|
+
if block_given?
|
167
|
+
@elements.each {|e| yield self.class.new([e], @attribute)}
|
168
|
+
else
|
169
|
+
Enumerator.new(self, :each)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def eval(vtable)
|
174
|
+
self.class.new(@elements.map{|elt| elt.eval(vtable)}, @attribute)
|
175
|
+
end
|
176
|
+
|
177
|
+
def include_variable?
|
178
|
+
@elements.any?{|elt| elt.include_variable?}
|
179
|
+
end
|
180
|
+
|
181
|
+
def ==(other)
|
182
|
+
return false unless other.kind_of?(self.class)
|
183
|
+
return false unless @elements == other.elements
|
184
|
+
return @attribute == other.attribute
|
185
|
+
end
|
186
|
+
alias :eql? :"=="
|
187
|
+
|
188
|
+
def hash
|
189
|
+
@elements.hash + @attribute.hash
|
190
|
+
end
|
191
|
+
|
192
|
+
def task_id_string
|
193
|
+
"<#{@elements}, #{@attribute}>"
|
194
|
+
end
|
195
|
+
|
196
|
+
def textize
|
197
|
+
"<%s [%s]>" % [shortname, @elements.map{|x| x.textize}.join(",")]
|
198
|
+
end
|
199
|
+
|
200
|
+
def inspect
|
201
|
+
"#<%s %s %s>" % [shortname, @elements, @attribute]
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
TypeSequence.instance_eval do
|
206
|
+
define_pione_method("!=", [:receiver_type], TypeBoolean) do |rec, other|
|
207
|
+
rec.call_pione_method("==", other).call_pione_method("not")
|
208
|
+
end
|
209
|
+
|
210
|
+
define_pione_method("|", [:receiver_type], :receiver_type) do |rec, other|
|
211
|
+
rec.concat(other)
|
212
|
+
end
|
213
|
+
|
214
|
+
define_pione_method("each", [], :receiver_type) do |rec|
|
215
|
+
rec.set_each
|
216
|
+
end
|
217
|
+
|
218
|
+
define_pione_method("each?", [], TypeBoolean) do |rec|
|
219
|
+
BooleanSequence.new([PioneBoolean.new(rec.each?)])
|
220
|
+
end
|
221
|
+
|
222
|
+
define_pione_method("all", [], :receiver_type) do |rec|
|
223
|
+
rec.set_all
|
224
|
+
end
|
225
|
+
|
226
|
+
define_pione_method("all?", [], TypeBoolean) do |rec|
|
227
|
+
BooleanSequence.new([PioneBoolean.new(rec.all?)])
|
228
|
+
end
|
229
|
+
|
230
|
+
define_pione_method("i", [], TypeInteger) do |rec|
|
231
|
+
rec.call_pione_method("as_integer")
|
232
|
+
end
|
233
|
+
|
234
|
+
define_pione_method("f", [], TypeFloat) do |rec|
|
235
|
+
rec.call_pione_method("as_float")
|
236
|
+
end
|
237
|
+
|
238
|
+
define_pione_method("str", [], TypeString) do |rec|
|
239
|
+
rec.call_pione_method("as_string")
|
240
|
+
end
|
241
|
+
|
242
|
+
define_pione_method("d", [], TypeDataExpr) do |rec|
|
243
|
+
rec.call_pione_method("as_data_expr")
|
244
|
+
end
|
245
|
+
|
246
|
+
define_pione_method("length", [], TypeInteger) do |rec|
|
247
|
+
IntegerSequence.new([PioneInteger.new(rec.elements.size)])
|
248
|
+
end
|
249
|
+
|
250
|
+
define_pione_method("[]", [:index_type], :receiver_type) do |rec, index|
|
251
|
+
rec.call_pione_method("nth", index)
|
252
|
+
end
|
253
|
+
|
254
|
+
define_pione_method("member?", [:receiver_type], TypeBoolean) do |rec, target|
|
255
|
+
sequential_map1(TypeBoolean, target) do |target_elt|
|
256
|
+
rec.elements.map{|elt| elt.value}.include?(target_elt.value)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
define_pione_method(":", [TypeSequence], TypeKeyedSequence) do |keys, vals|
|
261
|
+
keys.elements.map do |key_elt|
|
262
|
+
vals.elements.map do |val_elt|
|
263
|
+
KeyedSequence.new(key_elt => [val_elt])
|
264
|
+
end
|
265
|
+
end.flatten.inject(KeyedSequence.new({})){|seq, _seq| seq.concat(_seq)}
|
266
|
+
end
|
267
|
+
|
268
|
+
define_pione_method("textize", [], TypeString) do |rec|
|
269
|
+
rec.call_pione_method("as_string").call_pione_method("join", PioneString.new(rec.separator).to_seq)
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|