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
@@ -0,0 +1,105 @@
1
+ module Pione
2
+ module Log
3
+ # XESLog is a class for XES formatted log.
4
+ class XESLog < ProcessLogFormatter
5
+ set_format_name :xes
6
+
7
+ # Format as a XML document.
8
+ #
9
+ # @return [String]
10
+ # result string
11
+ def format(trace_filters=[])
12
+ filter = Proc.new {|trace| trace_filters.empty? or trace_filters.any?{|filter| filter.call(trace)}}
13
+ StringIO.new.tap do |out|
14
+ XES::Document.new.tap do |doc|
15
+ doc.log = XES::Log.default.tap do |log|
16
+ log.concept_name = "PIONE process log"
17
+ log.traces += [format_agent_activity + format_rule_process + format_task_process].flatten.select(&filter)
18
+ log.traces.flatten!
19
+ end
20
+ if doc.formattable?
21
+ doc.format.write(out, 2)
22
+ return out.string
23
+ else
24
+ raise ProcessLogFormatError.new("not formattable: %s" % doc.inspect)
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ # Format agent activity records.
33
+ #
34
+ # @return [Array<XES::Trace>]
35
+ def format_agent_activity
36
+ @bundles.map do |bundle|
37
+ bundle.agent_activity_log.group_by(:agent_uuid).map do |agent_uuid, records|
38
+ XES::Trace.new.tap do |trace|
39
+ trace.attributes << XES.string("pione:traceType", "agent_activity")
40
+ trace.identity_id = agent_uuid
41
+ trace.events = records.sort{|a, b| a.timestamp <=> b.timestamp}.map do |record|
42
+ XES::Event.new.tap do |event|
43
+ event.concept_name = record.state
44
+ event.org_resource = record.agent_type
45
+ event.time_timestamp = record.timestamp
46
+ event.lifecycle_transition = record.transition
47
+ end
48
+ end
49
+ end
50
+ end.flatten
51
+ end
52
+ end
53
+
54
+ # Format rule process records.
55
+ #
56
+ # @return [Array<XES::Trace>]
57
+ def format_rule_process
58
+ @bundles.map do |bundle|
59
+ XES::Trace.new.tap do |trace|
60
+ trace.concept_name = "rule_process %s" % Util.generate_uuid
61
+ trace.attributes << XES.string("pione:traceType", "rule_process")
62
+ trace.events = bundle.rule_process_log.records.map do |record|
63
+ XES::Event.new.tap do |event|
64
+ # standard attributes
65
+ event.concept_name = record.name
66
+ event.org_resource = record.caller
67
+ event.time_timestamp = record.timestamp
68
+ event.lifecycle_transition = record.transition
69
+
70
+ # pione extension attributes
71
+ event.attributes << XES.string("pione:ruleType", record.rule_type)
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ # Format task process records.
79
+ #
80
+ # @return [Array<XES::Trace>]
81
+ def format_task_process
82
+ @bundles.map do |bundle|
83
+ XES::Trace.new.tap do |trace|
84
+ trace.concept_name = "task process %s" % Util.generate_uuid
85
+ trace.attributes << XES.string("pione:traceType", "task_process")
86
+ trace.events = bundle.task_process_log.records.map do |record|
87
+ XES::Event.new.tap do |event|
88
+ # standard attributes
89
+ event.concept_name = record.name
90
+ # event.org_resource = record.caller
91
+ event.time_timestamp = record.timestamp
92
+ event.lifecycle_transition = record.transition
93
+
94
+ # pione extension attributes
95
+ event.attributes << XES.string("pione:ruleType", record.rule_type)
96
+ event.attributes << XES.string("pione:inputs", record.inputs)
97
+ event.attributes << XES.string("pione:parameters", record.parameters)
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -1,95 +1,103 @@
1
- module Pione::Model
2
- # Assignment represents a value assignment for variable.
3
- # @example
4
- # # assigning a string
5
- # $X := "a"
6
- # # => Assignment.new(Variable.new('X'), PioneString.new('a'))
7
- # @example
8
- # # assigning a variable value
9
- # $X := $Y
10
- # # => Assignment.new(Variable.new('X'), Variable.new('Y'))
11
- class Assignment < BasicModel
12
- set_pione_model_type TypeAssignment
1
+ module Pione
2
+ module Model
3
+ # Assignment represents a value assignment for variable.
4
+ #
5
+ # @example
6
+ # # assigning a string
7
+ # $X := "a"
8
+ # # => Assignment.new(Variable.new('X'), PioneString.new('a'))
9
+ # @example
10
+ # # assigning a variable value
11
+ # $X := $Y
12
+ # # => Assignment.new(Variable.new('X'), Variable.new('Y'))
13
+ class Assignment < BasicModel
14
+ set_pione_model_type TypeAssignment
13
15
 
