pione 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. data/.gitignore +2 -1
  2. data/History.txt +11 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +1 -1
  5. data/bin/pione-log +5 -0
  6. data/example/CountChar/CountChar.pione +1 -1
  7. data/example/SieveOfEratosthenes/SieveOfEratosthenes.pione +39 -38
  8. data/lib/pione.rb +14 -35
  9. data/lib/pione/agent/input-generator.rb +38 -40
  10. data/lib/pione/agent/logger.rb +52 -19
  11. data/lib/pione/agent/rule-provider.rb +5 -8
  12. data/lib/pione/agent/task-worker.rb +25 -32
  13. data/lib/pione/agent/tuple-space-client.rb +22 -14
  14. data/lib/pione/command.rb +21 -0
  15. data/lib/pione/command/basic-command.rb +267 -84
  16. data/lib/pione/command/child-process.rb +21 -18
  17. data/lib/pione/command/daemon-process.rb +9 -8
  18. data/lib/pione/command/front-owner-command.rb +8 -25
  19. data/lib/pione/command/pione-broker.rb +27 -24
  20. data/lib/pione/command/pione-clean.rb +6 -6
  21. data/lib/pione/command/pione-client.rb +143 -128
  22. data/lib/pione/command/pione-log.rb +61 -0
  23. data/lib/pione/command/pione-relay-account-db.rb +40 -38
  24. data/lib/pione/command/pione-relay-client-db.rb +38 -42
  25. data/lib/pione/command/pione-relay.rb +19 -20
  26. data/lib/pione/command/pione-syntax-checker.rb +70 -45
  27. data/lib/pione/command/pione-task-worker.rb +56 -66
  28. data/lib/pione/command/pione-tuple-space-provider.rb +36 -45
  29. data/lib/pione/command/pione-tuple-space-receiver.rb +34 -32
  30. data/lib/pione/command/pione-tuple-space-viewer.rb +63 -47
  31. data/lib/pione/location.rb +10 -0
  32. data/lib/pione/location/basic-location.rb +272 -0
  33. data/lib/pione/location/dropbox-location.rb +139 -0
  34. data/lib/pione/location/ftp-location.rb +156 -0
  35. data/lib/pione/location/local-location.rb +116 -0
  36. data/lib/pione/log.rb +10 -0
  37. data/lib/pione/log/domain-info.rb +72 -0
  38. data/lib/pione/log/process-log.rb +176 -0
  39. data/lib/pione/log/process-record.rb +189 -0
  40. data/lib/pione/log/xes-log.rb +105 -0
  41. data/lib/pione/model/assignment.rb +88 -80
  42. data/lib/pione/model/binary-operator.rb +74 -68
  43. data/lib/pione/model/block.rb +218 -207
  44. data/lib/pione/model/boolean.rb +123 -112
  45. data/lib/pione/model/call-rule.rb +72 -65
  46. data/lib/pione/model/data-expr.rb +596 -290
  47. data/lib/pione/model/float.rb +108 -103
  48. data/lib/pione/model/integer.rb +133 -129
  49. data/lib/pione/model/message.rb +79 -72
  50. data/lib/pione/model/package.rb +42 -38
  51. data/lib/pione/model/parameters.rb +265 -236
  52. data/lib/pione/model/rule-expr.rb +247 -242
  53. data/lib/pione/model/rule-io.rb +137 -133
  54. data/lib/pione/model/rule.rb +307 -292
  55. data/lib/pione/model/string.rb +110 -99
  56. data/lib/pione/model/variable-table.rb +300 -271
  57. data/lib/pione/model/variable.rb +88 -83
  58. data/lib/pione/option.rb +13 -0
  59. data/lib/pione/option/child-process-option.rb +19 -0
  60. data/lib/pione/{command-option → option}/common-option.rb +6 -5
  61. data/lib/pione/option/option-interface.rb +73 -0
  62. data/lib/pione/{command-option → option}/presence-notifier-option.rb +4 -3
  63. data/lib/pione/option/task-worker-owner-option.rb +24 -0
  64. data/lib/pione/{command-option → option}/tuple-space-provider-option.rb +6 -4
  65. data/lib/pione/option/tuple-space-provider-owner-option.rb +18 -0
  66. data/lib/pione/option/tuple-space-receiver-option.rb +8 -0
  67. data/lib/pione/parser/common-parser.rb +3 -2
  68. data/lib/pione/parser/expr-parser.rb +6 -1
  69. data/lib/pione/patch/em-ftpd-patch.rb +21 -0
  70. data/lib/pione/patch/rinda-patch.rb +31 -23
  71. data/lib/pione/rule-handler/action-handler.rb +35 -25
  72. data/lib/pione/rule-handler/basic-handler.rb +92 -18
  73. data/lib/pione/rule-handler/flow-handler.rb +104 -98
  74. data/lib/pione/rule-handler/root-handler.rb +11 -0
  75. data/lib/pione/system/common.rb +10 -0
  76. data/lib/pione/system/file-cache.rb +103 -84
  77. data/lib/pione/system/global.rb +67 -12
  78. data/lib/pione/system/init.rb +20 -0
  79. data/lib/pione/transformer/expr-transformer.rb +6 -1
  80. data/lib/pione/tuple-space/data-finder.rb +33 -6
  81. data/lib/pione/tuple-space/tuple-space-receiver.rb +4 -3
  82. data/lib/pione/tuple-space/tuple-space-server-interface.rb +58 -13
  83. data/lib/pione/tuple-space/tuple-space-server.rb +13 -11
  84. data/lib/pione/tuple-space/update-criteria.rb +8 -7
  85. data/lib/pione/tuple/base-location-tuple.rb +9 -0
  86. data/lib/pione/tuple/basic-tuple.rb +7 -7
  87. data/lib/pione/tuple/data-tuple.rb +5 -2
  88. data/lib/pione/tuple/lift-tuple.rb +14 -0
  89. data/lib/pione/tuple/rule-tuple.rb +1 -1
  90. data/lib/pione/tuple/task-tuple.rb +5 -1
  91. data/lib/pione/version.rb +1 -1
  92. data/pione.gemspec +5 -1
  93. data/test/location/spec_basic-location.rb +35 -0
  94. data/test/location/spec_ftp-location.rb +100 -0
  95. data/test/location/spec_local-location.rb +99 -0
  96. data/test/log/data/sample.log +1003 -0
  97. data/test/log/spec_xes-log.rb +11 -0
  98. data/test/model/spec_data-expr.rb +249 -6
  99. data/test/model/spec_data-expr.yml +45 -0
  100. data/test/parser/spec_expr-parser.yml +4 -0
  101. data/test/spec_data-finder.rb +13 -7
  102. data/test/spec_data-finder.yml +42 -13
  103. data/test/system/spec_file-cache.rb +39 -0
  104. data/test/test-util.rb +226 -1
  105. data/test/transformer/spec_expr-transformer.rb +12 -1
  106. metadata +107 -24
  107. data/bin/pione-search-log +0 -30
  108. data/lib/pione/command-option/basic-option.rb +0 -42
  109. data/lib/pione/command-option/child-process-option.rb +0 -17
  110. data/lib/pione/command-option/daemon-option.rb +0 -12
  111. data/lib/pione/command-option/task-worker-owner-option.rb +0 -17
  112. data/lib/pione/command-option/tuple-space-provider-owner-option.rb +0 -16
  113. data/lib/pione/command-option/tuple-space-receiver-option.rb +0 -12
  114. data/lib/pione/command/tuple-space-provider-owner.rb +0 -6
  115. data/lib/pione/resource/basic-resource.rb +0 -92
  116. data/lib/pione/resource/dropbox-resource.rb +0 -106
  117. data/lib/pione/resource/ftp.rb +0 -84
  118. data/lib/pione/resource/local.rb +0 -113
  119. data/lib/pione/tuple/base-uri-tuple.rb +0 -9
  120. data/lib/pione/tuple/shift-tuple.rb +0 -13
  121. data/lib/pione/util/log.rb +0 -79
  122. data/test/spec_resource.rb +0 -73
