tp_plus 0.0.73

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +65 -0
  3. data/Rakefile +21 -0
  4. data/bin/tpp +73 -0
  5. data/lib/tp_plus/interpreter.rb +129 -0
  6. data/lib/tp_plus/namespace.rb +66 -0
  7. data/lib/tp_plus/nodes/abort_node.rb +9 -0
  8. data/lib/tp_plus/nodes/argument_node.rb +19 -0
  9. data/lib/tp_plus/nodes/assignment_node.rb +45 -0
  10. data/lib/tp_plus/nodes/call_node.rb +34 -0
  11. data/lib/tp_plus/nodes/case_condition_node.rb +26 -0
  12. data/lib/tp_plus/nodes/case_node.rb +33 -0
  13. data/lib/tp_plus/nodes/comment_node.rb +22 -0
  14. data/lib/tp_plus/nodes/conditional_node.rb +54 -0
  15. data/lib/tp_plus/nodes/definition_node.rb +22 -0
  16. data/lib/tp_plus/nodes/digit_node.rb +21 -0
  17. data/lib/tp_plus/nodes/eval_node.rb +13 -0
  18. data/lib/tp_plus/nodes/expression_node.rb +65 -0
  19. data/lib/tp_plus/nodes/for_node.rb +20 -0
  20. data/lib/tp_plus/nodes/header_node.rb +27 -0
  21. data/lib/tp_plus/nodes/indirect_node.rb +49 -0
  22. data/lib/tp_plus/nodes/inline_conditional_node.rb +40 -0
  23. data/lib/tp_plus/nodes/io_method_node.rb +55 -0
  24. data/lib/tp_plus/nodes/io_node.rb +30 -0
  25. data/lib/tp_plus/nodes/jump_node.rb +23 -0
  26. data/lib/tp_plus/nodes/label_definition_node.rb +21 -0
  27. data/lib/tp_plus/nodes/motion_node.rb +62 -0
  28. data/lib/tp_plus/nodes/namespace_node.rb +16 -0
  29. data/lib/tp_plus/nodes/namespaced_var_node.rb +38 -0
  30. data/lib/tp_plus/nodes/numreg_node.rb +25 -0
  31. data/lib/tp_plus/nodes/offset_node.rb +27 -0
  32. data/lib/tp_plus/nodes/operator_node.rb +72 -0
  33. data/lib/tp_plus/nodes/pause_node.rb +9 -0
  34. data/lib/tp_plus/nodes/position_data_node.rb +50 -0
  35. data/lib/tp_plus/nodes/position_node.rb +25 -0
  36. data/lib/tp_plus/nodes/posreg_node.rb +48 -0
  37. data/lib/tp_plus/nodes/raise_node.rb +13 -0
  38. data/lib/tp_plus/nodes/real_node.rb +27 -0
  39. data/lib/tp_plus/nodes/set_node.rb +22 -0
  40. data/lib/tp_plus/nodes/skip_node.rb +22 -0
  41. data/lib/tp_plus/nodes/speed_node.rb +29 -0
  42. data/lib/tp_plus/nodes/string_node.rb +13 -0
  43. data/lib/tp_plus/nodes/string_register_node.rb +25 -0
  44. data/lib/tp_plus/nodes/termination_node.rb +18 -0
  45. data/lib/tp_plus/nodes/terminator_node.rb +16 -0
  46. data/lib/tp_plus/nodes/time_node.rb +24 -0
  47. data/lib/tp_plus/nodes/timer_method_node.rb +37 -0
  48. data/lib/tp_plus/nodes/timer_node.rb +21 -0
  49. data/lib/tp_plus/nodes/units_node.rb +20 -0
  50. data/lib/tp_plus/nodes/use_node.rb +21 -0
  51. data/lib/tp_plus/nodes/user_alarm_node.rb +15 -0
  52. data/lib/tp_plus/nodes/var_method_node.rb +23 -0
  53. data/lib/tp_plus/nodes/var_node.rb +39 -0
  54. data/lib/tp_plus/nodes/vision_register_node.rb +21 -0
  55. data/lib/tp_plus/nodes/wait_for_node.rb +54 -0
  56. data/lib/tp_plus/nodes/wait_until_node.rb +65 -0
  57. data/lib/tp_plus/nodes/while_node.rb +36 -0
  58. data/lib/tp_plus/parser.rb +1592 -0
  59. data/lib/tp_plus/scanner.rb +383 -0
  60. data/lib/tp_plus/version.rb +3 -0
  61. data/lib/tp_plus.rb +62 -0
  62. data/test/test_helper.rb +5 -0
  63. data/test/tp_plus/test_interpreter.rb +1168 -0
  64. data/test/tp_plus/test_parser.rb +489 -0
  65. data/test/tp_plus/test_scanner.rb +522 -0
  66. data/tp_plus.gemspec +28 -0
  67. metadata +156 -0
