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
@@ -1,5 +1,37 @@
1
1
  module Pione
2
2
  module Model
3
+ # DataExpr::Compiler is a regexp compiler for data expression.
4
+ module DataExprCompiler
5
+ TABLE = {}
6
+
7
+ # Define a string matcher.
8
+ def self.define_matcher(matcher, replace)
9
+ TABLE[Regexp.escape(matcher)] = replace
10
+ end
11
+
12
+ # Asterisk symbol is multi-characters matcher(empty string is not matched).
13
+ define_matcher('*', '(.+)')
14
+
15
+ # Question symbol is single character matcher(empty string is not matched).
16
+ define_matcher('?', '(.)')
17
+
18
+ # Compiles data name into regular expression.
19
+ #
20
+ # @param name [String]
21
+ # data name
22
+ def compile(name)
23
+ return name unless name.kind_of?(String)
24
+
25
+ s = "^#{Regexp.escape(name)}$"
26
+ TABLE.keys.each {|key| s.gsub!(key, TABLE)}
27
+ s.gsub!(/\\\[(!|\\\^)?(.*)\\\]/){"[#{'^' if $1}#{$2.gsub('\-','-')}]"}
28
+ s.gsub!(/\\{(.*)\\}/){"(#{$1.split(',').join('|')})"}
29
+ Regexp.new(s)
30
+ end
31
+ module_function :compile
32
+ end
33
+
34
+
3
35
  # DataExpr is a class for data name expressions of rule input and output.
4
36
  #
5
37
  # @example
@@ -8,42 +40,10 @@ module Pione
8
40
  # @example
9
41
  # # incomplete name
10
42
  # DataExpr.new("*.txt")
11
- class DataExpr < BasicModel
12
-
13
- # separator symbol for all modifier
43
+ class DataExpr < Element
44
+ # separator symbol for all distribution
14
45
  SEPARATOR = ':'
15
46
 
16
- # DataExpr::Compiler is a regexp compiler for data expression.
17
- module Compiler
18
- TABLE = {}
19
-
20
- # Define a string matcher.
21
- def self.define_matcher(matcher, replace)
22
- TABLE[Regexp.escape(matcher)] = replace
23
- end
24
-
25
- # Asterisk symbol is multi-characters matcher(empty string is not matched).
26
- define_matcher('*', '(.+)')
27
-
28
- # Question symbol is single character matcher(empty string is not matched).
29
- define_matcher('?', '(.)')
30
-
31
- # Compiles data name into regular expression.
32
- #
33
- # @param name [String]
34
- # data name
35
- def compile(name)
36
- return name unless name.kind_of?(String)
37
-
38
- s = "^#{Regexp.escape(name)}$"
39
- TABLE.keys.each {|key| s.gsub!(key, TABLE)}
40
- s.gsub!(/\\\[(!|\\\^)?(.*)\\\]/){"[#{'^' if $1}#{$2.gsub('\-','-')}]"}
41
- s.gsub!(/\\{(.*)\\}/){"(#{$1.split(',').join('|')})"}
42
- Regexp.new(s)
43
- end
44
- module_function :compile
45
- end
46
-
47
47
  class << self
48
48
  alias :orig_new :new
49
49
 
@@ -51,7 +51,7 @@ module Pione
51
51
  def new(*args)
52
52
  # check OR expression
53
53
  name = args.first
54
- if self == DataExpr and name.include?(SEPARATOR)
54
+ if self == DataExpr and name and name.include?(SEPARATOR)
55
55
  name.split(SEPARATOR).map do |single_name|
56
56
  orig_new(single_name, *args.drop(1))
57
57
  end.tap {|exprs| return DataExprOr.new(exprs)}
@@ -69,42 +69,6 @@ module Pione
69
69
  new(name)
70
70
  end
71
71
 