@@ -1,138 +1,149 @@
1
- module Pione::Model
2
- # PioneBoolean representes truth value in PIONE system.
3
- class PioneBoolean < BasicModel
4
- set_pione_model_type TypeBoolean
5
-
6
- # Returns the value in ruby.
7
- attr_reader :value
8
-
9
- class << self
10
- # Returns true value in PIONE system.
11
- # @return [PioneBoolean]
12
- # true value
13
- def true
14
- new(true)
1
+ module Pione
2
+ module Model
3
+ # PioneBoolean representes truth value in PIONE system.
4
+ class PioneBoolean < BasicModel
5
+ set_pione_model_type TypeBoolean
6
+
7
+ # Returns the value in ruby.
8
+ attr_reader :value
9
+
10
+ class << self
11
+ # Return true value in PIONE system.
12
+ #
13
+ # @return [PioneBoolean]
14
+ # true value
15
+ def true
16
+ new(true)
17
+ end
18
+
19
+ # Return false value in PIONE system.
20
+ #
21
+ # @return [PioneBoolean]
22
+ # false value
23
+ def false
24
+ new(false)
25
+ end
26
+
27
+ # Return inverse value of it.
28
+ #
29
+ # @param boolean [Boolean]
30
+ # target value
31
+ # @return [PioneBoolean]
32
+ # true if the param is false, or false
33
+ def not(boolean)
34
+ new(not(boolean.value))
35
+ end
36
+
37
+ # Return true value if arguments include true value.
38
+ #
39
+ # @param args [Array<PioneBoolean>]
40
+ # @return [PioneBoolean]
41
+ # true value if arguments include true value
42
+ def or(*args)
43
+ new(args.any?{|arg| arg.true?})
44
+ end
45
+
46
+ # Return true value if all arguments has true value.
47
+ #
48
+ # @param args [Array<PioneBoolean>]
49
+ # @return [PioneBoolean]
50
+ # true value if all arguments has true value
51
+ def and(*args)
52
+ new(args.all?{|arg| arg.true?})
53
+ end
15
54
  end
16
55
 
17
- # Returns false value in PIONE system.
18
- # @return [PioneBoolean]
19
- # false value
20
- def false
21
- new(false)
56
+ # Create a value.
57
+ #
58
+ # @param value [Boolean]
59
+ # true or false
60
+ def initialize(value)
61
+ @value = value
62
+ super()
22
63
  end
23
64
 
24
- # Returns inverse value of it.
25
- # @param [Boolean] boolean
26
- # target value
27
- # @return [PioneBoolean]
28
- # true if the param is false, or false
29
- def not(boolean)
30
- new(not(boolean.value))
65
+ # @api private
66
+ def task_id_string
67
+ "Boolean<#{@value}>"
31
68
  end
32
69
 
33
- # Returns true value if arguments include true value.
34
- # @param [Array<PioneBoolean>] args
35
- # @return [PioneBoolean]
36
- # true value if arguments include true value
37
- def or(*args)
38
- new(args.any?{|arg| arg.true?})
70
+ # @api private
71
+ def textize
72
+ @value.to_s
39
73
  end
40
74
 
41
- # Returns true value if all arguments has true value.
42
- # @param [Array<PioneBoolean>] args
43
- # @return [PioneBoolean]
44
- # true value if all arguments has true value
45
- def and(*args)
46
- new(args.all?{|arg| arg.true?})
75
+ # Return true if the value is true.
76
+ #
77
+ # @return [Boolean]
78
+ # true if the value is true
79
+ def true?
80
+ @value == true
47
81
  end
