tp_plus 0.0.77 → 0.0.87

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +87 -84
  3. data/Rakefile +35 -35
  4. data/bin/tpp +92 -92
  5. data/lib/tp_plus/interpreter.rb +152 -152
  6. data/lib/tp_plus/namespace.rb +66 -66
  7. data/lib/tp_plus/nodes/abort_node.rb +9 -9
  8. data/lib/tp_plus/nodes/acc_node.rb +19 -19
  9. data/lib/tp_plus/nodes/address_node.rb +22 -22
  10. data/lib/tp_plus/nodes/argument_node.rb +20 -20
  11. data/lib/tp_plus/nodes/assignment_node.rb +52 -45
  12. data/lib/tp_plus/nodes/base_node.rb +9 -0
  13. data/lib/tp_plus/nodes/call_node.rb +34 -34
  14. data/lib/tp_plus/nodes/case_condition_node.rb +26 -26
  15. data/lib/tp_plus/nodes/case_node.rb +33 -33
  16. data/lib/tp_plus/nodes/comment_node.rb +18 -22
  17. data/lib/tp_plus/nodes/conditional_node.rb +60 -60
  18. data/lib/tp_plus/nodes/definition_node.rb +22 -22
  19. data/lib/tp_plus/nodes/digit_node.rb +22 -22
  20. data/lib/tp_plus/nodes/empty_stmt_node.rb +9 -9
  21. data/lib/tp_plus/nodes/eval_node.rb +13 -13
  22. data/lib/tp_plus/nodes/expression_node.rb +68 -68
  23. data/lib/tp_plus/nodes/for_node.rb +20 -20
  24. data/lib/tp_plus/nodes/header_node.rb +27 -27
  25. data/lib/tp_plus/nodes/indirect_node.rb +27 -51
  26. data/lib/tp_plus/nodes/inline_conditional_node.rb +36 -40
  27. data/lib/tp_plus/nodes/io_method_node.rb +55 -55
  28. data/lib/tp_plus/nodes/io_node.rb +31 -31
  29. data/lib/tp_plus/nodes/jpos_node.rb +13 -0
  30. data/lib/tp_plus/nodes/jump_node.rb +23 -23
  31. data/lib/tp_plus/nodes/label_definition_node.rb +21 -21
  32. data/lib/tp_plus/nodes/lpos_node.rb +13 -0
  33. data/lib/tp_plus/nodes/motion_node.rb +62 -62
  34. data/lib/tp_plus/nodes/namespace_node.rb +16 -16
  35. data/lib/tp_plus/nodes/namespaced_var_node.rb +38 -38
  36. data/lib/tp_plus/nodes/numreg_node.rb +26 -26
  37. data/lib/tp_plus/nodes/offset_node.rb +27 -27
  38. data/lib/tp_plus/nodes/operator_node.rb +80 -78
  39. data/lib/tp_plus/nodes/paren_expression_node.rb +17 -17
  40. data/lib/tp_plus/nodes/pause_node.rb +9 -9
  41. data/lib/tp_plus/nodes/position_data_node.rb +66 -66
  42. data/lib/tp_plus/nodes/position_node.rb +26 -26
  43. data/lib/tp_plus/nodes/posreg_node.rb +64 -64
  44. data/lib/tp_plus/nodes/raise_node.rb +13 -13
  45. data/lib/tp_plus/nodes/real_node.rb +27 -27
  46. data/lib/tp_plus/nodes/return_node.rb +9 -0
  47. data/lib/tp_plus/nodes/set_skip_node.rb +14 -14
  48. data/lib/tp_plus/nodes/skip_node.rb +22 -22
  49. data/lib/tp_plus/nodes/speed_node.rb +29 -29
  50. data/lib/tp_plus/nodes/string_node.rb +13 -13
  51. data/lib/tp_plus/nodes/string_register_node.rb +26 -26
  52. data/lib/tp_plus/nodes/termination_node.rb +23 -23
  53. data/lib/tp_plus/nodes/terminator_node.rb +16 -16
  54. data/lib/tp_plus/nodes/time_node.rb +24 -24
  55. data/lib/tp_plus/nodes/timer_method_node.rb +33 -37
  56. data/lib/tp_plus/nodes/timer_node.rb +16 -16
  57. data/lib/tp_plus/nodes/unary_expression_node.rb +39 -0
  58. data/lib/tp_plus/nodes/units_node.rb +20 -20
  59. data/lib/tp_plus/nodes/use_node.rb +21 -21
  60. data/lib/tp_plus/nodes/user_alarm_node.rb +16 -16
  61. data/lib/tp_plus/nodes/var_method_node.rb +23 -23
  62. data/lib/tp_plus/nodes/var_node.rb +39 -39
  63. data/lib/tp_plus/nodes/vision_register_node.rb +22 -22
  64. data/lib/tp_plus/nodes/wait_for_node.rb +50 -54
  65. data/lib/tp_plus/nodes/wait_until_node.rb +61 -65
  66. data/lib/tp_plus/nodes/while_node.rb +40 -42
  67. data/lib/tp_plus/parser.rb +1749 -1697
  68. data/lib/tp_plus/scanner.rb +295 -295
  69. data/lib/tp_plus/token.rb +101 -98
  70. data/lib/tp_plus/version.rb +3 -3
  71. data/lib/tp_plus.rb +72 -67
  72. data/test/test_helper.rb +5 -5
  73. data/test/tp_plus/test_interpreter.rb +1372 -1329
  74. data/test/tp_plus/test_parser.rb +502 -502
  75. data/test/tp_plus/test_scanner.rb +591 -577
  76. data/tp_plus.gemspec +31 -31
  77. metadata +8 -3