72
- # Create a name expression with 'each' modifier.
73
- #
74
- # @param name [String]
75
- # data name
76
- def each(name)
77
- new(name, modifier: :each)
78
- end
79
-
80
- # Create a name expression with 'all' modifier.
81
- #
82
- # @param name [String]
83
- # data name
84
- def all(name)
85
- new(name, modifier: :all)
86
- end
87
-
88
- # Create a new data name for stdout ouput.
89
- #
90
- # @param name [String]
91
- # data name
92
- # @return [DataExpr]
93
- # data expression for stdout
94
- def stdout(name)
95
- new(name, modifier: :each, mode: :stdout)
96
- end
97
-
98
- # Create a new data name for stderr output.
99
- #
100
- # @param name [String]
101
- # data name
102
- # @return [DataExpr]
103
- # data expression for stderr
104
- def stderr(name)
105
- new(name, modifier: :each, mode: :stderr)
106
- end
107
-
108
72
  # Return convertion prcedure for enumerable.
109
73
  #
110
74
  # @return [Proc]
@@ -114,11 +78,9 @@ module Pione
114
78
  end
115
79
  end
116
80
 
117
- set_pione_model_type TypeDataExpr
118
-
119
81
  attr_reader :name
120
82
  alias :core :name
121
- forward_as_key! :@data, :modifier, :mode, :exceptions, :update_criteria
83
+ forward_as_key! :@data, :exceptions, :matched_data, :location
122
84
 
123
85
  # Create a data expression.
124
86
  #
@@ -126,75 +88,19 @@ module Pione
126
88
  # data expression name
127
89
  # @param opts [Hash]
128
90
  # options of the expression
129
- # @option opts [Symbol] :modifier
130
- # :all or :each
131
- # @option opts [Symbol] :mode
132
- # nil, :stdout, or :stderr
133
91
  # @option opts [Array<DataExpr>] :exceptions
134
92
  # exceptional expressions
135
- # @option opts [Boolean] :update_criteria
136
- # the flag whether the data disregards update criterias
93
+ # @option opts [String] :match
137
94
  def initialize(name, data={})
138
- unless name.kind_of? String or name.kind_of? Regexp
139
- raise ArgumentError.new(name)
140
- end
141
-
142
95
  @name = name
143
96
  @data = Hash.new
144
- @data[:modifier] = data[:modifier] || :each
145
- @data[:mode] = data[:mode]
146
97
  @data[:exceptions] = data[:exceptions] || []
147
- @data[:update_criteria] = data[:update_criteria] || :care
148
-
149
- super()
150
- end
151
-
152
- # Return new data expression with each modifier.
153
- #
154
- # @return [DataExpr]
155
- # new data expression with each modifier
156
- def each
157
- return self.class.new(@name, @data.merge(modifier: :each))
98
+ @data[:matched_data] = data[:matched_data] || []
99
+ @data[:location] = data[:location] || nil
158
100
  end
159
101
 
160
- # Return new data expression with all modifier.
161
- #
162
- # @return [DataExpr]
163
- # new data expression with all modifier
164
- def all
165
- return self.class.new(@name, @data.merge(modifier: :all))
166
- end
167
-
168
- # Return new data expression with stdout mode.
169
- #
170
- # @return [DataExpr]
171
- # new data expression with stdout mode
172
- def stdout
173
- return self.class.new(@name, @data.merge(mode: :stdout))
174
- end
175
-
176
- # Return new data expression with stderr mode.
177
- #
178
- # @return [DataExpr]
179
- # new data expression with stderr mode
180
- def stderr
181
- return self.class.new(@name, @data.merge(mode: :stderr))
182
- end
183
-
184
- # Return new data expression with disregarding update-criteria.
185
- #
186
- # @return [DataExpr]
187
- # new data expression with disregarding update-criteria
188
- def neglect
189
- return self.class.new(@name, @data.merge(update_criteria: :neglect))
190
- end
191
-
192
- # Return new data expression with regarding update-criteria.
193
- #
194
- # @return [DataExpr]
195
- # new data expression with regarding update-criteria
196
- def care
197
- return self.class.new(@name, @data.merge(update_criteria: :care))
102
+ def set_data(data)
103
+ self.class.new(@name, @data.merge(data))
198
104
  end
199
105
 
200
106
  # Evaluate the data expression.
@@ -218,66 +124,16 @@ module Pione
218
124
 
219
125
  # @api private
220
126
  def task_id_string
221
- "DataExpr<#{name},#{modifier},[%s]>" % [
222
- exceptions.map{|exc| exc.task_id_string}.join(",")
223
- ]
127
+ "DataExpr<#{name}, [%s]>" % exceptions.map{|exc| exc.task_id_string}.join(",")
224
128
  end
