tp_plus 0.0.87 → 0.0.88

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +87 -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