48
- end
49
-
50
- # Creates a value.
51
- # @param [Boolean] value
52
- # true or false
53
- def initialize(value)
54
- @value = value
55
- super()
56
- end
57
-
58
- # @api private
59
- def task_id_string
60
- "Boolean<#{@value}>"
61
- end
62
-
63
- # @api private
64
- def textize
65
- @value.to_s
66
- end
67
82
 
68
- # Returns true if the value is true.
69
- # @return [Boolean]
70
- # true if the value is true
71
- def true?
72
- @value == true
73
- end
74
-
75
- # Returns true if the value is false.
76
- # @return [Boolean]
77
- # true if the value is false
78
- def false?
79
- @value == false
80
- end
83
+ # Return true if the value is false.
84
+ #
85
+ # @return [Boolean]
86
+ # true if the value is false
87
+ def false?
88
+ @value == false
89
+ end
81
90
 
82
- # Returns ruby's boolean value.
83
- # @return [Boolean]
84
- # ruby's boolean value
85
- def to_ruby
86
- return @value
87
- end
91
+ # Return ruby's boolean value.
92
+ #
93
+ # @return [Boolean]
94
+ # ruby's boolean value
95
+ def to_ruby
96
+ return @value
97
+ end
88
98
 
89
- # @api private
90
- def ==(other)
91
- return false unless other.kind_of?(self.class)
92
- @value == other.value
93
- end
99
+ # @api private
100
+ def ==(other)
101
+ return false unless other.kind_of?(self.class)
102
+ @value == other.value
103
+ end
94
104
 
95
- alias :eql? :==
105
+ alias :eql? :"=="
96
106
 
97
- # @api private
98
- def hash
99
- @value.hash
100
- end
107
+ # @api private
108
+ def hash
109
+ @value.hash
110
+ end
101
111
 
102
- #
103
- # pione methods
104
- #
112
+ #
113
+ # pione methods
114
+ #
105
115
 
106
- define_pione_method("==", [TypeBoolean], TypeBoolean) do |rec, other|
107
- PioneBoolean.new(rec.value == other.value)
108
- end
116
+ define_pione_method("==", [TypeBoolean], TypeBoolean) do |rec, other|
117
+ PioneBoolean.new(rec.value == other.value)
118
+ end
109
119
 
110
- define_pione_method("!=", [TypeBoolean], TypeBoolean) do |rec, other|
111
- PioneBoolean.not(rec.call_pione_method("==", other))
112
- end
120
+ define_pione_method("!=", [TypeBoolean], TypeBoolean) do |rec, other|
121
+ PioneBoolean.not(rec.call_pione_method("==", other))
122
+ end
113
123
 
114
- define_pione_method("&&", [TypeBoolean], TypeBoolean) do |rec, other|
115
- PioneBoolean.new(rec.value && other.value)
116
- end
124
+ define_pione_method("&&", [TypeBoolean], TypeBoolean) do |rec, other|
125
+ PioneBoolean.new(rec.value && other.value)
126
+ end
117
127
 
118
- define_pione_method("||", [TypeBoolean], TypeBoolean) do |rec, other|
119
- PioneBoolean.new(rec.value || other.value)
120
- end
128
+ define_pione_method("||", [TypeBoolean], TypeBoolean) do |rec, other|
129
+ PioneBoolean.new(rec.value || other.value)
130
+ end
121
131
 
122
- define_pione_method("and", [TypeBoolean], TypeBoolean) do |rec, other|
123
- rec.call_pione_method("&&", other)
124
- end
132
+ define_pione_method("and", [TypeBoolean], TypeBoolean) do |rec, other|
133
+ rec.call_pione_method("&&", other)
134
+ end
125
135
 
126
- define_pione_method("or", [TypeBoolean], TypeBoolean) do |rec, other|
127
- rec.call_pione_method("||", other)
128
- end
136
+ define_pione_method("or", [TypeBoolean], TypeBoolean) do |rec, other|
137
+ rec.call_pione_method("||", other)
138
+ end
129
139
 
130
- define_pione_method("as_string", [], TypeString) do |rec|
131
- PioneString.new(rec.value.to_s)
132
- end
140
+ define_pione_method("as_string", [], TypeString) do |rec|
141
+ PioneString.new(rec.value.to_s)
142
+ end
133
143
 
134
- define_pione_method("not", [], TypeBoolean) do |rec|
135
- PioneBoolean.not(rec)
144
+ define_pione_method("not", [], TypeBoolean) do |rec|
145
+ PioneBoolean.not(rec)
146
+ end
136
147
  end
137
148
  end
138
149
  end
@@ -1,79 +1,86 @@
1
- module Pione::Model
2
- # CallRule represents the application of a rule.
3
- # @example
4
- # # simple rule calling:
5
- # rule r1
6
- # #=> CallRule.new(RuleExpr.new('r1'))
7
- # @example
8
- # # with absolute path:
9
- # rule /abc:a
10
- # #=> CallRule.new(RuleExpr.new('/abc:a'))
11
- # @example
12
- # # with variable:
13
- # rule $X
14
- # #=> CallRule.new(Variable.new('X'))
15
- class CallRule < BasicModel
16
- attr_reader :expr
1
+ module Pione
2
+ module Model
3
+ # CallRule represents the application of a rule.
4
+ #
5
+ # @example
6
+ # # simple rule calling:
7
+ # rule r1
8
+ # #=> CallRule.new(RuleExpr.new('r1'))
9
+ # @example
10
+ # # with absolute path:
11
+ # rule /abc:a
12
+ # #=> CallRule.new(RuleExpr.new('/abc:a'))
13
+ # @example
14
+ # # with variable:
15
+ # rule $X
16
+ # #=> CallRule.new(Variable.new('X'))
17
+ class CallRule < BasicModel
18
+ attr_reader :expr
17
19
 