14
- # Returns the variable part of assignment.
15
- attr_reader :variable
16
+ # Return the variable part of assignment.
17
+ attr_reader :variable
16
18
 
17
- # Returns the expression part of assignment.
18
- attr_reader :expr
19
+ # Return the expression part of assignment.
20
+ attr_reader :expr
19
21
 
20
- # Creates an assignment.
21
- # @param [Variable] variable
22
- # variable part of assignment
23
- # @param [BasicModel] expr
24
- # expression part of assignment
25
- def initialize(variable, expr)
26
- check_argument_type(variable, Variable)
27
- check_argument_type(expr, BasicModel)
28
- @variable = variable
29
- @expr = expr
30
- super()
31
- end
22
+ # Create an assignment.
23
+ #
24
+ # @param variable [Variable]
25
+ # variable part of assignment
26
+ # @param expr [BasicModel]
27
+ # expression part of assignment
28
+ def initialize(variable, expr)
29
+ check_argument_type(variable, Variable)
30
+ check_argument_type(expr, BasicModel)
31
+ @variable = variable
32
+ @expr = expr
33
+ super()
34
+ end
32
35
 
33
- # Evaluates the assignment. This method updates the variable table with the
34
- # variable and expression. The expression is pushed into the table directory
35
- # as it is because of lazy evaluation.
36
- # @param [VariableTable] vtable
37
- # variable table for evaluation
38
- # @return [BasicModel]
39
- # self
40
- def eval(vtable)
41
- vtable.set(@variable, @expr)
42
- end
36
+ # Evaluate the assignment. This method updates the variable table with the
37
+ # variable and expression. The expression is pushed into the table directory
38
+ # as it is because of lazy evaluation.
39
+ #
40
+ # @param vtable [VariableTable]
41
+ # variable table for evaluation
42
+ # @return [BasicModel]
43
+ # self
44
+ def eval(vtable)
45
+ vtable.set(@variable, @expr)
46
+ end
43
47
 
44
- # Set truth of toplevel assignment.
45
- def set_toplevel(b)
46
- @variable.set_toplevel(b)
47
- end
48
-
49
- # Set truth of user parameter.
50
- def set_user_param(b)
51
- @variable.set_user_param(b)
52
- end
48
+ # Set truth of toplevel assignment.
49
+ def set_toplevel(b)
50
+ @variable.set_toplevel(b)
51
+ end
53
52
 
54
- # Returns true if the assignment is defined in toplevel.
55
- # @return [Boolean]
56
- # true if the assignment is defined in toplevel
57
- def toplevel?
58
- @variable.toplevel?
59
- end
53
+ # Set truth of user parameter.
54
+ def set_user_param(b)
55
+ @variable.set_user_param(b)
56
+ end
60
57
 
61
- # Returns false because assignment form is complex(pair of variable and
62
- # expression).
63
- # @return [Boolean]
64
- # false
65
- def atomic?
66
- false
67
- end
58
+ # Return true if the assignment is defined in toplevel.
59
+ #
60
+ # @return [Boolean]
61
+ # true if the assignment is defined in toplevel
62
+ def toplevel?
63
+ @variable.toplevel?
64
+ end
68
65
 
69
- # Returns true if the expression part of assignment includes variable.
70
- # @return [Boolean]
71
- # true if the expression part of assignment includes variable
72
- def include_variable?
73
- @expr.include_variable?
74
- end
66
+ # Return false because assignment form is complex(pair of variable and
67
+ # expression).
68
+ #
69
+ # @return [Boolean]
70
+ # false
71
+ def atomic?
72
+ false
73
+ end
75
74
 
