tp_plus 0.0.73

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 (67) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +65 -0
  3. data/Rakefile +21 -0
  4. data/bin/tpp +73 -0
  5. data/lib/tp_plus/interpreter.rb +129 -0
  6. data/lib/tp_plus/namespace.rb +66 -0
  7. data/lib/tp_plus/nodes/abort_node.rb +9 -0
  8. data/lib/tp_plus/nodes/argument_node.rb +19 -0
  9. data/lib/tp_plus/nodes/assignment_node.rb +45 -0
  10. data/lib/tp_plus/nodes/call_node.rb +34 -0
  11. data/lib/tp_plus/nodes/case_condition_node.rb +26 -0
  12. data/lib/tp_plus/nodes/case_node.rb +33 -0
  13. data/lib/tp_plus/nodes/comment_node.rb +22 -0
  14. data/lib/tp_plus/nodes/conditional_node.rb +54 -0
  15. data/lib/tp_plus/nodes/definition_node.rb +22 -0
  16. data/lib/tp_plus/nodes/digit_node.rb +21 -0
  17. data/lib/tp_plus/nodes/eval_node.rb +13 -0
  18. data/lib/tp_plus/nodes/expression_node.rb +65 -0
  19. data/lib/tp_plus/nodes/for_node.rb +20 -0
  20. data/lib/tp_plus/nodes/header_node.rb +27 -0
  21. data/lib/tp_plus/nodes/indirect_node.rb +49 -0
  22. data/lib/tp_plus/nodes/inline_conditional_node.rb +40 -0
  23. data/lib/tp_plus/nodes/io_method_node.rb +55 -0
  24. data/lib/tp_plus/nodes/io_node.rb +30 -0
  25. data/lib/tp_plus/nodes/jump_node.rb +23 -0
  26. data/lib/tp_plus/nodes/label_definition_node.rb +21 -0
  27. data/lib/tp_plus/nodes/motion_node.rb +62 -0
  28. data/lib/tp_plus/nodes/namespace_node.rb +16 -0
  29. data/lib/tp_plus/nodes/namespaced_var_node.rb +38 -0
  30. data/lib/tp_plus/nodes/numreg_node.rb +25 -0
  31. data/lib/tp_plus/nodes/offset_node.rb +27 -0
  32. data/lib/tp_plus/nodes/operator_node.rb +72 -0
  33. data/lib/tp_plus/nodes/pause_node.rb +9 -0
  34. data/lib/tp_plus/nodes/position_data_node.rb +50 -0
  35. data/lib/tp_plus/nodes/position_node.rb +25 -0
  36. data/lib/tp_plus/nodes/posreg_node.rb +48 -0
  37. data/lib/tp_plus/nodes/raise_node.rb +13 -0
  38. data/lib/tp_plus/nodes/real_node.rb +27 -0
  39. data/lib/tp_plus/nodes/set_node.rb +22 -0
  40. data/lib/tp_plus/nodes/skip_node.rb +22 -0
  41. data/lib/tp_plus/nodes/speed_node.rb +29 -0
  42. data/lib/tp_plus/nodes/string_node.rb +13 -0
  43. data/lib/tp_plus/nodes/string_register_node.rb +25 -0
  44. data/lib/tp_plus/nodes/termination_node.rb +18 -0
  45. data/lib/tp_plus/nodes/terminator_node.rb +16 -0
  46. data/lib/tp_plus/nodes/time_node.rb +24 -0
  47. data/lib/tp_plus/nodes/timer_method_node.rb +37 -0
  48. data/lib/tp_plus/nodes/timer_node.rb +21 -0
  49. data/lib/tp_plus/nodes/units_node.rb +20 -0
  50. data/lib/tp_plus/nodes/use_node.rb +21 -0
  51. data/lib/tp_plus/nodes/user_alarm_node.rb +15 -0
  52. data/lib/tp_plus/nodes/var_method_node.rb +23 -0
  53. data/lib/tp_plus/nodes/var_node.rb +39 -0
  54. data/lib/tp_plus/nodes/vision_register_node.rb +21 -0
  55. data/lib/tp_plus/nodes/wait_for_node.rb +54 -0
  56. data/lib/tp_plus/nodes/wait_until_node.rb +65 -0
  57. data/lib/tp_plus/nodes/while_node.rb +36 -0
  58. data/lib/tp_plus/parser.rb +1592 -0
  59. data/lib/tp_plus/scanner.rb +383 -0
  60. data/lib/tp_plus/version.rb +3 -0
  61. data/lib/tp_plus.rb +62 -0
  62. data/test/test_helper.rb +5 -0
  63. data/test/tp_plus/test_interpreter.rb +1168 -0
  64. data/test/tp_plus/test_parser.rb +489 -0
  65. data/test/tp_plus/test_scanner.rb +522 -0
  66. data/tp_plus.gemspec +28 -0
  67. metadata +156 -0