18
- # Creates a callee rule.
19
- # @param [BasicModel] expr
20
- # callee rule
21
- def initialize(expr)
22
- @expr = expr
23
- super()
24
- end
20
+ # Create a callee rule.
21
+ #
22
+ # @param expr [BasicModel]
23
+ # callee rule
24
+ def initialize(expr)
25
+ @expr = expr
26
+ super()
27
+ end
25
28
 
26
- # Returns a rule path string with expanding variables.
27
- # @return [String]
28
- # rule path(package name and rule name)
29
- def rule_path
30
- if @expr.include_variable?
31
- raise UnboundVariableError.new(@expr)
29
+ # Return a rule path string with expanding variables.
30
+ #
31
+ # @return [String]
32
+ # rule path(package name and rule name)
33
+ def rule_path
34
+ if @expr.include_variable?
35
+ raise UnboundVariableError.new(@expr)
36
+ end
37
+ @expr.rule_path
32
38
  end
33
- @expr.rule_path
34
- end
35
39
 
36
- # Returns true if the expression has variables.
37
- # @return [Boolean]
38
- # true if the expression has variables
39
- def include_variable?
40
- @expr.include_variable?
41
- end
40
+ # Return true if the expression has variables.
41
+ #
42
+ # @return [Boolean]
43
+ # true if the expression has variables
44
+ def include_variable?
45
+ @expr.include_variable?
46
+ end
42
47
 
43
- # Evaluates the expression.
44
- # @param [VariableTable] vtable
45
- # variable table for evaluation
46
- # @return [BasicModel]
47
- # evaluation result
48
- def eval(vtable)
49
- self.class.new(@expr.eval(vtable))
50
- end
48
+ # Evaluate the expression.
49
+ #
50
+ # @param vtable [VariableTable]
51
+ # variable table for evaluation
52
+ # @return [BasicModel]
53
+ # evaluation result
54
+ def eval(vtable)
55
+ self.class.new(@expr.eval(vtable))
56
+ end
51
57
 
52
- # Return a set of call-rules that the rule expression are expanded.
53
- #
54
- # @return [Set<CallRule>]
55
- # a set of call-rules
56
- def to_set
57
- @expr.to_set.map do |expr|
58
- self.class.new(expr)
58
+ # Return a set of call-rules that the rule expression are expanded.
59
+ #
60
+ # @return [Set<CallRule>]
61
+ # a set of call-rules
62
+ def to_set
63
+ @expr.to_set.map do |expr|
64
+ self.class.new(expr)
65
+ end
59
66
  end
60
- end
61
67
 
62
- # @api private
63
- def textize
64
- "call_rule(%s)" % [@expr.textize]
65
- end
68
+ # @api private
69
+ def textize
70
+ "call_rule(%s)" % [@expr.textize]
71
+ end
66
72
 
67
- # @api private
68
- def ==(other)
69
- @expr == other.expr
70
- end
73
+ # @api private
74
+ def ==(other)
75
+ @expr == other.expr
76
+ end
71
77
 
72
- alias :eql? :==
78
+ alias :eql? :"=="
73
79
 
74
- # @api private
75
- def hash
76
- @expr.hash
80
+ # @api private
81
+ def hash
82
+ @expr.hash
83
+ end
77
84
  end
78
85
  end
79
86
  end
@@ -1,360 +1,666 @@
1
- module Pione::Model
1
+ module Pione
2
+ module Model
3
+ # DataExpr is a class for data name expressions of rule input and output.
4
+ #
5
+ # @example
6
+ # # complete name
7
+ # DataExpr.new("test.txt")
8
+ # @example
9
+ # # incomplete name
10
+ # DataExpr.new("*.txt")
11
+ class DataExpr < BasicModel
12
+
13
+ # separator symbol for all modifier
14
+ SEPARATOR = ':'
15
+
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
2
46
 
3
- # DataExpr is a class for data name expressions of rule input and output.
4
- # @example
5
- # # complete name
6
- # DataExpr.new("test.txt")
7
- # @example
8
- # # incomplete name
9
- # DataExpr.new("*.txt")
10
- class DataExpr < BasicModel
47
+ class << self
48
+ alias :orig_new :new
49
+
50
+ # Create a data expression. If the name includes separators, create DataExprOr instance.
51
+ def new(*args)
52
+ # check OR expression
53
+ name = args.first
54
+ if self == DataExpr and name.include?(SEPARATOR)
55
+ name.split(SEPARATOR).map do |single_name|
56
+ orig_new(single_name, *args.drop(1))
57
+ end.tap {|exprs| return DataExprOr.new(exprs)}
58
+ end
59
+
60
+ # other cases
61
+ return orig_new(*args)
62
+ end
63
+
64
+ # Create a named expression.
65
+ #
66
+ # @param name [String]
67
+ # data name
68
+ def [](name)
69
+ new(name)
70
+ end
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
+ # Return convertion prcedure for enumerable.
109
+ #
110
+ # @return [Proc]
111
+ # +Proc+ object that returns data expression with name
112
+ def to_proc
113
+ Proc.new{|name| name.kind_of?(self) ? name : self.new(name)}
114
+ end
115
+ end
11
116
 