@@ -1,152 +1,152 @@
1
- require_relative 'parser'
2
-
3
- module TPPlus
4
- class Interpreter
5
- attr_accessor :line_count, :nodes, :position_data, :header_data
6
- attr_reader :labels, :variables, :constants, :namespaces, :source_line_count
7
- def initialize
8
- @line_count = 0
9
- @nodes = []
10
- @labels = {}
11
- @namespaces = {}
12
- @variables = {}
13
- @constants = {}
14
- @position_data = {}
15
- @header_data = {}
16
- @current_label = 99
17
- end
18
-
19
- def load_environment(string)
20
- scanner = TPPlus::Scanner.new
21
- parser = TPPlus::Parser.new(scanner, self)
22
- scanner.scan_setup(string)
23
- parser.parse
24
- eval
25
- rescue RuntimeError => e
26
- raise "Runtime error in environment on line #{@source_line_count}:\n#{e}"
27
- end
28
-
29
- def next_label
30
- @current_label += 1
31
- end
32
-
33
- def add_namespace(name, block)
34
- if @namespaces[name.to_sym].nil?
35
- @namespaces[name.to_sym] = TPPlus::Namespace.new(name, block)
36
- else
37
- @namespaces[name.to_sym].reopen!(block)
38
- end
39
- end
40
-
41
- def add_label(identifier)
42
- raise "Label @#{identifier} already defined" if @labels[identifier.to_sym]
43
- @labels[identifier.to_sym] = next_label
44
- end
45
-
46
- def add_var(identifier, node)
47
- raise "Variable #{identifier} already defined" if @variables[identifier.to_sym]
48
-
49
- @variables[identifier.to_sym] = node
50
- node.comment = identifier
51
- end
52
-
53
- def add_constant(identifier, node)
54
- raise "Constant #{identifier} already defined" if @constants[identifier.to_sym]
55
-
56
- @constants[identifier.to_sym] = node
57
- end
58
-
59
- def get_namespace(identifier)
60
- if ns = @namespaces[identifier.to_sym]
61
- return ns
62
- end
63
-
64
- false
65
- end
66
-
67
- def get_var(identifier)
68
- raise "Variable (#{identifier}) not defined" if @variables[identifier.to_sym].nil?
69
-
70
- @variables[identifier.to_sym]
71
- end
72
-
73
- def get_constant(identifier)
74
- raise "Constant (#{identifier}) not defined" if @constants[identifier.to_sym].nil?
75
-
76
- @constants[identifier.to_sym]
77
- end
78
-
79
- def define_labels
80
- @nodes.select {|n| n.is_a? Nodes::LabelDefinitionNode}.each do |n|
81
- add_label(n.identifier)
82
- end
83
- end
84
-
85
- def pos_section
86
- return "" if @position_data.empty?
87
- return "" if @position_data[:positions].empty?
88
-
89
- @position_data[:positions].inject("") do |s,p|
90
- s << %(P[#{p[:id]}:"#{p[:comment]}"]{\n)
91
-
92
- p[:mask].each do |q|
93
- s << pos_return(q)
94
- end
95
-
96
- s << %(\n};\n)
97
- end
98
- end
99
-
100
- def pos_return(position_hash)
101
- s = ""
102
- if position_hash[:config].is_a?(Hash)
103
- s << %( GP#{position_hash[:group]}:
104
- UF : #{position_hash[:uframe]}, UT : #{position_hash[:utool]}, CONFIG : '#{position_hash[:config][:flip] ? 'F' : 'N'} #{position_hash[:config][:up] ? 'U' : 'D'} #{position_hash[:config][:top] ? 'T' : 'B'}, #{position_hash[:config][:turn_counts].join(', ')}',
105
- X = #{position_hash[:components][:x]} mm, Y = #{position_hash[:components][:y]} mm, Z = #{position_hash[:components][:z]} mm,
106
- W = #{position_hash[:components][:w]} deg, P = #{position_hash[:components][:p]} deg, R = #{position_hash[:components][:r]} deg)
107
- else
108
- s << %( GP#{position_hash[:group]}:
109
- UF : #{position_hash[:uframe]}, UT : #{position_hash[:utool]})
110
- if position_hash[:components].is_a?(Hash)
111
- position_hash[:components].each_with_index do |key, joint|
112
- s << %(, \n)
113
- s << %(\tJ#{key} = #{joint[1]} deg)
114
- end
115
- s << %(\n)
116
- end
117
- end
118
-
119
- return s
120
- end
121
-
122
- def eval
123
- s = ""
124
- last_node = nil
125
-
126
- define_labels
127
-
128
- @source_line_count = 0
129
-
130
- @nodes.each do |n|
131
- @source_line_count += 1 unless n.is_a?(Nodes::TerminatorNode) && !last_node.is_a?(Nodes::TerminatorNode)
132
- raise if n.is_a?(String)
133
-
134
- res = n.eval(self)
135
-
136
- # preserve whitespace
137
- if n.is_a?(Nodes::TerminatorNode) && last_node.is_a?(Nodes::TerminatorNode)
138
- s += " ;\n"
139
- end
140
- last_node = n
141
- # end preserve whitespace
142
-
143
- next if res.nil?
144
-
145
- s += "#{res} ;\n"
146
- end
147
- s
148
- rescue RuntimeError => e
149
- raise "Runtime error on line #{@source_line_count}:\n#{e}"
150
- end
151
- end
152
- end
1
+ require_relative 'parser'
2
+
3
+ module TPPlus
4
+ class Interpreter
5
+ attr_accessor :line_count, :nodes, :position_data, :header_data
6
+ attr_reader :labels, :variables, :constants, :namespaces, :source_line_count
7
+ def initialize
8
+ @line_count = 0
9
+ @nodes = []
10
+ @labels = {}
11
+ @namespaces = {}
12
+ @variables = {}
13
+ @constants = {}
14
+ @position_data = {}
15
+ @header_data = {}
16
+ @current_label = 99
17
+ end
18
+
19
+ def load_environment(string)
20
+ scanner = TPPlus::Scanner.new
21
+ parser = TPPlus::Parser.new(scanner, self)
22
+ scanner.scan_setup(string)
23
+ parser.parse
24
+ eval
25
+ rescue RuntimeError => e
26
+ raise "Runtime error in environment on line #{@source_line_count}:\n#{e}"
27
+ end
28
+
29
+ def next_label
30
+ @current_label += 1
31
+ end
32
+
33
+ def add_namespace(name, block)
34
+ if @namespaces[name.to_sym].nil?
35
+ @namespaces[name.to_sym] = TPPlus::Namespace.new(name, block)
36
+ else
37
+ @namespaces[name.to_sym].reopen!(block)
38
+ end
39
+ end
40
+
41
+ def add_label(identifier)
42
+ raise "Label @#{identifier} already defined" if @labels[identifier.to_sym]
43
+ @labels[identifier.to_sym] = next_label
44
+ end
45
+
46
+ def add_var(identifier, node)
47
+ raise "Variable #{identifier} already defined" if @variables[identifier.to_sym]
48
+
49
+ @variables[identifier.to_sym] = node
50
+ node.comment = identifier
51
+ end
52
+
53
+ def add_constant(identifier, node)
54
+ raise "Constant #{identifier} already defined" if @constants[identifier.to_sym]
55
+
56
+ @constants[identifier.to_sym] = node
57
+ end
58
+
59
+ def get_namespace(identifier)
60
+ if ns = @namespaces[identifier.to_sym]
61
+ return ns
62
+ end
63
+
64
+ false
65
+ end
66
+
67
+ def get_var(identifier)
68
+ raise "Variable (#{identifier}) not defined" if @variables[identifier.to_sym].nil?
69
+
70
+ @variables[identifier.to_sym]
71
+ end
72
+
73
+ def get_constant(identifier)
74
+ raise "Constant (#{identifier}) not defined" if @constants[identifier.to_sym].nil?
75
+
76
+ @constants[identifier.to_sym]
77
+ end
78
+
79
+ def define_labels
80
+ @nodes.select {|n| n.is_a? Nodes::LabelDefinitionNode}.each do |n|
81
+ add_label(n.identifier)
82
+ end
83
+ end
84
+
85
+ def pos_section
86
+ return "" if @position_data.empty?
87
+ return "" if @position_data[:positions].empty?
88
+
89
+ @position_data[:positions].inject("") do |s,p|
90
+ s << %(P[#{p[:id]}:"#{p[:comment]}"]{\n)
91
+
92
+ p[:mask].each do |q|
93
+ s << pos_return(q)
94
+ end
95
+
96
+ s << %(\n};\n)
97
+ end
98
+ end
99
+
100
+ def pos_return(position_hash)
101
+ s = ""
102
+ if position_hash[:config].is_a?(Hash)
103
+ s << %( GP#{position_hash[:group]}:
104
+ UF : #{position_hash[:uframe]}, UT : #{position_hash[:utool]}, CONFIG : '#{position_hash[:config][:flip] ? 'F' : 'N'} #{position_hash[:config][:up] ? 'U' : 'D'} #{position_hash[:config][:top] ? 'T' : 'B'}, #{position_hash[:config][:turn_counts].join(', ')}',
105
+ X = #{position_hash[:components][:x]} mm, Y = #{position_hash[:components][:y]} mm, Z = #{position_hash[:components][:z]} mm,
106
+ W = #{position_hash[:components][:w]} deg, P = #{position_hash[:components][:p]} deg, R = #{position_hash[:components][:r]} deg)
107
+ else
108
+ s << %( GP#{position_hash[:group]}:
109
+ UF : #{position_hash[:uframe]}, UT : #{position_hash[:utool]})
110
+ if position_hash[:components].is_a?(Hash)
111
+ position_hash[:components].each_with_index do |key, joint|
112
+ s << %(, \n)
113
+ s << %(\tJ#{key} = #{joint[1]} deg)
114
+ end
115
+ s << %(\n)
116
+ end
117
+ end
118
+
119
+ return s
120
+ end
121
+
122
+ def eval
123
+ s = ""
124
+ last_node = nil
125
+
126
+ define_labels
127
+
128
+ @source_line_count = 0
129
+
130
+ @nodes.each do |n|
131
+ @source_line_count += 1 unless n.is_a?(Nodes::TerminatorNode) && !last_node.is_a?(Nodes::TerminatorNode)
132
+ raise if n.is_a?(String)
133
+
134
+ res = n.eval(self)
135
+
136
+ # preserve whitespace
137
+ if n.is_a?(Nodes::TerminatorNode) && last_node.is_a?(Nodes::TerminatorNode)
138
+ s += " ;\n"
139
+ end
140
+ last_node = n
141
+ # end preserve whitespace
142
+
143
+ next if res.nil?
144
+
145
+ s += "#{res} ;\n"
146
+ end
147
+ s
148
+ rescue RuntimeError => e
149
+ raise "Runtime error on line #{@source_line_count}:\n#{e}"
150
+ end
151
+ end
152
+ end
@@ -1,66 +1,66 @@
1
- module TPPlus
2
- class Namespace
3
- def initialize(name, block)
4
- @name = name
5
- @block = block
6
- @namespaces = {}
7
- @variables = {}
8
- @constants = {}
9
-
10
- define!
11
- end
12
-
13
- def define!
14
- @block.flatten.select {|n| [TPPlus::Nodes::DefinitionNode, TPPlus::Nodes::NamespaceNode].include? n.class }.each do |node|
15
- node.eval(self)
16
- end
17
- end
18
-
19
- def reopen!(block)
20
- @block = block
21
- define!
22
- end
23
-
24
- def add_constant(identifier, node)
25
- raise "Constant (#{identifier}) already defined within namespace #{@name}" unless @constants[identifier.to_sym].nil?
26
-
27
- @constants[identifier.to_sym] = node
28
- end
29
-
30
- def add_namespace(identifier, block)
31
- if @namespaces[identifier.to_sym].nil?
32
- @namespaces[identifier.to_sym] = TPPlus::Namespace.new("#{@name} #{identifier}", block)
33
- else
34
- @namespaces[identifier.to_sym].reopen!(block)
35
- end
36
- end
37
-
38
- def add_var(identifier, node)
39
- raise "Variable (#{identifier}) already defined within namespace #{@name}" unless @variables[identifier.to_sym].nil?
40
-
41
- @variables[identifier.to_sym] = node
42
- node.comment = "#{@name} #{identifier}"
43
- end
44
-
45
- def get_constant(identifier)
46
- raise "Constant (#{identifier}) not defined within namespace #{@name}" if @constants[identifier.to_sym].nil?
47
-
48
- @constants[identifier.to_sym]
49
- end
50
-
51
- def get_var(identifier)
52
- return get_constant(identifier) if identifier.upcase == identifier
53
- raise "Variable (#{identifier}) not defined within namespace #{@name}" if @variables[identifier.to_sym].nil?
54
-
55
- @variables[identifier.to_sym]
56
- end
57
-
58
- def get_namespace(identifier)
59
- if ns = @namespaces[identifier.to_sym]
60
- return ns
61
- end
62
-
63
- false
64
- end
65
- end
66
- end
1
+ module TPPlus
2
+ class Namespace
3
+ def initialize(name, block)
4
+ @name = name
5
+ @block = block
6
+ @namespaces = {}
7
+ @variables = {}
8
+ @constants = {}
9
+
10
+ define!
11
+ end
12
+
13
+ def define!
14
+ @block.flatten.select {|n| [TPPlus::Nodes::DefinitionNode, TPPlus::Nodes::NamespaceNode].include? n.class }.each do |node|
15
+ node.eval(self)
16
+ end
17
+ end
18
+
19
+ def reopen!(block)
20
+ @block = block
21
+ define!
22
+ end
23
+
24
+ def add_constant(identifier, node)
25
+ raise "Constant (#{identifier}) already defined within namespace #{@name}" unless @constants[identifier.to_sym].nil?
26
+
27
+ @constants[identifier.to_sym] = node
28
+ end
29
+
30
+ def add_namespace(identifier, block)
31
+ if @namespaces[identifier.to_sym].nil?
32
+ @namespaces[identifier.to_sym] = TPPlus::Namespace.new("#{@name} #{identifier}", block)
33
+ else
34
+ @namespaces[identifier.to_sym].reopen!(block)
35
+ end
36
+ end
37
+
38
+ def add_var(identifier, node)
39
+ raise "Variable (#{identifier}) already defined within namespace #{@name}" unless @variables[identifier.to_sym].nil?
40
+
41
+ @variables[identifier.to_sym] = node
42
+ node.comment = "#{@name} #{identifier}"
43
+ end
44
+
45
+ def get_constant(identifier)
46
+ raise "Constant (#{identifier}) not defined within namespace #{@name}" if @constants[identifier.to_sym].nil?
47
+
48
+ @constants[identifier.to_sym]
49
+ end
50
+
51
+ def get_var(identifier)
52
+ return get_constant(identifier) if identifier.upcase == identifier
53
+ raise "Variable (#{identifier}) not defined within namespace #{@name}" if @variables[identifier.to_sym].nil?
54
+
55
+ @variables[identifier.to_sym]
56
+ end
57
+
58
+ def get_namespace(identifier)
59
+ if ns = @namespaces[identifier.to_sym]
60
+ return ns
61
+ end
62
+
63
+ false
64
+ end
65
+ end
66
+ end
@@ -1,9 +1,9 @@
1
- module TPPlus
2
- module Nodes
3
- class AbortNode
4
- def eval(context)
5
- "ABORT"
6
- end
7
- end
8
- end
9
- end
1
+ module TPPlus
2
+ module Nodes
3
+ class AbortNode < BaseNode
4
+ def eval(context)
5
+ "ABORT"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -1,19 +1,19 @@
1
- module TPPlus
2
- module Nodes
3
- class AccNode
4
- def initialize(value)
5
- @value = value
6
- end
7
-
8
- def eval(context)
9
- val = @value.eval(context)
10
- case val
11
- when Integer
12
- "ACC#{val}"
13
- else
14
- "ACC #{val}"
15
- end
16
- end
17
- end
18
- end
19
- end
1
+ module TPPlus
2
+ module Nodes
3
+ class AccNode < BaseNode
4
+ def initialize(value)
5
+ @value = value
6
+ end
7
+
8
+ def eval(context)
9
+ val = @value.eval(context)
10
+ case val
11
+ when Integer
12
+ "ACC#{val}"
13
+ else
14
+ "ACC #{val}"
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,22 +1,22 @@
1
- module TPPlus
2
- module Nodes
3
- class AddressNode
4
- attr_reader :id
5
- def initialize(id)
6
- @id = id
7
- end
8
-
9
- def requires_mixed_logic?(context)
10
- false
11
- end
12
-
13
- def node(context)
14
- context.get_var(@id)
15
- end
16
-
17
- def eval(context,options={})
18
- node(context).id.to_s
19
- end
20
- end
21
- end
22
- end
1
+ module TPPlus
2
+ module Nodes
3
+ class AddressNode < BaseNode
4
+ attr_reader :id
5
+ def initialize(id)
6
+ @id = id
7
+ end
8
+
9
+ def requires_mixed_logic?(context)
10
+ false
11
+ end
12
+
13
+ def node(context)
14
+ context.get_var(@id)
15
+ end
16
+
17
+ def eval(context,options={})
18
+ node(context).id.to_s
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,20 +1,20 @@
1
- module TPPlus
2
- module Nodes
3
- class ArgumentNode
4
- attr_accessor :comment
5
- attr_reader :id
6
- def initialize(id)
7
- @id = id
8
- @comment = comment
9
- end
10
-
11
- def requires_mixed_logic?(context)
12
- true
13
- end
14
-
15
- def eval(context,options={})
16
- "AR[#{@id}]"
17
- end
18
- end
19
- end
20
- end
1
+ module TPPlus
2
+ module Nodes
3
+ class ArgumentNode < BaseNode
4
+ attr_accessor :comment
5
+ attr_reader :id
6
+ def initialize(id)
7
+ @id = id
8
+ @comment = comment
9
+ end
10
+
11
+ def requires_mixed_logic?(context)
12
+ true
13
+ end
14
+
15
+ def eval(context,options={})
16
+ "AR[#{@id}]"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,45 +1,52 @@
1
- module TPPlus
2
- module Nodes
3
- class AssignmentNode
4
- attr_reader :identifier, :assignable
5
- def initialize(identifier,assignable)
6
- @identifier = identifier
7
- @assignable = assignable
8
- end
9
-
10
- def assignable_string(context,options={})
11
- if @assignable.is_a?(ExpressionNode)
12
- options[:mixed_logic] = true if @assignable.contains_expression?
13
- options[:mixed_logic] = true if @assignable.op.requires_mixed_logic?(context)
14
- options[:mixed_logic] = true if @assignable.op.boolean?
15
- options[:mixed_logic] = true if @assignable.boolean_result?
16
- else
17
- options[:mixed_logic] = true if @assignable.requires_mixed_logic?(context)
18
- options[:mixed_logic] = true if @identifier.requires_mixed_logic?(context)
19
- end
20
-
21
- if options[:mixed_logic]
22
- "(#{@assignable.eval(context)})"
23
- else
24
- @assignable.eval(context)
25
- end
26
- end
27
-
28
- def requires_mixed_logic?(context)
29
- true
30
- end
31
-
32
- def can_be_inlined?
33
- true
34
- end
35
-
36
- def identifier_string(context)
37
- @identifier.eval(context)
38
- end
39
-
40
- def eval(context,options={})
41
- "#{identifier_string(context)}=#{assignable_string(context,options)}"
42
- end
43
- end
44
- end
45
- end
1
+ module TPPlus
2
+ module Nodes
3
+ class AssignmentNode < BaseNode
4
+ attr_reader :identifier, :assignable
5
+ def initialize(identifier,assignable)
6
+ @identifier = identifier
7
+ @assignable = assignable
8
+ end
9
+
10
+ def assignable_string(context,options={})
11
+ if @assignable.is_a?(ExpressionNode)
12
+ options[:mixed_logic] = true if @assignable.contains_expression?
13
+ options[:mixed_logic] = true if @assignable.op.requires_mixed_logic?(context)
14
+ options[:mixed_logic] = true if @assignable.op.boolean?
15
+ options[:mixed_logic] = true if @assignable.boolean_result?
16
+ # this is a hack that fixes issue #12
17
+ # PR[a]=PR[b]+PR[c]+PR[d] (no parens)
18
+ if @identifier.is_a? VarNode
19
+ options[:mixed_logic] = false if @identifier.target_node(context).is_a? PosregNode
20
+ end
21
+ elsif @assignable.is_a?(VarNode)
22
+ options[:mixed_logic] = true if @assignable.target_node(context).is_a? IONode
23
+ else
24
+ options[:mixed_logic] = true if @assignable.requires_mixed_logic?(context)
25
+ options[:mixed_logic] = true if @identifier.requires_mixed_logic?(context)
26
+ end
27
+
28
+ if options[:mixed_logic]
29
+ "(#{@assignable.eval(context)})"
30
+ else
31
+ @assignable.eval(context)
32
+ end
33
+ end
34
+
35
+ def requires_mixed_logic?(context)
36
+ true
37
+ end
38
+
39
+ def can_be_inlined?
40
+ true
41
+ end
42
+
43
+ def identifier_string(context)
44
+ @identifier.eval(context)
45
+ end
46
+
47
+ def eval(context,options={})
48
+ "#{identifier_string(context)}=#{assignable_string(context,options)}"
49
+ end
50
+ end
51
+ end
52
+ end