76
- # @api private
77
- def textize
78
- "%s:=%s" % [@variable.textize, @expr.textize]
79
- end
75
+ # Return true if the expression part of assignment includes variable.
76
+ #
77
+ # @return [Boolean]
78
+ # true if the expression part of assignment includes variable
79
+ def include_variable?
80
+ @expr.include_variable?
81
+ end
80
82
 
81
- # Returns true if other is a variable object which name is same as myself.
82
- # @api private
83
- def ==(other)
84
- return false unless other.kind_of?(self.class)
85
- @variable == other.variable && @expr == other.expr
86
- end
83
+ # @api private
84
+ def textize
85
+ "%s:=%s" % [@variable.textize, @expr.textize]
86
+ end
87
87
 
88
- alias :eql? :"=="
88
+ # Return true if other is a variable object which name is same as myself.
89
+ #
90
+ # @api private
91
+ def ==(other)
92
+ return false unless other.kind_of?(self.class)
93
+ @variable == other.variable && @expr == other.expr
94
+ end
95
+ alias :eql? :"=="
89
96
 
90
- # @api private
91
- def hash
92
- @variable.hash + @expr.hash
97
+ # @api private
98
+ def hash
99
+ @variable.hash + @expr.hash
100
+ end
93
101
  end
94
102
  end
95
103
  end
@@ -1,80 +1,86 @@
1
- module Pione::Model
1
+ module Pione
2
+ module Model
3
+ # BinaryOperator represents applications between Pione model objects.
4
+ #
5
+ # @example
6
+ # 1 + 1
7
+ # @example
8
+ # true == false
9
+ # @example
10
+ # $X * $Y
11
+ class BinaryOperator < BasicModel
12
+ attr_reader :symbol
13
+ attr_reader :left
14
+ attr_reader :right
2
15
 
3
- # BinaryOperator represents applications between Pione model objects.
4
- # @example
5
- # 1 + 1
6
- # @example
7
- # true == false
8
- # @example
9
- # $X * $Y
10
- class BinaryOperator < BasicModel
11
- attr_reader :symbol
12
- attr_reader :left
13
- attr_reader :right
16
+ # Create a binary operator.
17
+ #
18
+ # @param symbol [String]
19
+ # operator's symbol
20
+ # @param left [BasicModel]
21
+ # left operand
22
+ # @param right [BasicModel]
23
+ # right operand
24
+ def initialize(symbol, left, right)
25
+ @symbol = symbol
26
+ @left = left
27
+ @right = right
28
+ super()
29
+ end
14
30
 
15
- # Create a binary operator.
16
- # @param [String] symbol
17
- # operator's symbol
18
- # @param [BasicModel] left
19
- # left operand
20
- # @param [BasicModel] right
21
- # right operand
22
- def initialize(symbol, left, right)
23
- @symbol = symbol
24
- @left = left
25
- @right = right
26
- super()
27
- end
28
-
29
- # Returns false because Message has complex form.
30
- # @return [Boolean]
31
- # false
32
- def atomic?
33
- false
34
- end
31
+ # Return false because Message has complex form.
32
+ #
33
+ # @return [Boolean]
34
+ # false
35
+ def atomic?
36
+ false
37
+ end
35
38
 
36
- # Returns true if the left or right expression includes variable.
37
- # @return [Boolean]
38
- # true if the left or right expression includes variable
39
- def include_variable?
40
- @left.include_variable? or @right.include_variable?
41
- end
39
+ # Return true if the left or right expression includes variable.
40
+ #
41
+ # @return [Boolean]
42
+ # true if the left or right expression includes variable
43
+ def include_variable?
44
+ @left.include_variable? or @right.include_variable?
45
+ end
42
46
 
43
- # @api private
44
- def pione_model_type
45
- @left.pione_model_type.method_interface[@symbol].output
46
- end
47
+ # @api private
48
+ def pione_model_type
49
+ @left.pione_model_type.method_interface[@symbol].output
50
+ end
47
51
 