12
- # separator symbol for all modifier
13
- SEPARATOR = ':'
117
+ set_pione_model_type TypeDataExpr
118
+
119
+ attr_reader :name
120
+ alias :core :name
121
+ forward_as_key! :@data, :modifier, :mode, :exceptions, :update_criteria
122
+
123
+ # Create a data expression.
124
+ #
125
+ # @param name [String]
126
+ # data expression name
127
+ # @param opts [Hash]
128
+ # options of the expression
129
+ # @option opts [Symbol] :modifier
130
+ # :all or :each
131
+ # @option opts [Symbol] :mode
132
+ # nil, :stdout, or :stderr
133
+ # @option opts [Array<DataExpr>] :exceptions
134
+ # exceptional expressions
135
+ # @option opts [Boolean] :update_criteria
136
+ # the flag whether the data disregards update criterias
137
+ def initialize(name, data={})
138
+ unless name.kind_of? String or name.kind_of? Regexp
139
+ raise ArgumentError.new(name)
140
+ end
141
+
142
+ @name = name
143
+ @data = Hash.new
144
+ @data[:modifier] = data[:modifier] || :each
145
+ @data[:mode] = data[:mode]
146
+ @data[:exceptions] = data[:exceptions] || []
147
+ @data[:update_criteria] = data[:update_criteria] || :care
148
+
149
+ super()
150
+ end
14
151
 
15
- # DataExpr::Compiler is a regexp compiler for data expression.
16
- module Compiler
17
- TABLE = {}
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))
158
+ end
18
159
 
19
- # Define a string matcher.
20
- def self.define_matcher(matcher, replace)
21
- TABLE[Regexp.escape(matcher)] = replace
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))
22
166
  end
23
167
 
24
- # Asterisk symbol is multi-characters matcher(empty string is matched).
25
- define_matcher('*', '(.*)')
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
26
175
 
27
- # Question symbol is single character matcher(empty string is not matched).
28
- define_matcher('?', '(.)')
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
29
183
 
30
- # Compiles data name into regular expression.
31
- def compile(name)
32
- return name unless name.kind_of?(String)
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
33
191
 
34
- s = "^#{Regexp.escape(name)}$"
35
- TABLE.keys.each {|key| s.gsub!(key, TABLE)}
36
- s.gsub!(/\\\[(!|\\\^)?(.*)\\\]/){"[#{'^' if $1}#{$2.gsub('\-','-')}]"}
37
- s.gsub!(/\\{(.*)\\}/){"(#{$1.split(',').join('|')})"}
38
- Regexp.new(s)
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))
39
198
  end
40
- module_function :compile
41
- end
42
199
 
43
- # This module implements DataExpr singleton methods.
44
- module SingletonMethod
45
- # Create a named expression.
46
- # @param [String] name
47
- # data expression
48
- def [](name)
49
- new(name)
200
+ # Evaluate the data expression.
201
+ #
202
+ # @param vtable [VariableTable]
203
+ # variable table for evaluation
204
+ # @return [BasicModel]
205
+ # evaluation result
206
+ def eval(vtable)
207
+ new_exceptions = exceptions.map {|exc| exc.eval(vtable)}
208
+ self.class.new(vtable.expand(name), @data.merge(exceptions: new_exceptions))
50
209
  end
51
210
 
52
- # Create a name expression with 'each' modifier.
53
- def each(name)
54
- new(name, :each)
211
+ # Return true if the name includes variables.
212
+ #
213
+ # @return [Boolean]
214
+ # true if the name includes variables
215
+ def include_variable?
216
+ VariableTable.check_include_variable(name)
55
217
  end
56
218
 
57
- # Create a name expression with 'all' modifier.
58
- def all(name)
59
- new(name, :all)
219
+ # @api private
220
+ def task_id_string
221
+ "DataExpr<#{name},#{modifier},[%s]>" % [
222
+ exceptions.map{|exc| exc.task_id_string}.join(",")
223
+ ]
60
224
  end
61
225
 
62
- # Creates a new data name for stdout ouput.
63
- # @param [String] name
64
- # data name
65
- # @return [DataExpr]
66
- # data expression for stdout
67
- def stdout(name)
68
- new(name, :each, :stdout)
226
+ # @api private
227
+ def textize
228
+ "data_expr(\"#{name}\",:#{modifier},[%s])" % [
229
+ exceptions.map{|exc| exc.textize}.join(",")
230
+ ]
69
231
  end
70
232
 
71
- # Creates a new data name for stderr output.
72
- # @param [String] name
73
- # data name
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
+ # Create new data expression with appending the exception.
282
+ #
283
+ # @param exc [DataExpr, String]
284
+ # data name for exceptions
74
285
  # @return [DataExpr]
75
- # data expression for stderr
76
- def stderr(name)
77
- new(name, :each, :stderr)
286
+ # new data name with the exception
287
+ def except(exc)
288
+ new_exceptions = exceptions + [exc.kind_of?(DataExpr) ? exc : DataExpr.new(exc)]
289
+ return self.class.new(core, @data.merge(exceptions: new_exceptions))
78
290
  end
79
291
 
80
- # Returns convertion prcedure for enumerable.
81
- # @return [Proc]
82
- # +Proc+ object that returns data expression with name
83
- def to_proc
84
- Proc.new{|name| name.kind_of?(self) ? name : self.new(name)}
292
+ # Return matched data if the name is matched with the expression.
293
+ #
294
+ # @param other [String]
295
+ # data name string
296
+ # @return [MatchedData]
297
+ # matched data
298
+ def match(other)
299
+ # check exceptions
300
+ return false if match_exceptions(other)
301
+ # match test
302
+ return compile_to_regexp(name).match(other)
85
303
  end
86
- end
87
304
 
88
- extend SingletonMethod
305
+ # Return if the expression accepts nonexistence of corresponding data.
306
+ #
307
+ # @return [Boolean]
308
+ # false because data expression needs corresponding data
309
+ def accept_nonexistence?
310
+ false
311
+ end
89
312
 
