tp_plus 0.0.87 → 0.0.88

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 -87
  3. data/Rakefile +35 -35
  4. data/bin/tpp +92 -92
  5. data/lib/tp_plus/interpreter.rb +153 -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 +24 -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 -52
  12. data/lib/tp_plus/nodes/base_node.rb +9 -9
  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 -18
  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 +71 -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 -27
  26. data/lib/tp_plus/nodes/inline_conditional_node.rb +36 -36
  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 -13
  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 -13
  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 +78 -80
  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 -9
  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 +29 -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 -33
  56. data/lib/tp_plus/nodes/timer_node.rb +16 -16
  57. data/lib/tp_plus/nodes/unary_expression_node.rb +40 -39
  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 +57 -50
  65. data/lib/tp_plus/nodes/wait_until_node.rb +61 -61
  66. data/lib/tp_plus/nodes/while_node.rb +40 -40
  67. data/lib/tp_plus/parser.rb +1749 -1749
  68. data/lib/tp_plus/scanner.rb +295 -295
  69. data/lib/tp_plus/token.rb +101 -101
  70. data/lib/tp_plus/version.rb +3 -3
  71. data/lib/tp_plus.rb +72 -72
  72. data/test/test_helper.rb +5 -5
  73. data/test/tp_plus/test_interpreter.rb +1378 -1372
  74. data/test/tp_plus/test_parser.rb +502 -502
  75. data/test/tp_plus/test_scanner.rb +591 -591
  76. data/tp_plus.gemspec +31 -31
  77. metadata +4 -3
