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
@@ -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