90
- set_pione_model_type TypeDataExpr
313
+ # Select from name list matched with the expression.
314
+ #
315
+ # @param [Array<String>] names
316
+ # name list
317
+ def select(*names)
318
+ names.flatten.select {|name| match(name) }
319
+ end
91
320
 
92
- attr_reader :name
93
- attr_reader :modifier
94
- attr_reader :mode
95
- attr_reader :exceptions
321
+ # Generate concrete name string by arguments.
322
+ #
323
+ # @example
324
+ # DataExpr["test-*.rb"].generate(1)
325
+ # # => "test-1.rb"
326
+ def generate(*args)
327
+ name = @name.clone
328
+ while name =~ /(\*|\?)/ and not(args.empty?)
329
+ val = args.shift.to_s
330
+ name.sub!(/(\*|\?)/){$1 == "*" ? val : val[0]}
331
+ end
332
+ return name
333
+ end
96
334
 
97
- # Creates a data expression.
98
- # @param [String] name
99
- # data expression name
100
- # @param [Symbol] modifier
101
- # :all or :each
102
- # @param [Symbol] mode
103
- # nil, :stdout, or :stderr
104
- def initialize(name, modifier = :each, mode = nil, exceptions = [])
105
- unless name.kind_of? String or name.kind_of? Regexp
106
- raise ArgumentError.new(name)
335
+ # Create OR relation data expression. Self and the other element have the
336
+ # same attributes.
337
+ #
338
+ # @example
339
+ # expr = DataExpr.new("A") | DataExpr.new("B")
340
+ # expr.match("A") # => true
341
+ # expr.match("B") # => true
342
+ # expr.match("C") # => false
343
+ # @example
344
+ # DataExpr.all("A") | DataExpr.each("B")
345
+ # # => raise ArgumentError
346
+ def |(other)
347
+ raise ArgumentError.new(other) unless other.kind_of?(DataExpr)
348
+ return DataExprOr.new([self, other])
107
349
  end
108
350
 
109
- @name = name
110
- @modifier = modifier
111
- @mode = mode
112
- @exceptions = exceptions
351
+ # @api private
352
+ def to_s
353
+ "#<#<#{self.class.name}> name='#{name}' data=#{@data.inspect}>"
354
+ end
113
355
 
114
- super()
115
- end
356
+ # Return true if name, modifier, mode, and exceptions are the same.
357
+ #
358
+ # @api private
359
+ def ==(other)
360
+ return false unless other.kind_of?(self.class)
361
+ return false unless name == other.name
362
+ return false unless modifier == other.modifier
363
+ return false unless mode == other.mode
364
+ return false unless exceptions.sort == other.exceptions.sort
365
+ return true
366
+ end
367
+ alias :eql? :"=="
116
368
 
117
- # Returns new data expression with each modifier.
118
- # @return [DataExpr]
119
- # new data expression with each modifier
120
- def each
121
- return self.class.new(@name, :each, @mode, @exceptions)
122
- end
369
+ # @api private
370
+ def hash
371
+ [name, modifier, mode, exceptions].join("\000").hash
372
+ end
123
373
 
124
- # Returns new data expression with all modifier.
125
- # @return [DataExpr]
126
- # new data expression with all modifier
127
- def all
128
- return self.class.new(@name, :all, @mode, @exceptions)
129
- end
374
+ # Same as Regexp#=~ but return 0 if it matched.
375
+ def =~(other)
376
+ match(other) ? 0 : nil
377
+ end
130
378
 
131
- # Returns new data expression with stdout mode.
132
- # @return [DataExpr]
133
- # new data expression with stdout mode
134
- def stdout
135
- return self.class.new(@name, @modifier, :stdout, @exceptions)
136
- end
379
+ # Pattern match.
380
+ #
381
+ # @api private
382
+ def ===(other)
383
+ match(other) ? true : false
384
+ end
137
385
 
138
- # Returns new data expression with stderr mode.
139
- # @return [DataExpr]
140
- # new data expression with stderr mode
141
- def stderr
142
- return self.class.new(@name, @modifier, :stderr, @exceptions)
143
- end
386
+ private
144
387
 
145
- # Evaluates the data expression.
146
- # @param [VariableTable] vtable
147
- # variable table for evaluation
148
- # @return [BasicModel]
149
- # evaluation result
150
- def eval(vtable)
151
- exceptions = @exceptions.map {|exc| exc.eval(vtable)}
152
- self.class.new(vtable.expand(name), @modifier, @mode, exceptions)
153
- end
388
+ # @api private
389
+ def compile_to_regexp(name)
390
+ Compiler.compile(name)
391
+ end
154
392
 
155
- # Returns true if the name includes variables.
156
- # @return [Boolean]
157
- # true if the name includes variables
158
- def include_variable?
159
- VariableTable.check_include_variable(@name)
393
+ # Return true if the name matchs exceptions.
394
+ #
395
+ # @api private
396
+ def match_exceptions(name)
397
+ not(exceptions.select{|ex| ex.match(name)}.empty?)
398
+ end
160
399
  end
161
400
 
162
- # @api private
163
- def task_id_string
164
- "DataExpr<#{@name},#{@modifier},[%s]>" % [
165
- @exceptions.map{|exc| exc.task_id_string}.join(",")
166
- ]
167
- end
401
+ class DataExprNull < DataExpr
402
+ include Singleton
168
403
 
169
- # @api private
170
- def textize
171
- "data_expr(\"#{@name}\",:#{@modifier},[%s])" % [
172
- @exceptions.map{|exc| exc.textize}.join(",")
173
- ]
174
- end
404
+ # null returns itself for property change methods
405
+ def return_self
406
+ self
407
+ end
408
+ alias :all :return_self
409
+ alias :each :return_self
410
+ alias :stdout :return_self
411
+ alias :stderr :return_self
412
+ alias :neglect :return_self
413
+ alias :care :return_self
414
+
415
+ def initialize
416
+ @data = {}
417
+ end
175
418
 
