tp_plus 0.0.77 → 0.0.87

Sign up to get free protection for your applications and to get access to all the features.
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