225
129
 
226
130
  # @api private
227
131
  def textize
228
- "data_expr(\"#{name}\",:#{modifier},[%s])" % [
132
+ "data_expr(\"#{name}\", [%s])" % [
229
133
  exceptions.map{|exc| exc.textize}.join(",")
230
134
  ]
231
135
  end
232
136
 
233
- # Return true if the name has 'all' modifier.
234
- #
235
- # @return [Boolean]
236
- # true if the name has 'all' modifier
237
- def all?
238
- modifier == :all
239
- end
240
-
241
- # Return true if the name has 'each' modifier.
242
- #
243
- # @return [Boolean]
244
- # true if the name has 'each' modifier
245
- def each?
246
- modifier == :each
247
- end
248
-
249
- # Return true if the data content is in stdout.
250
- #
251
- # @return [Boolean]
252
- # true if the data content is in stdout
253
- def stdout?
254
- mode == :stdout
255
- end
256
-
257
- # Return true if the data content is in stderr.
258
- #
259
- # @return [Boolean]
260
- # true if the data content is in stderr
261
- def stderr?
262
- mode == :stderr
263
- end
264
-
265
- # Return true if the data disregards update criteria.
266
- #
267
- # @return [Boolean]
268
- # true if the data disregards update criteria
269
- def neglect?
270
- update_criteria == :neglect
271
- end
272
-
273
- # Return true if the data regards update criteria.
274
- #
275
- # @return [Boolean]
276
- # true if the data regards update criteria
277
- def care?
278
- update_criteria == :care
279
- end
280
-
281
137
  # Create new data expression with appending the exception.
282
138
  #
283
139
  # @param exc [DataExpr, String]
@@ -350,17 +206,15 @@ module Pione
350
206
 
351
207
  # @api private
352
208
  def to_s
353
- "#<#<#{self.class.name}> name='#{name}' data=#{@data.inspect}>"
209
+ "#<DataExpr '%s' %s>" % [name, @data.inspect]
354
210
  end
355
211
 
356
- # Return true if name, modifier, mode, and exceptions are the same.
212
+ # Return true if name, distribution, mode, and exceptions are the same.
357
213
  #
358
214
  # @api private
359
215
  def ==(other)
360
216
  return false unless other.kind_of?(self.class)
361
217
  return false unless name == other.name
362
- return false unless modifier == other.modifier
363
- return false unless mode == other.mode
364
218
  return false unless exceptions.sort == other.exceptions.sort
365
219
  return true
366
220
  end
@@ -368,7 +222,7 @@ module Pione
368
222
 
369
223
  # @api private
370
224
  def hash
371
- [name, modifier, mode, exceptions].join("\000").hash
225
+ [name, exceptions].join("\000").hash
372
226
  end
373
227
 
374
228
  # Same as Regexp#=~ but return 0 if it matched.
@@ -387,7 +241,7 @@ module Pione
387
241
 
388
242
  # @api private
389
243
  def compile_to_regexp(name)
390
- Compiler.compile(name)
244
+ DataExprCompiler.compile(name)
391
245
  end
392
246
 
393
247
  # Return true if the name matchs exceptions.
@@ -398,6 +252,7 @@ module Pione
398
252
  end
399
253
  end
400
254
 
255
+ # DataExprNull is a data exppresion that accepts data nonexistence.
401
256
  class DataExprNull < DataExpr
402
257
  include Singleton
403
258
 
@@ -405,25 +260,29 @@ module Pione
405
260
  def return_self
406
261
  self
407
262
  end
263
+
408
264
  alias :all :return_self
409
265
  alias :each :return_self
410
266
  alias :stdout :return_self
411
267
  alias :stderr :return_self
412
268
  alias :neglect :return_self
413
269
  alias :care :return_self
270
+ alias :write :return_self
271
+ alias :remove :return_self
272
+ alias :touch :return_self
414
273
 
415
274
  def initialize
416
275
  @data = {}
417
276
  end
418
277
 
419
- def accept_nonexistence?
420
- true
421
- end
422
-
423
278
  def match(name)
424
279
  nil
425
280
  end
426
281
 
282
+ def accept_nonexistence?
283
+ true
284
+ end
285
+
427
286
  # Evaluate the data expression. The result is myself.
428
287
  #
429
288
  # @param vtable [VariableTable]
@@ -440,7 +299,7 @@ module Pione
440
299
 
441
300
  # @api private
442
301
  def to_s
443
- "#<#<#{self.class.name}>>"
302
+ "#<DataExprNull>"
444
303
  end
445
304
 
446
305
  # @api private
@@ -451,13 +310,11 @@ module Pione
451
310
  end
452
311
 
453
312
  # DataExprOr represents or-relation of data expressions. Expressions have
454
- # same properties about modifier and mode.
313
+ # same properties about distribution and mode.
455
314
  class DataExprOr < DataExpr
456
315
  attr_reader :elements
457
316
  alias :core :elements
458
317
 
459
- forward! Proc.new{find_not_null_element}, :modifier, :mode, :update_criteria
460
-
461
318
  # @param elements [Array<DataExpr>]
462
319
  # elements that have OR relation
463
320
  # @param data [Hash]
@@ -468,21 +325,6 @@ module Pione
468
325
  @elements = elements
469
326
  @data = {}
470
327
  @data[:exceptions] = data[:exceptions] || []
471
-
472
- # check whether all elements have same modifier
473
- unless elements.all?{|elt| modifier == elt.modifier or elt.kind_of?(DataExprNull)}
474
- raise ArgumentError.new(elements)
475
- end
476
-
477
- # check whether all elements have same mode
478
- unless elements.all?{|elt| mode == elt.mode or elt.kind_of?(DataExprNull)}
479
- raise ArmguentError.new(elements)
480
- end
481
-
482
- # check whether all elements have same mode
483
- unless elements.all?{|elt| update_criteria == elt.update_criteria or elt.kind_of?(DataExprNull)}
484
- raise ArmguentError.new(elements)
485
- end
486
328
  end
487
329
 
488
330
  # Match if the name is matched one of elements.
@@ -502,60 +344,8 @@ module Pione
502
344
  end.tap {return nil}
503
345
  end
504
346
 
505
- # Return true if at least one element accepts nonexistence.
506
- #
507
- # @return [Boolean]
508
- # true if at least one element accepts nonexistence
509
347
  def accept_nonexistence?
510
- @elements.any?{|element| element.accept_nonexistence?}
511
- end
512
-
513
- # Return a new instance that has elements with "all" modifier.
514
- #
515
- # @return [DataExprOr]
516
- # a new instance that has elements with "all" modifier
517
- def all
518
- self.class.new(@elements.map{|elt| elt.all}, @data)
519
- end
520
-
521
- # Return a new instance that has elements with "each" modifier.
522
- #
523
- # @return [DataExprOr]
524
- # a new instance that has elements with "each" modifier
525
- def each
526
- self.class.new(@elements.map{|elt| elt.each}, @data)
527
- end
528
-
529
- # Return a new instance that has elements with stdout mode.
530
- #
531
- # @return [DataExprOr]
532
- # a new instance that has elements with stdout mode
533
- def stdout
534
- self.class.new(@elements.map{|elt| elt.stdout}, @data)
535
- end
536
-
537
- # Return a new instance that has elements with stderr mode.
538
- #
539
- # @return [DataExprOr]
540
- # a new instance that has elements with stderr mode
541
- def stderr
542
- self.class.new(@elements.map{|elt| elt.stderr}, @data)
543
- end
544
-
545
- # Return a new instance that has elements with neglecting update criteria.
546
- #
547
- # @return [DataExprOr]
548
- # a new instance that has elements with neglecting update criteria
549
- def neglect
550
- self.class.new(@elements.map{|elt| elt.neglect}, @data)
551
- end
552
-
553
- # Return a new instance that has elements with caring update criteria.
554
- #
555
- # @return [DataExprOr]
556
- # a new instance that has elements with caring update criteria
557
- def care
558
- self.class.new(@elements.map{|elt| elt.care}, @data)
348
+ @elements.any?{|elt| elt.accept_nonexistence?}
559
349
  end
560
350
 
561
351
  # Evaluate the data expression. This evaluates all elements of the expression.
@@ -576,13 +366,13 @@ module Pione
576
366
 
577
367
  # @api private
578
368
  def to_s
579
- "#<#<#{self.class.name}> #{@elements} #{@data}>"
369
+ "#<DataExprOr #{@elements} #{@data}>"
580
370
  end
581
371
 
582
372
  # @api private
583
373
  def ==(other)
584
374
  return false unless other.kind_of?(self.class)
585
- (@elements - other.elements).empty?
375
+ return @elements == other.elements
586
376
  end
587
377
  alias :eql? :"=="
588
378
 
@@ -593,73 +383,170 @@ module Pione
593
383
 
594
384
  private
595
385
 
386
+ # Check attribute consistency.
387
+ #
388
+ # @return [void]
389
+ def check_attribute_consistency(name)
390
+ unless @elements.all?{|elt| send(name) == elt.send(name) or elt.kind_of?(DataExprNull)}
391
+ raise ArgumentError.new(@elements)
392
+ end
393
+ end
394
+
596
395
  def find_not_null_element
597
396
  @elements.find{|elt| not(elt.kind_of?(DataExprNull))}
598
397
  end
599
398
  end
600
399
 
400
+ class DataExprSequence < OrdinalSequence
401
+ set_pione_model_type TypeDataExpr
402
+ set_element_class DataExpr
403
+ set_shortname "DSeq"
404
+ DataExpr.set_sequence_class self
405
+ DataExprNull.set_sequence_class self
406
+ DataExprOr.set_sequence_class self
407
+
408
+ define_sequence_attribute :output_mode, :file, :stdout, :stderr
409
+ define_sequence_attribute :update_criteria, :care, :neglect
410
+ define_sequence_attribute :operation, :write, :remove, :touch
411
+ define_sequence_attribute :location, nil
412
+
413
+ forward! Proc.new{@elements.first}, :match, :name
414
+
415
+ # Return true if the sequence accepts nonexistence matching. This is
416
+ # determined that it includes null expression.
417
+ def accept_nonexistence?
418
+ @elements.any?{|elt| elt.accept_nonexistence?}
419
+ end
420
+ end
421
+
601
422
  TypeDataExpr.instance_eval do
602
423
  define_pione_method("==", [TypeDataExpr], TypeBoolean) do |rec, other|
603
- PioneBoolean.new(rec == other)
424
+ PioneBoolean.new(rec == other).to_seq
604
425
  end
605
426
 
606
- define_pione_method("!=", [TypeDataExpr], TypeBoolean) do |rec, other|
607
- PioneBoolean.not(rec.call_pione_method("==", other))
427
+ define_pione_method("[]", [TypeInteger], TypeString) do |rec, index|
428
+ sequential_map2(TypeString, rec, index) do |rec_elt, index_elt|
429
+ rec_elt.matched_data[index_elt.value]
430
+ end.set_separator(DataExpr::SEPARATOR)
608
431
  end
609
432
 
610
433
  define_pione_method("all", [], TypeDataExpr) do |rec|
611
- rec.all
434
+ rec.set_all
435
+ end
436
+
437
+ define_pione_method("all?", [], TypeBoolean) do |rec|
438
+ rec.all?
612
439
  end
613
440
 
614
441
  define_pione_method("each", [], TypeDataExpr) do |rec|
615
- rec.each
442
+ rec.set_each
616
443
  end
617
444
 
618
- define_pione_method("except", [TypeDataExpr], TypeDataExpr) do |rec, target|
619
- rec.except(target)
445
+ define_pione_method("each?", [], TypeBoolean) do |rec|
446
+ rec.each?
620
447
  end
621
448
 
622
449
  define_pione_method("stdout", [], TypeDataExpr) do |rec|
623
- rec.stdout
450
+ rec.set_stdout
451
+ end
452
+
453
+ define_pione_method("stdout?", [], TypeBoolean) do |rec|
454
+ rec.stdout?
624
455
  end
625
456
 
626
457
  define_pione_method("stderr", [], TypeDataExpr) do |rec|
627
- rec.stderr
458
+ rec.set_stderr
459
+ end
460
+
461
+ define_pione_method("stderr?", [], TypeBoolean) do |rec|
462
+ rec.stderr?
628
463
  end
629
464
 
630
465
  define_pione_method("neglect", [], TypeDataExpr) do |rec|
631
- rec.neglect
466
+ rec.set_neglect
467
+ end
468
+
469
+ define_pione_method("neglect?", [], TypeBoolean) do |rec|
470
+ rec.neglect?
632
471
  end
633
472
 
634
473
  define_pione_method("care", [], TypeDataExpr) do |rec|
635
- rec.care
474
+ rec.set_care
475
+ end
476
+
477
+ define_pione_method("care?", [], TypeBoolean) do |rec|
478
+ rec.care?
479
+ end
480
+
481
+ define_pione_method("write", [], TypeDataExpr) do |rec|
482
+ rec.set_write
483
+ end
484
+
485
+ define_pione_method("write?", [], TypeBoolean) do |rec|
486
+ rec.write?
487
+ end
488
+
489
+ define_pione_method("remove", [], TypeDataExpr) do |rec|
490
+ rec.set_remove
491
+ end
492
+
493
+ define_pione_method("remove?", [], TypeBoolean) do |rec|
494
+ rec.remove?
495
+ end
496
+
497
+ define_pione_method("touch", [], TypeDataExpr) do |rec|
498
+ rec.set_touch
499
+ end
500
+
501
+ define_pione_method("touch?", [], TypeBoolean) do |rec|
502
+ rec.touch?
503
+ end
504
+
505
+ define_pione_method("except", [TypeDataExpr], TypeDataExpr) do |rec, target|
506
+ map2(rec, target) do |rec_elt, target_elt|
507
+ rec_elt.except(target_elt)
508
+ end
509
+ end
510
+
511
+ define_pione_method("exceptions", [], TypeDataExpr) do |rec|
512
+ rec.elements.map do |elt|
513
+ elt.exceptions
514
+ end.flatten.tap{|x| break DataExprSequence.new(x)}
636
515
  end
637
516
 
638
517
  define_pione_method("or", [TypeDataExpr], TypeDataExpr) do |rec, other|
639
- DataExprOr.new([rec, other])
518
+ map2(rec, other) do |rec_elt, other_elt|
519
+ DataExprOr.new([rec_elt, other_elt])
520
+ end
640
521
  end
641
522
 
642
- define_pione_method("join", [TypeString], TypeString) do |rec, connective|
643
- PioneString.new(rec.elements.map{|elt| elt.name}.join(connective.to_ruby))
523
+ define_pione_method("match", [TypeString], TypeString) do |rec, name|
524
+ rec.match(name.value).to_a.inject(StringSequence.empty) do |seq, matched|
525
+ seq.push(PioneString.new(matched))
526
+ end
644
527
  end
645
528
 
646
529
  define_pione_method("match?", [TypeString], TypeBoolean) do |rec, name|
647
- if rec.match(name.value)
648
- PioneBoolean.true
649
- else
650
- PioneBoolean.false
530
+ sequential_map2(TypeBoolean, rec, name) do |rec_elt, name_elt|
531
+ not(rec_elt.match(name_elt.value).nil?)
651
532
  end
652
533
  end
653
534
 
654
535
  define_pione_method("as_string", [], TypeString) do |rec|
655
- case rec
656
- when DataExprNull
657
- PioneString.new("")
658
- when DataExprOr
659
- PioneString.new(rec.elements.map{|elt| elt.name}.join(DataExpr::SEPARATOR))
660
- when DataExpr
661
- PioneString.new(rec.name)
662
- end
536
+ sequential_map1(TypeString, rec) do |rec_elt|
537
+ case rec_elt
538
+ when DataExprNull
539
+ ""
540
+ when DataExprOr
541
+ rec_elt.elements.map{|elt| elt.name}.join(DataExpr::SEPARATOR)
542
+ when DataExpr
543
+ rec_elt.name
544
+ end
545
+ end.set_separator(DataExpr::SEPARATOR)
546
+ end
547
+
548
+ define_pione_method("accept_nonexistence?", [], TypeBoolean) do |rec|
549
+ PioneBoolean.new(rec.accept_nonexistence?).to_seq
663
550
  end
664
551
  end
665
552
  end