176
- # Return true if the name has 'all' modifier.
177
- # @return [Boolean]
178
- # true if the name has 'all' modifier
179
- def all?
180
- @modifier == :all
181
- end
419
+ def accept_nonexistence?
420
+ true
421
+ end
182
422
 
183
- # Return true if the name has 'each' modifier.
184
- # @return [Boolean]
185
- # true if the name has 'each' modifier
186
- def each?
187
- @modifier == :each
188
- end
423
+ def match(name)
424
+ nil
425
+ end
189
426
 
190
- # Return true if the data content is in stdout.
191
- # @return [Boolean]
192
- # true if the data content is in stdout
193
- def stdout?
194
- @mode == :stdout
195
- end
427
+ # Evaluate the data expression. The result is myself.
428
+ #
429
+ # @param vtable [VariableTable]
430
+ # variable table for evaluation
431
+ # @return [BasicModel]
432
+ # self
433
+ def eval(vtable)
434
+ self
435
+ end
196
436
 
197
- # Returns true if the data content is in stderr.
198
- # @return [Boolean]
199
- # true if the data content is in stderr
200
- def stderr?
201
- @mode == :stderr
202
- end
437
+ def textize
438
+ "data_expr(null)"
439
+ end
203
440
 
204
- # Creates new data expression with a exception name.
205
- # @param [DataExpr, String] name
206
- # data name for exceptions
207
- # @return [DataExpr]
208
- # new data name with the exception
209
- def except(name)
210
- exceptions =
211
- @exceptions.clone + [name.kind_of?(DataExpr) ? name : DataExpr.new(name)]
212
- return self.class.new(@name, @modifier, @mode, exceptions)
213
- end
441
+ # @api private
442
+ def to_s
443
+ "#<#<#{self.class.name}>>"
444
+ end
214
445
 
215
- # Returns matched data if the name is matched with the expression.
216
- # @param [String] other
217
- # data name string
218
- def match(other)
219
- # check exceptions
220
- return false if match_exceptions(other)
221
- # match test
222
- md = nil
223
- @name.split(SEPARATOR).each do |name|
224
- break if md = compile_to_regexp(name).match(other)
225
- end
226
- return md
227
- end
446
+ # @api private
447
+ def ==(other)
448
+ self.class == other.class
449
+ end
450
+ alias :eql? :"=="
451
+ end
452
+
453
+ # DataExprOr represents or-relation of data expressions. Expressions have
454
+ # same properties about modifier and mode.
455
+ class DataExprOr < DataExpr
456
+ attr_reader :elements
457
+ alias :core :elements
458
+
459
+ forward! Proc.new{find_not_null_element}, :modifier, :mode, :update_criteria
460
+
461
+ # @param elements [Array<DataExpr>]
462
+ # elements that have OR relation
463
+ # @param data [Hash]
464
+ # options of the expression
465
+ # @option opts [Array<DataExpr>] :exceptions
466
+ # exceptional expressions
467
+ def initialize(elements, data={})
468
+ @elements = elements
469
+ @data = {}
470
+ @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
+ end
228
487
 
229
- # Selects from name list matched with the expression.
230
- # @param [Array<String>] names
231
- # name list
232
- def select(*names)
233
- names.flatten.select {|name| match(name) }
234
- end
488
+ # Match if the name is matched one of elements.
489
+ #
490
+ # @param name [String]
491
+ # data name
492
+ # @return [MatchedData,nil]
493
+ # the matchde data, or nil
494
+ def match(name)
495
+ # check exceptions
496
+ return false if match_exceptions(name)
497
+ # check to match the expression
498
+ @elements.each do |element|
499
+ if md = element.match(name)
500
+ return md
501
+ end
502
+ end.tap {return nil}
503
+ end
235
504
 
236
- # Generates concrete name string by arguments.
237
- # @example
238
- # DataExpr["test-*.rb"].generate(1)
239
- # # => "test-1.rb"
240
- def generate(*args)
241
- name = @name.clone
242
- while name =~ /(\*|\?)/ and not(args.empty?)
243
- val = args.shift.to_s
244
- name.sub!(/(\*|\?)/){$1 == "*" ? val : val[0]}
245
- end
246
- return name
247
- end
505
+ # Return true if at least one element accepts nonexistence.
506
+ #
507
+ # @return [Boolean]
508
+ # true if at least one element accepts nonexistence
509
+ def accept_nonexistence?
510
+ @elements.any?{|element| element.accept_nonexistence?}
511
+ end
248
512
 
249
- # Create OR relation data expression. Self and the other element have the
250
- # same attributes.
251
- # @example
252
- # expr = DataExpr.new("A") | DataExpr.new("B")
253
- # expr.match("A") # => true
254
- # expr.match("B") # => true
255
- # expr.match("C") # => false
256
- # @example
257
- # DataExpr.all("A") | DataExpr.each("B")
258
- # # => raise ArgumentError
259
- def |(other)
260
- raise ArgumentError.new(other) unless other.kind_of?(DataExpr)
261
- return DataExprOr.new(self, other)
262
- end
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
263
520
 
264
- # @api private
265
- def to_s
266
- "#<#<#{self.class.name}> #{@name}>"
267
- end
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
268
528
 
269
- # Returns true if name, modifier, mode, and exceptions are the same.
270
- # @api private
271
- def ==(other)
272
- return false unless other.kind_of?(self.class)
273
- return false unless @name == other.name
274
- return false unless @modifier == other.modifier
275
- return false unless @mode == other.mode
276
- return false unless @exceptions.sort == other.exceptions.sort
277
- return true
278
- end
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
279
536
 
280
- alias eql? ==
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
281
544
 
