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
@@ -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
- # rule inputs condition
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
- # rule outputs condition
10
+ # output data condition
15
11
  attr_reader :outputs
16
12
 
17
- # the value of attribute params
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, Array<DataExpr>>]
44
- # rule inputs
45
- # @param outputs [Array<DataExpr, Array<DataExpr>>]
46
- # rule outputs
47
- # @param params [Parameters]
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
- # @param features [Feature]
24
+ # @option condition [Feature] features
50
25
  # rule features
51
- # @param input_ticket_expr [TicketExpr]
52
- # input ticket expression
53
- # @param output_ticket_expr [TicketExpr]
54
- # output ticket expression
55
- def initialize(inputs, outputs, params, features, input_ticket_expr, output_ticket_expr)
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
- @params = params
61
- @features = features
62
- @input_ticket_expr = input_ticket_expr
63
- @output_ticket_expr = output_ticket_expr
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
- [ @inputs.any? {|input| input.include_variable?},
73
- @outputs.any? {|output| output.include_variable?},
74
- @params.include_variable?,
75
- @features.include_variable?,
76
- @input_tickets.any? {|ticket| ticket.include_variable?},
77
- @output_tickets.any? {|ticket| ticket.include_variable?}
78
- ].any?
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
- return false unless @inputs == other.inputs
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 + @params.hash + @features.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
- extend Forwardable
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
- # Returns rule type.
102
- def self.rule_type
103
- @rule_type
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
- # Return the value of attribute expr.
107
- #
108
- # @return [Array<DataExpr, Array<DataExpr>>]
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 expr [RuleExpr]
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(expr, condition, body)
128
- @expr = expr
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 @expr.include_variable?
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<Data, Array<Data>>]
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 @expr == other.expr
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
- @expr.hash + @condition.hash + @body.hash
181
+ @rule_expr.hash + @condition.hash + @body.hash
205
182
  end
206
183
  end
207
184
 
208
- # ActionRule is a rule writing action.
185
+ # ActionRule is a rule that have some actions. This rule makes data
186
+ # processing.
209
187
  class ActionRule < Rule
210
- @rule_type = :action
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 represents a flow structured rule. This rule is consisted by flow
219
- # elements and executes elements actions.
192
+ # FlowRule is a rule that have flow elements. This rule makes flows of PIONE
193
+ # processing.
220
194
  class FlowRule < Rule
221
- @rule_type = :flow
195
+ set_rule_type :flow
196
+ set_handler_class RuleHandler::FlowHandler
197
+ end
222
198
 
223
- # @api private
224
- def handler_class
225
- RuleHandler::FlowHandler
226
- end
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 flow rule like the following:
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 < FlowRule
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", Parameters.empty, TicketExpr.empty, TicketExpr.empty),
256
- condition,
257
- FlowBlock.new(CallRule.new(@main.expr.set_params(@params)))
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, @params.as_variable_table)
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
- @params,
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 < ActionRule
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
- Package.new('system'),
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