@@ -0,0 +1,1168 @@
1
+ require '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(RuntimeError) 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_fanuc_set_uframe_with_pr
497
+ parse("foo := PR[1]\nset_uframe 5, foo")
498
+ assert_prog "UFRAME[5]=PR[1:foo] ;\n"
499
+ end
500
+
501
+ def test_fanuc_set_uframe_with_constant
502
+ parse("foo := PR[1]\nBAR := 5\nset_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]\nset_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
+ def test_bang_with_grouping
582
+ parse "foo := F[1]\nbar := F[2]\nbaz := F[3]\nfoo = foo || !(bar || baz)"
583
+ assert_prog "F[1:foo]=(F[1:foo] OR !(F[2:bar] OR F[3:baz])) ;\n"
584
+ end
585
+
586
+ def test_opposite_flag_in_simple_if
587
+ parse "foo := F[1]\nif foo\n# foo is true\nend"
588
+ assert_prog "IF (!F[1:foo]),JMP LBL[100] ;\n! foo is true ;\nLBL[100] ;\n"
589
+ end
590
+
591
+ def test_opposite_flag_in_simple_unless
592
+ parse "foo := F[1]\nunless foo\n# foo is false\nend"
593
+ assert_prog "IF (F[1:foo]),JMP LBL[100] ;\n! foo is false ;\nLBL[100] ;\n"
594
+ end
595
+
596
+ def test_inline_if_with_flag
597
+ parse "foo := F[1]\njump_to @end if foo\n@end"
598
+ assert_prog "IF (F[1:foo]),JMP LBL[100] ;\nLBL[100:end] ;\n"
599
+ end
600
+
601
+ def test_inline_unless_with_flag
602
+ parse "foo := F[1]\njump_to @end unless foo\n@end"
603
+ assert_prog "IF (!F[1:foo]),JMP LBL[100] ;\nLBL[100:end] ;\n"
604
+ end
605
+
606
+ def test_automatic_parens_on_boolean
607
+ parse "foo := F[1]\njump_to @end if foo || foo\n@end"
608
+ assert_prog "IF (F[1:foo] OR F[1:foo]),JMP LBL[100] ;\nLBL[100:end] ;\n"
609
+ end
610
+
611
+ def test_no_extra_parens_with_booleans
612
+ parse "foo := F[1]\njump_to @end if foo || foo || foo\n@end"
613
+ assert_prog "IF (F[1:foo] OR F[1:foo] OR F[1:foo]),JMP LBL[100] ;\nLBL[100:end] ;\n"
614
+ end
615
+
616
+ def test_assignment_as_bool_result
617
+ parse "foo := F[1]\nbar := R[1]\nfoo = bar == 1"
618
+ assert_prog "F[1:foo]=(R[1:bar]=1) ;\n"
619
+ end
620
+
621
+ def test_args_dont_get_comments
622
+ parse "foo := AR[1]\njump_to @end if foo == 1\n@end"
623
+ assert_prog "IF (AR[1]=1),JMP LBL[100] ;\nLBL[100:end] ;\n"
624
+ end
625
+
626
+ def test_indirect_position_assignment
627
+ parse "foo := PR[1]\nfoo = indirect('position',5)"
628
+ assert_prog "PR[1:foo]=P[5] ;\n"
629
+ end
630
+
631
+ def test_indirect_indirect_position_assignment
632
+ parse "foo := PR[1]\nbar := R[1]\nfoo = indirect('position',bar)"
633
+ assert_prog "PR[1:foo]=P[R[1:bar]] ;\n"
634
+ end
635
+
636
+ def test_indirect_posreg_assignment
637
+ parse "foo := PR[1]\nfoo = indirect('position_register',5)"
638
+ assert_prog "PR[1:foo]=PR[5] ;\n"
639
+ end
640
+
641
+ def test_namespace
642
+ parse "namespace Foo\nbar := R[1]\nend\nFoo::bar = 5"
643
+ assert_prog "R[1:Foo bar]=5 ;\n"
644
+ end
645
+
646
+ def test_no_namespace_collision
647
+ parse "namespace Foo\nbar := R[1]\nend\nbar := R[2]\nbar = 2\nFoo::bar = 1"
648
+ assert_prog "R[2:bar]=2 ;\nR[1:Foo bar]=1 ;\n"
649
+ end
650
+
651
+ def test_namespace_constant_definition
652
+ parse "namespace Math\nPI := 3.14\nend\nfoo := R[1]\nfoo = Math::PI"
653
+ assert_prog "R[1:foo]=3.14 ;\n"
654
+ end
655
+
656
+ def test_namespace_swallows_everything
657
+ parse "namespace Foo\n# this is a comment\n#this is another comment\nend"
658
+ assert_prog ""
659
+ end
660
+
661
+ def test_nested_namespace
662
+ parse %(namespace Foo
663
+ bar := R[1]
664
+ namespace Bar
665
+ baz := R[2]
666
+ end
667
+ end
668
+ Foo::bar = 1
669
+ Foo::Bar::baz = 2)
670
+ assert_prog "R[1:Foo bar]=1 ;\nR[2:Foo Bar baz]=2 ;\n"
671
+ end
672
+
673
+ def test_load_environment
674
+ environment = "foo := R[1]\nbar := R[2]\n#asdf\n#asdf"
675
+ @interpreter.load_environment(environment)
676
+ parse "foo = 5"
677
+ assert_prog "R[1:foo]=5 ;\n"
678
+ assert_equal 1, @interpreter.source_line_count
679
+ end
680
+
681
+ def test_load_environment_only_saves_definitions_etc
682
+ environment = "foo := R[1]\nbar := R[2]\n#asdf\n#asdf\nfoo=3"
683
+ @interpreter.load_environment(environment)
684
+ parse "foo = 5"
685
+ assert_prog "R[1:foo]=5 ;\n"
686
+ assert_equal 1, @interpreter.source_line_count
687
+ end
688
+
689
+
690
+ def test_bad_environment
691
+ assert_raise(RuntimeError) do
692
+ @interpreter.load_environment("asdf")
693
+ end
694
+ end
695
+
696
+ def test_inline_conditional_with_namespaced_var
697
+ parse "namespace Foo\nbar := DI[1]\nend\njump_to @end unless Foo::bar\n@end"
698
+ assert_prog "IF (!DI[1:Foo bar]),JMP LBL[100] ;\nLBL[100:end] ;\n"
699
+ end
700
+
701
+ def test_namespaced_var_as_condition
702
+ parse "namespace Foo\nbar := DI[1]\nend\nif Foo::bar\n# bar is on\nend"
703
+ assert_prog "IF (!DI[1:Foo bar]),JMP LBL[100] ;\n! bar is on ;\nLBL[100] ;\n"
704
+ end
705
+
706
+ def test_reopen_namespace
707
+ parse "namespace Foo\nbar := R[1]\nend\nnamespace Foo\nbaz := R[2]\nend\nFoo::bar = 1\nFoo::baz = 2"
708
+ assert_prog "R[1:Foo bar]=1 ;\nR[2:Foo baz]=2 ;\n"
709
+ end
710
+
711
+ def test_eval
712
+ parse %(eval "R[1]=5")
713
+ assert_prog "R[1]=5 ;\n"
714
+ end
715
+
716
+ def test_multiline_eval
717
+ parse %(eval "R[1]=5 ;\nR[2]=3")
718
+ assert_prog "R[1]=5 ;\nR[2]=3 ;\n"
719
+ end
720
+
721
+ def test_namespaced_position_reg_component
722
+ parse "namespace Fixture\npick_offset := PR[1]\nend\nFixture::pick_offset.x = 10"
723
+ assert_prog "PR[1,1:Fixture pick_offset]=10 ;\n"
724
+ end
725
+
726
+ def test_inline_program_call_two
727
+ parse "foo := R[1]\nbar() if foo >= 5"
728
+ assert_prog "IF R[1:foo]>=5,CALL BAR ;\n"
729
+ end
730
+
731
+ def test_forlooop
732
+ parse "foo := R[1]\nfor foo in (1 TO 10)\n# bar\nend"
733
+ assert_prog "FOR R[1:foo]=1 TO 10 ;\n! bar ;\nENDFOR ;\n"
734
+ end
735
+
736
+ def test_forloop_with_vars
737
+ parse "foo := R[1]\nmin := R[2]\nmax := R[3]\nfor foo in (min to max)\n#bar\nend"
738
+ assert_prog "FOR R[1:foo]=R[2:min] TO R[3:max] ;\n! bar ;\nENDFOR ;\n"
739
+ end
740
+
741
+ def test_indirect_flag
742
+ parse "foo := R[1]\nturn_on indirect('flag',foo)"
743
+ assert_prog "F[R[1:foo]]=(ON) ;\n"
744
+ end
745
+
746
+ def test_indirect_flag_condition
747
+ parse "foo := R[1]\njump_to @end if indirect('flag',foo)\n@end"
748
+ assert_prog "IF (F[R[1:foo]]),JMP LBL[100] ;\nLBL[100:end] ;\n"
749
+ end
750
+
751
+ def test_indirect_flag_condition_not_inline
752
+ parse "foo := R[1]\nif indirect('flag',foo)\n# bar\nend"
753
+ assert_prog "IF (!F[R[1:foo]]),JMP LBL[100] ;\n! bar ;\nLBL[100] ;\n"
754
+ end
755
+
756
+ def test_indirect_unless_flag_condition
757
+ parse "foo := R[1]\njump_to @end unless indirect('flag',foo)\n@end"
758
+ assert_prog "IF (!F[R[1:foo]]),JMP LBL[100] ;\nLBL[100:end] ;\n"
759
+ end
760
+
761
+ def test_indirect_flag_with_if_bang
762
+ parse "foo := R[1]\njump_to @end if !indirect('flag',foo)\n@end"
763
+ assert_prog "IF (!F[R[1:foo]]),JMP LBL[100] ;\nLBL[100:end] ;\n"
764
+ end
765
+
766
+ def test_while_loop
767
+ parse "foo := R[1]\nwhile foo < 10\n# bar\nend"
768
+ assert_prog "LBL[100] ;\nIF R[1:foo]>=10,JMP LBL[101] ;\n! bar ;\nJMP LBL[100] ;\nLBL[101] ;\n"
769
+ end
770
+
771
+ def test_while_with_not_flag
772
+ parse "foo := F[1]\nwhile !foo\n#bar\nend"
773
+ assert_prog "LBL[100] ;\nIF (F[1:foo]),JMP LBL[101] ;\n! bar ;\nJMP LBL[100] ;\nLBL[101] ;\n"
774
+ end
775
+
776
+ def test_while_with_flag
777
+ parse "foo := F[1]\nwhile foo\n#bar\nend"
778
+ assert_prog "LBL[100] ;\nIF (!F[1:foo]),JMP LBL[101] ;\n! bar ;\nJMP LBL[100] ;\nLBL[101] ;\n"
779
+ end
780
+
781
+ def test_timer_start
782
+ parse "foo := TIMER[1]\nstart foo"
783
+ assert_prog "TIMER[1:foo]=START ;\n"
784
+ end
785
+
786
+ def test_timer_reset
787
+ parse "foo := TIMER[1]\nreset foo"
788
+ assert_prog "TIMER[1:foo]=RESET ;\n"
789
+ end
790
+
791
+ def test_timer_stop
792
+ parse "foo := TIMER[1]\nstop foo"
793
+ assert_prog "TIMER[1:foo]=STOP ;\n"
794
+ end
795
+
796
+ def test_timer_restart
797
+ parse "foo := TIMER[1]\nrestart foo"
798
+ assert_prog "TIMER[1:foo]=STOP ;\nTIMER[1:foo]=RESET ;\nTIMER[1:foo]=START ;\n"
799
+ end
800
+
801
+ def test_indirect_timer
802
+ parse "foo := R[1]\nfoo = indirect('timer', 3)"
803
+ assert_prog "R[1:foo]=TIMER[3] ;\n"
804
+ end
805
+
806
+ def test_indirect_indirect_timer
807
+ parse "foo := R[1]\nfoo = indirect('timer', foo)"
808
+ assert_prog "R[1:foo]=TIMER[R[1:foo]] ;\n"
809
+ end
810
+
811
+ def test_start_indirect_timer
812
+ parse "start indirect('timer', 3)"
813
+ assert_prog "TIMER[3]=START ;\n"
814
+ end
815
+
816
+ def test_start_indirect_indirect_timer
817
+ parse "foo := R[1]\nstart indirect('timer', foo)"
818
+ assert_prog "TIMER[R[1:foo]]=START ;\n"
819
+ end
820
+
821
+ def test_position_data_does_not_output_with_eval
822
+ parse %(position_data
823
+ {
824
+ 'positions': [
825
+ {
826
+ 'id': 1,
827
+ 'comment': "test",
828
+ 'group': 1,
829
+ 'uframe': 1,
830
+ 'utool': 1,
831
+ 'config': {
832
+ 'flip': true,
833
+ 'up': true,
834
+ 'top': false,
835
+ 'turn_counts': [-1,0,1]
836
+ },
837
+ 'components': {
838
+ 'x': -50.0,
839
+ 'y': 0.0,
840
+ 'z': 0.0,
841
+ 'w': 0.0,
842
+ 'p': 0.0,
843
+ 'r': 0.0
844
+ }
845
+ }
846
+ ]
847
+ }
848
+ end)
849
+
850
+ assert_prog ""
851
+ end
852
+
853
+ def test_position_data_populates_interpreter_position_data
854
+ parse %(position_data
855
+ {
856
+ 'positions': [
857
+ {
858
+ 'id': 1,
859
+ 'comment': "test",
860
+ 'group': 1,
861
+ 'uframe': 1,
862
+ 'utool': 1,
863
+ 'config': {
864
+ 'flip': true,
865
+ 'up': true,
866
+ 'top': false,
867
+ 'turn_counts': [0,0,0]
868
+ },
869
+ 'components': {
870
+ 'x': 0.0,
871
+ 'y': 0.0,
872
+ 'z': 0.0,
873
+ 'w': 0.0,
874
+ 'p': 0.0,
875
+ 'r': 0.0
876
+ }
877
+ }
878
+ ]
879
+ }
880
+ end)
881
+
882
+ assert_prog ""
883
+ assert_equal 1, @interpreter.position_data[:positions].length
884
+ end
885
+
886
+ def test_throws_a_fault_if_position_data_invalid
887
+ parse %(position_data
888
+ {
889
+ 'positions' : "asdf"
890
+ }
891
+ end)
892
+ assert_raise(RuntimeError) do
893
+ @interpreter.eval
894
+ end
895
+ end
896
+
897
+ def test_outputs_position_data_correctly
898
+ parse %(position_data
899
+ {
900
+ 'positions': [
901
+ {
902
+ 'id': 1,
903
+ 'comment': "test",
904
+ 'group': 1,
905
+ 'uframe': 1,
906
+ 'utool': 1,
907
+ 'config': {
908
+ 'flip': true,
909
+ 'up': true,
910
+ 'top': true,
911
+ 'turn_counts': [0,0,0]
912
+ },
913
+ 'components': {
914
+ 'x': 0.0,
915
+ 'y': 0.0,
916
+ 'z': 0.0,
917
+ 'w': 0.0,
918
+ 'p': 0.0,
919
+ 'r': 0.0
920
+ }
921
+ }
922
+ ]
923
+ }
924
+ end)
925
+
926
+ assert_prog ""
927
+ assert_equal %(P[1:"test"]{
928
+ GP1:
929
+ UF : 1, UT : 1, CONFIG : 'F U T, 0, 0, 0',
930
+ X = 0.0 mm, Y = 0.0 mm, Z = 0.0 mm,
931
+ W = 0.0 deg, P = 0.0 deg, R = 0.0 deg
932
+ };\n), @interpreter.pos_section
933
+ end
934
+
935
+ def test_outputs_position_data_correctly_with_two_positions
936
+ parse %(position_data
937
+ {
938
+ 'positions': [
939
+ {
940
+ 'id': 1,
941
+ 'comment': "test",
942
+ 'group': 1,
943
+ 'uframe': 1,
944
+ 'utool': 1,
945
+ 'config': {
946
+ 'flip': true,
947
+ 'up': true,
948
+ 'top': true,
949
+ 'turn_counts': [0,0,0]
950
+ },
951
+ 'components': {
952
+ 'x': 0.0,
953
+ 'y': 0.0,
954
+ 'z': 0.0,
955
+ 'w': 0.0,
956
+ 'p': 0.0,
957
+ 'r': 0.0
958
+ }
959
+ },
960
+ {
961
+ 'id': 2,
962
+ 'comment': "test2",
963
+ 'group': 1,
964
+ 'uframe': 1,
965
+ 'utool': 1,
966
+ 'config': {
967
+ 'flip': true,
968
+ 'up': true,
969
+ 'top': true,
970
+ 'turn_counts': [0,0,0]
971
+ },
972
+ 'components': {
973
+ 'x': 0.0,
974
+ 'y': 0.0,
975
+ 'z': 0.0,
976
+ 'w': 0.0,
977
+ 'p': 0.0,
978
+ 'r': 0.0
979
+ }
980
+ }
981
+ ]
982
+ }
983
+ end)
984
+
985
+ assert_prog ""
986
+ assert_equal %(P[1:"test"]{
987
+ GP1:
988
+ UF : 1, UT : 1, CONFIG : 'F U T, 0, 0, 0',
989
+ X = 0.0 mm, Y = 0.0 mm, Z = 0.0 mm,
990
+ W = 0.0 deg, P = 0.0 deg, R = 0.0 deg
991
+ };
992
+ P[2:"test2"]{
993
+ GP1:
994
+ UF : 1, UT : 1, CONFIG : 'F U T, 0, 0, 0',
995
+ X = 0.0 mm, Y = 0.0 mm, Z = 0.0 mm,
996
+ W = 0.0 deg, P = 0.0 deg, R = 0.0 deg
997
+ };\n), @interpreter.pos_section
998
+ end
999
+
1000
+ def test_simple_pulse
1001
+ parse "foo := DO[1]\npulse foo"
1002
+ assert_prog "DO[1:foo]=PULSE ;\n"
1003
+ end
1004
+
1005
+ def test_pulse_for_seconds
1006
+ parse "foo := DO[1]\npulse(foo,5,'s')"
1007
+ assert_prog "DO[1:foo]=PULSE,5.0sec ;\n"
1008
+ end
1009
+
1010
+ def test_pulse_for_ms
1011
+ parse "foo := DO[1]\npulse(foo,500,'ms')"
1012
+ assert_prog "DO[1:foo]=PULSE,0.5sec ;\n"
1013
+ end
1014
+
1015
+ def test_indirect_numreg
1016
+ parse "foo := R[1]\nindirect('register',foo) = 5"
1017
+ assert_prog "R[R[1:foo]]=5 ;\n"
1018
+ end
1019
+
1020
+ def test_raise
1021
+ parse "my_alarm := UALM[1]\nraise my_alarm"
1022
+ assert_prog "UALM[1] ;\n"
1023
+ end
1024
+
1025
+ def test_indirect_raise
1026
+ parse "raise indirect('user_alarm',1)"
1027
+ assert_prog "UALM[1] ;\n"
1028
+ end
1029
+
1030
+ def test_indirect_indirect_raise
1031
+ parse "foo := R[1]\nraise indirect('user_alarm',foo)"
1032
+ assert_prog "UALM[R[1:foo]] ;\n"
1033
+ end
1034
+
1035
+ def test_namespaced_pr_component_assignment
1036
+ parse "namespace Foo\nbar := PR[1]\nend\nFoo::bar.x = 10"
1037
+ assert_prog "PR[1,1:Foo bar]=10 ;\n"
1038
+ end
1039
+
1040
+ def test_namespaced_pr_component_plus_equals
1041
+ parse "namespace Foo\nbar := PR[1]\nend\nFoo::bar.x += 10"
1042
+ assert_prog "PR[1,1:Foo bar]=PR[1,1:Foo bar]+10 ;\n"
1043
+ end
1044
+
1045
+ def test_namespaced_pr_component_in_expression
1046
+ parse "namespace Foo\nbar := PR[1]\nend\nFoo::bar.x += Foo::bar.x * 10 \n"
1047
+ assert_prog "PR[1,1:Foo bar]=(PR[1,1:Foo bar]+PR[1,1:Foo bar]*10) ;\n"
1048
+ end
1049
+
1050
+ def test_namespaced_pr_assignment_then_expression
1051
+ parse "namespace Foo\nbar := PR[1]\nend\nbaz := P[1]\nFoo::bar = baz\nFoo::bar.x += 5"
1052
+ assert_prog "PR[1:Foo bar]=P[1:baz] ;\nPR[1,1:Foo bar]=PR[1,1:Foo bar]+5 ;\n"
1053
+ end
1054
+
1055
+ def test_wait_until_does_not_get_inlined
1056
+ parse "foo := DO[1]\nunless foo\nwait_until(foo)\nend"
1057
+ assert_prog "IF (DO[1:foo]),JMP LBL[100] ;\nWAIT (DO[1:foo]) ;\nLBL[100] ;\n"
1058
+ end
1059
+
1060
+ def test_wait_for_does_not_get_inlined
1061
+ parse "foo := DO[1]\nunless foo\nwait_for(1,'s')\nend"
1062
+ assert_prog "IF (DO[1:foo]),JMP LBL[100] ;\nWAIT 1.00(sec) ;\nLBL[100] ;\n"
1063
+ end
1064
+
1065
+ def test_inline_conditional_does_not_get_inlined
1066
+ parse "foo := DO[1]\nif foo\nturn_off foo if foo\nend"
1067
+ assert_prog "IF (!DO[1:foo]),JMP LBL[100] ;\nIF (DO[1:foo]),DO[1:foo]=(OFF) ;\nLBL[100] ;\n"
1068
+ end
1069
+
1070
+ def test_run
1071
+ parse "run foo()"
1072
+ assert_prog "RUN FOO ;\n"
1073
+ end
1074
+
1075
+ def test_tp_ignore_pause
1076
+ parse "TP_IGNORE_PAUSE = true"
1077
+ assert_prog ""
1078
+ assert @interpreter.header_data[:ignore_pause]
1079
+ end
1080
+
1081
+ def test_tp_subtype
1082
+ parse "TP_SUBTYPE = 'macro'"
1083
+ assert_prog ""
1084
+ assert_equal :macro, @interpreter.header_data[:subtype]
1085
+ end
1086
+
1087
+ def test_tp_comment
1088
+ parse %(TP_COMMENT = "foo")
1089
+ assert_prog ""
1090
+ assert_equal "foo", @interpreter.header_data[:comment]
1091
+ end
1092
+
1093
+ def test_tp_groupmask
1094
+ parse %(TP_GROUPMASK = "*,*,*,*,*")
1095
+ assert_prog ""
1096
+ assert_equal "*,*,*,*,*", @interpreter.header_data[:group_mask]
1097
+ end
1098
+
1099
+ def test_mixed_logic_or
1100
+ parse %(foo := DI[1]\nbar := DI[2]\nif foo || bar\n# do something\nend)
1101
+ assert_prog "IF (!DI[1:foo] AND !DI[2:bar]),JMP LBL[100] ;\n! do something ;\nLBL[100] ;\n"
1102
+ end
1103
+
1104
+ def test_flag_assignment_always_gets_parens
1105
+ parse %(foo := F[1]\nbar := DI[2]\nfoo = bar)
1106
+ assert_prog "F[1:foo]=(DI[2:bar]) ;\n"
1107
+ end
1108
+
1109
+ def test_tool_offset
1110
+ parse %(p := P[1]\ntoff := PR[1]\nlinear_move.to(p).at(2000,'mm/s').term(0).tool_offset(toff))
1111
+ assert_prog "L P[1:p] 2000mm/sec CNT0 Tool_Offset,PR[1:toff] ;\n"
1112
+ end
1113
+
1114
+ def test_wait_for_digit
1115
+ parse %(wait_for(1,'s'))
1116
+ assert_prog "WAIT 1.00(sec) ;\n"
1117
+ end
1118
+
1119
+ def test_wait_for_real
1120
+ parse %(wait_for(0.5,'s'))
1121
+ assert_prog "WAIT .50(sec) ;\n"
1122
+ end
1123
+
1124
+ def test_wait_for_real_const
1125
+ parse %(FOO := 0.5\nwait_for(FOO,'s'))
1126
+ assert_prog "WAIT .50(sec) ;\n"
1127
+ end
1128
+
1129
+ def test_negative_numbers_have_parens
1130
+ parse %(foo := R[1]\njump_to @end if foo > -1\njump_to @end if foo > -5.3\n@end)
1131
+ assert_prog "IF R[1:foo]>(-1),JMP LBL[100] ;\nIF R[1:foo]>(-5.3),JMP LBL[100] ;\nLBL[100:end] ;\n"
1132
+ end
1133
+
1134
+ def test_modulus
1135
+ parse %(foo := R[1]\nfoo = 5 % 2)
1136
+ assert_prog "R[1:foo]=5 MOD 2 ;\n"
1137
+ end
1138
+
1139
+ def test_assignment_to_sop
1140
+ parse %(foo := DO[1]\nbar := SO[1]\nfoo = bar)
1141
+ assert_prog "DO[1:foo]=(SO[1:bar]) ;\n"
1142
+ end
1143
+
1144
+ def test_assignment_to_di
1145
+ parse %(foo := DO[1]\nbar := DI[1]\nfoo = bar)
1146
+ assert_prog "DO[1:foo]=(DI[1:bar]) ;\n"
1147
+ end
1148
+
1149
+ def test_string_register_definition
1150
+ parse %(foo := SR[1]\nbar := SR[2]\nfoo = bar)
1151
+ assert_prog "SR[1:foo]=SR[2:bar] ;\n"
1152
+ end
1153
+
1154
+ def test_string_argument
1155
+ parse %(foo('bar'))
1156
+ assert_prog "CALL FOO('bar') ;\n"
1157
+ end
1158
+
1159
+ def test_pause
1160
+ parse %(pause)
1161
+ assert_prog "PAUSE ;\n"
1162
+ end
1163
+
1164
+ def test_abort
1165
+ parse %(abort)
1166
+ assert_prog "ABORT ;\n"
1167
+ end
1168
+ end