282
- # @api private
283
- def hash
284
- [@name, @modifier, @mode, @exceptions].join("\000").hash
285
- end
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
286
552
 
287
- # Same as Regexp#=~ but return 0 if it matched.
288
- def =~(other)
289
- match(other) ? 0 : nil
290
- end
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)
559
+ end
291
560
 
292
- # Pattern match.
293
- # @api private
294
- def ===(other)
295
- match(other) ? true : false
296
- end
561
+ # Evaluate the data expression. This evaluates all elements of the expression.
562
+ #
563
+ # @param vtable [VariableTable]
564
+ # variable table for evaluation
565
+ # @return [BasicModel]
566
+ # evaluation result
567
+ def eval(vtable)
568
+ new_elements = @elements.map {|elt| elt.eval(vtable)}
569
+ new_exceptions = exceptions.map {|exc| exc.eval(vtable)}
570
+ self.class.new(new_elements, @data.merge(exceptions: new_exceptions))
571
+ end
297
572
 
298
- private
573
+ def textize
574
+ "data_expr_or(%s)" % @elements.map{|elt| elt.textize}.join(", ")
575
+ end
299
576
 
300
- # @api private
301
- def compile_to_regexp(name)
302
- Compiler.compile(name)
303
- end
577
+ # @api private
578
+ def to_s
579
+ "#<#<#{self.class.name}> #{@elements} #{@data}>"
580
+ end
304
581
 
305
- # Returns true if the name matchs exceptions.
306
- # @api private
307
- def match_exceptions(name)
308
- not(@exceptions.select{|ex| ex.match(name)}.empty?)
309
- end
310
- end
582
+ # @api private
583
+ def ==(other)
584
+ return false unless other.kind_of?(self.class)
585
+ (@elements - other.elements).empty?
586
+ end
587
+ alias :eql? :"=="
311
588
 
312
- # DataExprOr represents or-relation of data expressions.
313
- class DataExprOr < DataExpr
314
- extend Forwardable
315
- def_delegator :@left, :modifier
316
- def_delegator :@left, :mode
317
-
318
- def initialize(left, right)
319
- raise ArgumentError.new([left, right]) unless left.modifier == right.modifier
320
- raise ArmguentError.new([left, right]) unless left.mode == right.mode
321
- @left = left
322
- @right = right
323
- end
589
+ # @api private
590
+ def hash
591
+ @elements.hash
592
+ end
324
593
 
325
- # @api private
326
- def match(name)
327
- @left.match(name) or @right.match(name)
328
- end
329
- end
594
+ private
330
595
 
331
- TypeDataExpr.instance_eval do
332
- define_pione_method("==", [TypeDataExpr], TypeBoolean) do |rec, other|
333
- PioneBoolean.new(rec == other)
596
+ def find_not_null_element
597
+ @elements.find{|elt| not(elt.kind_of?(DataExprNull))}
598
+ end
334
599
  end
335
600
 
336
- define_pione_method("!=", [TypeDataExpr], TypeBoolean) do |rec, other|
337
- PioneBoolean.not(rec.call_pione_method("==", other))
338
- end
601
+ TypeDataExpr.instance_eval do
602
+ define_pione_method("==", [TypeDataExpr], TypeBoolean) do |rec, other|
603
+ PioneBoolean.new(rec == other)
604
+ end
339
605
 
340
- define_pione_method("all", [], TypeDataExpr) do |rec|
341
- rec.all
342
- end
606
+ define_pione_method("!=", [TypeDataExpr], TypeBoolean) do |rec, other|
607
+ PioneBoolean.not(rec.call_pione_method("==", other))
608
+ end
343
609
 
344
- define_pione_method("each", [], TypeDataExpr) do |rec|
345
- rec.each
346
- end
610
+ define_pione_method("all", [], TypeDataExpr) do |rec|
611
+ rec.all
612
+ end
347
613
 
348
- define_pione_method("except", [TypeDataExpr], TypeDataExpr) do |rec, target|
349
- rec.except(target)
350
- end
614
+ define_pione_method("each", [], TypeDataExpr) do |rec|
615
+ rec.each
616
+ end
351
617
 
352
- define_pione_method("stdout", [], TypeDataExpr) do |rec|
353
- rec.stdout
354
- end
618
+ define_pione_method("except", [TypeDataExpr], TypeDataExpr) do |rec, target|
619
+ rec.except(target)
620
+ end
355
621
 
356
- define_pione_method("stderr", [], TypeDataExpr) do |rec|
357
- rec.stderr
622
+ define_pione_method("stdout", [], TypeDataExpr) do |rec|
623
+ rec.stdout
624
+ end
625
+
626
+ define_pione_method("stderr", [], TypeDataExpr) do |rec|
627
+ rec.stderr
628
+ end
629
+
630
+ define_pione_method("neglect", [], TypeDataExpr) do |rec|
631
+ rec.neglect
632
+ end
633
+
634
+ define_pione_method("care", [], TypeDataExpr) do |rec|
635
+ rec.care
636
+ end
637
+
638
+ define_pione_method("or", [TypeDataExpr], TypeDataExpr) do |rec, other|
639
+ DataExprOr.new([rec, other])
640
+ end
641
+
642
+ define_pione_method("join", [TypeString], TypeString) do |rec, connective|
643
+ PioneString.new(rec.elements.map{|elt| elt.name}.join(connective.to_ruby))
644
+ end
645
+
646
+ define_pione_method("match?", [TypeString], TypeBoolean) do |rec, name|
647
+ if rec.match(name.value)
648
+ PioneBoolean.true
649
+ else
650
+ PioneBoolean.false
651
+ end
652
+ end
653
+
654
+ 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
663
+ end
358
664
  end
359
665
  end
360
666
  end