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
@@ -0,0 +1,39 @@
1
+ module TPPlus
2
+ module Nodes
3
+ class UnaryExpressionNode < BaseNode
4
+ attr_reader :op, :x
5
+ def initialize(op, x)
6
+ @op = OperatorNode.new(op)
7
+ @x = x
8
+ end
9
+
10
+ def grouped?
11
+ false
12
+ end
13
+
14
+ def requires_mixed_logic?(context)
15
+ true
16
+ end
17
+
18
+ def contains_expression?
19
+ false
20
+ end
21
+
22
+ def boolean_result?
23
+ false
24
+ end
25
+
26
+ def eval(context,options={})
27
+ if options[:opposite]
28
+ options[:opposite] = false #VarNode.eval() with options[:opposite] will add a !
29
+ @x.eval(context, options)
30
+ elsif options[:disable_mixed_logic]
31
+ options[:disable_mixed_logic] = false
32
+ "#{@x.eval(context, options)}=OFF"
33
+ else
34
+ "#{@op.eval(context, options)}#{@x.eval(context, options)}"
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,20 +1,20 @@
1
- module TPPlus
2
- module Nodes
3
- class UnitsNode
4
- def initialize(s)
5
- @s = s
6
- end
7
-
8
- def eval(context)
9
- case @s
10
- when "mm/s"
11
- "mm/sec"
12
- when "%"
13
- "%"
14
- else
15
- raise "Unknown unit: #{@s}"
16
- end
17
- end
18
- end
19
- end
20
- end
1
+ module TPPlus
2
+ module Nodes
3
+ class UnitsNode < BaseNode
4
+ def initialize(s)
5
+ @s = s
6
+ end
7
+
8
+ def eval(context)
9
+ case @s
10
+ when "mm/s"
11
+ "mm/sec"
12
+ when "%"
13
+ "%"
14
+ else
15
+ raise "Unknown unit: #{@s}"
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,21 +1,21 @@
1
- module TPPlus
2
- module Nodes
3
- class UseNode
4
- def initialize(type, value)
5
- @type = type
6
- @value = value
7
- end
8
-
9
- def eval(context)
10
- case @type
11
- when "use_uframe"
12
- "UFRAME_NUM=#{@value.eval(context)}"
13
- when "use_utool"
14
- "UTOOL_NUM=#{@value.eval(context)}"
15
- when "use_payload"
16
- "PAYLOAD[#{@value.eval(context)}]"
17
- end
18
- end
19
- end
20
- end
21
- end
1
+ module TPPlus
2
+ module Nodes
3
+ class UseNode < BaseNode
4
+ def initialize(type, value)
5
+ @type = type
6
+ @value = value
7
+ end
8
+
9
+ def eval(context)
10
+ case @type
11
+ when "use_uframe"
12
+ "UFRAME_NUM=#{@value.eval(context)}"
13
+ when "use_utool"
14
+ "UTOOL_NUM=#{@value.eval(context)}"
15
+ when "use_payload"
16
+ "PAYLOAD[#{@value.eval(context)}]"
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,16 +1,16 @@
1
- module TPPlus
2
- module Nodes
3
- class UserAlarmNode
4
- attr_accessor :comment
5
- attr_reader :id
6
- def initialize(id)
7
- @id = id
8
- @comment = ""
9
- end
10
-
11
- def eval(context, options={})
12
- "UALM[#{@id}]"
13
- end
14
- end
15
- end
16
- end
1
+ module TPPlus
2
+ module Nodes
3
+ class UserAlarmNode < BaseNode
4
+ attr_accessor :comment
5
+ attr_reader :id
6
+ def initialize(id)
7
+ @id = id
8
+ @comment = ""
9
+ end
10
+
11
+ def eval(context, options={})
12
+ "UALM[#{@id}]"
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,23 +1,23 @@
1
- module TPPlus
2
- module Nodes
3
- class VarMethodNode
4
- attr_reader :identifier
5
- def initialize(identifier, method)
6
- @identifier = identifier
7
- @method = method || {}
8
- end
9
-
10
- def requires_mixed_logic?(context)
11
- node(context).requires_mixed_logic?(context)
12
- end
13
-
14
- def node(context)
15
- context.get_var(@identifier)
16
- end
17
-
18
- def eval(context,options={})
19
- node(context).eval(context,options.merge(@method))
20
- end
21
- end
22
- end
23
- end
1
+ module TPPlus
2
+ module Nodes
3
+ class VarMethodNode < BaseNode
4
+ attr_reader :identifier
5
+ def initialize(identifier, method)
6
+ @identifier = identifier
7
+ @method = method || {}
8
+ end
9
+
10
+ def requires_mixed_logic?(context)
11
+ node(context).requires_mixed_logic?(context)
12
+ end
13
+
14
+ def node(context)
15
+ context.get_var(@identifier)
16
+ end
17
+
18
+ def eval(context,options={})
19
+ node(context).eval(context,options.merge(@method))
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,39 +1,39 @@
1
- module TPPlus
2
- module Nodes
3
- class VarNode
4
- attr_reader :identifier
5
- def initialize(identifier)
6
- @identifier = identifier
7
- end
8
-
9
- def target_node(context)
10
- constant? ? context.get_constant(@identifier) : context.get_var(@identifier)
11
- end
12
-
13
- def constant?
14
- @identifier.upcase == @identifier
15
- end
16
-
17
- def requires_mixed_logic?(context)
18
- target_node(context).requires_mixed_logic?(context)
19
- end
20
-
21
- def with_parens(s, options)
22
- return s unless options[:as_condition]
23
-
24
- "(#{s})"
25
- end
26
-
27
- def eval(context,options={})
28
- return target_node(context).eval(context) if constant?
29
-
30
- s = ""
31
- if options[:opposite]
32
- s += "!"
33
- end
34
-
35
- with_parens(s + target_node(context).eval(context, options), options)
36
- end
37
- end
38
- end
39
- end
1
+ module TPPlus
2
+ module Nodes
3
+ class VarNode < BaseNode
4
+ attr_reader :identifier
5
+ def initialize(identifier)
6
+ @identifier = identifier
7
+ end
8
+
9
+ def target_node(context)
10
+ constant? ? context.get_constant(@identifier) : context.get_var(@identifier)
11
+ end
12
+
13
+ def constant?
14
+ @identifier.upcase == @identifier
15
+ end
16
+
17
+ def requires_mixed_logic?(context)
18
+ target_node(context).requires_mixed_logic?(context)
19
+ end
20
+
21
+ def with_parens(s, options)
22
+ return s unless options[:as_condition]
23
+
24
+ "(#{s})"
25
+ end
26
+
27
+ def eval(context,options={})
28
+ return target_node(context).eval(context) if constant?
29
+
30
+ s = ""
31
+ if options[:opposite]
32
+ s += "!"
33
+ end
34
+
35
+ with_parens(s + target_node(context).eval(context, options), options)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,22 +1,22 @@
1
- module TPPlus
2
- module Nodes
3
- class VisionRegisterNode
4
- attr_accessor :comment
5
- attr_reader :id
6
- def initialize(id)
7
- @id = id
8
- @comment = ""
9
- end
10
-
11
- def comment_string
12
- return "" if @comment == ""
13
-
14
- ":#{@comment}"
15
- end
16
-
17
- def eval(context,options={})
18
- "VR[#{@id}#{comment_string}]"
19
- end
20
- end
21
- end
22
- end
1
+ module TPPlus
2
+ module Nodes
3
+ class VisionRegisterNode < BaseNode
4
+ attr_accessor :comment
5
+ attr_reader :id
6
+ def initialize(id)
7
+ @id = id
8
+ @comment = ""
9
+ end
10
+
11
+ def comment_string
12
+ return "" if @comment == ""
13
+
14
+ ":#{@comment}"
15
+ end
16
+
17
+ def eval(context,options={})
18
+ "VR[#{@id}#{comment_string}]"
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,54 +1,50 @@
1
- module TPPlus
2
- module Nodes
3
- class WaitForNode
4
- def initialize(time, units)
5
- @time = time
6
- @units = units
7
- end
8
-
9
- def units_valid?
10
- ["s","ms"].include?(@units)
11
- end
12
-
13
- # 2 decimal places and remove leading 0s
14
- def time(context)
15
- if @time.eval(context).is_a?(String)
16
- case @units
17
- when "s"
18
- @time.eval(context)
19
- else
20
- raise "Invalid units"
21
- end
22
- else
23
- ("%.2f" % case @units
24
- when "s"
25
- @time.eval(context)
26
- when "ms"
27
- @time.eval(context).to_f / 1000
28
- end).sub(/^0+/, "") + "(sec)"
29
- end
30
- end
31
-
32
- def can_be_inlined?
33
- false
34
- end
35
-
36
- def expression
37
- case @units
38
- when "s"
39
- @time
40
- when "ms"
41
- e = ExpressionNode.new(@time,"/",DigitNode.new(1000))
42
- e.grouped = true
43
- e
44
- end
45
- end
46
-
47
- def eval(context)
48
- raise "Invalid units" unless units_valid?
49
-
50
- "WAIT #{time(context)}"
51
- end
52
- end
53
- end
54
- end
1
+ module TPPlus
2
+ module Nodes
3
+ class WaitForNode < BaseNode
4
+ def initialize(time, units)
5
+ @time = time
6
+ @units = units
7
+ end
8
+
9
+ def units_valid?
10
+ ["s","ms"].include?(@units)
11
+ end
12
+
13
+ # 2 decimal places and remove leading 0s
14
+ def time(context)
15
+ if @time.eval(context).is_a?(String)
16
+ case @units
17
+ when "s"
18
+ @time.eval(context)
19
+ else
20
+ raise "Indirect values can only use seconds ('s') as the units argument"
21
+ end
22
+ else
23
+ ("%.2f" % case @units
24
+ when "s"
25
+ @time.eval(context)
26
+ when "ms"
27
+ @time.eval(context).to_f / 1000
28
+ end).sub(/^0+/, "") + "(sec)"
29
+ end
30
+ end
31
+
32
+ def expression
33
+ case @units
34
+ when "s"
35
+ @time
36
+ when "ms"
37
+ e = ExpressionNode.new(@time,"/",DigitNode.new(1000))
38
+ e.grouped = true
39
+ e
40
+ end
41
+ end
42
+
43
+ def eval(context)
44
+ raise "Invalid units" unless units_valid?
45
+
46
+ "WAIT #{time(context)}"
47
+ end
48
+ end
49
+ end
50
+ end
@@ -1,65 +1,61 @@
1
- module TPPlus
2
- module Nodes
3
- class WaitUntilNode
4
- def initialize(expression, timeout_options)
5
- @expression = expression
6
- @timeout_options = timeout_options || {}
7
- end
8
-
9
- def timeout(context)
10
- return "" if @timeout_options[:label].nil?
11
-
12
- " TIMEOUT,LBL[#{context.labels[@timeout_options[:label].to_sym]}]"
13
- end
14
-
15
- def val(context)
16
- value_node = @timeout_options[:timeout][0]
17
- units = @timeout_options[:timeout][1]
18
-
19
- if value_node.is_a?(VarNode)
20
- value = value_node.eval(context)
21
-
22
- case units
23
- when "s"
24
- value = "#{value}*100"
25
- when "ms"
26
- value = "#{value}*.1"
27
- else
28
- raise "invalid units"
29
- end
30
- else
31
- value = value_node.eval(context).to_i
32
-
33
- case units
34
- when "s"
35
- value = (value * 100).to_i
36
- when "ms"
37
- value = (value * 0.1).to_i
38
- else
39
- raise "invalid units"
40
- end
41
- end
42
-
43
- value
44
- end
45
-
46
- def can_be_inlined?
47
- false
48
- end
49
-
50
- def wait_timeout(context)
51
- return "" if @timeout_options[:timeout].nil?
52
-
53
- "$WAITTMOUT=(#{val(context)}) ;\n"
54
- end
55
-
56
- def string_value(context)
57
- "(#{@expression.eval(context)})"
58
- end
59
-
60
- def eval(context)
61
- "#{wait_timeout(context)}WAIT #{string_value(context)}#{timeout(context)}"
62
- end
63
- end
64
- end
65
- end
1
+ module TPPlus
2
+ module Nodes
3
+ class WaitUntilNode < BaseNode
4
+ def initialize(expression, timeout_options)
5
+ @expression = expression
6
+ @timeout_options = timeout_options || {}
7
+ end
8
+
9
+ def timeout(context)
10
+ return "" if @timeout_options[:label].nil?
11
+
12
+ " TIMEOUT,LBL[#{context.labels[@timeout_options[:label].to_sym]}]"
13
+ end
14
+
15
+ def val(context)
16
+ value_node = @timeout_options[:timeout][0]
17
+ units = @timeout_options[:timeout][1]
18
+
19
+ if value_node.is_a?(VarNode)
20
+ value = value_node.eval(context)
21
+
22
+ case units
23
+ when "s"
24
+ value = "#{value}*100"
25
+ when "ms"
26
+ value = "#{value}*.1"
27
+ else
28
+ raise "invalid units"
29
+ end
30
+ else
31
+ value = value_node.eval(context).to_i
32
+
33
+ case units
34
+ when "s"
35
+ value = (value * 100).to_i
36
+ when "ms"
37
+ value = (value * 0.1).to_i
38
+ else
39
+ raise "invalid units"
40
+ end
41
+ end
42
+
43
+ value
44
+ end
45
+
46
+ def wait_timeout(context)
47
+ return "" if @timeout_options[:timeout].nil?
48
+
49
+ "$WAITTMOUT=(#{val(context)}) ;\n"
50
+ end
51
+
52
+ def string_value(context)
53
+ "(#{@expression.eval(context)})"
54
+ end
55
+
56
+ def eval(context)
57
+ "#{wait_timeout(context)}WAIT #{string_value(context)}#{timeout(context)}"
58
+ end
59
+ end
60
+ end
61
+ end
@@ -1,42 +1,40 @@
1
- module TPPlus
2
- module Nodes
3
- class WhileNode
4
- def initialize(condition_node, block)
5
- @condition_node = condition_node
6
- @block = block.flatten.reject {|n| n.is_a?(TerminatorNode) }
7
- end
8
-
9
- def top_label(context)
10
- @top_label ||= context.next_label
11
- end
12
-
13
- def bottom_label(context)
14
- @bottom_label ||= context.next_label
15
- end
16
-
17
- def parens(s, context)
18
- return s unless @condition_node.requires_mixed_logic?(context)
19
-
20
- "(#{s})"
21
- end
22
-
23
- def if_statement(context)
24
- "IF #{parens(condition(context), context)},JMP LBL[#{bottom_label(context)}] ;\n"
25
- end
26
-
27
-
28
- def condition(context)
29
- @condition_node.eval(context, opposite: true)
30
- end
31
-
32
-
33
- def block(context)
34
- @block.inject("") {|s,n| s << "#{n.eval(context)} ;\n" }
35
- end
36
-
37
- def eval(context)
38
- "LBL[#{top_label(context)}] ;\n#{if_statement(context)}#{block(context)}JMP LBL[#{top_label(context)}] ;\nLBL[#{bottom_label(context)}]"
39
- end
40
- end
41
- end
42
- end
1
+ module TPPlus
2
+ module Nodes
3
+ class WhileNode < BaseNode
4
+ def initialize(condition_node, block)
5
+ @condition_node = condition_node
6
+ @block = block.flatten.reject {|n| n.is_a?(TerminatorNode) }
7
+ end
8
+
9
+ def top_label(context)
10
+ @top_label ||= context.next_label
11
+ end
12
+
13
+ def bottom_label(context)
14
+ @bottom_label ||= context.next_label
15
+ end
16
+
17
+ def parens(s, context)
18
+ return s unless @condition_node.requires_mixed_logic?(context)
19
+
20
+ "(#{s})"
21
+ end
22
+
23
+ def if_statement(context)
24
+ "IF #{parens(condition(context), context)},JMP LBL[#{bottom_label(context)}] ;\n"
25
+ end
26
+
27
+ def condition(context)
28
+ @condition_node.eval(context, opposite: true)
29
+ end
30
+
31
+ def block(context)
32
+ @block.inject("") {|s,n| s << "#{n.eval(context)} ;\n" }
33
+ end
34
+
35
+ def eval(context)
36
+ "LBL[#{top_label(context)}] ;\n#{if_statement(context)}#{block(context)}JMP LBL[#{top_label(context)}] ;\nLBL[#{bottom_label(context)}]"
37
+ end
38
+ end
39
+ end
40
+ end