48
- # Evaluates the application expression and returns application result.
49
- # @param [VariableTable] vtable
50
- # variable table for the evaluation
51
- # @return [BasicModel]
52
- # evaluation result object
53
- def eval(vtable)
54
- left = @left.eval(vtable)
55
- right = @right.eval(vtable)
56
- left.call_pione_method(@symbol, right)
57
- end
52
+ # Evaluate the application expression and returns application result.
53
+ #
54
+ # @param vtable [VariableTable]
55
+ # variable table for the evaluation
56
+ # @return [BasicModel]
57
+ # evaluation result object
58
+ def eval(vtable)
59
+ left = @left.eval(vtable)
60
+ right = @right.eval(vtable)
61
+ left.call_pione_method(@symbol, right)
62
+ end
58
63
 
59
- # @api private
60
- def textize
61
- "%s%s%s" % [@left.textize, @symbol.to_s, @right.textize]
62
- end
64
+ # @api private
65
+ def textize
66
+ "%s%s%s" % [@left.textize, @symbol.to_s, @right.textize]
67
+ end
63
68
 
64
- # @api private
65
- def ==(other)
66
- return false unless other.kind_of?(self.class)
67
- return false unless @symbol == other.symbol
68
- return false unless @left == other.left
69
- return false unless @right == other.right
70
- return true
71
- end
69
+ # @api private
70
+ def ==(other)
71
+ return false unless other.kind_of?(self.class)
72
+ return false unless @symbol == other.symbol
73
+ return false unless @left == other.left
74
+ return false unless @right == other.right
75
+ return true
76
+ end
72
77
 
73
- alias :eql? :"=="
78
+ alias :eql? :"=="
74
79
 
75
- # @api private
76
- def hash
77
- @symbol.hash + @left.hash + @right.hash
80
+ # @api private
81
+ def hash
82
+ @symbol.hash + @left.hash + @right.hash
83
+ end
78
84
  end
79
85
  end
80
86
  end
@@ -1,234 +1,245 @@
1
- module Pione::Model
2
- # ActionBlock represents content script of action.
3
- # @example
4
- # Action
5
- # echo "abc"
6
- # End
7
- # #=> ActionBlock.new(" echo \"abc\"")
8
- class ActionBlock < BasicModel
9
- attr_reader :content
10
-
11
- # Creates a action block.
12
- # @param [String] content
13
- # action content of shell script
14
- def initialize(content)
15
- @content = content
16
- super()
17
- end
18
-
19
- # Evaluates the object.
20
- # @param [VariableTable] vtable
21
- # variable table for evaluation
22
- # @return [BasicModel]
23
- # evaluation result
24
- def eval(vtable)
25
- self.class.new(vtable.expand(@content))
26
- end
27
-
28
- # Returns true if the content includes variables.
29
- # @return [Boolean]
30
- # true if the content includes variables
31
- def include_variable?
32
- return VariableTable.check_include_variable(@content)
33
- end
1
+ module Pione
2
+ module Model
3
+ # ActionBlock represents content script of action.
4
+ #
5
+ # @example
6
+ # Action
7
+ # echo "abc"
8
+ # End
9
+ # #=> ActionBlock.new(" echo \"abc\"")
10
+ class ActionBlock < BasicModel
11
+ attr_reader :content
12
+
13
+ # Create an action block.
14
+ #
15
+ # @param content [String]
16
+ # action content of shell script
17
+ def initialize(content)
18
+ @content = content
19
+ super()
20
+ end
34
21
 
35
- # @api private
36
- def textize
37
- "action_block(\"#{@content}\")"
38
- end
22
+ # Evaluate the block. Variables of the content is expanded by the variable
23
+ # table.
24
+ #
25
+ # @param vtable [VariableTable]
26
+ # variable table for evaluation
27
+ # @return [BasicModel]
28
+ # evaluation result
29
+ def eval(vtable)
30
+ self.class.new(vtable.expand(@content))
31
+ end
39
32
 
40
- # @api private
41
- def ==(other)
42
- return false unless other.kind_of?(self.class)
43
- @content == other.content
44
- end
33
+ # Return true if the content includes variables.
34
+ #
35
+ # @return [Boolean]
36
+ # true if the content includes variables
37
+ def include_variable?
38
+ return VariableTable.check_include_variable(@content)
39
+ end
45
40
 
46
- alias :eql? :==
41
+ # @api private
42
+ def textize
43
+ "action_block(\"#{@content}\")"
44
+ end
47
45
 