@@ -0,0 +1,48 @@
1
+ module TPPlus
2
+ module Nodes
3
+ class PosregNode
4
+
5
+ COMPONENTS = {
6
+ "x" => 1,
7
+ "y" => 2,
8
+ "z" => 3,
9
+ "w" => 4,
10
+ "p" => 5,
11
+ "r" => 6
12
+ }
13
+
14
+ attr_accessor :comment
15
+ def initialize(id)
16
+ @id = id
17
+ @comment = ""
18
+ end
19
+
20
+ def comment_string
21
+ return "" if @comment == ""
22
+
23
+ ":#{@comment}"
24
+ end
25
+
26
+ def component(m)
27
+ return "" if m == ""
28
+
29
+ ",#{COMPONENTS[m]}"
30
+ end
31
+
32
+ def component_valid?(c)
33
+ [""].concat(COMPONENTS.keys).include? c
34
+ end
35
+
36
+ def requires_mixed_logic?(context)
37
+ false
38
+ end
39
+
40
+ def eval(context,options={})
41
+ options[:method] ||= ""
42
+ raise "Invalid component" unless component_valid?(options[:method])
43
+
44
+ "PR[#{@id}#{component(options[:method])}#{comment_string}]"
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,13 @@
1
+ module TPPlus
2
+ module Nodes
3
+ class RaiseNode
4
+ def initialize(target)
5
+ @target = target
6
+ end
7
+
8
+ def eval(context, options={})
9
+ "#{@target.eval(context)}"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,27 @@
1
+ module TPPlus
2
+ module Nodes
3
+ class RealNode
4
+ def initialize(value)
5
+ @value = value
6
+ end
7
+
8
+ def requires_mixed_logic?(context)
9
+ false
10
+ end
11
+
12
+ def eval(context,options={})
13
+ val = if options[:as_string]
14
+ ("%.2f" % @value).sub(/^0/,'')
15
+ else
16
+ @value
17
+ end
18
+
19
+ if @value < 0
20
+ "(#{val})"
21
+ else
22
+ val
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,22 @@
1
+ module TPPlus
2
+ module Nodes
3
+ class SetNode
4
+ def initialize(type, target, value)
5
+ @type = type
6
+ @target = target
7
+ @value = value
8
+ end
9
+
10
+ def eval(context)
11
+ case @type
12
+ when "set_uframe"
13
+ "UFRAME[#{@target.eval(context)}]=#{@value.eval(context)}"
14
+ when "set_skip_condition"
15
+ "SKIP CONDITION #{@value.eval(context, disable_mixed_logic: true)}"
16
+ else
17
+ raise "Unsupported FANUC setter"
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ module TPPlus
2
+ module Nodes
3
+ class SkipNode
4
+ def initialize(target, lpos_pr)
5
+ @target = target
6
+ @lpos_pr = lpos_pr
7
+ end
8
+
9
+ def lpos_pr(context)
10
+ return "" if @lpos_pr.nil?
11
+
12
+ ",#{@lpos_pr.eval(context)}=LPOS"
13
+ end
14
+
15
+ def eval(context)
16
+ raise "Label (#{@target}) not found" if context.labels[@target.to_sym].nil?
17
+
18
+ "Skip,LBL[#{context.labels[@target.to_sym]}]#{lpos_pr(context)}"
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,29 @@
1
+ module TPPlus
2
+ module Nodes
3
+ class SpeedNode
4
+ def initialize(speed_hash)
5
+ @speed_hash = speed_hash
6
+ end
7
+
8
+ def speed(context)
9
+ @speed_hash[:speed].eval(context)
10
+ end
11
+
12
+ def units
13
+ case @speed_hash[:units]
14
+ when "mm/s"
15
+ "mm/sec"
16
+ else
17
+ @speed_hash[:units]
18
+ end
19
+ end
20
+
21
+
22
+ def eval(context)
23
+ return @speed_hash[:speed] if @speed_hash[:units].nil?
24
+
25
+ "#{speed(context)}#{units}"
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,13 @@
1
+ module TPPlus
2
+ module Nodes
3
+ class StringNode
4
+ def initialize(s)
5
+ @s = s
6
+ end
7
+
8
+ def eval(context)
9
+ "'#{@s}'"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,25 @@
1
+ module TPPlus
2
+ module Nodes
3
+ class StringRegisterNode
4
+ attr_accessor :comment
5
+ def initialize(id)
6
+ @id = id
7
+ @comment = ""
8
+ end
9
+
10
+ def requires_mixed_logic?(context)
11
+ false
12
+ end
13
+
14
+ def comment_string
15
+ return "" if @comment == ""
16
+
17
+ ":#{@comment}"
18
+ end
19
+
20
+ def eval(context,options={})
21
+ "SR[#{@id}#{comment_string}]"
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,18 @@
1
+ module TPPlus
2
+ module Nodes
3
+ class TerminationNode
4
+ def initialize(value)
5
+ @value = value
6
+ end
7
+
8
+ def eval(context)
9
+ if @value.is_a? DigitNode
10
+ "CNT#{@value.eval(context)}"
11
+ else
12
+ # for registers
13
+ "CNT #{@value.eval(context)}"
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,16 @@
1
+ module TPPlus
2
+ module Nodes
3
+ class TerminatorNode
4
+ def eval(context)
5
+ nil
6
+ end
7
+ end
8
+ end
9
+ end
10
+
11
+ # IF R[1:foo]<>1,JMP LBL[100] ;
12
+ # R[1:foo]=2 ;
13
+ # JMP LBL[101] ;
14
+ # LBL[100] ;
15
+ # R[1:foo]=1 ;
16
+ # LBL[101] ;
@@ -0,0 +1,24 @@
1
+ module TPPlus
2
+ module Nodes
3
+ class TimeNode
4
+ def initialize(type, time, action)
5
+ @type = type
6
+ @time = time
7
+ @action = action
8
+ end
9
+
10
+ def type
11
+ case @type.downcase
12
+ when "time_before"
13
+ "TB"
14
+ when "time_after"
15
+ "TA"
16
+ end
17
+ end
18
+
19
+ def eval(context)
20
+ "#{type} #{@time.eval(context,as_string: true)}sec,#{@action.eval(context)}"
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,37 @@
1
+ module TPPlus
2
+ module Nodes
3
+ class TimerMethodNode
4
+ def initialize(method, target)
5
+ @method = method
6
+ @target = target
7
+ end
8
+
9
+ def requires_mixed_logic?(context)
10
+ true
11
+ end
12
+
13
+ def can_be_inlined?
14
+ false
15
+ end
16
+
17
+ def timer(context)
18
+ @timer ||= @target.eval(context)
19
+ end
20
+
21
+ def eval(context,options={})
22
+ case @method
23
+ when :start
24
+ "#{timer(context)}=START"
25
+ when :stop
26
+ "#{timer(context)}=STOP"
27
+ when :reset
28
+ "#{timer(context)}=RESET"
29
+ when :restart
30
+ "#{timer(context)}=STOP ;\n#{timer(context)}=RESET ;\n#{timer(context)}=START"
31
+ else
32
+ raise "Invalid timer method (#{@method})"
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,21 @@
1
+ module TPPlus
2
+ module Nodes
3
+ class TimerNode
4
+ attr_accessor :comment
5
+ def initialize(id)
6
+ @id = id
7
+ @comment = ""
8
+ end
9
+
10
+ def comment_string
11
+ return "" if @comment == ""
12
+
13
+ ":#{comment}"
14
+ end
15
+
16
+ def eval(context, options={})
17
+ "TIMER[#{@id}#{comment_string}]"
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +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
@@ -0,0 +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
@@ -0,0 +1,15 @@
1
+ module TPPlus
2
+ module Nodes
3
+ class UserAlarmNode
4
+ attr_accessor :comment
5
+ def initialize(id)
6
+ @id = id
7
+ @comment = ""
8
+ end
9
+
10
+ def eval(context, options={})
11
+ "UALM[#{@id}]"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +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:@method))
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +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
@@ -0,0 +1,21 @@
1
+ module TPPlus
2
+ module Nodes
3
+ class VisionRegisterNode
4
+ attr_accessor :comment
5
+ def initialize(id)
6
+ @id = id
7
+ @comment = ""
8
+ end
9
+
10
+ def comment_string
11
+ return "" if @comment == ""
12
+
13
+ ":#{@comment}"
14
+ end
15
+
16
+ def eval(context,options={})
17
+ "VR[#{@id}#{comment_string}]"
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,54 @@
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
@@ -0,0 +1,65 @@
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, force_parens: true)}"
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
@@ -0,0 +1,36 @@
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 if_statement(context)
18
+ "IF #{condition(context)},JMP LBL[#{bottom_label(context)}] ;\n"
19
+ end
20
+
21
+
22
+ def condition(context)
23
+ @condition_node.eval(context, opposite: true, as_condition: true)
24
+ end
25
+
26
+
27
+ def block(context)
28
+ @block.inject("") {|s,n| s << "#{n.eval(context)} ;\n" }
29
+ end
30
+
31
+ def eval(context)
32
+ "LBL[#{top_label(context)}] ;\n#{if_statement(context)}#{block(context)}JMP LBL[#{top_label(context)}] ;\nLBL[#{bottom_label(context)}]"
33
+ end
34
+ end
35
+ end
36
+ end