@@ -1,1372 +1,1378 @@
1
- require_relative '../test_helper'
2
-
3
- class TestInterpreter < Test::Unit::TestCase
4
- include TPPlus::Nodes
5
-
6
- def setup
7
- @scanner = TPPlus::Scanner.new
8
- @parser = TPPlus::Parser.new @scanner
9
- @interpreter = @parser.interpreter
10
- end
11
-
12
- def parse(s)
13
- @scanner.scan_setup(s)
14
- @parser.parse
15
- end
16
-
17
- def last_node
18
- @last_node ||= @interpreter.nodes.last
19
- end
20
-
21
- def assert_node_type(t, n)
22
- assert_equal t, n.class
23
- end
24
-
25
- def assert_prog(s)
26
- assert_equal s, @interpreter.eval
27
- end
28
-
29
- def test_blank_prog
30
- parse("")
31
- assert_prog ""
32
- end
33
-
34
- def test_definition
35
- parse("foo := R[1]")
36
- assert_prog ""
37
- end
38
-
39
- def test_multi_define_fails
40
- parse("foo := R[1]\nfoo := R[2]")
41
- assert_raise(RuntimeError) do
42
- assert_prog ""
43
- end
44
- end
45
-
46
- def test_var_usage
47
- parse("foo := R[1]\nfoo = 1")
48
- assert_prog "R[1:foo]=1 ;\n"
49
- end
50
-
51
- def test_basic_addition
52
- parse("foo := R[1]\nfoo = 1 + 1")
53
- assert_prog "R[1:foo]=1+1 ;\n"
54
- end
55
-
56
- def test_basic_addition_with_var
57
- parse("foo := R[1]\n foo = foo + 1")
58
- assert_prog "R[1:foo]=R[1:foo]+1 ;\n"
59
- end
60
-
61
- def test_label_definition
62
- parse("@foo")
63
- assert_prog "LBL[100:foo] ;\n"
64
- end
65
-
66
- def test_duplicate_label_definition
67
- parse("@foo\n@foo")
68
- assert_raise RuntimeError do
69
- assert_prog ""
70
- end
71
- end
72
-
73
- def test_jump_to_label
74
- parse("@foo\njump_to @foo")
75
- assert_prog "LBL[100:foo] ;\nJMP LBL[100] ;\n"
76
- end
77
-
78
- def test_nonexistent_label_error
79
- parse("jump_to @foo")
80
- assert_raise RuntimeError do
81
- assert_prog ""
82
- end
83
- end
84
-
85
- def test_turn_on
86
- parse("foo := DO[1]\nturn_on foo")
87
- assert_prog "DO[1:foo]=ON ;\n"
88
- end
89
-
90
- def test_turn_off
91
- parse("foo := DO[1]\nturn_off foo")
92
- assert_prog "DO[1:foo]=OFF ;\n"
93
- end
94
-
95
- def test_toggle
96
- parse("foo := DO[1]\ntoggle foo")
97
- assert_prog "DO[1:foo]=(!DO[1:foo]) ;\n"
98
- end
99
-
100
- def test_simple_linear_motion
101
- parse("foo := PR[1]\nlinear_move.to(foo).at(2000, 'mm/s').term(0)")
102
- assert_prog "L PR[1:foo] 2000mm/sec CNT0 ;\n"
103
- end
104
-
105
- def test_simple_if
106
- parse("foo := R[1]\nif foo==1\nfoo=2\nend")
107
- assert_prog "IF (R[1:foo]=1),R[1:foo]=(2) ;\n"
108
- end
109
-
110
- def test_simple_if_else
111
- parse("foo := R[1]\nif foo==1\nfoo=2\nelse\nfoo=1\nend")
112
- assert_prog "IF R[1:foo]<>1,JMP LBL[100] ;\nR[1:foo]=2 ;\nJMP LBL[101] ;\nLBL[100] ;\nR[1:foo]=1 ;\nLBL[101] ;\n"
113
- end
114
-
115
- def test_simple_unless
116
- parse("foo := R[1]\nunless foo==1\nfoo=2\nend")
117
- assert_prog "IF (R[1:foo]<>1),R[1:foo]=(2) ;\n"
118
- end
119
-
120
- def test_simple_unless_else
121
- parse("foo := R[1]\nunless foo==1\nfoo=2\nelse\nfoo=1\nend")
122
- assert_prog "IF R[1:foo]=1,JMP LBL[100] ;\nR[1:foo]=2 ;\nJMP LBL[101] ;\nLBL[100] ;\nR[1:foo]=1 ;\nLBL[101] ;\n"
123
- end
124
-
125
- def test_comment
126
- parse("# this is a comment")
127
- assert_prog "! this is a comment ;\n"
128
- end
129
-
130
- def test_two_comments
131
- parse("# comment one\n# comment two")
132
- assert_prog "! comment one ;\n! comment two ;\n"
133
- end
134
-
135
- def test_inline_comment
136
- parse("foo := R[1] # comment\nfoo = 1 # another comment")
137
- assert_prog "! comment ;\nR[1:foo]=1 ;\n! another comment ;\n"
138
- end
139
-
140
- def test_inline_conditional_if_on_jump
141
- parse("foo := R[1]\n@bar\njump_to @bar if foo==1\n")
142
- assert_prog "LBL[100:bar] ;\nIF R[1:foo]=1,JMP LBL[100] ;\n"
143
- end
144
-
145
- def test_inline_conditional_unless_on_jump
146
- parse("foo := R[1]\n@bar\njump_to @bar unless foo==1\n")
147
- assert_prog "LBL[100:bar] ;\nIF R[1:foo]<>1,JMP LBL[100] ;\n"
148
- end
149
-
150
- def test_inline_assignment
151
- parse("foo := R[1]\nfoo=2 if foo==1\n")
152
- assert_prog "IF (R[1:foo]=1),R[1:foo]=(2) ;\n"
153
- end
154
-
155
- def test_inline_io_method
156
- parse("foo := DO[1]\nbar := R[1]\nturn_on foo if bar < 10\n")
157
- assert_prog "IF (R[1:bar]<10),DO[1:foo]=(ON) ;\n"
158
- end
159
-
160
- def test_program_call
161
- parse("foo()")
162
- assert_prog "CALL FOO ;\n"
163
- end
164
-
165
- def test_program_call_with_simple_arg
166
- parse("foo(1)")
167
- assert_prog "CALL FOO(1) ;\n"
168
- end
169
-
170
- def test_program_call_with_multiple_simple_args
171
- parse("foo(1,2,3)")
172
- assert_prog "CALL FOO(1,2,3) ;\n"
173
- end
174
-
175
- def test_program_call_with_variable_argument
176
- parse("foo := R[1]\nbar(foo)")
177
- assert_prog "CALL BAR(R[1:foo]) ;\n"
178
- end
179
-
180
- def test_preserve_whitespace
181
- parse("\n\n")
182
- assert_prog " ;\n"
183
- end
184
-
185
- def test_plus_equals
186
- parse("foo := R[1]\nfoo += 1\n")
187
- assert_prog "R[1:foo]=R[1:foo]+1 ;\n"
188
- end
189
-
190
- def test_minus_equals
191
- parse("foo := R[1]\nfoo -= 1\n")
192
- assert_prog "R[1:foo]=R[1:foo]-1 ;\n"
193
- end
194
-
195
- def test_motion_to_a_position
196
- parse("foo := P[1]\nlinear_move.to(foo).at(2000, 'mm/s').term(0)")
197
- assert_prog "L P[1:foo] 2000mm/sec CNT0 ;\n"
198
- end
199
-
200
- def test_joint_move
201
- parse("foo := P[1]\njoint_move.to(foo).at(100, '%').term(0)")
202
- assert_prog "J P[1:foo] 100% CNT0 ;\n"
203
- end
204
-
205
- def test_joint_move_throws_error_with_bad_units
206
- parse("foo := P[1]\njoint_move.to(foo).at(2000, 'mm/s').term(0)")
207
- assert_raise(RuntimeError) do
208
- assert_prog "J P[1:foo] 100% CNT0 ;\n"
209
- end
210
- end
211
-
212
- def test_linear_move_throws_error_with_bad_units
213
- parse("foo := P[1]\nlinear_move.to(foo).at(100, '%').term(0)")
214
- assert_raise(RuntimeError) do
215
- assert_prog "L P[1:foo] 100% CNT0 ;\n"
216
- end
217
- end
218
-
219
-
220
- def test_pr_offset
221
- parse("home := P[1]\nmy_offset := PR[1]\nlinear_move.to(home).at(2000, 'mm/s').term(0).offset(my_offset)")
222
- assert_prog "L P[1:home] 2000mm/sec CNT0 Offset,PR[1:my_offset] ;\n"
223
- end
224
-
225
- def test_vr_offset
226
- parse("home := P[1]\nvoff := VR[1]\nlinear_move.to(home).at(2000, 'mm/s').term(0).vision_offset(voff)")
227
- assert_prog "L P[1:home] 2000mm/sec CNT0 VOFFSET,VR[1:voff] ;\n"
228
- end
229
-
230
- def test_time_before
231
- parse("p := P[1]\nlinear_move.to(p).at(2000, 'mm/s').term(0).time_before(0.5, foo())")
232
- assert_prog "L P[1:p] 2000mm/sec CNT0 TB .50sec,CALL FOO ;\n"
233
- end
234
-
235
- def test_time_after
236
- parse("p := P[1]\nlinear_move.to(p).at(2000, 'mm/s').term(0).time_after(0.5, foo())")
237
- assert_prog "L P[1:p] 2000mm/sec CNT0 TA .50sec,CALL FOO ;\n"
238
- end
239
-
240
- def test_time_before_with_register_time
241
- parse("p := P[1]\nt := R[1]\nlinear_move.to(p).at(2000, 'mm/s').term(0).time_before(t, foo())")
242
- assert_prog "L P[1:p] 2000mm/sec CNT0 TB R[1:t]sec,CALL FOO ;\n"
243
- end
244
-
245
- def test_time_before_with_io_method
246
- parse("p := P[1]\nbar := DO[1]\nlinear_move.to(p).at(2000, 'mm/s').term(0).time_before(0.5, turn_on bar)")
247
- assert_prog "L P[1:p] 2000mm/sec CNT0 TB .50sec,DO[1:bar]=ON ;\n"
248
- end
249
-
250
- def test_motion_with_indirect_termination
251
- parse("p := P[1]\ncnt := R[1]\nlinear_move.to(p).at(2000, 'mm/s').term(cnt)")
252
- assert_prog "L P[1:p] 2000mm/sec CNT R[1:cnt] ;\n"
253
- end
254
-
255
- def test_motion_with_indirect_speed
256
- parse("p := P[1]\nspeed := R[1]\nlinear_move.to(p).at(speed, 'mm/s').term(0)")
257
- assert_prog "L P[1:p] R[1:speed]mm/sec CNT0 ;\n"
258
- end
259
-
260
- def test_motion_with_max_speed
261
- parse("p := P[1]\nlinear_move.to(p).at('max_speed').term(0)")
262
- assert_prog "L P[1:p] max_speed CNT0 ;\n"
263
- end
264
-
265
- def test_use_uframe
266
- parse("use_uframe 5")
267
- assert_prog "UFRAME_NUM=5 ;\n"
268
- end
269
-
270
- def test_indirect_uframe
271
- parse("foo := R[1]\nuse_uframe foo")
272
- assert_prog "UFRAME_NUM=R[1:foo] ;\n"
273
- end
274
-
275
- def test_use_utool
276
- parse("use_utool 5")
277
- assert_prog "UTOOL_NUM=5 ;\n"
278
- end
279
-
280
- def test_indirect_utool
281
- parse("foo := R[1]\nuse_utool foo")
282
- assert_prog "UTOOL_NUM=R[1:foo] ;\n"
283
- end
284
-
285
- def test_payload
286
- parse("use_payload 1")
287
- assert_prog "PAYLOAD[1] ;\n"
288
- end
289
-
290
- def test_indirect_payload
291
- parse("foo := R[1]\nuse_payload foo")
292
- assert_prog "PAYLOAD[R[1:foo]] ;\n"
293
- end
294
-
295
- def test_nested_conditionals
296
- parse("foo := R[1]\nif foo==1\nif foo==2\nfoo=3\nelse\nfoo=4\nend\nend")
297
- assert_prog "IF R[1:foo]<>1,JMP LBL[100] ;\nIF R[1:foo]<>2,JMP LBL[101] ;\nR[1:foo]=3 ;\nJMP LBL[102] ;\nLBL[101] ;\nR[1:foo]=4 ;\nLBL[102] ;\nLBL[100] ;\n"
298
- end
299
-
300
- def test_inline_unless
301
- parse("foo := R[1]\n@bar\njump_to @bar unless foo > 1")
302
- assert_prog "LBL[100:bar] ;\nIF R[1:foo]<=1,JMP LBL[100] ;\n"
303
- end
304
-
305
- def test_inline_unless_with_two_vars
306
- parse("foo := R[1]\nbar := R[2]\n@baz\njump_to @baz unless foo > bar")
307
- assert_prog "LBL[100:baz] ;\nIF R[1:foo]<=R[2:bar],JMP LBL[100] ;\n"
308
- end
309
-
310
- def test_labels_can_be_defined_after_jumps_to_them
311
- parse("jump_to @foo\n@foo")
312
- assert_prog "JMP LBL[100] ;\nLBL[100:foo] ;\n"
313
- end
314
-
315
- def test_multiple_motion_modifiers
316
- parse("p := P[1]\no := PR[1]\nlinear_move.to(p).at('max_speed').term(0).offset(o).time_before(0.5,foo())")
317
- assert_prog "L P[1:p] max_speed CNT0 Offset,PR[1:o] TB .50sec,CALL FOO ;\n"
318
- end
319
-
320
- def test_motion_modifiers_swallow_terminators_after_dots
321
- parse("p := P[1]\no := PR[1]\nlinear_move.\nto(p).\nat('max_speed').\nterm(0).\noffset(o).\ntime_before(0.5,foo())")
322
- assert_prog "L P[1:p] max_speed CNT0 Offset,PR[1:o] TB .50sec,CALL FOO ;\n"
323
- end
324
-
325
- def test_wait_for_with_seconds
326
- parse("wait_for(5,'s')")
327
- assert_prog "WAIT 5.00(sec) ;\n"
328
- end
329
-
330
- def test_wait_for_with_invalid_units_throws_error
331
- parse("wait_for(5,'ns')")
332
- assert_raise(RuntimeError) do
333
- assert_prog ""
334
- end
335
- end
336
-
337
- def test_wait_for_with_milliseconds
338
- parse("wait_for(100,'ms')")
339
- assert_prog "WAIT .10(sec) ;\n"
340
- end
341
-
342
- def test_wait_for_with_indirect_seconds
343
- parse "foo := R[1]\nwait_for(foo, 's')"
344
- assert_prog "WAIT R[1:foo] ;\n"
345
- end
346
-
347
- def test_wait_for_with_indirect_ms
348
- parse "foo := R[1]\nwait_for(foo, 'ms')"
349
- assert_raise_message("Runtime error on line 2:\nIndirect values can only use seconds ('s') as the units argument") do
350
- assert_prog ""
351
- end
352
- end
353
-
354
- def test_wait_until_with_exp
355
- parse("wait_until(1==0)")
356
- assert_prog "WAIT (1=0) ;\n"
357
- end
358
-
359
- def test_wait_until_with_flag
360
- parse("foo := F[1]\nwait_until(foo)")
361
- assert_prog "WAIT (F[1:foo]) ;\n"
362
- end
363
-
364
- def test_wait_until_with_di
365
- parse("foo := DI[1]\nwait_until(foo)")
366
- assert_prog "WAIT (DI[1:foo]) ;\n"
367
- end
368
-
369
- def test_wait_until_with_boolean
370
- parse("foo := DI[1]\nbar := DI[2]\nwait_until(foo && bar)")
371
- assert_prog "WAIT (DI[1:foo] AND DI[2:bar]) ;\n"
372
- end
373
-
374
- def test_wait_until_with_timeout_to
375
- parse("wait_until(1==0).timeout_to(@end)\n@end")
376
- assert_prog "WAIT (1=0) TIMEOUT,LBL[100] ;\nLBL[100:end] ;\n"
377
- end
378
-
379
- def test_wait_until_with_timeout_to_and_after
380
- parse("wait_until(1==0).timeout_to(@end).after(1, 's')\n@end")
381
- assert_prog "$WAITTMOUT=(100) ;\nWAIT (1=0) TIMEOUT,LBL[100] ;\nLBL[100:end] ;\n"
382
- end
383
-
384
- def test_wait_until_after_ms
385
- parse("wait_until(1==0).timeout_to(@end).after(1000, 'ms')\n@end")
386
- assert_prog "$WAITTMOUT=(100) ;\nWAIT (1=0) TIMEOUT,LBL[100] ;\nLBL[100:end] ;\n"
387
- end
388
-
389
- def test_wait_until_after_indirect
390
- parse("foo := R[1]\nwait_until(1==0).timeout_to(@end).after(foo, 's')\n@end")
391
- assert_prog "$WAITTMOUT=(R[1:foo]*100) ;\nWAIT (1=0) TIMEOUT,LBL[100] ;\nLBL[100:end] ;\n"
392
- end
393
-
394
- def test_wait_until_with_constant
395
- parse("WAIT := 5\nwait_until(1==0).timeout_to(@end).after(WAIT, 's')\n@end")
396
- assert_prog "$WAITTMOUT=(5*100) ;\nWAIT (1=0) TIMEOUT,LBL[100] ;\nLBL[100:end] ;\n"
397
- end
398
-
399
- def test_pr_components
400
- parse("foo := PR[1]\nfoo.x=5\nfoo.y=6\nfoo.z=7\nfoo.w=8\nfoo.p=9\nfoo.r=10\n")
401
- assert_prog "PR[1,1:foo]=5 ;\nPR[1,2:foo]=6 ;\nPR[1,3:foo]=7 ;\nPR[1,4:foo]=8 ;\nPR[1,5:foo]=9 ;\nPR[1,6:foo]=10 ;\n"
402
- end
403
-
404
- #def test_pr_with_invalid_component_raises_error
405
- # parse("foo := PR[1]\nfoo.bar=5\n")
406
- # assert_raise(RuntimeError) do
407
- # assert_prog ""
408
- # end
409
- #end
410
-
411
- def test_simple_case_statement
412
- parse("foo := R[1]\ncase foo\nwhen 1\njump_to @asdf\nend\n@asdf")
413
- assert_prog %(SELECT R[1:foo]=1,JMP LBL[100] ;\nLBL[100:asdf] ;\n)
414
- end
415
-
416
- def test_simple_case_with_else_statement
417
- parse("foo := R[1]\ncase foo\nwhen 1\njump_to @asdf\nelse\njump_to @ghjk\nend\n@asdf\n@ghjk")
418
- assert_prog %(SELECT R[1:foo]=1,JMP LBL[100] ;
419
- ELSE,JMP LBL[101] ;
420
- LBL[100:asdf] ;
421
- LBL[101:ghjk] ;\n)
422
- end
423
-
424
- def test_case_statement_with_two_whens
425
- parse("foo := R[1]\ncase foo\nwhen 1\njump_to @asdf\nwhen 2\njump_to @ghjk\nend\n@asdf\n@ghjk")
426
- assert_prog %(SELECT R[1:foo]=1,JMP LBL[100] ;
427
- =2,JMP LBL[101] ;
428
- LBL[100:asdf] ;
429
- LBL[101:ghjk] ;\n)
430
- end
431
-
432
- def test_case_statement_with_three_whens
433
- parse("foo := R[1]\ncase foo\nwhen 1\nbar()\nwhen 2\nbar()\nwhen 3\nbar()\nend")
434
- assert_prog %(SELECT R[1:foo]=1,CALL BAR ;
435
- =2,CALL BAR ;
436
- =3,CALL BAR ;\n)
437
- end
438
-
439
- def test_case_statement_with_three_whens_and_else
440
- parse("foo := R[1]\ncase foo\nwhen 1\nbar()\nwhen 2\nbar()\nwhen 3\nbar()\nelse\nbar()\nend")
441
- assert_prog %(SELECT R[1:foo]=1,CALL BAR ;
442
- =2,CALL BAR ;
443
- =3,CALL BAR ;
444
- ELSE,CALL BAR ;\n)
445
- end
446
-
447
- def test_can_use_simple_io_value_as_condition
448
- parse("foo := UI[5]\n@top\njump_to @top if foo")
449
- assert_prog "LBL[100:top] ;\nIF (UI[5:foo]),JMP LBL[100] ;\n"
450
- end
451
-
452
- def test_can_use_simple_io_value_as_condition_with_unless
453
- parse("foo := UI[5]\n@top\njump_to @top unless foo")
454
- assert_prog "LBL[100:top] ;\nIF (!UI[5:foo]),JMP LBL[100] ;\n"
455
- end
456
-
457
- def test_inline_program_call
458
- parse("foo := UI[5]\nbar() unless foo")
459
- assert_prog "IF (!UI[5:foo]),CALL BAR ;\n"
460
- end
461
-
462
- def test_constant_definition
463
- parse("FOO := 5\nfoo := R[1]\nfoo = FOO")
464
- assert_prog "R[1:foo]=5 ;\n"
465
- end
466
-
467
- def test_constant_definition_real
468
- parse("PI := 3.14159\nfoo:= R[1]\nfoo = PI")
469
- assert_prog "R[1:foo]=3.14159 ;\n"
470
- end
471
-
472
- def test_redefining_const_throws_error
473
- assert_raise(RuntimeError) do
474
- parse("PI := 3.14\nPI := 5")
475
- assert_prog ""
476
- end
477
- end
478
-
479
- def test_defining_const_without_caps_raises_error
480
- parse("pi := 3.14")
481
- assert_raise(RuntimeError) do
482
- assert_prog ""
483
- end
484
- end
485
-
486
- def test_using_argument_var
487
- parse("foo := AR[1]\n@top\njump_to @top if foo==1")
488
- assert_prog "LBL[100:top] ;\nIF (AR[1]=1),JMP LBL[100] ;\n"
489
- end
490
-
491
- def test_use_uframe_with_constant
492
- parse("FOO := 1\nuse_uframe FOO")
493
- assert_prog "UFRAME_NUM=1 ;\n"
494
- end
495
-
496
- def test_set_uframe_with_pr
497
- parse("foo := PR[1]\nindirect('uframe',5)=foo")
498
- assert_prog "UFRAME[5]=PR[1:foo] ;\n"
499
- end
500
-
501
- def test_set_uframe_with_constant
502
- parse("foo := PR[1]\nBAR := 5\nindirect('uframe',BAR)=foo")
503
- assert_prog "UFRAME[5]=PR[1:foo] ;\n"
504
- end
505
-
506
- def test_fanuc_set_uframe_with_reg
507
- parse("foo := PR[1]\nbar := R[1]\nindirect('uframe',bar)=foo")
508
- assert_prog "UFRAME[R[1:bar]]=PR[1:foo] ;\n"
509
- end
510
-
511
- def test_set_skip_condition
512
- parse("foo := RI[1]\nset_skip_condition foo")
513
- assert_prog "SKIP CONDITION RI[1:foo]=ON ;\n"
514
- end
515
-
516
- def test_set_skip_condition_with_bang
517
- parse("foo := RI[1]\nset_skip_condition !foo")
518
- assert_prog "SKIP CONDITION RI[1:foo]=OFF ;\n"
519
- end
520
-
521
- def test_skip_to
522
- parse("p := P[1]\n@somewhere\nlinear_move.to(p).at(2000,'mm/s').term(0).skip_to(@somewhere)")
523
- assert_prog "LBL[100:somewhere] ;\nL P[1:p] 2000mm/sec CNT0 Skip,LBL[100] ;\n"
524
- end
525
-
526
- def test_skip_to_with_pr
527
- parse("p := P[1]\nlpos := PR[1]\n@somewhere\nlinear_move.to(p).at(2000,'mm/s').term(0).skip_to(@somewhere, lpos)")
528
- assert_prog "LBL[100:somewhere] ;\nL P[1:p] 2000mm/sec CNT0 Skip,LBL[100],PR[1:lpos]=LPOS ;\n"
529
- end
530
-
531
- def test_label_comment_automatically_adds_a_comment_if_over_16_chars
532
- parse("@foo_bar_foo_bar_foo")
533
- assert_prog "LBL[100:foo_bar_foo_bar_] ;\n! foo_bar_foo_bar_foo ;\n"
534
- end
535
-
536
- def test_automatic_long_comment_wrapping
537
- parse("# this is a really long comment so it should wrap")
538
- assert_prog "! this is a really long comment ;\n! so it should wrap ;\n"
539
- end
540
-
541
- def test_turning_on_a_flag_requires_mixed_logic
542
- parse("foo := F[1]\nturn_on foo")
543
- assert_prog "F[1:foo]=(ON) ;\n"
544
- end
545
-
546
- def test_boolean_assignment
547
- parse("foo := F[1]\nfoo = 1 && 1")
548
- assert_prog "F[1:foo]=(1 AND 1) ;\n"
549
- end
550
-
551
- def test_simple_math
552
- parse("foo := R[1]\nfoo=1+1")
553
- assert_prog "R[1:foo]=1+1 ;\n"
554
- end
555
-
556
- def test_more_complicated_math
557
- parse("foo := R[1]\nfoo=1+2+3")
558
- assert_prog "R[1:foo]=(1+2+3) ;\n"
559
- end
560
-
561
- def test_operator_precedence
562
- parse "foo := R[1]\nfoo=1+2*3"
563
- assert_prog "R[1:foo]=(1+2*3) ;\n"
564
- end
565
-
566
- def test_expression_grouping
567
- parse "foo := R[1]\nfoo=(1+2)*3"
568
- assert_prog "R[1:foo]=((1+2)*3) ;\n"
569
- end
570
-
571
- def test_boolean_expression
572
- parse "foo := F[1]\nfoo = 1 || 1 && 0"
573
- assert_prog "F[1:foo]=(1 OR 1 AND 0) ;\n"
574
- end
575
-
576
- def test_bang
577
- parse "foo := F[1]\nbar := F[2]\nfoo = !bar"
578
- assert_prog "F[1:foo]=(!F[2:bar]) ;\n"
579
- end
580
-
581
- # issue #15 https://github.com/onerobotics/tp_plus/issues/15
582
- def test_assign_output_to_ro
583
- parse "foo := DO[1]\nbar := RO[1]\nfoo = bar"
584
- assert_prog "DO[1:foo]=(RO[1:bar]) ;\n"
585
- end
586
-
587
- def test_assign_output_to_numreg_requires_no_parens
588
- parse "foo := DO[1]\nbar := R[1]\nfoo = bar"
589
- assert_prog "DO[1:foo]=R[1:bar] ;\n"
590
- end
591
-
592
- # issue #16 https://github.com/onerobotics/tp_plus/issues/16
593
- def test_negative_assignment
594
- parse "foo := R[1]\nfoo = -foo"
595
- assert_prog "R[1:foo]=R[1:foo]*(-1) ;\n"
596
- end
597
-
598
- def test_bang_with_grouping
599
- parse "foo := F[1]\nbar := F[2]\nbaz := F[3]\nfoo = foo || !(bar || baz)"
600
- assert_prog "F[1:foo]=(F[1:foo] OR !(F[2:bar] OR F[3:baz])) ;\n"
601
- end
602
-
603
- def test_opposite_flag_in_simple_if
604
- parse "foo := F[1]\nif foo\n# foo is true\nend"
605
- assert_prog "IF (!F[1:foo]),JMP LBL[100] ;\n! foo is true ;\nLBL[100] ;\n"
606
- end
607
-
608
- def test_opposite_with_boolean_and
609
- parse "foo := F[1]\nbar := F[2]\nbaz := F[3]\nif foo && bar && baz\n#foo, bar and baz are true\nend"
610
- assert_prog "IF (!F[1:foo] OR !F[2:bar] OR !F[3:baz]),JMP LBL[100] ;\n! foo, bar and baz are true ;\nLBL[100] ;\n"
611
- end
612
-
613
- def test_opposite_with_boolean_or
614
- parse "foo := F[1]\nbar := F[2]\nbaz := F[3]\nif foo || bar || baz\n#foo or bar or baz is true\nend"
615
- assert_prog "IF (!F[1:foo] AND !F[2:bar] AND !F[3:baz]),JMP LBL[100] ;\n! foo or bar or baz is true ;\nLBL[100] ;\n"
616
- end
617
-
618
- def test_opposite_flag_in_simple_unless
619
- parse "foo := F[1]\nunless foo\n# foo is false\nend"
620
- assert_prog "IF (F[1:foo]),JMP LBL[100] ;\n! foo is false ;\nLBL[100] ;\n"
621
- end
622
-
623
- def test_inline_if_with_flag
624
- parse "foo := F[1]\njump_to @end if foo\n@end"
625
- assert_prog "IF (F[1:foo]),JMP LBL[100] ;\nLBL[100:end] ;\n"
626
- end
627
-
628
- def test_inline_unless_with_flag
629
- parse "foo := F[1]\njump_to @end unless foo\n@end"
630
- assert_prog "IF (!F[1:foo]),JMP LBL[100] ;\nLBL[100:end] ;\n"
631
- end
632
-
633
- def test_automatic_parens_on_boolean
634
- parse "foo := F[1]\njump_to @end if foo || foo\n@end"
635
- assert_prog "IF (F[1:foo] OR F[1:foo]),JMP LBL[100] ;\nLBL[100:end] ;\n"
636
- end
637
-
638
- def test_no_extra_parens_with_booleans
639
- parse "foo := F[1]\njump_to @end if foo || foo || foo\n@end"
640
- assert_prog "IF (F[1:foo] OR F[1:foo] OR F[1:foo]),JMP LBL[100] ;\nLBL[100:end] ;\n"
641
- end
642
-
643
- def test_assignment_as_bool_result
644
- parse "foo := F[1]\nbar := R[1]\nfoo = bar == 1"
645
- assert_prog "F[1:foo]=(R[1:bar]=1) ;\n"
646
- end
647
-
648
- def test_args_dont_get_comments
649
- parse "foo := AR[1]\njump_to @end if foo == 1\n@end"
650
- assert_prog "IF (AR[1]=1),JMP LBL[100] ;\nLBL[100:end] ;\n"
651
- end
652
-
653
- def test_indirect_position_assignment
654
- parse "foo := PR[1]\nfoo = indirect('p',5)"
655
- assert_prog "PR[1:foo]=P[5] ;\n"
656
- end
657
-
658
- # Issue #11
659
- def test_indirect_gi
660
- parse "foo := R[1]\nbar := R[2]\nfoo = indirect('gi', bar)"
661
- assert_prog "R[1:foo]=GI[R[2:bar]] ;\n"
662
- end
663
-
664
- def test_indirect_indirect_position_assignment
665
- parse "foo := PR[1]\nbar := R[1]\nfoo = indirect('p',bar)"
666
- assert_prog "PR[1:foo]=P[R[1:bar]] ;\n"
667
- end
668
-
669
- def test_indirect_posreg_assignment
670
- parse "foo := PR[1]\nfoo = indirect('pr',5)"
671
- assert_prog "PR[1:foo]=PR[5] ;\n"
672
- end
673
-
674
- def test_add_posregs
675
- parse "a := PR[1]\nb := PR[2]\nc := PR[3]\nd := PR[4]\na=b+c+d"
676
- assert_prog "PR[1:a]=PR[2:b]+PR[3:c]+PR[4:d] ;\n"
677
- end
678
-
679
- def test_namespace
680
- parse "namespace Foo\nbar := R[1]\nend\nFoo::bar = 5"
681
- assert_prog "R[1:Foo bar]=5 ;\n"
682
- end
683
-
684
- def test_no_namespace_collision
685
- parse "namespace Foo\nbar := R[1]\nend\nbar := R[2]\nbar = 2\nFoo::bar = 1"
686
- assert_prog "R[2:bar]=2 ;\nR[1:Foo bar]=1 ;\n"
687
- end
688
-
689
- def test_namespace_constant_definition
690
- parse "namespace Math\nPI := 3.14\nend\nfoo := R[1]\nfoo = Math::PI"
691
- assert_prog "R[1:foo]=3.14 ;\n"
692
- end
693
-
694
- def test_namespace_swallows_everything
695
- parse "namespace Foo\n# this is a comment\n#this is another comment\nend"
696
- assert_prog ""
697
- end
698
-
699
- def test_nested_namespace
700
- parse %(namespace Foo
701
- bar := R[1]
702
- namespace Bar
703
- baz := R[2]
704
- end
705
- end
706
- Foo::bar = 1
707
- Foo::Bar::baz = 2)
708
- assert_prog "R[1:Foo bar]=1 ;\nR[2:Foo Bar baz]=2 ;\n"
709
- end
710
-
711
- def test_load_environment
712
- environment = "foo := R[1]\nbar := R[2]\n#asdf\n#asdf"
713
- @interpreter.load_environment(environment)
714
- parse "foo = 5"
715
- assert_prog "R[1:foo]=5 ;\n"
716
- assert_equal 1, @interpreter.source_line_count
717
- end
718
-
719
- def test_load_environment_only_saves_definitions_etc
720
- environment = "foo := R[1]\nbar := R[2]\n#asdf\n#asdf\nfoo=3"
721
- @interpreter.load_environment(environment)
722
- parse "foo = 5"
723
- assert_prog "R[1:foo]=5 ;\n"
724
- assert_equal 1, @interpreter.source_line_count
725
- end
726
-
727
-
728
- def test_bad_environment
729
- assert_raise(TPPlus::Parser::ParseError) do
730
- @interpreter.load_environment("asdf")
731
- end
732
- end
733
-
734
- def test_inline_conditional_with_namespaced_var
735
- parse "namespace Foo\nbar := DI[1]\nend\njump_to @end unless Foo::bar\n@end"
736
- assert_prog "IF (!DI[1:Foo bar]),JMP LBL[100] ;\nLBL[100:end] ;\n"
737
- end
738
-
739
- def test_namespaced_var_as_condition
740
- parse "namespace Foo\nbar := DI[1]\nend\nif Foo::bar\n# bar is on\nend"
741
- assert_prog "IF (!DI[1:Foo bar]),JMP LBL[100] ;\n! bar is on ;\nLBL[100] ;\n"
742
- end
743
-
744
- def test_reopen_namespace
745
- parse "namespace Foo\nbar := R[1]\nend\nnamespace Foo\nbaz := R[2]\nend\nFoo::bar = 1\nFoo::baz = 2"
746
- assert_prog "R[1:Foo bar]=1 ;\nR[2:Foo baz]=2 ;\n"
747
- end
748
-
749
- def test_eval
750
- parse %(eval "R[1]=5")
751
- assert_prog "R[1]=5 ;\n"
752
- end
753
-
754
- def test_multiline_eval
755
- parse %(eval "R[1]=5 ;\nR[2]=3")
756
- assert_prog "R[1]=5 ;\nR[2]=3 ;\n"
757
- end
758
-
759
- def test_namespaced_position_reg_component
760
- parse "namespace Fixture\npick_offset := PR[1]\nend\nFixture::pick_offset.x = 10"
761
- assert_prog "PR[1,1:Fixture pick_offset]=10 ;\n"
762
- end
763
-
764
- def test_inline_program_call_two
765
- parse "foo := R[1]\nbar() if foo >= 5"
766
- assert_prog "IF R[1:foo]>=5,CALL BAR ;\n"
767
- end
768
-
769
- def test_forlooop
770
- parse "foo := R[1]\nfor foo in (1 to 10)\n# bar\nend"
771
- assert_prog "FOR R[1:foo]=1 TO 10 ;\n! bar ;\nENDFOR ;\n"
772
- end
773
-
774
- def test_forloop_with_vars
775
- parse "foo := R[1]\nmin := R[2]\nmax := R[3]\nfor foo in (min to max)\n#bar\nend"
776
- assert_prog "FOR R[1:foo]=R[2:min] TO R[3:max] ;\n! bar ;\nENDFOR ;\n"
777
- end
778
-
779
- def test_indirect_flag
780
- parse "foo := R[1]\nturn_on indirect('f',foo)"
781
- assert_prog "F[R[1:foo]]=(ON) ;\n"
782
- end
783
-
784
- def test_indirect_flag_condition
785
- parse "foo := R[1]\njump_to @end if indirect('f',foo)\n@end"
786
- assert_prog "IF (F[R[1:foo]]),JMP LBL[100] ;\nLBL[100:end] ;\n"
787
- end
788
-
789
- def test_indirect_flag_condition_not_inline
790
- parse "foo := R[1]\nif indirect('f',foo)\n# bar\nend"
791
- assert_prog "IF (!F[R[1:foo]]),JMP LBL[100] ;\n! bar ;\nLBL[100] ;\n"
792
- end
793
-
794
- def test_indirect_unless_flag_condition
795
- parse "foo := R[1]\njump_to @end unless indirect('f',foo)\n@end"
796
- assert_prog "IF (!F[R[1:foo]]),JMP LBL[100] ;\nLBL[100:end] ;\n"
797
- end
798
-
799
- def test_indirect_flag_with_if_bang
800
- parse "foo := R[1]\njump_to @end if !indirect('f',foo)\n@end"
801
- assert_prog "IF (!F[R[1:foo]]),JMP LBL[100] ;\nLBL[100:end] ;\n"
802
- end
803
-
804
- def test_while_loop
805
- parse "foo := R[1]\nwhile foo < 10\n# bar\nend"
806
- assert_prog "LBL[100] ;\nIF R[1:foo]>=10,JMP LBL[101] ;\n! bar ;\nJMP LBL[100] ;\nLBL[101] ;\n"
807
- end
808
-
809
- def test_while_with_not_flag
810
- parse "foo := F[1]\nwhile !foo\n#bar\nend"
811
- assert_prog "LBL[100] ;\nIF (F[1:foo]),JMP LBL[101] ;\n! bar ;\nJMP LBL[100] ;\nLBL[101] ;\n"
812
- end
813
-
814
- def test_while_with_flag
815
- parse "foo := F[1]\nwhile foo\n#bar\nend"
816
- assert_prog "LBL[100] ;\nIF (!F[1:foo]),JMP LBL[101] ;\n! bar ;\nJMP LBL[100] ;\nLBL[101] ;\n"
817
- end
818
-
819
- def test_timer_start
820
- parse "foo := TIMER[1]\nstart foo"
821
- assert_prog "TIMER[1]=START ;\n"
822
- end
823
-
824
- def test_timer_reset
825
- parse "foo := TIMER[1]\nreset foo"
826
- assert_prog "TIMER[1]=RESET ;\n"
827
- end
828
-
829
- def test_timer_stop
830
- parse "foo := TIMER[1]\nstop foo"
831
- assert_prog "TIMER[1]=STOP ;\n"
832
- end
833
-
834
- def test_timer_restart
835
- parse "foo := TIMER[1]\nrestart foo"
836
- assert_prog "TIMER[1]=STOP ;\nTIMER[1]=RESET ;\nTIMER[1]=START ;\n"
837
- end
838
-
839
- def test_indirect_timer
840
- parse "foo := R[1]\nfoo = indirect('timer', 3)"
841
- assert_prog "R[1:foo]=TIMER[3] ;\n"
842
- end
843
-
844
- def test_indirect_indirect_timer
845
- parse "foo := R[1]\nfoo = indirect('timer', foo)"
846
- assert_prog "R[1:foo]=TIMER[R[1:foo]] ;\n"
847
- end
848
-
849
- def test_start_indirect_timer
850
- parse "start indirect('timer', 3)"
851
- assert_prog "TIMER[3]=START ;\n"
852
- end
853
-
854
- def test_start_indirect_indirect_timer
855
- parse "foo := R[1]\nstart indirect('timer', foo)"
856
- assert_prog "TIMER[R[1:foo]]=START ;\n"
857
- end
858
-
859
- def test_position_data_does_not_output_with_eval
860
- parse %(position_data
861
- {
862
- 'positions': [
863
- {
864
- 'id': 1,
865
- 'comment': "test",
866
- 'mask' : [{
867
- 'group': 1,
868
- 'uframe': 1,
869
- 'utool': 1,
870
- 'config': {
871
- 'flip': true,
872
- 'up': true,
873
- 'top': false,
874
- 'turn_counts': [-1,0,1]
875
- },
876
- 'components': {
877
- 'x': -50.0,
878
- 'y': 0.0,
879
- 'z': 0.0,
880
- 'w': 0.0,
881
- 'p': 0.0,
882
- 'r': 0.0
883
- }
884
- }]
885
- }
886
- ]
887
- }
888
- end)
889
-
890
- assert_prog ""
891
- end
892
-
893
- def test_position_data_populates_interpreter_position_data
894
- parse %(position_data
895
- {
896
- 'positions': [
897
- {
898
- 'id': 1,
899
- 'comment': "test",
900
- 'mask': [{
901
- 'group': 1,
902
- 'uframe': 1,
903
- 'utool': 1,
904
- 'config': {
905
- 'flip': true,
906
- 'up': true,
907
- 'top': false,
908
- 'turn_counts': [0,0,0]
909
- },
910
- 'components': {
911
- 'x': 0.0,
912
- 'y': 0.0,
913
- 'z': 0.0,
914
- 'w': 0.0,
915
- 'p': 0.0,
916
- 'r': 0.0
917
- }
918
- }]
919
- }
920
- ]
921
- }
922
- end)
923
-
924
- assert_prog ""
925
- assert_equal 1, @interpreter.position_data[:positions].length
926
- end
927
-
928
- def test_throws_a_fault_if_position_data_invalid
929
- parse %(position_data
930
- {
931
- 'positions' : "asdf"
932
- }
933
- end)
934
- assert_raise(RuntimeError) do
935
- @interpreter.eval
936
- end
937
- end
938
-
939
- def test_outputs_position_data_correctly
940
- parse %(position_data
941
- {
942
- 'positions': [
943
- {
944
- 'id': 1,
945
- 'comment': "test",
946
- 'mask' : [{
947
- 'group': 1,
948
- 'uframe': 1,
949
- 'utool': 1,
950
- 'config': {
951
- 'flip': true,
952
- 'up': true,
953
- 'top': true,
954
- 'turn_counts': [0,0,0]
955
- },
956
- 'components': {
957
- 'x': 0.0,
958
- 'y': 0.0,
959
- 'z': 0.0,
960
- 'w': 0.0,
961
- 'p': 0.0,
962
- 'r': 0.0
963
- }
964
- }]
965
- }
966
- ]
967
- }
968
- end)
969
-
970
- assert_prog ""
971
- assert_equal %(P[1:"test"]{
972
- GP1:
973
- UF : 1, UT : 1, CONFIG : 'F U T, 0, 0, 0',
974
- X = 0.0 mm, Y = 0.0 mm, Z = 0.0 mm,
975
- W = 0.0 deg, P = 0.0 deg, R = 0.0 deg
976
- };\n), @interpreter.pos_section
977
- end
978
-
979
- def test_outputs_position_data_correctly_with_two_positions
980
- parse %(position_data
981
- {
982
- 'positions': [
983
- {
984
- 'id': 1,
985
- 'comment': "test",
986
- 'mask': [{
987
- 'group': 1,
988
- 'uframe': 1,
989
- 'utool': 1,
990
- 'config': {
991
- 'flip': true,
992
- 'up': true,
993
- 'top': true,
994
- 'turn_counts': [0,0,0]
995
- },
996
- 'components': {
997
- 'x': 0.0,
998
- 'y': 0.0,
999
- 'z': 0.0,
1000
- 'w': 0.0,
1001
- 'p': 0.0,
1002
- 'r': 0.0
1003
- }
1004
- }]
1005
- },
1006
- {
1007
- 'id': 2,
1008
- 'comment': "test2",
1009
- 'mask': [{
1010
- 'group': 1,
1011
- 'uframe': 1,
1012
- 'utool': 1,
1013
- 'config': {
1014
- 'flip': true,
1015
- 'up': true,
1016
- 'top': true,
1017
- 'turn_counts': [0,0,0]
1018
- },
1019
- 'components': {
1020
- 'x': 0.0,
1021
- 'y': 0.0,
1022
- 'z': 0.0,
1023
- 'w': 0.0,
1024
- 'p': 0.0,
1025
- 'r': 0.0
1026
- }
1027
- }]
1028
- }
1029
- ]
1030
- }
1031
- end)
1032
-
1033
- assert_prog ""
1034
- assert_equal %(P[1:"test"]{
1035
- GP1:
1036
- UF : 1, UT : 1, CONFIG : 'F U T, 0, 0, 0',
1037
- X = 0.0 mm, Y = 0.0 mm, Z = 0.0 mm,
1038
- W = 0.0 deg, P = 0.0 deg, R = 0.0 deg
1039
- };
1040
- P[2:"test2"]{
1041
- GP1:
1042
- UF : 1, UT : 1, CONFIG : 'F U T, 0, 0, 0',
1043
- X = 0.0 mm, Y = 0.0 mm, Z = 0.0 mm,
1044
- W = 0.0 deg, P = 0.0 deg, R = 0.0 deg
1045
- };\n), @interpreter.pos_section
1046
- end
1047
-
1048
- def test_simple_pulse
1049
- parse "foo := DO[1]\npulse foo"
1050
- assert_prog "DO[1:foo]=PULSE ;\n"
1051
- end
1052
-
1053
- def test_pulse_for_seconds
1054
- parse "foo := DO[1]\npulse(foo,5,'s')"
1055
- assert_prog "DO[1:foo]=PULSE,5.0sec ;\n"
1056
- end
1057
-
1058
- def test_pulse_for_ms
1059
- parse "foo := DO[1]\npulse(foo,500,'ms')"
1060
- assert_prog "DO[1:foo]=PULSE,0.5sec ;\n"
1061
- end
1062
-
1063
- def test_indirect_numreg
1064
- parse "foo := R[1]\nindirect('r',foo) = 5"
1065
- assert_prog "R[R[1:foo]]=5 ;\n"
1066
- end
1067
-
1068
- def test_raise
1069
- parse "my_alarm := UALM[1]\nraise my_alarm"
1070
- assert_prog "UALM[1] ;\n"
1071
- end
1072
-
1073
- def test_indirect_raise
1074
- parse "raise indirect('ualm',1)"
1075
- assert_prog "UALM[1] ;\n"
1076
- end
1077
-
1078
- def test_indirect_indirect_raise
1079
- parse "foo := R[1]\nraise indirect('ualm',foo)"
1080
- assert_prog "UALM[R[1:foo]] ;\n"
1081
- end
1082
-
1083
- def test_namespaced_pr_component_assignment
1084
- parse "namespace Foo\nbar := PR[1]\nend\nFoo::bar.x = 10"
1085
- assert_prog "PR[1,1:Foo bar]=10 ;\n"
1086
- end
1087
-
1088
- def test_namespaced_pr_component_plus_equals
1089
- parse "namespace Foo\nbar := PR[1]\nend\nFoo::bar.x += 10"
1090
- assert_prog "PR[1,1:Foo bar]=PR[1,1:Foo bar]+10 ;\n"
1091
- end
1092
-
1093
- def test_namespaced_pr_component_in_expression
1094
- parse "namespace Foo\nbar := PR[1]\nend\nFoo::bar.x += Foo::bar.x * 10 \n"
1095
- assert_prog "PR[1,1:Foo bar]=(PR[1,1:Foo bar]+PR[1,1:Foo bar]*10) ;\n"
1096
- end
1097
-
1098
- def test_namespaced_pr_assignment_then_expression
1099
- parse "namespace Foo\nbar := PR[1]\nend\nbaz := P[1]\nFoo::bar = baz\nFoo::bar.x += 5"
1100
- assert_prog "PR[1:Foo bar]=P[1:baz] ;\nPR[1,1:Foo bar]=PR[1,1:Foo bar]+5 ;\n"
1101
- end
1102
-
1103
- def test_wait_until_does_not_get_inlined
1104
- parse "foo := DO[1]\nunless foo\nwait_until(foo)\nend"
1105
- assert_prog "IF (DO[1:foo]),JMP LBL[100] ;\nWAIT (DO[1:foo]) ;\nLBL[100] ;\n"
1106
- end
1107
-
1108
- def test_wait_for_does_not_get_inlined
1109
- parse "foo := DO[1]\nunless foo\nwait_for(1,'s')\nend"
1110
- assert_prog "IF (DO[1:foo]),JMP LBL[100] ;\nWAIT 1.00(sec) ;\nLBL[100] ;\n"
1111
- end
1112
-
1113
- def test_inline_conditional_does_not_get_inlined
1114
- parse "foo := DO[1]\nif foo\nturn_off foo if foo\nend"
1115
- assert_prog "IF (!DO[1:foo]),JMP LBL[100] ;\nIF (DO[1:foo]),DO[1:foo]=(OFF) ;\nLBL[100] ;\n"
1116
- end
1117
-
1118
- def test_run
1119
- parse "run foo()"
1120
- assert_prog "RUN FOO ;\n"
1121
- end
1122
-
1123
- def test_tp_ignore_pause
1124
- parse "TP_IGNORE_PAUSE = true"
1125
- assert_prog ""
1126
- assert @interpreter.header_data[:ignore_pause]
1127
- end
1128
-
1129
- def test_tp_subtype
1130
- parse "TP_SUBTYPE = 'macro'"
1131
- assert_prog ""
1132
- assert_equal :macro, @interpreter.header_data[:subtype]
1133
- end
1134
-
1135
- def test_tp_comment
1136
- parse %(TP_COMMENT = "foo")
1137
- assert_prog ""
1138
- assert_equal "foo", @interpreter.header_data[:comment]
1139
- end
1140
-
1141
- def test_tp_groupmask
1142
- parse %(TP_GROUPMASK = "*,*,*,*,*")
1143
- assert_prog ""
1144
- assert_equal "*,*,*,*,*", @interpreter.header_data[:group_mask]
1145
- end
1146
-
1147
- def test_mixed_logic_or
1148
- parse %(foo := DI[1]\nbar := DI[2]\nif foo || bar\n# do something\nend)
1149
- assert_prog "IF (!DI[1:foo] AND !DI[2:bar]),JMP LBL[100] ;\n! do something ;\nLBL[100] ;\n"
1150
- end
1151
-
1152
- def test_flag_assignment_always_gets_parens
1153
- parse %(foo := F[1]\nbar := DI[2]\nfoo = bar)
1154
- assert_prog "F[1:foo]=(DI[2:bar]) ;\n"
1155
- end
1156
-
1157
- def test_tool_offset
1158
- parse %(p := P[1]\ntoff := PR[1]\nlinear_move.to(p).at(2000,'mm/s').term(0).tool_offset(toff))
1159
- assert_prog "L P[1:p] 2000mm/sec CNT0 Tool_Offset,PR[1:toff] ;\n"
1160
- end
1161
-
1162
- def test_wait_for_digit
1163
- parse %(wait_for(1,'s'))
1164
- assert_prog "WAIT 1.00(sec) ;\n"
1165
- end
1166
-
1167
- def test_wait_for_real
1168
- parse %(wait_for(0.5,'s'))
1169
- assert_prog "WAIT .50(sec) ;\n"
1170
- end
1171
-
1172
- def test_wait_for_real_const
1173
- parse %(FOO := 0.5\nwait_for(FOO,'s'))
1174
- assert_prog "WAIT .50(sec) ;\n"
1175
- end
1176
-
1177
- def test_negative_numbers_have_parens
1178
- parse %(foo := R[1]\njump_to @end if foo > -1\njump_to @end if foo > -5.3\n@end)
1179
- assert_prog "IF R[1:foo]>(-1),JMP LBL[100] ;\nIF R[1:foo]>(-5.3),JMP LBL[100] ;\nLBL[100:end] ;\n"
1180
- end
1181
-
1182
- def test_modulus
1183
- parse %(foo := R[1]\nfoo = 5 % 2)
1184
- assert_prog "R[1:foo]=5 MOD 2 ;\n"
1185
- end
1186
-
1187
- def test_assignment_to_sop
1188
- parse %(foo := DO[1]\nbar := SO[1]\nfoo = bar)
1189
- assert_prog "DO[1:foo]=(SO[1:bar]) ;\n"
1190
- end
1191
-
1192
- def test_assignment_to_di
1193
- parse %(foo := DO[1]\nbar := DI[1]\nfoo = bar)
1194
- assert_prog "DO[1:foo]=(DI[1:bar]) ;\n"
1195
- end
1196
-
1197
- def test_string_register_definition
1198
- parse %(foo := SR[1]\nbar := SR[2]\nfoo = bar)
1199
- assert_prog "SR[1:foo]=SR[2:bar] ;\n"
1200
- end
1201
-
1202
- def test_string_argument
1203
- parse %(foo('bar'))
1204
- assert_prog "CALL FOO('bar') ;\n"
1205
- end
1206
-
1207
- def test_pause
1208
- parse %(pause)
1209
- assert_prog "PAUSE ;\n"
1210
- end
1211
-
1212
- def test_abort
1213
- parse %(abort)
1214
- assert_prog "ABORT ;\n"
1215
- end
1216
-
1217
- def test_div
1218
- parse %(foo := R[1]\nfoo = 1 DIV 5)
1219
- assert_prog "R[1:foo]=1 DIV 5 ;\n"
1220
- end
1221
-
1222
- def test_conditional_equals
1223
- parse("foo := R[1]\nfoo2 := R[2]\nif foo == foo2\nfoo = 1\nfoo2 = 2\nend")
1224
- assert_prog "IF R[1:foo]<>R[2:foo2],JMP LBL[100] ;\nR[1:foo]=1 ;\nR[2:foo2]=2 ;\nLBL[100] ;\n"
1225
- end
1226
-
1227
- def test_if_statement_multiple_arguments
1228
- parse("foo := R[1]\nfoo2 := R[2]\nif foo == 1 && foo2 == 2\nfoo = 1\nfoo2 = 2\nend")
1229
- assert_prog "IF (R[1:foo]<>1 OR R[2:foo2]<>2),JMP LBL[100] ;\nR[1:foo]=1 ;\nR[2:foo2]=2 ;\nLBL[100] ;\n"
1230
- end
1231
-
1232
- def test_parse_error_on_invalid_term
1233
- assert_raise do
1234
- parse("foo := PR[1]\nlinear_move.to(foo).at(2000, 'mm/s').term(-2)")
1235
- end
1236
- end
1237
-
1238
- def test_acc_zero
1239
- parse("foo := PR[1]\nlinear_move.to(foo).at(2000, 'mm/s').term(0).acc(0)")
1240
- assert_prog "L PR[1:foo] 2000mm/sec CNT0 ACC0 ;\n"
1241
- end
1242
-
1243
- def test_acc_150
1244
- parse("foo := PR[1]\nlinear_move.to(foo).at(2000, 'mm/s').term(0).acc(150)")
1245
- assert_prog "L PR[1:foo] 2000mm/sec CNT0 ACC150 ;\n"
1246
- end
1247
-
1248
- def test_acc_with_constant
1249
- parse("foo := PR[1]\nBAR := 50\nlinear_move.to(foo).at(2000, 'mm/s').term(0).acc(BAR)")
1250
- assert_prog "L PR[1:foo] 2000mm/sec CNT0 ACC50 ;\n"
1251
- end
1252
-
1253
- def test_acc_with_var
1254
- parse("foo := PR[1]\nbar := R[1]\nlinear_move.to(foo).at(2000, 'mm/s').term(0).acc(bar)")
1255
- assert_prog "L PR[1:foo] 2000mm/sec CNT0 ACC R[1:bar] ;\n"
1256
- end
1257
-
1258
- def test_term_fine_with_constant
1259
- parse("foo := PR[1]\nTERM := -1\nlinear_move.to(foo).at(2000, 'mm/s').term(TERM)")
1260
- assert_prog "L PR[1:foo] 2000mm/sec FINE ;\n"
1261
- end
1262
-
1263
- def test_term_cnt_with_constant
1264
- parse("foo := PR[1]\nTERM := 100\nlinear_move.to(foo).at(2000, 'mm/s').term(TERM)")
1265
- assert_prog "L PR[1:foo] 2000mm/sec CNT100 ;\n"
1266
- end
1267
-
1268
- def test_pr_components_groups
1269
- parse("foo := PR[1]\nfoo.group(1).y=5\n")
1270
- assert_prog "PR[GP1:1,2:foo]=5 ;\n"
1271
- end
1272
-
1273
- def test_position_data_with_mask
1274
- parse %(position_data
1275
- {
1276
- 'positions' : [
1277
- {
1278
- 'id' : 1,
1279
- 'mask' : [{
1280
- 'group' : 1,
1281
- 'uframe' : 5,
1282
- 'utool' : 2,
1283
- 'config' : {
1284
- 'flip' : false,
1285
- 'up' : true,
1286
- 'top' : true,
1287
- 'turn_counts' : [0,0,0]
1288
- },
1289
- 'components' : {
1290
- 'x' : -.590,
1291
- 'y' : -29.400,
1292
- 'z' : 1304.471,
1293
- 'w' : 78.512,
1294
- 'p' : 89.786,
1295
- 'r' : -11.595
1296
- }
1297
- },
1298
- {
1299
- 'group' : 2,
1300
- 'uframe' : 5,
1301
- 'utool' : 2,
1302
- 'components' : {
1303
- 'J1' : 0.00
1304
- }
1305
- }]
1306
- }
1307
- ]
1308
- }
1309
- end)
1310
- assert_prog ""
1311
- #output = @interpreter.pos_section
1312
- #output = output
1313
- assert_equal 1, @interpreter.position_data[:positions].length
1314
- end
1315
-
1316
- def test_conditional_equals_minus_one
1317
- parse("foo := R[1]\nfoo2 := R[2]\nif foo == (foo2-1)\nfoo = 1\nfoo2 = 2\nend")
1318
- assert_prog "IF (R[1:foo]<>(R[2:foo2]-1)),JMP LBL[100] ;\nR[1:foo]=1 ;\nR[2:foo2]=2 ;\nLBL[100] ;\n"
1319
- end
1320
-
1321
- def test_conditional_equals_minus_and
1322
- parse("foo := R[1]\nfoo2 := R[2]\nif foo >= (foo2-1) && foo <= (foo2+1) \nfoo = 1\nfoo2 = 2\nend")
1323
- assert_prog "IF (R[1:foo]<(R[2:foo2]-1) OR R[1:foo]>(R[2:foo2]+1)),JMP LBL[100] ;\nR[1:foo]=1 ;\nR[2:foo2]=2 ;\nLBL[100] ;\n"
1324
- end
1325
-
1326
- def test_inline_conditional_equals_minus_and
1327
- parse("foo := R[1]\nfoo2 := R[2]\nif foo >= (foo2-1) && foo <= (foo2+1) \nfoo2 = 2\nend")
1328
- assert_prog "IF (R[1:foo]>=(R[2:foo2]-1) AND R[1:foo]<=(R[2:foo2]+1)),R[2:foo2]=(2) ;\n"
1329
- end
1330
-
1331
- def test_address
1332
- parse("a := AR[1]
1333
- b := DI[2]
1334
- c := R[3]
1335
- d := P[4]
1336
- e := PR[5]
1337
- f := SR[6]
1338
- g := TIMER[7]
1339
- h := UALM[8]
1340
- i := VR[9]
1341
- TEST(&a,&b,&c,&d,&e,&f,&g,&h,&i)")
1342
- assert_prog "CALL TEST(1,2,3,4,5,6,7,8,9) ;\n"
1343
- end
1344
-
1345
- def test_address_assignment
1346
- parse("foo := R[1]
1347
- foo = &foo")
1348
- assert_prog "R[1:foo]=1 ;\n"
1349
- end
1350
-
1351
- def test_invalid_address_throws_error
1352
- parse("foo := R[1]\nfoo = &bar")
1353
- assert_raise(RuntimeError) do
1354
- assert_prog ""
1355
- end
1356
- end
1357
-
1358
- def test_lpos
1359
- parse "foo := PR[1]\nget_linear_position(foo)"
1360
- assert_prog "PR[1:foo]=LPOS ;\n"
1361
- end
1362
-
1363
- def test_jpos
1364
- parse "foo := PR[1]\nget_joint_position(foo)"
1365
- assert_prog "PR[1:foo]=JPOS ;\n"
1366
- end
1367
-
1368
- def test_return
1369
- parse "return"
1370
- assert_prog "END ;\n"
1371
- end
1372
- end
1
+ require_relative '../test_helper'
2
+
3
+ class TestInterpreter < Test::Unit::TestCase
4
+ include TPPlus::Nodes
5
+
6
+ def setup
7
+ @scanner = TPPlus::Scanner.new
8
+ @parser = TPPlus::Parser.new @scanner
9
+ @interpreter = @parser.interpreter
10
+ end
11
+
12
+ def parse(s)
13
+ @scanner.scan_setup(s)
14
+ @parser.parse
15
+ end
16
+
17
+ def last_node
18
+ @last_node ||= @interpreter.nodes.last
19
+ end
20
+
21
+ def assert_node_type(t, n)
22
+ assert_equal t, n.class
23
+ end
24
+
25
+ def assert_prog(s)
26
+ assert_equal s, @interpreter.eval
27
+ end
28
+
29
+ def test_blank_prog
30
+ parse("")
31
+ assert_prog ""
32
+ end
33
+
34
+ def test_definition
35
+ parse("foo := R[1]")
36
+ assert_prog ""
37
+ end
38
+
39
+ def test_multi_define_fails
40
+ parse("foo := R[1]\nfoo := R[2]")
41
+ assert_raise(RuntimeError) do
42
+ assert_prog ""
43
+ end
44
+ end
45
+
46
+ def test_var_usage
47
+ parse("foo := R[1]\nfoo = 1")
48
+ assert_prog "R[1:foo]=1 ;\n"
49
+ end
50
+
51
+ def test_basic_addition
52
+ parse("foo := R[1]\nfoo = 1 + 1")
53
+ assert_prog "R[1:foo]=1+1 ;\n"
54
+ end
55
+
56
+ def test_basic_addition_with_var
57
+ parse("foo := R[1]\n foo = foo + 1")
58
+ assert_prog "R[1:foo]=R[1:foo]+1 ;\n"
59
+ end
60
+
61
+ def test_label_definition
62
+ parse("@foo")
63
+ assert_prog "LBL[100:foo] ;\n"
64
+ end
65
+
66
+ def test_duplicate_label_definition
67
+ parse("@foo\n@foo")
68
+ assert_raise RuntimeError do
69
+ assert_prog ""
70
+ end
71
+ end
72
+
73
+ def test_jump_to_label
74
+ parse("@foo\njump_to @foo")
75
+ assert_prog "LBL[100:foo] ;\nJMP LBL[100] ;\n"
76
+ end
77
+
78
+ def test_nonexistent_label_error
79
+ parse("jump_to @foo")
80
+ assert_raise RuntimeError do
81
+ assert_prog ""
82
+ end
83
+ end
84
+
85
+ def test_turn_on
86
+ parse("foo := DO[1]\nturn_on foo")
87
+ assert_prog "DO[1:foo]=ON ;\n"
88
+ end
89
+
90
+ def test_turn_off
91
+ parse("foo := DO[1]\nturn_off foo")
92
+ assert_prog "DO[1:foo]=OFF ;\n"
93
+ end
94
+
95
+ def test_toggle
96
+ parse("foo := DO[1]\ntoggle foo")
97
+ assert_prog "DO[1:foo]=(!DO[1:foo]) ;\n"
98
+ end
99
+
100
+ def test_simple_linear_motion
101
+ parse("foo := PR[1]\nlinear_move.to(foo).at(2000, 'mm/s').term(0)")
102
+ assert_prog "L PR[1:foo] 2000mm/sec CNT0 ;\n"
103
+ end
104
+
105
+ def test_simple_if
106
+ parse("foo := R[1]\nif foo==1\nfoo=2\nend")
107
+ assert_prog "IF (R[1:foo]=1),R[1:foo]=(2) ;\n"
108
+ end
109
+
110
+ def test_simple_if_else
111
+ parse("foo := R[1]\nif foo==1\nfoo=2\nelse\nfoo=1\nend")
112
+ assert_prog "IF R[1:foo]<>1,JMP LBL[100] ;\nR[1:foo]=2 ;\nJMP LBL[101] ;\nLBL[100] ;\nR[1:foo]=1 ;\nLBL[101] ;\n"
113
+ end
114
+
115
+ def test_simple_unless
116
+ parse("foo := R[1]\nunless foo==1\nfoo=2\nend")
117
+ assert_prog "IF (R[1:foo]<>1),R[1:foo]=(2) ;\n"
118
+ end
119
+
120
+ def test_simple_unless_else
121
+ parse("foo := R[1]\nunless foo==1\nfoo=2\nelse\nfoo=1\nend")
122
+ assert_prog "IF R[1:foo]=1,JMP LBL[100] ;\nR[1:foo]=2 ;\nJMP LBL[101] ;\nLBL[100] ;\nR[1:foo]=1 ;\nLBL[101] ;\n"
123
+ end
124
+
125
+ def test_comment
126
+ parse("# this is a comment")
127
+ assert_prog "! this is a comment ;\n"
128
+ end
129
+
130
+ def test_two_comments
131
+ parse("# comment one\n# comment two")
132
+ assert_prog "! comment one ;\n! comment two ;\n"
133
+ end
134
+
135
+ def test_inline_comment
136
+ parse("foo := R[1] # comment\nfoo = 1 # another comment")
137
+ assert_prog "! comment ;\nR[1:foo]=1 ;\n! another comment ;\n"
138
+ end
139
+
140
+ def test_inline_conditional_if_on_jump
141
+ parse("foo := R[1]\n@bar\njump_to @bar if foo==1\n")
142
+ assert_prog "LBL[100:bar] ;\nIF R[1:foo]=1,JMP LBL[100] ;\n"
143
+ end
144
+
145
+ def test_inline_conditional_unless_on_jump
146
+ parse("foo := R[1]\n@bar\njump_to @bar unless foo==1\n")
147
+ assert_prog "LBL[100:bar] ;\nIF R[1:foo]<>1,JMP LBL[100] ;\n"
148
+ end
149
+
150
+ def test_inline_assignment
151
+ parse("foo := R[1]\nfoo=2 if foo==1\n")
152
+ assert_prog "IF (R[1:foo]=1),R[1:foo]=(2) ;\n"
153
+ end
154
+
155
+ def test_inline_io_method
156
+ parse("foo := DO[1]\nbar := R[1]\nturn_on foo if bar < 10\n")
157
+ assert_prog "IF (R[1:bar]<10),DO[1:foo]=(ON) ;\n"
158
+ end
159
+
160
+ def test_program_call
161
+ parse("foo()")
162
+ assert_prog "CALL FOO ;\n"
163
+ end
164
+
165
+ def test_program_call_with_simple_arg
166
+ parse("foo(1)")
167
+ assert_prog "CALL FOO(1) ;\n"
168
+ end
169
+
170
+ def test_program_call_with_multiple_simple_args
171
+ parse("foo(1,2,3)")
172
+ assert_prog "CALL FOO(1,2,3) ;\n"
173
+ end
174
+
175
+ def test_program_call_with_variable_argument
176
+ parse("foo := R[1]\nbar(foo)")
177
+ assert_prog "CALL BAR(R[1:foo]) ;\n"
178
+ end
179
+
180
+ def test_preserve_whitespace
181
+ parse("\n\n")
182
+ assert_prog " ;\n"
183
+ end
184
+
185
+ def test_plus_equals
186
+ parse("foo := R[1]\nfoo += 1\n")
187
+ assert_prog "R[1:foo]=R[1:foo]+1 ;\n"
188
+ end
189
+
190
+ def test_minus_equals
191
+ parse("foo := R[1]\nfoo -= 1\n")
192
+ assert_prog "R[1:foo]=R[1:foo]-1 ;\n"
193
+ end
194
+
195
+ def test_motion_to_a_position
196
+ parse("foo := P[1]\nlinear_move.to(foo).at(2000, 'mm/s').term(0)")
197
+ assert_prog "L P[1:foo] 2000mm/sec CNT0 ;\n"
198
+ end
199
+
200
+ def test_joint_move
201
+ parse("foo := P[1]\njoint_move.to(foo).at(100, '%').term(0)")
202
+ assert_prog "J P[1:foo] 100% CNT0 ;\n"
203
+ end
204
+
205
+ def test_joint_move_throws_error_with_bad_units
206
+ parse("foo := P[1]\njoint_move.to(foo).at(2000, 'mm/s').term(0)")
207
+ assert_raise(RuntimeError) do
208
+ assert_prog "J P[1:foo] 100% CNT0 ;\n"
209
+ end
210
+ end
211
+
212
+ def test_linear_move_throws_error_with_bad_units
213
+ parse("foo := P[1]\nlinear_move.to(foo).at(100, '%').term(0)")
214
+ assert_raise(RuntimeError) do
215
+ assert_prog "L P[1:foo] 100% CNT0 ;\n"
216
+ end
217
+ end
218
+
219
+
220
+ def test_pr_offset
221
+ parse("home := P[1]\nmy_offset := PR[1]\nlinear_move.to(home).at(2000, 'mm/s').term(0).offset(my_offset)")
222
+ assert_prog "L P[1:home] 2000mm/sec CNT0 Offset,PR[1:my_offset] ;\n"
223
+ end
224
+
225
+ def test_vr_offset
226
+ parse("home := P[1]\nvoff := VR[1]\nlinear_move.to(home).at(2000, 'mm/s').term(0).vision_offset(voff)")
227
+ assert_prog "L P[1:home] 2000mm/sec CNT0 VOFFSET,VR[1:voff] ;\n"
228
+ end
229
+
230
+ def test_time_before
231
+ parse("p := P[1]\nlinear_move.to(p).at(2000, 'mm/s').term(0).time_before(0.5, foo())")
232
+ assert_prog "L P[1:p] 2000mm/sec CNT0 TB .50sec,CALL FOO ;\n"
233
+ end
234
+
235
+ def test_time_after
236
+ parse("p := P[1]\nlinear_move.to(p).at(2000, 'mm/s').term(0).time_after(0.5, foo())")
237
+ assert_prog "L P[1:p] 2000mm/sec CNT0 TA .50sec,CALL FOO ;\n"
238
+ end
239
+
240
+ def test_time_before_with_register_time
241
+ parse("p := P[1]\nt := R[1]\nlinear_move.to(p).at(2000, 'mm/s').term(0).time_before(t, foo())")
242
+ assert_prog "L P[1:p] 2000mm/sec CNT0 TB R[1:t]sec,CALL FOO ;\n"
243
+ end
244
+
245
+ def test_time_before_with_io_method
246
+ parse("p := P[1]\nbar := DO[1]\nlinear_move.to(p).at(2000, 'mm/s').term(0).time_before(0.5, turn_on bar)")
247
+ assert_prog "L P[1:p] 2000mm/sec CNT0 TB .50sec,DO[1:bar]=ON ;\n"
248
+ end
249
+
250
+ def test_motion_with_indirect_termination
251
+ parse("p := P[1]\ncnt := R[1]\nlinear_move.to(p).at(2000, 'mm/s').term(cnt)")
252
+ assert_prog "L P[1:p] 2000mm/sec CNT R[1:cnt] ;\n"
253
+ end
254
+
255
+ def test_motion_with_indirect_speed
256
+ parse("p := P[1]\nspeed := R[1]\nlinear_move.to(p).at(speed, 'mm/s').term(0)")
257
+ assert_prog "L P[1:p] R[1:speed]mm/sec CNT0 ;\n"
258
+ end
259
+
260
+ def test_motion_with_max_speed
261
+ parse("p := P[1]\nlinear_move.to(p).at('max_speed').term(0)")
262
+ assert_prog "L P[1:p] max_speed CNT0 ;\n"
263
+ end
264
+
265
+ def test_use_uframe
266
+ parse("use_uframe 5")
267
+ assert_prog "UFRAME_NUM=5 ;\n"
268
+ end
269
+
270
+ def test_indirect_uframe
271
+ parse("foo := R[1]\nuse_uframe foo")
272
+ assert_prog "UFRAME_NUM=R[1:foo] ;\n"
273
+ end
274
+
275
+ def test_use_utool
276
+ parse("use_utool 5")
277
+ assert_prog "UTOOL_NUM=5 ;\n"
278
+ end
279
+
280
+ def test_indirect_utool
281
+ parse("foo := R[1]\nuse_utool foo")
282
+ assert_prog "UTOOL_NUM=R[1:foo] ;\n"
283
+ end
284
+
285
+ def test_payload
286
+ parse("use_payload 1")
287
+ assert_prog "PAYLOAD[1] ;\n"
288
+ end
289
+
290
+ def test_indirect_payload
291
+ parse("foo := R[1]\nuse_payload foo")
292
+ assert_prog "PAYLOAD[R[1:foo]] ;\n"
293
+ end
294
+
295
+ def test_nested_conditionals
296
+ parse("foo := R[1]\nif foo==1\nif foo==2\nfoo=3\nelse\nfoo=4\nend\nend")
297
+ assert_prog "IF R[1:foo]<>1,JMP LBL[100] ;\nIF R[1:foo]<>2,JMP LBL[101] ;\nR[1:foo]=3 ;\nJMP LBL[102] ;\nLBL[101] ;\nR[1:foo]=4 ;\nLBL[102] ;\nLBL[100] ;\n"
298
+ end
299
+
300
+ def test_inline_unless
301
+ parse("foo := R[1]\n@bar\njump_to @bar unless foo > 1")
302
+ assert_prog "LBL[100:bar] ;\nIF R[1:foo]<=1,JMP LBL[100] ;\n"
303
+ end
304
+
305
+ def test_inline_unless_with_two_vars
306
+ parse("foo := R[1]\nbar := R[2]\n@baz\njump_to @baz unless foo > bar")
307
+ assert_prog "LBL[100:baz] ;\nIF R[1:foo]<=R[2:bar],JMP LBL[100] ;\n"
308
+ end
309
+
310
+ def test_labels_can_be_defined_after_jumps_to_them
311
+ parse("jump_to @foo\n@foo")
312
+ assert_prog "JMP LBL[100] ;\nLBL[100:foo] ;\n"
313
+ end
314
+
315
+ def test_multiple_motion_modifiers
316
+ parse("p := P[1]\no := PR[1]\nlinear_move.to(p).at('max_speed').term(0).offset(o).time_before(0.5,foo())")
317
+ assert_prog "L P[1:p] max_speed CNT0 Offset,PR[1:o] TB .50sec,CALL FOO ;\n"
318
+ end
319
+
320
+ def test_motion_modifiers_swallow_terminators_after_dots
321
+ parse("p := P[1]\no := PR[1]\nlinear_move.\nto(p).\nat('max_speed').\nterm(0).\noffset(o).\ntime_before(0.5,foo())")
322
+ assert_prog "L P[1:p] max_speed CNT0 Offset,PR[1:o] TB .50sec,CALL FOO ;\n"
323
+ end
324
+
325
+ def test_wait_for_with_seconds
326
+ parse("wait_for(5,'s')")
327
+ assert_prog "WAIT 5.00(sec) ;\n"
328
+ end
329
+
330
+ def test_wait_for_with_invalid_units_throws_error
331
+ parse("wait_for(5,'ns')")
332
+ assert_raise(RuntimeError) do
333
+ assert_prog ""
334
+ end
335
+ end
336
+
337
+ def test_wait_for_with_milliseconds
338
+ parse("wait_for(100,'ms')")
339
+ assert_prog "WAIT .10(sec) ;\n"
340
+ end
341
+
342
+ def test_wait_for_with_indirect_seconds
343
+ parse "foo := R[1]\nwait_for(foo, 's')"
344
+ assert_prog "WAIT R[1:foo] ;\n"
345
+ end
346
+
347
+ def test_wait_for_with_indirect_ms
348
+ parse "foo := R[1]\nwait_for(foo, 'ms')"
349
+ assert_raise_message("Runtime error on line 2:\nIndirect values can only use seconds ('s') as the units argument") do
350
+ assert_prog ""
351
+ end
352
+ end
353
+
354
+ def test_wait_until_with_exp
355
+ parse("wait_until(1==0)")
356
+ assert_prog "WAIT (1=0) ;\n"
357
+ end
358
+
359
+ def test_wait_until_with_flag
360
+ parse("foo := F[1]\nwait_until(foo)")
361
+ assert_prog "WAIT (F[1:foo]) ;\n"
362
+ end
363
+
364
+ def test_wait_until_with_di
365
+ parse("foo := DI[1]\nwait_until(foo)")
366
+ assert_prog "WAIT (DI[1:foo]) ;\n"
367
+ end
368
+
369
+ def test_wait_until_with_boolean
370
+ parse("foo := DI[1]\nbar := DI[2]\nwait_until(foo && bar)")
371
+ assert_prog "WAIT (DI[1:foo] AND DI[2:bar]) ;\n"
372
+ end
373
+
374
+ def test_wait_until_with_timeout_to
375
+ parse("wait_until(1==0).timeout_to(@end)\n@end")
376
+ assert_prog "WAIT (1=0) TIMEOUT,LBL[100] ;\nLBL[100:end] ;\n"
377
+ end
378
+
379
+ def test_wait_until_with_timeout_to_and_after
380
+ parse("wait_until(1==0).timeout_to(@end).after(1, 's')\n@end")
381
+ assert_prog "$WAITTMOUT=(100) ;\nWAIT (1=0) TIMEOUT,LBL[100] ;\nLBL[100:end] ;\n"
382
+ end
383
+
384
+ def test_wait_until_after_ms
385
+ parse("wait_until(1==0).timeout_to(@end).after(1000, 'ms')\n@end")
386
+ assert_prog "$WAITTMOUT=(100) ;\nWAIT (1=0) TIMEOUT,LBL[100] ;\nLBL[100:end] ;\n"
387
+ end
388
+
389
+ def test_wait_until_after_indirect
390
+ parse("foo := R[1]\nwait_until(1==0).timeout_to(@end).after(foo, 's')\n@end")
391
+ assert_prog "$WAITTMOUT=(R[1:foo]*100) ;\nWAIT (1=0) TIMEOUT,LBL[100] ;\nLBL[100:end] ;\n"
392
+ end
393
+
394
+ def test_wait_until_with_constant
395
+ parse("WAIT := 5\nwait_until(1==0).timeout_to(@end).after(WAIT, 's')\n@end")
396
+ assert_prog "$WAITTMOUT=(5*100) ;\nWAIT (1=0) TIMEOUT,LBL[100] ;\nLBL[100:end] ;\n"
397
+ end
398
+
399
+ def test_pr_components
400
+ parse("foo := PR[1]\nfoo.x=5\nfoo.y=6\nfoo.z=7\nfoo.w=8\nfoo.p=9\nfoo.r=10\n")
401
+ assert_prog "PR[1,1:foo]=5 ;\nPR[1,2:foo]=6 ;\nPR[1,3:foo]=7 ;\nPR[1,4:foo]=8 ;\nPR[1,5:foo]=9 ;\nPR[1,6:foo]=10 ;\n"
402
+ end
403
+
404
+ #def test_pr_with_invalid_component_raises_error
405
+ # parse("foo := PR[1]\nfoo.bar=5\n")
406
+ # assert_raise(RuntimeError) do
407
+ # assert_prog ""
408
+ # end
409
+ #end
410
+
411
+ def test_simple_case_statement
412
+ parse("foo := R[1]\ncase foo\nwhen 1\njump_to @asdf\nend\n@asdf")
413
+ assert_prog %(SELECT R[1:foo]=1,JMP LBL[100] ;\nLBL[100:asdf] ;\n)
414
+ end
415
+
416
+ def test_simple_case_with_else_statement
417
+ parse("foo := R[1]\ncase foo\nwhen 1\njump_to @asdf\nelse\njump_to @ghjk\nend\n@asdf\n@ghjk")
418
+ assert_prog %(SELECT R[1:foo]=1,JMP LBL[100] ;
419
+ ELSE,JMP LBL[101] ;
420
+ LBL[100:asdf] ;
421
+ LBL[101:ghjk] ;\n)
422
+ end
423
+
424
+ def test_case_statement_with_two_whens
425
+ parse("foo := R[1]\ncase foo\nwhen 1\njump_to @asdf\nwhen 2\njump_to @ghjk\nend\n@asdf\n@ghjk")
426
+ assert_prog %(SELECT R[1:foo]=1,JMP LBL[100] ;
427
+ =2,JMP LBL[101] ;
428
+ LBL[100:asdf] ;
429
+ LBL[101:ghjk] ;\n)
430
+ end
431
+
432
+ def test_case_statement_with_three_whens
433
+ parse("foo := R[1]\ncase foo\nwhen 1\nbar()\nwhen 2\nbar()\nwhen 3\nbar()\nend")
434
+ assert_prog %(SELECT R[1:foo]=1,CALL BAR ;
435
+ =2,CALL BAR ;
436
+ =3,CALL BAR ;\n)
437
+ end
438
+
439
+ def test_case_statement_with_three_whens_and_else
440
+ parse("foo := R[1]\ncase foo\nwhen 1\nbar()\nwhen 2\nbar()\nwhen 3\nbar()\nelse\nbar()\nend")
441
+ assert_prog %(SELECT R[1:foo]=1,CALL BAR ;
442
+ =2,CALL BAR ;
443
+ =3,CALL BAR ;
444
+ ELSE,CALL BAR ;\n)
445
+ end
446
+
447
+ def test_can_use_simple_io_value_as_condition
448
+ parse("foo := UI[5]\n@top\njump_to @top if foo")
449
+ assert_prog "LBL[100:top] ;\nIF (UI[5:foo]),JMP LBL[100] ;\n"
450
+ end
451
+
452
+ def test_can_use_simple_io_value_as_condition_with_unless
453
+ parse("foo := UI[5]\n@top\njump_to @top unless foo")
454
+ assert_prog "LBL[100:top] ;\nIF (!UI[5:foo]),JMP LBL[100] ;\n"
455
+ end
456
+
457
+ def test_inline_program_call
458
+ parse("foo := UI[5]\nbar() unless foo")
459
+ assert_prog "IF (!UI[5:foo]),CALL BAR ;\n"
460
+ end
461
+
462
+ def test_constant_definition
463
+ parse("FOO := 5\nfoo := R[1]\nfoo = FOO")
464
+ assert_prog "R[1:foo]=5 ;\n"
465
+ end
466
+
467
+ def test_constant_definition_real
468
+ parse("PI := 3.14159\nfoo:= R[1]\nfoo = PI")
469
+ assert_prog "R[1:foo]=3.14159 ;\n"
470
+ end
471
+
472
+ def test_redefining_const_throws_error
473
+ assert_raise(RuntimeError) do
474
+ parse("PI := 3.14\nPI := 5")
475
+ assert_prog ""
476
+ end
477
+ end
478
+
479
+ def test_defining_const_without_caps_raises_error
480
+ parse("pi := 3.14")
481
+ assert_raise(RuntimeError) do
482
+ assert_prog ""
483
+ end
484
+ end
485
+
486
+ def test_using_argument_var
487
+ parse("foo := AR[1]\n@top\njump_to @top if foo==1")
488
+ assert_prog "LBL[100:top] ;\nIF (AR[1]=1),JMP LBL[100] ;\n"
489
+ end
490
+
491
+ def test_use_uframe_with_constant
492
+ parse("FOO := 1\nuse_uframe FOO")
493
+ assert_prog "UFRAME_NUM=1 ;\n"
494
+ end
495
+
496
+ def test_set_uframe_with_pr
497
+ parse("foo := PR[1]\nindirect('uframe',5)=foo")
498
+ assert_prog "UFRAME[5]=PR[1:foo] ;\n"
499
+ end
500
+
501
+ def test_set_uframe_with_constant
502
+ parse("foo := PR[1]\nBAR := 5\nindirect('uframe',BAR)=foo")
503
+ assert_prog "UFRAME[5]=PR[1:foo] ;\n"
504
+ end
505
+
506
+ def test_fanuc_set_uframe_with_reg
507
+ parse("foo := PR[1]\nbar := R[1]\nindirect('uframe',bar)=foo")
508
+ assert_prog "UFRAME[R[1:bar]]=PR[1:foo] ;\n"
509
+ end
510
+
511
+ def test_set_skip_condition
512
+ parse("foo := RI[1]\nset_skip_condition foo")
513
+ assert_prog "SKIP CONDITION RI[1:foo]=ON ;\n"
514
+ end
515
+
516
+ def test_set_skip_condition_with_bang
517
+ parse("foo := RI[1]\nset_skip_condition !foo")
518
+ assert_prog "SKIP CONDITION RI[1:foo]=OFF ;\n"
519
+ end
520
+
521
+ def test_skip_to
522
+ parse("p := P[1]\n@somewhere\nlinear_move.to(p).at(2000,'mm/s').term(0).skip_to(@somewhere)")
523
+ assert_prog "LBL[100:somewhere] ;\nL P[1:p] 2000mm/sec CNT0 Skip,LBL[100] ;\n"
524
+ end
525
+
526
+ def test_skip_to_with_pr
527
+ parse("p := P[1]\nlpos := PR[1]\n@somewhere\nlinear_move.to(p).at(2000,'mm/s').term(0).skip_to(@somewhere, lpos)")
528
+ assert_prog "LBL[100:somewhere] ;\nL P[1:p] 2000mm/sec CNT0 Skip,LBL[100],PR[1:lpos]=LPOS ;\n"
529
+ end
530
+
531
+ def test_label_comment_automatically_adds_a_comment_if_over_16_chars
532
+ parse("@foo_bar_foo_bar_foo")
533
+ assert_prog "LBL[100:foo_bar_foo_bar_] ;\n! foo_bar_foo_bar_foo ;\n"
534
+ end
535
+
536
+ def test_automatic_long_comment_wrapping
537
+ parse("# this is a really long comment so it should wrap")
538
+ assert_prog "! this is a really long comment ;\n! so it should wrap ;\n"
539
+ end
540
+
541
+ def test_turning_on_a_flag_requires_mixed_logic
542
+ parse("foo := F[1]\nturn_on foo")
543
+ assert_prog "F[1:foo]=(ON) ;\n"
544
+ end
545
+
546
+ def test_boolean_assignment
547
+ parse("foo := F[1]\nfoo = 1 && 1")
548
+ assert_prog "F[1:foo]=(1 AND 1) ;\n"
549
+ end
550
+
551
+ def test_simple_math
552
+ parse("foo := R[1]\nfoo=1+1")
553
+ assert_prog "R[1:foo]=1+1 ;\n"
554
+ end
555
+
556
+ def test_more_complicated_math
557
+ parse("foo := R[1]\nfoo=1+2+3")
558
+ assert_prog "R[1:foo]=(1+2+3) ;\n"
559
+ end
560
+
561
+ def test_operator_precedence
562
+ parse "foo := R[1]\nfoo=1+2*3"
563
+ assert_prog "R[1:foo]=(1+2*3) ;\n"
564
+ end
565
+
566
+ def test_expression_grouping
567
+ parse "foo := R[1]\nfoo=(1+2)*3"
568
+ assert_prog "R[1:foo]=((1+2)*3) ;\n"
569
+ end
570
+
571
+ def test_boolean_expression
572
+ parse "foo := F[1]\nfoo = 1 || 1 && 0"
573
+ assert_prog "F[1:foo]=(1 OR 1 AND 0) ;\n"
574
+ end
575
+
576
+ def test_bang
577
+ parse "foo := F[1]\nbar := F[2]\nfoo = !bar"
578
+ assert_prog "F[1:foo]=(!F[2:bar]) ;\n"
579
+ end
580
+
581
+ # issue #15 https://github.com/onerobotics/tp_plus/issues/15
582
+ def test_assign_output_to_ro
583
+ parse "foo := DO[1]\nbar := RO[1]\nfoo = bar"
584
+ assert_prog "DO[1:foo]=(RO[1:bar]) ;\n"
585
+ end
586
+
587
+ def test_assign_output_to_numreg_requires_no_parens
588
+ parse "foo := DO[1]\nbar := R[1]\nfoo = bar"
589
+ assert_prog "DO[1:foo]=R[1:bar] ;\n"
590
+ end
591
+
592
+ # issue #16 https://github.com/onerobotics/tp_plus/issues/16
593
+ def test_negative_assignment
594
+ parse "foo := R[1]\nfoo = -foo"
595
+ assert_prog "R[1:foo]=R[1:foo]*(-1) ;\n"
596
+ end
597
+
598
+ def test_bang_with_grouping
599
+ parse "foo := F[1]\nbar := F[2]\nbaz := F[3]\nfoo = foo || !(bar || baz)"
600
+ assert_prog "F[1:foo]=(F[1:foo] OR !(F[2:bar] OR F[3:baz])) ;\n"
601
+ end
602
+
603
+ def test_opposite_flag_in_simple_if
604
+ parse "foo := F[1]\nif foo\n# foo is true\nend"
605
+ assert_prog "IF (!F[1:foo]),JMP LBL[100] ;\n! foo is true ;\nLBL[100] ;\n"
606
+ end
607
+
608
+ def test_opposite_with_boolean_and
609
+ parse "foo := F[1]\nbar := F[2]\nbaz := F[3]\nif foo && bar && baz\n#foo, bar and baz are true\nend"
610
+ assert_prog "IF (!F[1:foo] OR !F[2:bar] OR !F[3:baz]),JMP LBL[100] ;\n! foo, bar and baz are true ;\nLBL[100] ;\n"
611
+ end
612
+
613
+ def test_opposite_with_boolean_or
614
+ parse "foo := F[1]\nbar := F[2]\nbaz := F[3]\nif foo || bar || baz\n#foo or bar or baz is true\nend"
615
+ assert_prog "IF (!F[1:foo] AND !F[2:bar] AND !F[3:baz]),JMP LBL[100] ;\n! foo or bar or baz is true ;\nLBL[100] ;\n"
616
+ end
617
+
618
+ def test_opposite_flag_in_simple_unless
619
+ parse "foo := F[1]\nunless foo\n# foo is false\nend"
620
+ assert_prog "IF (F[1:foo]),JMP LBL[100] ;\n! foo is false ;\nLBL[100] ;\n"
621
+ end
622
+
623
+ def test_inline_if_with_flag
624
+ parse "foo := F[1]\njump_to @end if foo\n@end"
625
+ assert_prog "IF (F[1:foo]),JMP LBL[100] ;\nLBL[100:end] ;\n"
626
+ end
627
+
628
+ def test_inline_unless_with_flag
629
+ parse "foo := F[1]\njump_to @end unless foo\n@end"
630
+ assert_prog "IF (!F[1:foo]),JMP LBL[100] ;\nLBL[100:end] ;\n"
631
+ end
632
+
633
+ def test_automatic_parens_on_boolean
634
+ parse "foo := F[1]\njump_to @end if foo || foo\n@end"
635
+ assert_prog "IF (F[1:foo] OR F[1:foo]),JMP LBL[100] ;\nLBL[100:end] ;\n"
636
+ end
637
+
638
+ def test_no_extra_parens_with_booleans
639
+ parse "foo := F[1]\njump_to @end if foo || foo || foo\n@end"
640
+ assert_prog "IF (F[1:foo] OR F[1:foo] OR F[1:foo]),JMP LBL[100] ;\nLBL[100:end] ;\n"
641
+ end
642
+
643
+ def test_assignment_as_bool_result
644
+ parse "foo := F[1]\nbar := R[1]\nfoo = bar == 1"
645
+ assert_prog "F[1:foo]=(R[1:bar]=1) ;\n"
646
+ end
647
+
648
+ def test_args_dont_get_comments
649
+ parse "foo := AR[1]\njump_to @end if foo == 1\n@end"
650
+ assert_prog "IF (AR[1]=1),JMP LBL[100] ;\nLBL[100:end] ;\n"
651
+ end
652
+
653
+ def test_indirect_position_assignment
654
+ parse "foo := PR[1]\nfoo = indirect('p',5)"
655
+ assert_prog "PR[1:foo]=P[5] ;\n"
656
+ end
657
+
658
+ # Issue #11
659
+ def test_indirect_gi
660
+ parse "foo := R[1]\nbar := R[2]\nfoo = indirect('gi', bar)"
661
+ assert_prog "R[1:foo]=GI[R[2:bar]] ;\n"
662
+ end
663
+
664
+ def test_indirect_indirect_position_assignment
665
+ parse "foo := PR[1]\nbar := R[1]\nfoo = indirect('p',bar)"
666
+ assert_prog "PR[1:foo]=P[R[1:bar]] ;\n"
667
+ end
668
+
669
+ def test_indirect_posreg_assignment
670
+ parse "foo := PR[1]\nfoo = indirect('pr',5)"
671
+ assert_prog "PR[1:foo]=PR[5] ;\n"
672
+ end
673
+
674
+ def test_add_posregs
675
+ parse "a := PR[1]\nb := PR[2]\nc := PR[3]\nd := PR[4]\na=b+c+d"
676
+ assert_prog "PR[1:a]=PR[2:b]+PR[3:c]+PR[4:d] ;\n"
677
+ end
678
+
679
+ def test_namespace
680
+ parse "namespace Foo\nbar := R[1]\nend\nFoo::bar = 5"
681
+ assert_prog "R[1:Foo bar]=5 ;\n"
682
+ end
683
+
684
+ def test_no_namespace_collision
685
+ parse "namespace Foo\nbar := R[1]\nend\nbar := R[2]\nbar = 2\nFoo::bar = 1"
686
+ assert_prog "R[2:bar]=2 ;\nR[1:Foo bar]=1 ;\n"
687
+ end
688
+
689
+ def test_namespace_constant_definition
690
+ parse "namespace Math\nPI := 3.14\nend\nfoo := R[1]\nfoo = Math::PI"
691
+ assert_prog "R[1:foo]=3.14 ;\n"
692
+ end
693
+
694
+ def test_namespace_swallows_everything
695
+ parse "namespace Foo\n# this is a comment\n#this is another comment\nend"
696
+ assert_prog ""
697
+ end
698
+
699
+ def test_nested_namespace
700
+ parse %(namespace Foo
701
+ bar := R[1]
702
+ namespace Bar
703
+ baz := R[2]
704
+ end
705
+ end
706
+ Foo::bar = 1
707
+ Foo::Bar::baz = 2)
708
+ assert_prog "R[1:Foo bar]=1 ;\nR[2:Foo Bar baz]=2 ;\n"
709
+ end
710
+
711
+ def test_load_environment
712
+ environment = "foo := R[1]\nbar := R[2]\n#asdf\n#asdf"
713
+ @interpreter.load_environment(environment)
714
+ parse "foo = 5"
715
+ assert_prog "R[1:foo]=5 ;\n"
716
+ assert_equal 1, @interpreter.source_line_count
717
+ end
718
+
719
+ def test_load_environment_only_saves_definitions_etc
720
+ environment = "foo := R[1]\nbar := R[2]\n#asdf\n#asdf\nfoo=3"
721
+ @interpreter.load_environment(environment)
722
+ parse "foo = 5"
723
+ assert_prog "R[1:foo]=5 ;\n"
724
+ assert_equal 1, @interpreter.source_line_count
725
+ end
726
+
727
+
728
+ def test_bad_environment
729
+ assert_raise(TPPlus::Parser::ParseError) do
730
+ @interpreter.load_environment("asdf")
731
+ end
732
+ end
733
+
734
+ def test_inline_conditional_with_namespaced_var
735
+ parse "namespace Foo\nbar := DI[1]\nend\njump_to @end unless Foo::bar\n@end"
736
+ assert_prog "IF (!DI[1:Foo bar]),JMP LBL[100] ;\nLBL[100:end] ;\n"
737
+ end
738
+
739
+ def test_namespaced_var_as_condition
740
+ parse "namespace Foo\nbar := DI[1]\nend\nif Foo::bar\n# bar is on\nend"
741
+ assert_prog "IF (!DI[1:Foo bar]),JMP LBL[100] ;\n! bar is on ;\nLBL[100] ;\n"
742
+ end
743
+
744
+ def test_reopen_namespace
745
+ parse "namespace Foo\nbar := R[1]\nend\nnamespace Foo\nbaz := R[2]\nend\nFoo::bar = 1\nFoo::baz = 2"
746
+ assert_prog "R[1:Foo bar]=1 ;\nR[2:Foo baz]=2 ;\n"
747
+ end
748
+
749
+ def test_eval
750
+ parse %(eval "R[1]=5")
751
+ assert_prog "R[1]=5 ;\n"
752
+ end
753
+
754
+ def test_multiline_eval
755
+ parse %(eval "R[1]=5 ;\nR[2]=3")
756
+ assert_prog "R[1]=5 ;\nR[2]=3 ;\n"
757
+ end
758
+
759
+ def test_namespaced_position_reg_component
760
+ parse "namespace Fixture\npick_offset := PR[1]\nend\nFixture::pick_offset.x = 10"
761
+ assert_prog "PR[1,1:Fixture pick_offset]=10 ;\n"
762
+ end
763
+
764
+ def test_inline_program_call_two
765
+ parse "foo := R[1]\nbar() if foo >= 5"
766
+ assert_prog "IF R[1:foo]>=5,CALL BAR ;\n"
767
+ end
768
+
769
+ def test_forlooop
770
+ parse "foo := R[1]\nfor foo in (1 to 10)\n# bar\nend"
771
+ assert_prog "FOR R[1:foo]=1 TO 10 ;\n! bar ;\nENDFOR ;\n"
772
+ end
773
+
774
+ def test_forloop_with_vars
775
+ parse "foo := R[1]\nmin := R[2]\nmax := R[3]\nfor foo in (min to max)\n#bar\nend"
776
+ assert_prog "FOR R[1:foo]=R[2:min] TO R[3:max] ;\n! bar ;\nENDFOR ;\n"
777
+ end
778
+
779
+ def test_indirect_flag
780
+ parse "foo := R[1]\nturn_on indirect('f',foo)"
781
+ assert_prog "F[R[1:foo]]=(ON) ;\n"
782
+ end
783
+
784
+ def test_indirect_flag_condition
785
+ parse "foo := R[1]\njump_to @end if indirect('f',foo)\n@end"
786
+ assert_prog "IF (F[R[1:foo]]),JMP LBL[100] ;\nLBL[100:end] ;\n"
787
+ end
788
+
789
+ def test_indirect_flag_condition_not_inline
790
+ parse "foo := R[1]\nif indirect('f',foo)\n# bar\nend"
791
+ assert_prog "IF (!F[R[1:foo]]),JMP LBL[100] ;\n! bar ;\nLBL[100] ;\n"
792
+ end
793
+
794
+ def test_indirect_unless_flag_condition
795
+ parse "foo := R[1]\njump_to @end unless indirect('f',foo)\n@end"
796
+ assert_prog "IF (!F[R[1:foo]]),JMP LBL[100] ;\nLBL[100:end] ;\n"
797
+ end
798
+
799
+ def test_indirect_flag_with_if_bang
800
+ parse "foo := R[1]\njump_to @end if !indirect('f',foo)\n@end"
801
+ assert_prog "IF (!F[R[1:foo]]),JMP LBL[100] ;\nLBL[100:end] ;\n"
802
+ end
803
+
804
+ def test_while_loop
805
+ parse "foo := R[1]\nwhile foo < 10\n# bar\nend"
806
+ assert_prog "LBL[100] ;\nIF R[1:foo]>=10,JMP LBL[101] ;\n! bar ;\nJMP LBL[100] ;\nLBL[101] ;\n"
807
+ end
808
+
809
+ def test_while_with_not_flag
810
+ parse "foo := F[1]\nwhile !foo\n#bar\nend"
811
+ assert_prog "LBL[100] ;\nIF (F[1:foo]),JMP LBL[101] ;\n! bar ;\nJMP LBL[100] ;\nLBL[101] ;\n"
812
+ end
813
+
814
+ def test_while_with_flag
815
+ parse "foo := F[1]\nwhile foo\n#bar\nend"
816
+ assert_prog "LBL[100] ;\nIF (!F[1:foo]),JMP LBL[101] ;\n! bar ;\nJMP LBL[100] ;\nLBL[101] ;\n"
817
+ end
818
+
819
+ def test_timer_start
820
+ parse "foo := TIMER[1]\nstart foo"
821
+ assert_prog "TIMER[1]=START ;\n"
822
+ end
823
+
824
+ def test_timer_reset
825
+ parse "foo := TIMER[1]\nreset foo"
826
+ assert_prog "TIMER[1]=RESET ;\n"
827
+ end
828
+
829
+ def test_timer_stop
830
+ parse "foo := TIMER[1]\nstop foo"
831
+ assert_prog "TIMER[1]=STOP ;\n"
832
+ end
833
+
834
+ def test_timer_restart
835
+ parse "foo := TIMER[1]\nrestart foo"
836
+ assert_prog "TIMER[1]=STOP ;\nTIMER[1]=RESET ;\nTIMER[1]=START ;\n"
837
+ end
838
+
839
+ def test_indirect_timer
840
+ parse "foo := R[1]\nfoo = indirect('timer', 3)"
841
+ assert_prog "R[1:foo]=TIMER[3] ;\n"
842
+ end
843
+
844
+ def test_indirect_indirect_timer
845
+ parse "foo := R[1]\nfoo = indirect('timer', foo)"
846
+ assert_prog "R[1:foo]=TIMER[R[1:foo]] ;\n"
847
+ end
848
+
849
+ def test_start_indirect_timer
850
+ parse "start indirect('timer', 3)"
851
+ assert_prog "TIMER[3]=START ;\n"
852
+ end
853
+
854
+ def test_start_indirect_indirect_timer
855
+ parse "foo := R[1]\nstart indirect('timer', foo)"
856
+ assert_prog "TIMER[R[1:foo]]=START ;\n"
857
+ end
858
+
859
+ def test_position_data_does_not_output_with_eval
860
+ parse %(position_data
861
+ {
862
+ 'positions': [
863
+ {
864
+ 'id': 1,
865
+ 'comment': "test",
866
+ 'mask' : [{
867
+ 'group': 1,
868
+ 'uframe': 1,
869
+ 'utool': 1,
870
+ 'config': {
871
+ 'flip': true,
872
+ 'up': true,
873
+ 'top': false,
874
+ 'turn_counts': [-1,0,1]
875
+ },
876
+ 'components': {
877
+ 'x': -50.0,
878
+ 'y': 0.0,
879
+ 'z': 0.0,
880
+ 'w': 0.0,
881
+ 'p': 0.0,
882
+ 'r': 0.0
883
+ }
884
+ }]
885
+ }
886
+ ]
887
+ }
888
+ end)
889
+
890
+ assert_prog ""
891
+ end
892
+
893
+ def test_position_data_populates_interpreter_position_data
894
+ parse %(position_data
895
+ {
896
+ 'positions': [
897
+ {
898
+ 'id': 1,
899
+ 'comment': "test",
900
+ 'mask': [{
901
+ 'group': 1,
902
+ 'uframe': 1,
903
+ 'utool': 1,
904
+ 'config': {
905
+ 'flip': true,
906
+ 'up': true,
907
+ 'top': false,
908
+ 'turn_counts': [0,0,0]
909
+ },
910
+ 'components': {
911
+ 'x': 0.0,
912
+ 'y': 0.0,
913
+ 'z': 0.0,
914
+ 'w': 0.0,
915
+ 'p': 0.0,
916
+ 'r': 0.0
917
+ }
918
+ }]
919
+ }
920
+ ]
921
+ }
922
+ end)
923
+
924
+ assert_prog ""
925
+ assert_equal 1, @interpreter.position_data[:positions].length
926
+ end
927
+
928
+ def test_throws_a_fault_if_position_data_invalid
929
+ parse %(position_data
930
+ {
931
+ 'positions' : "asdf"
932
+ }
933
+ end)
934
+ assert_raise(RuntimeError) do
935
+ @interpreter.eval
936
+ end
937
+ end
938
+
939
+ def test_outputs_position_data_correctly
940
+ parse %(position_data
941
+ {
942
+ 'positions': [
943
+ {
944
+ 'id': 1,
945
+ 'comment': "test",
946
+ 'mask' : [{
947
+ 'group': 1,
948
+ 'uframe': 1,
949
+ 'utool': 1,
950
+ 'config': {
951
+ 'flip': true,
952
+ 'up': true,
953
+ 'top': true,
954
+ 'turn_counts': [0,0,0]
955
+ },
956
+ 'components': {
957
+ 'x': 0.0,
958
+ 'y': 0.0,
959
+ 'z': 0.0,
960
+ 'w': 0.0,
961
+ 'p': 0.0,
962
+ 'r': 0.0
963
+ }
964
+ }]
965
+ }
966
+ ]
967
+ }
968
+ end)
969
+
970
+ assert_prog ""
971
+ assert_equal %(P[1:"test"]{
972
+ GP1:
973
+ UF : 1, UT : 1, CONFIG : 'F U T, 0, 0, 0',
974
+ X = 0.0 mm, Y = 0.0 mm, Z = 0.0 mm,
975
+ W = 0.0 deg, P = 0.0 deg, R = 0.0 deg
976
+ };\n), @interpreter.pos_section
977
+ end
978
+
979
+ def test_outputs_position_data_correctly_with_two_positions
980
+ parse %(position_data
981
+ {
982
+ 'positions': [
983
+ {
984
+ 'id': 1,
985
+ 'comment': "test",
986
+ 'mask': [{
987
+ 'group': 1,
988
+ 'uframe': 1,
989
+ 'utool': 1,
990
+ 'config': {
991
+ 'flip': true,
992
+ 'up': true,
993
+ 'top': true,
994
+ 'turn_counts': [0,0,0]
995
+ },
996
+ 'components': {
997
+ 'x': 0.0,
998
+ 'y': 0.0,
999
+ 'z': 0.0,
1000
+ 'w': 0.0,
1001
+ 'p': 0.0,
1002
+ 'r': 0.0
1003
+ }
1004
+ }]
1005
+ },
1006
+ {
1007
+ 'id': 2,
1008
+ 'comment': "test2",
1009
+ 'mask': [{
1010
+ 'group': 1,
1011
+ 'uframe': 1,
1012
+ 'utool': 1,
1013
+ 'config': {
1014
+ 'flip': true,
1015
+ 'up': true,
1016
+ 'top': true,
1017
+ 'turn_counts': [0,0,0]
1018
+ },
1019
+ 'components': {
1020
+ 'x': 0.0,
1021
+ 'y': 0.0,
1022
+ 'z': 0.0,
1023
+ 'w': 0.0,
1024
+ 'p': 0.0,
1025
+ 'r': 0.0
1026
+ }
1027
+ }]
1028
+ }
1029
+ ]
1030
+ }
1031
+ end)
1032
+
1033
+ assert_prog ""
1034
+ assert_equal %(P[1:"test"]{
1035
+ GP1:
1036
+ UF : 1, UT : 1, CONFIG : 'F U T, 0, 0, 0',
1037
+ X = 0.0 mm, Y = 0.0 mm, Z = 0.0 mm,
1038
+ W = 0.0 deg, P = 0.0 deg, R = 0.0 deg
1039
+ };
1040
+ P[2:"test2"]{
1041
+ GP1:
1042
+ UF : 1, UT : 1, CONFIG : 'F U T, 0, 0, 0',
1043
+ X = 0.0 mm, Y = 0.0 mm, Z = 0.0 mm,
1044
+ W = 0.0 deg, P = 0.0 deg, R = 0.0 deg
1045
+ };\n), @interpreter.pos_section
1046
+ end
1047
+
1048
+ def test_simple_pulse
1049
+ parse "foo := DO[1]\npulse foo"
1050
+ assert_prog "DO[1:foo]=PULSE ;\n"
1051
+ end
1052
+
1053
+ def test_pulse_for_seconds
1054
+ parse "foo := DO[1]\npulse(foo,5,'s')"
1055
+ assert_prog "DO[1:foo]=PULSE,5.0sec ;\n"
1056
+ end
1057
+
1058
+ def test_pulse_for_ms
1059
+ parse "foo := DO[1]\npulse(foo,500,'ms')"
1060
+ assert_prog "DO[1:foo]=PULSE,0.5sec ;\n"
1061
+ end
1062
+
1063
+ def test_indirect_numreg
1064
+ parse "foo := R[1]\nindirect('r',foo) = 5"
1065
+ assert_prog "R[R[1:foo]]=5 ;\n"
1066
+ end
1067
+
1068
+ def test_raise
1069
+ parse "my_alarm := UALM[1]\nraise my_alarm"
1070
+ assert_prog "UALM[1] ;\n"
1071
+ end
1072
+
1073
+ def test_indirect_raise
1074
+ parse "raise indirect('ualm',1)"
1075
+ assert_prog "UALM[1] ;\n"
1076
+ end
1077
+
1078
+ def test_indirect_indirect_raise
1079
+ parse "foo := R[1]\nraise indirect('ualm',foo)"
1080
+ assert_prog "UALM[R[1:foo]] ;\n"
1081
+ end
1082
+
1083
+ def test_namespaced_pr_component_assignment
1084
+ parse "namespace Foo\nbar := PR[1]\nend\nFoo::bar.x = 10"
1085
+ assert_prog "PR[1,1:Foo bar]=10 ;\n"
1086
+ end
1087
+
1088
+ def test_namespaced_pr_component_plus_equals
1089
+ parse "namespace Foo\nbar := PR[1]\nend\nFoo::bar.x += 10"
1090
+ assert_prog "PR[1,1:Foo bar]=PR[1,1:Foo bar]+10 ;\n"
1091
+ end
1092
+
1093
+ def test_namespaced_pr_component_in_expression
1094
+ parse "namespace Foo\nbar := PR[1]\nend\nFoo::bar.x += Foo::bar.x * 10 \n"
1095
+ assert_prog "PR[1,1:Foo bar]=(PR[1,1:Foo bar]+PR[1,1:Foo bar]*10) ;\n"
1096
+ end
1097
+
1098
+ def test_namespaced_pr_assignment_then_expression
1099
+ parse "namespace Foo\nbar := PR[1]\nend\nbaz := P[1]\nFoo::bar = baz\nFoo::bar.x += 5"
1100
+ assert_prog "PR[1:Foo bar]=P[1:baz] ;\nPR[1,1:Foo bar]=PR[1,1:Foo bar]+5 ;\n"
1101
+ end
1102
+
1103
+ def test_wait_until_does_not_get_inlined
1104
+ parse "foo := DO[1]\nunless foo\nwait_until(foo)\nend"
1105
+ assert_prog "IF (DO[1:foo]),JMP LBL[100] ;\nWAIT (DO[1:foo]) ;\nLBL[100] ;\n"
1106
+ end
1107
+
1108
+ def test_wait_for_does_not_get_inlined
1109
+ parse "foo := DO[1]\nunless foo\nwait_for(1,'s')\nend"
1110
+ assert_prog "IF (DO[1:foo]),JMP LBL[100] ;\nWAIT 1.00(sec) ;\nLBL[100] ;\n"
1111
+ end
1112
+
1113
+ def test_inline_conditional_does_not_get_inlined
1114
+ parse "foo := DO[1]\nif foo\nturn_off foo if foo\nend"
1115
+ assert_prog "IF (!DO[1:foo]),JMP LBL[100] ;\nIF (DO[1:foo]),DO[1:foo]=(OFF) ;\nLBL[100] ;\n"
1116
+ end
1117
+
1118
+ def test_run
1119
+ parse "run foo()"
1120
+ assert_prog "RUN FOO ;\n"
1121
+ end
1122
+
1123
+ def test_tp_ignore_pause
1124
+ parse "TP_IGNORE_PAUSE = true"
1125
+ assert_prog ""
1126
+ assert @interpreter.header_data[:ignore_pause]
1127
+ end
1128
+
1129
+ def test_tp_subtype
1130
+ parse "TP_SUBTYPE = 'macro'"
1131
+ assert_prog ""
1132
+ assert_equal :macro, @interpreter.header_data[:subtype]
1133
+ end
1134
+
1135
+ def test_tp_comment
1136
+ parse %(TP_COMMENT = "foo")
1137
+ assert_prog ""
1138
+ assert_equal "foo", @interpreter.header_data[:comment]
1139
+ end
1140
+
1141
+ def test_tp_groupmask
1142
+ parse %(TP_GROUPMASK = "*,*,*,*,*")
1143
+ assert_prog ""
1144
+ assert_equal "*,*,*,*,*", @interpreter.header_data[:group_mask]
1145
+ end
1146
+
1147
+ def test_mixed_logic_or
1148
+ parse %(foo := DI[1]\nbar := DI[2]\nif foo || bar\n# do something\nend)
1149
+ assert_prog "IF (!DI[1:foo] AND !DI[2:bar]),JMP LBL[100] ;\n! do something ;\nLBL[100] ;\n"
1150
+ end
1151
+
1152
+ def test_flag_assignment_always_gets_parens
1153
+ parse %(foo := F[1]\nbar := DI[2]\nfoo = bar)
1154
+ assert_prog "F[1:foo]=(DI[2:bar]) ;\n"
1155
+ end
1156
+
1157
+ def test_tool_offset
1158
+ parse %(p := P[1]\ntoff := PR[1]\nlinear_move.to(p).at(2000,'mm/s').term(0).tool_offset(toff))
1159
+ assert_prog "L P[1:p] 2000mm/sec CNT0 Tool_Offset,PR[1:toff] ;\n"
1160
+ end
1161
+
1162
+ def test_wait_for_digit
1163
+ parse %(wait_for(1,'s'))
1164
+ assert_prog "WAIT 1.00(sec) ;\n"
1165
+ end
1166
+
1167
+ def test_wait_for_real
1168
+ parse %(wait_for(0.5,'s'))
1169
+ assert_prog "WAIT .50(sec) ;\n"
1170
+ end
1171
+
1172
+ def test_wait_for_real_const
1173
+ parse %(FOO := 0.5\nwait_for(FOO,'s'))
1174
+ assert_prog "WAIT .50(sec) ;\n"
1175
+ end
1176
+
1177
+ def test_negative_numbers_have_parens
1178
+ parse %(foo := R[1]\njump_to @end if foo > -1\njump_to @end if foo > -5.3\n@end)
1179
+ assert_prog "IF R[1:foo]>(-1),JMP LBL[100] ;\nIF R[1:foo]>(-5.3),JMP LBL[100] ;\nLBL[100:end] ;\n"
1180
+ end
1181
+
1182
+ def test_modulus
1183
+ parse %(foo := R[1]\nfoo = 5 % 2)
1184
+ assert_prog "R[1:foo]=5 MOD 2 ;\n"
1185
+ end
1186
+
1187
+ def test_assignment_to_sop
1188
+ parse %(foo := DO[1]\nbar := SO[1]\nfoo = bar)
1189
+ assert_prog "DO[1:foo]=(SO[1:bar]) ;\n"
1190
+ end
1191
+
1192
+ def test_assignment_to_di
1193
+ parse %(foo := DO[1]\nbar := DI[1]\nfoo = bar)
1194
+ assert_prog "DO[1:foo]=(DI[1:bar]) ;\n"
1195
+ end
1196
+
1197
+ def test_string_register_definition
1198
+ parse %(foo := SR[1]\nbar := SR[2]\nfoo = bar)
1199
+ assert_prog "SR[1:foo]=SR[2:bar] ;\n"
1200
+ end
1201
+
1202
+ def test_string_argument
1203
+ parse %(foo('bar'))
1204
+ assert_prog "CALL FOO('bar') ;\n"
1205
+ end
1206
+
1207
+ def test_pause
1208
+ parse %(pause)
1209
+ assert_prog "PAUSE ;\n"
1210
+ end
1211
+
1212
+ def test_abort
1213
+ parse %(abort)
1214
+ assert_prog "ABORT ;\n"
1215
+ end
1216
+
1217
+ def test_div
1218
+ parse %(foo := R[1]\nfoo = 1 DIV 5)
1219
+ assert_prog "R[1:foo]=1 DIV 5 ;\n"
1220
+ end
1221
+
1222
+ def test_conditional_equals
1223
+ parse("foo := R[1]\nfoo2 := R[2]\nif foo == foo2\nfoo = 1\nfoo2 = 2\nend")
1224
+ assert_prog "IF R[1:foo]<>R[2:foo2],JMP LBL[100] ;\nR[1:foo]=1 ;\nR[2:foo2]=2 ;\nLBL[100] ;\n"
1225
+ end
1226
+
1227
+ def test_if_statement_multiple_arguments
1228
+ parse("foo := R[1]\nfoo2 := R[2]\nif foo == 1 && foo2 == 2\nfoo = 1\nfoo2 = 2\nend")
1229
+ assert_prog "IF (R[1:foo]<>1 OR R[2:foo2]<>2),JMP LBL[100] ;\nR[1:foo]=1 ;\nR[2:foo2]=2 ;\nLBL[100] ;\n"
1230
+ end
1231
+
1232
+ def test_parse_error_on_invalid_term
1233
+ assert_raise do
1234
+ parse("foo := PR[1]\nlinear_move.to(foo).at(2000, 'mm/s').term(-2)")
1235
+ end
1236
+ end
1237
+
1238
+ def test_acc_zero
1239
+ parse("foo := PR[1]\nlinear_move.to(foo).at(2000, 'mm/s').term(0).acc(0)")
1240
+ assert_prog "L PR[1:foo] 2000mm/sec CNT0 ACC0 ;\n"
1241
+ end
1242
+
1243
+ def test_acc_150
1244
+ parse("foo := PR[1]\nlinear_move.to(foo).at(2000, 'mm/s').term(0).acc(150)")
1245
+ assert_prog "L PR[1:foo] 2000mm/sec CNT0 ACC150 ;\n"
1246
+ end
1247
+
1248
+ def test_acc_with_constant
1249
+ parse("foo := PR[1]\nBAR := 50\nlinear_move.to(foo).at(2000, 'mm/s').term(0).acc(BAR)")
1250
+ assert_prog "L PR[1:foo] 2000mm/sec CNT0 ACC50 ;\n"
1251
+ end
1252
+
1253
+ def test_acc_with_var
1254
+ parse("foo := PR[1]\nbar := R[1]\nlinear_move.to(foo).at(2000, 'mm/s').term(0).acc(bar)")
1255
+ assert_prog "L PR[1:foo] 2000mm/sec CNT0 ACC R[1:bar] ;\n"
1256
+ end
1257
+
1258
+ def test_term_fine_with_constant
1259
+ parse("foo := PR[1]\nTERM := -1\nlinear_move.to(foo).at(2000, 'mm/s').term(TERM)")
1260
+ assert_prog "L PR[1:foo] 2000mm/sec FINE ;\n"
1261
+ end
1262
+
1263
+ def test_term_cnt_with_constant
1264
+ parse("foo := PR[1]\nTERM := 100\nlinear_move.to(foo).at(2000, 'mm/s').term(TERM)")
1265
+ assert_prog "L PR[1:foo] 2000mm/sec CNT100 ;\n"
1266
+ end
1267
+
1268
+ def test_pr_components_groups
1269
+ parse("foo := PR[1]\nfoo.group(1).y=5\n")
1270
+ assert_prog "PR[GP1:1,2:foo]=5 ;\n"
1271
+ end
1272
+
1273
+ def test_position_data_with_mask
1274
+ parse %(position_data
1275
+ {
1276
+ 'positions' : [
1277
+ {
1278
+ 'id' : 1,
1279
+ 'mask' : [{
1280
+ 'group' : 1,
1281
+ 'uframe' : 5,
1282
+ 'utool' : 2,
1283
+ 'config' : {
1284
+ 'flip' : false,
1285
+ 'up' : true,
1286
+ 'top' : true,
1287
+ 'turn_counts' : [0,0,0]
1288
+ },
1289
+ 'components' : {
1290
+ 'x' : -.590,
1291
+ 'y' : -29.400,
1292
+ 'z' : 1304.471,
1293
+ 'w' : 78.512,
1294
+ 'p' : 89.786,
1295
+ 'r' : -11.595
1296
+ }
1297
+ },
1298
+ {
1299
+ 'group' : 2,
1300
+ 'uframe' : 5,
1301
+ 'utool' : 2,
1302
+ 'components' : {
1303
+ 'J1' : 0.00
1304
+ }
1305
+ }]
1306
+ }
1307
+ ]
1308
+ }
1309
+ end)
1310
+ assert_prog ""
1311
+ #output = @interpreter.pos_section
1312
+ #output = output
1313
+ assert_equal 1, @interpreter.position_data[:positions].length
1314
+ end
1315
+
1316
+ def test_conditional_equals_minus_one
1317
+ parse("foo := R[1]\nfoo2 := R[2]\nif foo == (foo2-1)\nfoo = 1\nfoo2 = 2\nend")
1318
+ assert_prog "IF (R[1:foo]<>(R[2:foo2]-1)),JMP LBL[100] ;\nR[1:foo]=1 ;\nR[2:foo2]=2 ;\nLBL[100] ;\n"
1319
+ end
1320
+
1321
+ def test_conditional_equals_minus_and
1322
+ parse("foo := R[1]\nfoo2 := R[2]\nif foo >= (foo2-1) && foo <= (foo2+1) \nfoo = 1\nfoo2 = 2\nend")
1323
+ assert_prog "IF (R[1:foo]<(R[2:foo2]-1) OR R[1:foo]>(R[2:foo2]+1)),JMP LBL[100] ;\nR[1:foo]=1 ;\nR[2:foo2]=2 ;\nLBL[100] ;\n"
1324
+ end
1325
+
1326
+ def test_inline_conditional_equals_minus_and
1327
+ parse("foo := R[1]\nfoo2 := R[2]\nif foo >= (foo2-1) && foo <= (foo2+1) \nfoo2 = 2\nend")
1328
+ assert_prog "IF (R[1:foo]>=(R[2:foo2]-1) AND R[1:foo]<=(R[2:foo2]+1)),R[2:foo2]=(2) ;\n"
1329
+ end
1330
+
1331
+ def test_address
1332
+ parse("a := AR[1]
1333
+ b := DI[2]
1334
+ c := R[3]
1335
+ d := P[4]
1336
+ e := PR[5]
1337
+ f := SR[6]
1338
+ g := TIMER[7]
1339
+ h := UALM[8]
1340
+ i := VR[9]
1341
+ TEST(&a,&b,&c,&d,&e,&f,&g,&h,&i)")
1342
+ assert_prog "CALL TEST(1,2,3,4,5,6,7,8,9) ;\n"
1343
+ end
1344
+
1345
+ def test_address_assignment
1346
+ parse("foo := R[1]
1347
+ foo = &foo")
1348
+ assert_prog "R[1:foo]=1 ;\n"
1349
+ end
1350
+
1351
+ def test_invalid_address_throws_error
1352
+ parse("foo := R[1]\nfoo = &bar")
1353
+ assert_raise(RuntimeError) do
1354
+ assert_prog ""
1355
+ end
1356
+ end
1357
+
1358
+ def test_lpos
1359
+ parse "foo := PR[1]\nget_linear_position(foo)"
1360
+ assert_prog "PR[1:foo]=LPOS ;\n"
1361
+ end
1362
+
1363
+ def test_jpos
1364
+ parse "foo := PR[1]\nget_joint_position(foo)"
1365
+ assert_prog "PR[1:foo]=JPOS ;\n"
1366
+ end
1367
+
1368
+ def test_return
1369
+ parse "return"
1370
+ assert_prog "END ;\n"
1371
+ end
1372
+
1373
+ # issue #18 https://github.com/onerobotics/tp_plus/issues/18
1374
+ def test_mixed_logic_with_multiple_conditions_and_not_operator
1375
+ parse "foo := RI[1]\nbar := RI[2]\nif !foo && !bar\n# true\nend"
1376
+ assert_prog "IF (RI[1:foo] OR RI[2:bar]),JMP LBL[100] ;\n! true ;\nLBL[100] ;\n"
1377
+ end
1378
+ end