48
- # @api private
49
- def hash
50
- @content.hash
51
- end
52
- end
46
+ # @api private
47
+ def ==(other)
48
+ return false unless other.kind_of?(self.class)
49
+ @content == other.content
50
+ end
51
+ alias :eql? :"=="
53
52
 
54
- # FlowBlock represents flow element sequence.
55
- # @example
56
- # Flow
57
- # rule Test1
58
- # rule Test2
59
- # rule Test3
60
- # End
61
- # #=> Block.new([ CallRule.new('Test1'),
62
- # CallRule.new('Test2'),
63
- # CallRule.new('Test3') ])
64
- class FlowBlock < BasicModel
65
- attr_reader :elements
66
-
67
- # Create a flow block.
68
- # @param [Array<BasicModel>] elements
69
- # flow elements
70
- def initialize(*elements)
71
- unless elements.all? {|elt| elt.kind_of?(BasicModel)}
72
- raise ArgumentError.new(elements)
73
- end
74
- @elements = elements
53
+ # @api private
54
+ def hash
55
+ @content.hash
56
+ end
75
57
  end
76
58
 
77
- # Evaluate each elements and return it.
59
+ # FlowBlock represents flow element sequence.
78
60
  #
79
- # @param [VariableTable] vtable
80
- # variable table for evaluation
81
- # @return [BasicModel]
82
- # evaluation result
83
- def eval(vtable)
84
- assignments = @elements.select{|elt| elt.kind_of?(Assignment)}
85
- conditional_blocks = @elements.select{|elt| elt.kind_of?(ConditionalBlock)}
86
- call_rules = @elements.select{|elt| elt.kind_of?(CallRule)}
87
-
88
- if not(assignments.empty?)
89
- assignments.each do |assignment|
90
- assignment.eval(vtable)
61
+ # @example
62
+ # Flow
63
+ # rule Test1
64
+ # rule Test2
65
+ # rule Test3
66
+ # End
67
+ # #=> Block.new([ CallRule.new('Test1'),
68
+ # CallRule.new('Test2'),
69
+ # CallRule.new('Test3') ])
70
+ class FlowBlock < BasicModel
71
+ attr_reader :elements
72
+
73
+ # Create a flow block.
74
+ #
75
+ # @param elements [Array<BasicModel>]
76
+ # flow elements
77
+ def initialize(*elements)
78
+ unless elements.all? {|elt| elt.kind_of?(BasicModel)}
79
+ raise ArgumentError.new(elements)
91
80
  end
92
- FlowBlock.new(*(conditional_blocks+call_rules)).eval(vtable)
93
- elsif not(conditional_blocks.empty?)
94
- exception = nil
95
- new_blocks = []
96
- next_blocks = []
97
- conditional_blocks.each do |block|
98
- begin
99
- new_blocks << block.eval(vtable)
100
- rescue UnboundVariableError => e
101
- exception = e
102
- next_blocks << block
81
+ @elements = elements
82
+ end
83
+
84
+ # Evaluate each elements and return it.
85
+ #
86
+ # @param vtable [VariableTable]
87
+ # variable table for evaluation
88
+ # @return [BasicModel]
89
+ # evaluation result
90
+ def eval(vtable)
91
+ assignments = @elements.select{|elt| elt.kind_of?(Assignment)}
92
+ conditional_blocks = @elements.select{|elt| elt.kind_of?(ConditionalBlock)}
93
+ call_rules = @elements.select{|elt| elt.kind_of?(CallRule)}
94
+
95
+ if not(assignments.empty?)
96
+ assignments.each do |assignment|
97
+ assignment.eval(vtable)
103
98
  end
99
+ FlowBlock.new(*(conditional_blocks+call_rules)).eval(vtable)
100
+ elsif not(conditional_blocks.empty?)
101
+ exception = nil
102
+ new_blocks = []
103
+ next_blocks = []
104
+ conditional_blocks.each do |block|
105
+ begin
106
+ new_blocks << block.eval(vtable)
107
+ rescue UnboundVariableError => e
108
+ exception = e
109
+ next_blocks << block
110
+ end
111
+ end
112
+ # fail to evaluate conditional blocks
113
+ if conditional_blocks == next_blocks
114
+ raise exception
115
+ end
116
+ # next
117
+ elements = new_blocks.inject([]){|elts, block| elts += block.elements}
118
+ FlowBlock.new(*(elements + next_blocks + call_rules)).eval(vtable)
119
+ else
120
+ FlowBlock.new(*call_rules.map{|call_rule| call_rule.eval(vtable)})
104
121
  end
