tp_plus 0.0.73

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +65 -0
  3. data/Rakefile +21 -0
  4. data/bin/tpp +73 -0
  5. data/lib/tp_plus/interpreter.rb +129 -0
  6. data/lib/tp_plus/namespace.rb +66 -0
  7. data/lib/tp_plus/nodes/abort_node.rb +9 -0
  8. data/lib/tp_plus/nodes/argument_node.rb +19 -0
  9. data/lib/tp_plus/nodes/assignment_node.rb +45 -0
  10. data/lib/tp_plus/nodes/call_node.rb +34 -0
  11. data/lib/tp_plus/nodes/case_condition_node.rb +26 -0
  12. data/lib/tp_plus/nodes/case_node.rb +33 -0
  13. data/lib/tp_plus/nodes/comment_node.rb +22 -0
  14. data/lib/tp_plus/nodes/conditional_node.rb +54 -0
  15. data/lib/tp_plus/nodes/definition_node.rb +22 -0
  16. data/lib/tp_plus/nodes/digit_node.rb +21 -0
  17. data/lib/tp_plus/nodes/eval_node.rb +13 -0
  18. data/lib/tp_plus/nodes/expression_node.rb +65 -0
  19. data/lib/tp_plus/nodes/for_node.rb +20 -0
  20. data/lib/tp_plus/nodes/header_node.rb +27 -0
  21. data/lib/tp_plus/nodes/indirect_node.rb +49 -0
  22. data/lib/tp_plus/nodes/inline_conditional_node.rb +40 -0
  23. data/lib/tp_plus/nodes/io_method_node.rb +55 -0
  24. data/lib/tp_plus/nodes/io_node.rb +30 -0
  25. data/lib/tp_plus/nodes/jump_node.rb +23 -0
  26. data/lib/tp_plus/nodes/label_definition_node.rb +21 -0
  27. data/lib/tp_plus/nodes/motion_node.rb +62 -0
  28. data/lib/tp_plus/nodes/namespace_node.rb +16 -0
  29. data/lib/tp_plus/nodes/namespaced_var_node.rb +38 -0
  30. data/lib/tp_plus/nodes/numreg_node.rb +25 -0
  31. data/lib/tp_plus/nodes/offset_node.rb +27 -0
  32. data/lib/tp_plus/nodes/operator_node.rb +72 -0
  33. data/lib/tp_plus/nodes/pause_node.rb +9 -0
  34. data/lib/tp_plus/nodes/position_data_node.rb +50 -0
  35. data/lib/tp_plus/nodes/position_node.rb +25 -0
  36. data/lib/tp_plus/nodes/posreg_node.rb +48 -0
  37. data/lib/tp_plus/nodes/raise_node.rb +13 -0
  38. data/lib/tp_plus/nodes/real_node.rb +27 -0
  39. data/lib/tp_plus/nodes/set_node.rb +22 -0
  40. data/lib/tp_plus/nodes/skip_node.rb +22 -0
  41. data/lib/tp_plus/nodes/speed_node.rb +29 -0
  42. data/lib/tp_plus/nodes/string_node.rb +13 -0
  43. data/lib/tp_plus/nodes/string_register_node.rb +25 -0
  44. data/lib/tp_plus/nodes/termination_node.rb +18 -0
  45. data/lib/tp_plus/nodes/terminator_node.rb +16 -0
  46. data/lib/tp_plus/nodes/time_node.rb +24 -0
  47. data/lib/tp_plus/nodes/timer_method_node.rb +37 -0
  48. data/lib/tp_plus/nodes/timer_node.rb +21 -0
  49. data/lib/tp_plus/nodes/units_node.rb +20 -0
  50. data/lib/tp_plus/nodes/use_node.rb +21 -0
  51. data/lib/tp_plus/nodes/user_alarm_node.rb +15 -0
  52. data/lib/tp_plus/nodes/var_method_node.rb +23 -0
  53. data/lib/tp_plus/nodes/var_node.rb +39 -0
  54. data/lib/tp_plus/nodes/vision_register_node.rb +21 -0
  55. data/lib/tp_plus/nodes/wait_for_node.rb +54 -0
  56. data/lib/tp_plus/nodes/wait_until_node.rb +65 -0
  57. data/lib/tp_plus/nodes/while_node.rb +36 -0
  58. data/lib/tp_plus/parser.rb +1592 -0
  59. data/lib/tp_plus/scanner.rb +383 -0
  60. data/lib/tp_plus/version.rb +3 -0
  61. data/lib/tp_plus.rb +62 -0
  62. data/test/test_helper.rb +5 -0
  63. data/test/tp_plus/test_interpreter.rb +1168 -0
  64. data/test/tp_plus/test_parser.rb +489 -0
  65. data/test/tp_plus/test_scanner.rb +522 -0
  66. data/tp_plus.gemspec +28 -0
  67. metadata +156 -0
@@ -0,0 +1,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