105
- # fail to evaluate conditional blocks
106
- if conditional_blocks == next_blocks
107
- raise exception
108
- end
109
- # next
110
- elements = new_blocks.inject([]){|elts, block| elts += block.elements}
111
- FlowBlock.new(*(elements + next_blocks + call_rules)).eval(vtable)
112
- else
113
- FlowBlock.new(*call_rules.map{|call_rule| call_rule.eval(vtable)})
114
122
  end
115
- end
116
123
 
117
- # Returns true if the elements include variables.
118
- # @return [Boolean]
119
- # true if the elements include variables
120
- def include_variable?
121
- @elements.any?{|elt| elt.include_variable?}
122
- end
123
-
124
- # @api private
125
- def textize
126
- "flow_block(%s)" % [@elements.map{|elt| elt.textize}.join(",")]
127
- end
128
-
129
- # @api private
130
- def ==(other)
131
- return false unless other.kind_of?(self.class)
132
- @elements == other.elements
133
- end
124
+ # Return true if the elements include variables.
125
+ #
126
+ # @return [Boolean]
127
+ # true if the elements include variables
128
+ def include_variable?
129
+ @elements.any?{|elt| elt.include_variable?}
130
+ end
134
131
 
135
- alias :eql? :==
132
+ # @api private
133
+ def textize
134
+ "flow_block(%s)" % [@elements.map{|elt| elt.textize}.join(",")]
135
+ end
136
136
 
137
- # @api private
138
- def hash
139
- @elements.hash
140
- end
141
- end
137
+ # @api private
138
+ def ==(other)
139
+ return false unless other.kind_of?(self.class)
140
+ @elements == other.elements
141
+ end
142
+ alias :eql? :"=="
142
143
 
143
- # ConditionalBlock represents conditional flow applications.
144
- # @example
145
- # # if statement
146
- # if $X == "a"
147
- # rule Test1
148
- # else
149
- # rule Test2
150
- # end
151
- # #=> ConditionalBlock.new(
152
- # BinaryOperator::Equals.new(Variable.new('X'), 'a'),
153
- # { true => [CallRule.new('Test1')],
154
- # :else => [CallRule.new('Test2')] })
155
- # @example
156
- # # case statement
157
- # case $X
158
- # when "a"
159
- # rule Test1
160
- # when "b"
161
- # rule Test2
162
- # else
163
- # rule Test3
164
- # end
165
- # # => ConditionalBlock.new(
166
- # Variable.new('X'),
167
- # { 'a' => FlowBlock.new(CallRule.new('Test1')),
168
- # 'b' => FlowBlock.new(CallRule.new('Test2')),
169
- # :else => FlowBlock.new(CallRule.new('Test3')) })
170
- class ConditionalBlock < BasicModel
171
- attr_reader :condition
172
- attr_reader :blocks
173
-
174
- # Creates a conditional block.
175
- # @param [BasicModel] condition
176
- # condition value
177
- # @param [Hash{BasicModel => FlowBlock}] blocks
178
- # condition key and block
179
- def initialize(condition, blocks={})
180
- unless blocks.all?{|key,val|
181
- (key.kind_of?(BasicModel) or key == :else) &&
182
- val.kind_of?(FlowBlock)
183
- }
184
- raise ArgumentError.new(blocks)
185
- end
186
- @condition = condition
187
- @blocks = blocks
144
+ # @api private
145
+ def hash
146
+ @elements.hash
147
+ end
188
148
  end
189
149
 
190
- # Evaluates the condition and returns the flow block.
191
- # @param [VariableTable] vtable
192
- # variable table for evaluation
193
- # @return [BasicModel]
194
- # evaluation result
195
- def eval(vtable)
196
- value = @condition.eval(vtable)
197
- if block = @blocks.find {|key, _| key == value}
198
- return block[1].eval(vtable)
199
- elsif block = @blocks[:else]
200
- return block.eval(vtable)
201
- else
202
- return FlowBlock.new
150
+ # ConditionalBlock represents conditional flow applications.
151
+ #
152
+ # @example
153
+ # # if statement
154
+ # if $X == "a"
155
+ # rule Test1
156
+ # else
157
+ # rule Test2
158
+ # end
159
+ # #=> ConditionalBlock.new(
160
+ # BinaryOperator::Equals.new(Variable.new('X'), 'a'),
161
+ # { true => [CallRule.new('Test1')],
162
+ # :else => [CallRule.new('Test2')] })
163
+ # @example
164
+ # # case statement
165
+ # case $X
166
+ # when "a"
167
+ # rule Test1
168
+ # when "b"
169
+ # rule Test2
170
+ # else
171
+ # rule Test3
172
+ # end
173
+ # # => ConditionalBlock.new(
174
+ # Variable.new('X'),
175
+ # { 'a' => FlowBlock.new(CallRule.new('Test1')),
176
+ # 'b' => FlowBlock.new(CallRule.new('Test2')),
177
+ # :else => FlowBlock.new(CallRule.new('Test3')) })
178
+ class ConditionalBlock < BasicModel
179
+ attr_reader :condition
180
+ attr_reader :blocks
181
+
182
+ # Create a conditional block.
183
+ #
184
+ # @param condition [BasicModel]
185
+ # condition value
186
+ # @param blocks [Hash{BasicModel => FlowBlock}]
187
+ # condition key and block
188
+ def initialize(condition, blocks={})
189
+ unless blocks.all?{|key,val|
190
+ (key.kind_of?(BasicModel) or key == :else) &&
191
+ val.kind_of?(FlowBlock)
192
+ }
193
+ raise ArgumentError.new(blocks)
194
+ end
195
+ @condition = condition
196
+ @blocks = blocks
203
197
  end
204
- end
205
198
 
206
- # Returns ture if blocks include variables.
207
- # @return [Boolean]
208
- # ture if blocks include variables
209
- def include_variable?
210
- @blocks.values.any?{|block| block.include_variable?}
211
- end
199
+ # Evaluate the condition and returns the flow block.
200
+ #
201
+ # @param vtable [VariableTable]
202
+ # variable table for evaluation
203
+ # @return [BasicModel]
204
+ # evaluation result
205
+ def eval(vtable)
206
+ value = @condition.eval(vtable)
207
+ if block = @blocks.find {|key, _| key == value}
208
+ return block[1].eval(vtable)
209
+ elsif block = @blocks[:else]
210
+ return block.eval(vtable)
211
+ else
212
+ return FlowBlock.new
213
+ end
214
+ end
212
215
 
213
- # @api private
214
- def textize
215
- "conditional_block(%s,{%s})" % [
216
- @condition.textize,
217
- @blocks.map{|val, block| "%s=>%s" % [val,block]}.join(",")
218
- ]
219
- end
216
+ # Return ture if blocks include variables.
217
+ #
218
+ # @return [Boolean]
219
+ # ture if blocks include variables
220
+ def include_variable?
221
+ @blocks.values.any?{|block| block.include_variable?}
222
+ end
220
223
 
221
- # @api private
222
- def ==(other)
223
- return false unless other.kind_of?(self.class)
224
- @condition == other.condition && @blocks == other.blocks
225
- end
224
+ # @api private
225
+ def textize
226
+ "conditional_block(%s,{%s})" % [
227
+ @condition.textize,
228
+ @blocks.map{|val, block| "%s=>%s" % [val,block]}.join(",")
229
+ ]
230
+ end
226
231
 
227
- alias :eql? :==
232
+ # @api private
233
+ def ==(other)
234
+ return false unless other.kind_of?(self.class)
235
+ @condition == other.condition && @blocks == other.blocks
236
+ end
237
+ alias :eql? :"=="
228
238
 
229
- # @api private
230
- def hash
231
- @condition.hash + @blocks.hash
239
+ # @api private
240
+ def hash
241
+ @condition.hash + @blocks.hash
242
+ end
232
243
  end
233
244
  end
234
245
  end