slidefield 0.1

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 (56) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +674 -0
  5. data/README.md +254 -0
  6. data/Rakefile +7 -0
  7. data/bin/slidefield +89 -0
  8. data/examples/complete/assets/K2.jpg +0 -0
  9. data/examples/complete/assets/gobi.jpg +0 -0
  10. data/examples/complete/assets/mount_everest.jpg +0 -0
  11. data/examples/complete/assets/sahara.jpg +0 -0
  12. data/examples/complete/main.sfp +7 -0
  13. data/examples/complete/slides/deserts.sfi +19 -0
  14. data/examples/complete/slides/mountains.sfi +25 -0
  15. data/examples/complete/templates.sfi +95 -0
  16. data/examples/complete/variables.sfi +6 -0
  17. data/examples/minimal/main.sfp +43 -0
  18. data/examples/minimal/ruby-logo.png +0 -0
  19. data/lib/slidefield/animator.rb +104 -0
  20. data/lib/slidefield/errors.rb +6 -0
  21. data/lib/slidefield/interpreter.rb +414 -0
  22. data/lib/slidefield/object_data.rb +78 -0
  23. data/lib/slidefield/object_manager.rb +29 -0
  24. data/lib/slidefield/object_rules.rb +79 -0
  25. data/lib/slidefield/objects/_base.rb +29 -0
  26. data/lib/slidefield/objects/_root.rb +10 -0
  27. data/lib/slidefield/objects/animation.rb +10 -0
  28. data/lib/slidefield/objects/debug.rb +18 -0
  29. data/lib/slidefield/objects/image.rb +47 -0
  30. data/lib/slidefield/objects/include.rb +9 -0
  31. data/lib/slidefield/objects/layout.rb +10 -0
  32. data/lib/slidefield/objects/rect.rb +44 -0
  33. data/lib/slidefield/objects/slide.rb +43 -0
  34. data/lib/slidefield/objects/song.rb +31 -0
  35. data/lib/slidefield/objects/text.rb +57 -0
  36. data/lib/slidefield/parser.rb +99 -0
  37. data/lib/slidefield/version.rb +3 -0
  38. data/lib/slidefield/viewer.rb +89 -0
  39. data/lib/slidefield.rb +27 -0
  40. data/slidefield.gemspec +27 -0
  41. data/test/helper.rb +11 -0
  42. data/test/resources/include_sub.sfp +1 -0
  43. data/test/resources/parse_error.sfp +1 -0
  44. data/test/resources/recursive_include.sfp +1 -0
  45. data/test/resources/sub/include_parent.sfp +1 -0
  46. data/test/resources/unclosed_object.sfp +2 -0
  47. data/test/resources/unknown_object.sfp +1 -0
  48. data/test/resources/wrong_template.sfp +4 -0
  49. data/test/test_animator.rb +244 -0
  50. data/test/test_examples.rb +29 -0
  51. data/test/test_interpreter.rb +1766 -0
  52. data/test/test_object_data.rb +108 -0
  53. data/test/test_object_manager.rb +48 -0
  54. data/test/test_object_rules.rb +87 -0
  55. data/test/test_parser.rb +408 -0
  56. metadata +199 -0
@@ -0,0 +1,1766 @@
1
+ require File.expand_path '../helper', __FILE__
2
+
3
+ module SlideField::ObjectRules
4
+ class Parent < Base
5
+ def rules
6
+ child :child
7
+ child :value
8
+ child :aaaa
9
+ end
10
+ end
11
+
12
+ class Child < Base
13
+ end
14
+
15
+ class Type < Base
16
+ def rules
17
+ property :test, :point, [0,0]
18
+ end
19
+ end
20
+
21
+ class Value < Base
22
+ def rules
23
+ property :num, :integer, 0
24
+ property :num2, :integer, 0
25
+ property :str, :string, ""
26
+ end
27
+ end
28
+
29
+ class Picky < Base
30
+ def rules
31
+ property :king_name, :string
32
+ child :minOne, 1
33
+ child :minTwo, 2
34
+ child :maxOne, 1, 1
35
+ end
36
+ end
37
+ end
38
+
39
+ class TestInterpreter < MiniTest::Test
40
+ def setup
41
+ @col_cache = []
42
+ @interpreter = SlideField::Interpreter.new
43
+ @path = File.expand_path 'resources', __dir__
44
+ end
45
+
46
+ def slice(val, line)
47
+ @col_cache[line] = 0 unless @col_cache[line]
48
+ col = @col_cache[line] += 1
49
+
50
+ line_cache = MiniTest::Mock.new
51
+ line_cache.expect :line_and_column, [line, col], [Object]
52
+
53
+ pos = Parslet::Position.new val, 0
54
+ Parslet::Slice.new pos, val, line_cache
55
+ end
56
+
57
+ def test_excerpt_parse_error
58
+ error = assert_raises SlideField::ParseError do
59
+ @interpreter.run_string '"'
60
+ end
61
+
62
+ assert_match /\A\[input\] /, error.message
63
+ refute_match /\A\[input\] \[input\]/, error.message
64
+ assert_match /\n\t"\n\t\^\Z/, error.message
65
+ end
66
+
67
+ def test_excerpt_interpreter_error
68
+ error = assert_raises SlideField::InterpreterError do
69
+ @interpreter.run_string "\\object\n"
70
+ end
71
+
72
+ assert_match /\A\[input\] /, error.message
73
+ assert_match /\n\t\\object\n\t \^\Z/, error.message
74
+ end
75
+
76
+ def test_strip_excerpt
77
+ error = assert_raises SlideField::InterpreterError do
78
+ @interpreter.run_string "\t\t\t\t \t \\object"
79
+ end
80
+
81
+ assert_match /\A\[input\] /, error.message
82
+ assert_match /\n\t\\object\n\t \^\Z/, error.message
83
+ end
84
+
85
+ def test_run_interpreter_validation
86
+ error = assert_raises SlideField::InterpreterError do
87
+ @interpreter.run_string "% nothing\n"
88
+ end
89
+
90
+ assert_match /\A\[input\] /, error.message
91
+ assert_match /line 0 char 0\Z/, error.message
92
+ end
93
+
94
+ def test_empty_tree
95
+ o = SlideField::ObjectData.new :parent, 'loc'
96
+ @interpreter.interpret_tree "", o
97
+ end
98
+
99
+ def test_unsupported_object
100
+ tokens = [
101
+ {:object=>{:type=>slice('aaaa', 1)}},
102
+ ]
103
+
104
+ o = SlideField::ObjectData.new :parent, 'loc'
105
+ error = assert_raises RuntimeError do
106
+ @interpreter.interpret_tree tokens, o
107
+ end
108
+
109
+ assert_equal "Unsupported object 'aaaa'", error.message
110
+ end
111
+
112
+ def test_unsupported_statement
113
+ tokens = [
114
+ {:hello_world=>{}},
115
+ ]
116
+
117
+ o = SlideField::ObjectData.new :child, 'loc'
118
+ error = assert_raises RuntimeError do
119
+ @interpreter.interpret_tree tokens, o
120
+ end
121
+
122
+ assert_equal "Unsupported statement 'hello_world'", error.message
123
+ end
124
+
125
+ def test_unsupported_type
126
+ tokens = [
127
+ {:assignment=>{
128
+ :variable=>slice('var', 1),
129
+ :operator=>slice('=', 1),
130
+ :value=>{:filters=>[], :dog_food=>slice('yum', 1)}
131
+ }},
132
+ ]
133
+
134
+ o = SlideField::ObjectData.new :child, 'loc'
135
+ error = assert_raises RuntimeError do
136
+ @interpreter.interpret_tree tokens, o
137
+ end
138
+
139
+ assert_equal "Unsupported type 'dog_food' at line 1 char 3", error.message
140
+ end
141
+
142
+ def test_unsupported_operator
143
+ tokens = [
144
+ {:assignment=>{
145
+ :variable=>slice('var', 1),
146
+ :operator=>slice('baconize', 1),
147
+ :value=>{:filters=>[], :integer=>slice('42', 1)}
148
+ }},
149
+ ]
150
+
151
+ o = SlideField::ObjectData.new :child, 'loc'
152
+ error = assert_raises RuntimeError do
153
+ @interpreter.interpret_tree tokens, o
154
+ end
155
+
156
+ assert_equal "Unsupported operator 'baconize' at line 1 char 2", error.message
157
+ end
158
+
159
+ def test_set_already_defined
160
+ tokens = [
161
+ {:assignment=>{
162
+ :variable=>slice('var', 1),
163
+ :operator=>slice('=', 1),
164
+ :value=>{:filters=>[], :integer=>slice('42', 1)}
165
+ }},
166
+ ]
167
+
168
+ o = SlideField::ObjectData.new :child, 'loc'
169
+ o.set :var, 1
170
+
171
+ error = assert_raises SlideField::InterpreterError do
172
+ @interpreter.interpret_tree tokens, o
173
+ end
174
+
175
+ assert_equal "Variable 'var' is already defined at line 1 char 1", error.message
176
+ end
177
+
178
+ def test_set_integer
179
+ tokens = [
180
+ {:assignment=>{
181
+ :variable=>slice('var', 1),
182
+ :operator=>slice('=', 1),
183
+ :value=>{:filters=>[], :integer=>slice('42', 1)}
184
+ }},
185
+ ]
186
+
187
+ o = SlideField::ObjectData.new :child, 'loc'
188
+ @interpreter.interpret_tree tokens, o
189
+
190
+ assert_equal 42, o.get(:var)
191
+ assert_equal :integer, o.var_type(:var)
192
+ assert_equal 'line 1 char 3', o.var_loc(:var)
193
+ end
194
+
195
+ def test_set_point
196
+ tokens = [
197
+ {:assignment=>{
198
+ :variable=>slice('var', 1),
199
+ :operator=>slice('=', 1),
200
+ :value=>{:filters=>[], :point=>slice('12x34', 1)}
201
+ }},
202
+ ]
203
+
204
+ o = SlideField::ObjectData.new :child, 'loc'
205
+ @interpreter.interpret_tree tokens, o
206
+
207
+ assert_equal [12,34], o.get(:var)
208
+ assert_equal :point, o.var_type(:var)
209
+ assert_equal 'line 1 char 3', o.var_loc(:var)
210
+ end
211
+
212
+ def test_set_string
213
+ tokens = [
214
+ {:assignment=>{
215
+ :variable=>slice('var', 1),
216
+ :operator=>slice('=', 1),
217
+ :value=>{:filters=>[], :string=>slice('"hello"', 1)}
218
+ }},
219
+ ]
220
+
221
+ o = SlideField::ObjectData.new :child, 'loc'
222
+ @interpreter.interpret_tree tokens, o
223
+
224
+ assert_equal 'hello', o.get(:var)
225
+ assert_equal :string, o.var_type(:var)
226
+ assert_equal 'line 1 char 3', o.var_loc(:var)
227
+ end
228
+
229
+ def test_set_color
230
+ tokens = [
231
+ {:assignment=>{
232
+ :variable=>slice('var', 1),
233
+ :operator=>slice('=', 1),
234
+ :value=>{:filters=>[], :color=>slice('#C0FF33FF', 1)}
235
+ }},
236
+ ]
237
+
238
+ o = SlideField::ObjectData.new :child, 'loc'
239
+ @interpreter.interpret_tree tokens, o
240
+
241
+ assert_equal [192, 255, 51, 255], o.get(:var)
242
+ assert_equal :color, o.var_type(:var)
243
+ assert_equal 'line 1 char 3', o.var_loc(:var)
244
+ end
245
+
246
+ def test_set_boolean
247
+ tokens = [
248
+ {:assignment=>{
249
+ :variable=>slice('var', 1),
250
+ :operator=>slice('=', 1),
251
+ :value=>{:filters=>[], :boolean=>slice(':true', 1)}
252
+ }},
253
+ ]
254
+
255
+ o = SlideField::ObjectData.new :child, 'loc'
256
+ @interpreter.interpret_tree tokens, o
257
+
258
+ assert_equal true, o.get(:var)
259
+ assert_equal :boolean, o.var_type(:var)
260
+ assert_equal 'line 1 char 3', o.var_loc(:var)
261
+ end
262
+
263
+ def test_set_object
264
+ object = {
265
+ :type=>slice('type', 2),
266
+ :value=>{:filters=>[], :point=>slice('42x42', 2)}
267
+ }
268
+
269
+ tokens = [{
270
+ :assignment=>{
271
+ :variable=>slice('var', 1),
272
+ :operator=>slice('=', 1),
273
+ :value=>{:filters=>[], :object=>object}
274
+ }
275
+ }]
276
+
277
+ o = SlideField::ObjectData.new :child, 'loc'
278
+ o.include_path = 'include/path/'
279
+ o.context = 'the/file.sfp'
280
+
281
+ @interpreter.interpret_tree tokens, o
282
+ val = o.get(:var)
283
+
284
+ assert_equal object, o.get(:var)
285
+ assert_equal :object, o.var_type(:var)
286
+ assert_equal 'line 2 char 1', o.var_loc(:var)
287
+ end
288
+
289
+ def test_set_identifier
290
+ tokens = [
291
+ {:assignment=>{
292
+ :variable=>slice('var', 1),
293
+ :operator=>slice('=', 1),
294
+ :value=>{:filters=>[], :identifier=>slice('test', 1)}
295
+ }},
296
+ ]
297
+
298
+ o = SlideField::ObjectData.new :child, 'loc'
299
+ o.set :test, 'hello', 'loc', :string
300
+
301
+ @interpreter.interpret_tree tokens, o
302
+ assert_equal 'hello', o.get(:var)
303
+ assert_equal :string, o.var_type(:var)
304
+ assert_equal 'line 1 char 3', o.var_loc(:var)
305
+ end
306
+
307
+ def test_set_undefined_identifier
308
+ tokens = [
309
+ {:assignment=>{
310
+ :variable=>slice('var', 1),
311
+ :operator=>slice('=', 1),
312
+ :value=>{:filters=>[], :identifier=>slice('test', 1)}
313
+ }},
314
+ ]
315
+
316
+ o = SlideField::ObjectData.new :child, 'loc'
317
+ error = assert_raises SlideField::InterpreterError do
318
+ @interpreter.interpret_tree tokens, o
319
+ end
320
+
321
+ assert_equal "Undefined variable 'test' at line 1 char 3", error.message
322
+ end
323
+
324
+
325
+ def test_set_wrong_type
326
+ tokens = [
327
+ {:assignment=>{
328
+ :variable=>slice('test', 1),
329
+ :operator=>slice('=', 1),
330
+ :value=>{:filters=>[], :integer=>slice('42', 1)}
331
+ }},
332
+ ]
333
+
334
+ o = SlideField::ObjectData.new :type, 'loc'
335
+ error = assert_raises SlideField::InterpreterError do
336
+ @interpreter.interpret_tree tokens, o
337
+ end
338
+
339
+ assert_equal "Unexpected 'integer', expecting 'point' for property 'test' at line 1 char 3", error.message
340
+ end
341
+
342
+ def test_add_undefined
343
+ tokens = [
344
+ {:assignment=>{
345
+ :variable=>slice('var', 1),
346
+ :operator=>slice('+=', 1),
347
+ :value=>{:filters=>[], :integer=>slice('42', 1)}
348
+ }},
349
+ ]
350
+
351
+ o = SlideField::ObjectData.new :child, 'loc'
352
+ error = assert_raises SlideField::InterpreterError do
353
+ @interpreter.interpret_tree tokens, o
354
+ end
355
+
356
+ assert_equal "Undefined variable 'var' at line 1 char 1", error.message
357
+ end
358
+
359
+ def test_add_incompatible
360
+ tokens = [
361
+ {:assignment=>{
362
+ :variable=>slice('var', 1),
363
+ :operator=>slice('+=', 1),
364
+ :value=>{:filters=>[], :integer=>slice('42', 1)}
365
+ }},
366
+ ]
367
+
368
+ o = SlideField::ObjectData.new :child, 'loc'
369
+ o.set :var, 'test', 'loc', :string
370
+
371
+ error = assert_raises SlideField::InterpreterError do
372
+ @interpreter.interpret_tree tokens, o
373
+ end
374
+
375
+ assert_equal "Unexpected 'integer', expecting 'string' for variable or property 'var' at line 1 char 3", error.message
376
+ end
377
+
378
+ def test_add_integer
379
+ tokens = [
380
+ {:assignment=>{
381
+ :variable=>slice('var', 1),
382
+ :operator=>slice('+=', 1),
383
+ :value=>{:filters=>[], :integer=>slice('42', 1)}
384
+ }},
385
+ ]
386
+
387
+ o = SlideField::ObjectData.new :child, 'loc'
388
+ o.set :var, 42, 'loc', :integer
389
+
390
+ @interpreter.interpret_tree tokens, o
391
+ assert_equal 84, o.get(:var)
392
+ assert_equal :integer, o.var_type(:var)
393
+ assert_equal 'line 1 char 3', o.var_loc(:var)
394
+ end
395
+
396
+ def test_add_point
397
+ tokens = [
398
+ {:assignment=>{
399
+ :variable=>slice('var', 1),
400
+ :operator=>slice('+=', 1),
401
+ :value=>{:filters=>[], :point=>slice('42x42', 1)}
402
+ }},
403
+ ]
404
+
405
+ o = SlideField::ObjectData.new :child, 'loc'
406
+ o.set :var, [42,42], 'loc', :point
407
+
408
+ @interpreter.interpret_tree tokens, o
409
+ assert_equal [84,84], o.get(:var)
410
+ assert_equal :point, o.var_type(:var)
411
+ assert_equal 'line 1 char 3', o.var_loc(:var)
412
+ end
413
+
414
+ def test_add_string
415
+ tokens = [
416
+ {:assignment=>{
417
+ :variable=>slice('var', 1),
418
+ :operator=>slice('+=', 1),
419
+ :value=>{:filters=>[], :string=>slice('" world"', 1)}
420
+ }},
421
+ ]
422
+
423
+ o = SlideField::ObjectData.new :child, 'loc'
424
+ o.set :var, 'hello', 'loc', :string
425
+
426
+ @interpreter.interpret_tree tokens, o
427
+ assert_equal 'hello world', o.get(:var)
428
+ assert_equal :string, o.var_type(:var)
429
+ assert_equal 'line 1 char 3', o.var_loc(:var)
430
+ end
431
+
432
+ def test_add_color
433
+ tokens = [
434
+ {:assignment=>{
435
+ :variable=>slice('var', 1),
436
+ :operator=>slice('+=', 1),
437
+ :value=>{:filters=>[], :color=>slice('#01010101', 1)}
438
+ }},
439
+ ]
440
+
441
+ o = SlideField::ObjectData.new :child, 'loc'
442
+ o.set :var, [0, 0, 0, 0], 'loc', :color
443
+
444
+ @interpreter.interpret_tree tokens, o
445
+ assert_equal [1, 1, 1, 1], o.get(:var)
446
+ assert_equal :color, o.var_type(:var)
447
+ assert_equal 'line 1 char 3', o.var_loc(:var)
448
+ end
449
+
450
+ def test_add_color_overflow
451
+ tokens = [
452
+ {:assignment=>{
453
+ :variable=>slice('var', 1),
454
+ :operator=>slice('+=', 1),
455
+ :value=>{:filters=>[], :color=>slice('#01010101', 1)}
456
+ }},
457
+ ]
458
+
459
+ o = SlideField::ObjectData.new :child, 'loc'
460
+ o.set :var, [255, 255, 255, 255], 'loc', :color
461
+
462
+ @interpreter.interpret_tree tokens, o
463
+ assert_equal [255, 255, 255, 255], o.get(:var)
464
+ assert_equal :color, o.var_type(:var)
465
+ assert_equal 'line 1 char 3', o.var_loc(:var)
466
+ end
467
+
468
+ def test_add_boolean
469
+ tokens = [
470
+ {:assignment=>{
471
+ :variable=>slice('var', 1),
472
+ :operator=>slice('+=', 1),
473
+ :value=>{:filters=>[], :boolean=>slice(':true', 1)}
474
+ }},
475
+ ]
476
+
477
+ o = SlideField::ObjectData.new :child, 'loc'
478
+ o.set :var, true, 'loc', :boolean
479
+
480
+ error = assert_raises SlideField::InterpreterError do
481
+ @interpreter.interpret_tree tokens, o
482
+ end
483
+
484
+ assert_equal "Invalid operator '+=' for type 'boolean' at line 1 char 2", error.message
485
+ end
486
+
487
+ def test_add_identifier
488
+ tokens = [
489
+ {:assignment=>{
490
+ :variable=>slice('var', 1),
491
+ :operator=>slice('+=', 1),
492
+ :value=>{:filters=>[], :identifier=>slice('test', 1)}
493
+ }},
494
+ ]
495
+
496
+ o = SlideField::ObjectData.new :child, 'loc'
497
+ o.set :var, 'hello', 'loc', :string
498
+ o.set :test, ' world', 'loc', :string
499
+
500
+ @interpreter.interpret_tree tokens, o
501
+ assert_equal 'hello world', o.get(:var)
502
+ assert_equal :string, o.var_type(:var)
503
+ assert_equal 'line 1 char 3', o.var_loc(:var)
504
+ end
505
+
506
+ def test_sub_undefined
507
+ tokens = [
508
+ {:assignment=>{
509
+ :variable=>slice('var', 1),
510
+ :operator=>slice('-=', 1),
511
+ :value=>{:filters=>[], :integer=>slice('42', 1)}
512
+ }},
513
+ ]
514
+
515
+ o = SlideField::ObjectData.new :child, 'loc'
516
+ error = assert_raises SlideField::InterpreterError do
517
+ @interpreter.interpret_tree tokens, o
518
+ end
519
+
520
+ assert_equal "Undefined variable 'var' at line 1 char 1", error.message
521
+ end
522
+
523
+ def test_sub_incompatible
524
+ tokens = [
525
+ {:assignment=>{
526
+ :variable=>slice('var', 1),
527
+ :operator=>slice('-=', 1),
528
+ :value=>{:filters=>[], :integer=>slice('42', 1)}
529
+ }},
530
+ ]
531
+
532
+ o = SlideField::ObjectData.new :child, 'loc'
533
+ o.set :var, 'test', 'loc', :string
534
+
535
+ error = assert_raises SlideField::InterpreterError do
536
+ @interpreter.interpret_tree tokens, o
537
+ end
538
+
539
+ assert_equal "Unexpected 'integer', expecting 'string' for variable or property 'var' at line 1 char 3", error.message
540
+ end
541
+
542
+ def test_sub_integer
543
+ tokens = [
544
+ {:assignment=>{
545
+ :variable=>slice('var', 1),
546
+ :operator=>slice('-=', 1),
547
+ :value=>{:filters=>[], :integer=>slice('42', 1)}
548
+ }},
549
+ ]
550
+
551
+ o = SlideField::ObjectData.new :child, 'loc'
552
+ o.set :var, 44, 'loc', :integer
553
+
554
+ @interpreter.interpret_tree tokens, o
555
+ assert_equal 2, o.get(:var)
556
+ assert_equal :integer, o.var_type(:var)
557
+ assert_equal 'line 1 char 3', o.var_loc(:var)
558
+ end
559
+
560
+ def test_sub_point
561
+ tokens = [
562
+ {:assignment=>{
563
+ :variable=>slice('var', 1),
564
+ :operator=>slice('-=', 1),
565
+ :value=>{:filters=>[], :point=>slice('42x42', 1)}
566
+ }},
567
+ ]
568
+
569
+ o = SlideField::ObjectData.new :child, 'loc'
570
+ o.set :var, [46,44], 'loc', :point
571
+
572
+ @interpreter.interpret_tree tokens, o
573
+ assert_equal [4,2], o.get(:var)
574
+ assert_equal :point, o.var_type(:var)
575
+ assert_equal 'line 1 char 3', o.var_loc(:var)
576
+ end
577
+
578
+ def test_sub_string
579
+ tokens = [
580
+ {:assignment=>{
581
+ :variable=>slice('var', 1),
582
+ :operator=>slice('-=', 1),
583
+ :value=>{:filters=>[], :string=>slice('" world"', 1)}
584
+ }},
585
+ {:assignment=>{
586
+ :variable=>slice('var', 2),
587
+ :operator=>slice('-=', 2),
588
+ :value=>{:filters=>[], :string=>slice('"test"', 2)}
589
+ }},
590
+ ]
591
+
592
+ o = SlideField::ObjectData.new :child, 'loc'
593
+ o.set :var, 'hello world world', 'loc', :string
594
+
595
+ @interpreter.interpret_tree tokens, o
596
+ assert_equal 'hello', o.get(:var)
597
+ assert_equal :string, o.var_type(:var)
598
+ assert_equal 'line 2 char 3', o.var_loc(:var)
599
+ end
600
+
601
+ def test_sub_color
602
+ tokens = [
603
+ {:assignment=>{
604
+ :variable=>slice('var', 1),
605
+ :operator=>slice('-=', 1),
606
+ :value=>{:filters=>[], :color=>slice('#01010101', 1)}
607
+ }},
608
+ ]
609
+
610
+ o = SlideField::ObjectData.new :child, 'loc'
611
+ o.set :var, [1, 1, 1, 1], 'loc', :color
612
+
613
+ @interpreter.interpret_tree tokens, o
614
+ assert_equal [0, 0, 0, 0], o.get(:var)
615
+ assert_equal :color, o.var_type(:var)
616
+ assert_equal 'line 1 char 3', o.var_loc(:var)
617
+ end
618
+
619
+ def test_sub_color_underflow
620
+ tokens = [
621
+ {:assignment=>{
622
+ :variable=>slice('var', 1),
623
+ :operator=>slice('-=', 1),
624
+ :value=>{:filters=>[], :color=>slice('#01010101', 1)}
625
+ }},
626
+ ]
627
+
628
+ o = SlideField::ObjectData.new :child, 'loc'
629
+ o.set :var, [0, 0, 0, 0], 'loc', :color
630
+
631
+ @interpreter.interpret_tree tokens, o
632
+ assert_equal [0, 0, 0, 0], o.get(:var)
633
+ assert_equal :color, o.var_type(:var)
634
+ assert_equal 'line 1 char 3', o.var_loc(:var)
635
+ end
636
+
637
+ def test_sub_boolean
638
+ tokens = [
639
+ {:assignment=>{
640
+ :variable=>slice('var', 1),
641
+ :operator=>slice('-=', 1),
642
+ :value=>{:filters=>[], :boolean=>slice(':true', 1)}
643
+ }},
644
+ ]
645
+
646
+ o = SlideField::ObjectData.new :child, 'loc'
647
+ o.set :var, true, 'loc', :boolean
648
+
649
+ error = assert_raises SlideField::InterpreterError do
650
+ @interpreter.interpret_tree tokens, o
651
+ end
652
+
653
+ assert_equal "Invalid operator '-=' for type 'boolean' at line 1 char 2", error.message
654
+ end
655
+
656
+ def test_sub_identifier
657
+ tokens = [
658
+ {:assignment=>{
659
+ :variable=>slice('var', 1),
660
+ :operator=>slice('-=', 1),
661
+ :value=>{:filters=>[], :identifier=>slice('test', 1)}
662
+ }},
663
+ ]
664
+
665
+ o = SlideField::ObjectData.new :child, 'loc'
666
+ o.set :var, 3, 'loc', :integer
667
+ o.set :test, 2, 'loc', :integer
668
+
669
+ @interpreter.interpret_tree tokens, o
670
+ assert_equal 1, o.get(:var)
671
+ assert_equal :integer, o.var_type(:var)
672
+ assert_equal 'line 1 char 3', o.var_loc(:var)
673
+ end
674
+
675
+ def test_mul_undefined
676
+ tokens = [
677
+ {:assignment=>{
678
+ :variable=>slice('var', 1),
679
+ :operator=>slice('*=', 1),
680
+ :value=>{:filters=>[], :integer=>slice('42', 1)}
681
+ }},
682
+ ]
683
+
684
+ o = SlideField::ObjectData.new :child, 'loc'
685
+ error = assert_raises SlideField::InterpreterError do
686
+ @interpreter.interpret_tree tokens, o
687
+ end
688
+
689
+ assert_equal "Undefined variable 'var' at line 1 char 1", error.message
690
+ end
691
+
692
+ def test_mul_incompatible
693
+ tokens = [
694
+ {:assignment=>{
695
+ :variable=>slice('var', 1),
696
+ :operator=>slice('*=', 1),
697
+ :value=>{:filters=>[], :integer=>slice('42', 1)}
698
+ }},
699
+ ]
700
+
701
+ o = SlideField::ObjectData.new :child, 'loc'
702
+ o.set :var, 'test', 'loc', :string
703
+
704
+ error = assert_raises SlideField::InterpreterError do
705
+ @interpreter.interpret_tree tokens, o
706
+ end
707
+
708
+ assert_equal "Unexpected 'integer', expecting 'string' for variable or property 'var' at line 1 char 3", error.message
709
+ end
710
+
711
+ def test_mul_integer
712
+ tokens = [
713
+ {:assignment=>{
714
+ :variable=>slice('var', 1),
715
+ :operator=>slice('*=', 1),
716
+ :value=>{:filters=>[], :integer=>slice('4', 1)}
717
+ }},
718
+ ]
719
+
720
+ o = SlideField::ObjectData.new :child, 'loc'
721
+ o.set :var, 4, 'loc', :integer
722
+
723
+ @interpreter.interpret_tree tokens, o
724
+ assert_equal 16, o.get(:var)
725
+ assert_equal :integer, o.var_type(:var)
726
+ assert_equal 'line 1 char 3', o.var_loc(:var)
727
+ end
728
+
729
+ def test_mul_point
730
+ tokens = [
731
+ {:assignment=>{
732
+ :variable=>slice('var', 1),
733
+ :operator=>slice('*=', 1),
734
+ :value=>{:filters=>[], :point=>slice('4x2', 1)}
735
+ }},
736
+ ]
737
+
738
+ o = SlideField::ObjectData.new :child, 'loc'
739
+ o.set :var, [4,2], 'loc', :point
740
+
741
+ @interpreter.interpret_tree tokens, o
742
+ assert_equal [16,4], o.get(:var)
743
+ assert_equal :point, o.var_type(:var)
744
+ assert_equal 'line 1 char 3', o.var_loc(:var)
745
+ end
746
+
747
+ def test_mul_string
748
+ tokens = [
749
+ {:assignment=>{
750
+ :variable=>slice('var', 1),
751
+ :operator=>slice('*=', 1),
752
+ :value=>{:filters=>[], :string=>slice('"3"', 1)}
753
+ }},
754
+ ]
755
+
756
+ o = SlideField::ObjectData.new :child, 'loc'
757
+ o.set :var, 'test', 'loc', :string
758
+
759
+ @interpreter.interpret_tree tokens, o
760
+ assert_equal 'testtesttest', o.get(:var)
761
+ assert_equal :string, o.var_type(:var)
762
+ assert_equal 'line 1 char 3', o.var_loc(:var)
763
+ end
764
+
765
+ def test_mul_string_invalid
766
+ tokens = [
767
+ {:assignment=>{
768
+ :variable=>slice('var', 1),
769
+ :operator=>slice('*=', 1),
770
+ :value=>{:filters=>[], :string=>slice('"aaaa"', 1)}
771
+ }},
772
+ ]
773
+
774
+ o = SlideField::ObjectData.new :child, 'loc'
775
+ o.set :var, 'test', 'loc', :string
776
+
777
+ error = assert_raises SlideField::InterpreterError do
778
+ @interpreter.interpret_tree tokens, o
779
+ end
780
+
781
+ assert_equal "Invalid string multiplier 'aaaa', integer > 0 required at line 1 char 3", error.message
782
+ end
783
+
784
+ def test_mul_color
785
+ tokens = [
786
+ {:assignment=>{
787
+ :variable=>slice('var', 1),
788
+ :operator=>slice('*=', 1),
789
+ :value=>{:filters=>[], :color=>slice('#02020202', 1)}
790
+ }},
791
+ ]
792
+
793
+ o = SlideField::ObjectData.new :child, 'loc'
794
+ o.set :var, [4, 4, 4, 4], 'loc', :color
795
+
796
+ error = assert_raises SlideField::InterpreterError do
797
+ @interpreter.interpret_tree tokens, o
798
+ end
799
+
800
+ assert_equal "Invalid operator '*=' for type 'color' at line 1 char 2", error.message
801
+ end
802
+
803
+ def test_mul_boolean
804
+ tokens = [
805
+ {:assignment=>{
806
+ :variable=>slice('var', 1),
807
+ :operator=>slice('*=', 1),
808
+ :value=>{:filters=>[], :boolean=>slice(':true', 1)}
809
+ }},
810
+ ]
811
+
812
+ o = SlideField::ObjectData.new :child, 'loc'
813
+ o.set :var, true, 'loc', :boolean
814
+
815
+ error = assert_raises SlideField::InterpreterError do
816
+ @interpreter.interpret_tree tokens, o
817
+ end
818
+
819
+ assert_equal "Invalid operator '*=' for type 'boolean' at line 1 char 2", error.message
820
+ end
821
+
822
+ def test_mul_identifier
823
+ tokens = [
824
+ {:assignment=>{
825
+ :variable=>slice('var', 1),
826
+ :operator=>slice('*=', 1),
827
+ :value=>{:filters=>[], :identifier=>slice('test', 1)}
828
+ }},
829
+ ]
830
+
831
+ o = SlideField::ObjectData.new :child, 'loc'
832
+ o.set :var, 3, 'loc', :integer
833
+ o.set :test, 2, 'loc', :integer
834
+
835
+ @interpreter.interpret_tree tokens, o
836
+ assert_equal 6, o.get(:var)
837
+ assert_equal :integer, o.var_type(:var)
838
+ assert_equal 'line 1 char 3', o.var_loc(:var)
839
+ end
840
+
841
+ def test_div_undefined
842
+ tokens = [
843
+ {:assignment=>{
844
+ :variable=>slice('var', 1),
845
+ :operator=>slice('/=', 1),
846
+ :value=>{:filters=>[], :integer=>slice('42', 1)}
847
+ }},
848
+ ]
849
+
850
+ o = SlideField::ObjectData.new :child, 'loc'
851
+ error = assert_raises SlideField::InterpreterError do
852
+ @interpreter.interpret_tree tokens, o
853
+ end
854
+
855
+ assert_equal "Undefined variable 'var' at line 1 char 1", error.message
856
+ end
857
+
858
+ def test_div_incompatible
859
+ tokens = [
860
+ {:assignment=>{
861
+ :variable=>slice('var', 1),
862
+ :operator=>slice('/=', 1),
863
+ :value=>{:filters=>[], :integer=>slice('42', 1)}
864
+ }},
865
+ ]
866
+
867
+ o = SlideField::ObjectData.new :child, 'loc'
868
+ o.set :var, 'test', 'loc', :string
869
+
870
+ error = assert_raises SlideField::InterpreterError do
871
+ @interpreter.interpret_tree tokens, o
872
+ end
873
+
874
+ assert_equal "Unexpected 'integer', expecting 'string' for variable or property 'var' at line 1 char 3", error.message
875
+ end
876
+
877
+ def test_div_integer
878
+ tokens = [
879
+ {:assignment=>{
880
+ :variable=>slice('var', 1),
881
+ :operator=>slice('/=', 1),
882
+ :value=>{:filters=>[], :integer=>slice('2', 1)}
883
+ }},
884
+ ]
885
+
886
+ o = SlideField::ObjectData.new :child, 'loc'
887
+ o.set :var, 7, 'loc', :integer
888
+
889
+ @interpreter.interpret_tree tokens, o
890
+ assert_equal 3, o.get(:var)
891
+ assert_equal :integer, o.var_type(:var)
892
+ assert_equal 'line 1 char 3', o.var_loc(:var)
893
+ end
894
+
895
+ def test_div_integer_by_zero
896
+ tokens = [
897
+ {:assignment=>{
898
+ :variable=>slice('var', 1),
899
+ :operator=>slice('/=', 1),
900
+ :value=>{:filters=>[], :integer=>slice('0', 1)}
901
+ }},
902
+ ]
903
+
904
+ o = SlideField::ObjectData.new :child, 'loc'
905
+ o.set :var, 42, 'loc', :integer
906
+
907
+ error = assert_raises SlideField::InterpreterError do
908
+ @interpreter.interpret_tree tokens, o
909
+ end
910
+
911
+ assert_equal "divided by zero at line 1 char 3", error.message
912
+ end
913
+
914
+ def test_div_point
915
+ tokens = [
916
+ {:assignment=>{
917
+ :variable=>slice('var', 1),
918
+ :operator=>slice('/=', 1),
919
+ :value=>{:filters=>[], :point=>slice('2x3', 1)}
920
+ }},
921
+ ]
922
+
923
+ o = SlideField::ObjectData.new :child, 'loc'
924
+ o.set :var, [7,42], 'loc', :point
925
+
926
+ @interpreter.interpret_tree tokens, o
927
+ assert_equal [3,14], o.get(:var)
928
+ assert_equal :point, o.var_type(:var)
929
+ assert_equal 'line 1 char 3', o.var_loc(:var)
930
+ end
931
+
932
+ def test_div_point_by_zero
933
+ tokens = [
934
+ {:assignment=>{
935
+ :variable=>slice('var', 1),
936
+ :operator=>slice('/=', 1),
937
+ :value=>{:filters=>[], :point=>slice('2x0', 1)}
938
+ }},
939
+ ]
940
+
941
+ o = SlideField::ObjectData.new :child, 'loc'
942
+ o.set :var, [42,42], 'loc', :point
943
+
944
+ error = assert_raises SlideField::InterpreterError do
945
+ @interpreter.interpret_tree tokens, o
946
+ end
947
+
948
+ assert_equal "divided by zero at line 1 char 3", error.message
949
+ end
950
+
951
+ def test_div_string
952
+ tokens = [
953
+ {:assignment=>{
954
+ :variable=>slice('var', 1),
955
+ :operator=>slice('/=', 1),
956
+ :value=>{:filters=>[], :string=>slice('" world"', 1)}
957
+ }},
958
+ ]
959
+
960
+ o = SlideField::ObjectData.new :child, 'loc'
961
+ o.set :var, 'hello world', 'loc', :string
962
+
963
+ error = assert_raises SlideField::InterpreterError do
964
+ @interpreter.interpret_tree tokens, o
965
+ end
966
+
967
+ assert_equal "Invalid operator '/=' for type 'string' at line 1 char 2", error.message
968
+ end
969
+
970
+ def test_div_color
971
+ tokens = [
972
+ {:assignment=>{
973
+ :variable=>slice('var', 1),
974
+ :operator=>slice('/=', 1),
975
+ :value=>{:filters=>[], :color=>slice('#02020202', 1)}
976
+ }},
977
+ ]
978
+
979
+ o = SlideField::ObjectData.new :child, 'loc'
980
+ o.set :var, [4, 4, 4, 4], 'loc', :color
981
+
982
+ error = assert_raises SlideField::InterpreterError do
983
+ @interpreter.interpret_tree tokens, o
984
+ end
985
+
986
+ assert_equal "Invalid operator '/=' for type 'color' at line 1 char 2", error.message
987
+ end
988
+
989
+ def test_div_boolean
990
+ tokens = [
991
+ {:assignment=>{
992
+ :variable=>slice('var', 1),
993
+ :operator=>slice('/=', 1),
994
+ :value=>{:filters=>[], :boolean=>slice(':true', 1)}
995
+ }},
996
+ ]
997
+
998
+ o = SlideField::ObjectData.new :child, 'loc'
999
+ o.set :var, true, 'loc', :boolean
1000
+
1001
+ error = assert_raises SlideField::InterpreterError do
1002
+ @interpreter.interpret_tree tokens, o
1003
+ end
1004
+
1005
+ assert_equal "Invalid operator '/=' for type 'boolean' at line 1 char 2", error.message
1006
+ end
1007
+
1008
+ def test_div_identifier
1009
+ tokens = [
1010
+ {:assignment=>{
1011
+ :variable=>slice('var', 1),
1012
+ :operator=>slice('/=', 1),
1013
+ :value=>{:filters=>[], :identifier=>slice('test', 1)}
1014
+ }},
1015
+ ]
1016
+
1017
+ o = SlideField::ObjectData.new :child, 'loc'
1018
+ o.set :var, 6, 'loc', :integer
1019
+ o.set :test, 2, 'loc', :integer
1020
+
1021
+ @interpreter.interpret_tree tokens, o
1022
+ assert_equal 3, o.get(:var)
1023
+ assert_equal :integer, o.var_type(:var)
1024
+ assert_equal 'line 1 char 3', o.var_loc(:var)
1025
+ end
1026
+
1027
+ def test_children
1028
+ tokens = [
1029
+ {:object=>{:type=>slice('child', 1), :body=>[
1030
+ {:assignment=>{
1031
+ :variable=>slice('var', 1),
1032
+ :operator=>slice('=', 1),
1033
+ :value=>{:filters=>[], :identifier=>slice('parent_var', 1)}
1034
+ }},
1035
+ ]}},
1036
+ ]
1037
+
1038
+ o = SlideField::ObjectData.new :parent, 'loc'
1039
+ o.set :parent_var, 'hello', 'loc', :string
1040
+
1041
+ @interpreter.interpret_tree tokens, o
1042
+ assert_equal 1, o.children.count
1043
+ assert_equal 'hello', o[:child][0].get(:var)
1044
+ end
1045
+
1046
+ def test_object_value
1047
+ tokens = [
1048
+ {:object=>{
1049
+ :type=>slice('value', 1),
1050
+ :value=>{:filters=>[], :integer=>slice('42', 1)}
1051
+ }},
1052
+ ]
1053
+
1054
+ o = SlideField::ObjectData.new :parent, 'loc'
1055
+
1056
+ @interpreter.interpret_tree tokens, o
1057
+ assert_equal 1, o.children.count
1058
+ assert_equal 42, o[:value][0].get(:num)
1059
+ end
1060
+
1061
+ def test_object_identifier_value
1062
+ tokens = [
1063
+ {:object=>{
1064
+ :type=>slice('value', 1),
1065
+ :value=>{:filters=>[], :identifier=>slice('test', 1)}
1066
+ }},
1067
+ ]
1068
+
1069
+ o = SlideField::ObjectData.new :parent, 'loc'
1070
+ o.set :test, 42, 'loc', :integer
1071
+
1072
+ @interpreter.interpret_tree tokens, o
1073
+ assert_equal 1, o.children.count
1074
+ assert_equal 42, o[:value][0].get(:num)
1075
+ end
1076
+
1077
+ def test_object_invalid_value
1078
+ tokens = [
1079
+ {:object=>{
1080
+ :type=>slice('value', 1),
1081
+ :value=>{:filters=>[], :point=>slice('12x3', 1)}
1082
+ }},
1083
+ ]
1084
+
1085
+ o = SlideField::ObjectData.new :parent, 'loc'
1086
+ error = assert_raises SlideField::InterpreterError do
1087
+ @interpreter.interpret_tree tokens, o
1088
+ end
1089
+
1090
+ assert_equal "Unexpected 'point', expecting one of [:integer, :string] at line 1 char 2", error.message
1091
+ end
1092
+
1093
+ def test_unknown_object
1094
+ tokens = [
1095
+ {:object=>{:type=>slice('qwfpgjluy', 1)}},
1096
+ ]
1097
+
1098
+ o = SlideField::ObjectData.new :parent, 'loc'
1099
+ error = assert_raises SlideField::InterpreterError do
1100
+ @interpreter.interpret_tree tokens, o
1101
+ end
1102
+
1103
+ assert_equal "Unexpected object 'qwfpgjluy', expecting one of [:aaaa, :child, :value] at line 1 char 1", error.message
1104
+ end
1105
+
1106
+ def test_missing_variable
1107
+ o = SlideField::ObjectData.new :picky, 'location'
1108
+
1109
+ error = assert_raises SlideField::InterpreterError do
1110
+ @interpreter.interpret_tree [], o
1111
+ end
1112
+
1113
+ assert_equal "Missing property 'king_name' for object 'picky' at location", error.message
1114
+ end
1115
+
1116
+ def test_missing_child
1117
+ o = SlideField::ObjectData.new :picky, 'location'
1118
+ o.set :king_name, 'value', 'var loc', :string
1119
+
1120
+ error = assert_raises SlideField::InterpreterError do
1121
+ @interpreter.interpret_tree [], o
1122
+ end
1123
+
1124
+ assert_equal "Object 'picky' must have at least 1 'minOne', 0 found at location", error.message
1125
+
1126
+ c1 = SlideField::ObjectData.new :minOne, 'location'
1127
+ o << c1
1128
+
1129
+ c2 = SlideField::ObjectData.new :minTwo, 'location'
1130
+ o << c2
1131
+
1132
+ error = assert_raises SlideField::InterpreterError do
1133
+ @interpreter.interpret_tree [], o
1134
+ end
1135
+
1136
+ assert_equal "Object 'picky' must have at least 2 'minTwo', 1 found at location", error.message
1137
+ end
1138
+
1139
+ def test_child_overdose
1140
+ o = SlideField::ObjectData.new :picky, 'location'
1141
+ o.set :king_name, 'value', 'var loc', :string
1142
+
1143
+ c1 = SlideField::ObjectData.new :minOne, 'location'
1144
+ o << c1
1145
+
1146
+ c2 = SlideField::ObjectData.new :minTwo, 'location'
1147
+ o << c2
1148
+ o << c2
1149
+
1150
+ c3 = SlideField::ObjectData.new :maxOne, 'location'
1151
+ o << c3
1152
+ o << c3
1153
+
1154
+ error = assert_raises SlideField::InterpreterError do
1155
+ @interpreter.interpret_tree [], o
1156
+ end
1157
+
1158
+ assert_equal "Object 'picky' can not have more than 1 'maxOne', 2 found at location", error.message
1159
+ end
1160
+
1161
+ def test_file_not_found
1162
+ i = @interpreter
1163
+ error = assert_raises SlideField::InterpreterError do
1164
+ i.run_file 'no.entry'
1165
+ end
1166
+
1167
+ assert_equal "No such file or directory @ rb_sysopen - no.entry", error.message
1168
+ end
1169
+
1170
+ def test_include_not_found
1171
+ i = @interpreter
1172
+ error = assert_raises SlideField::InterpreterError do
1173
+ i.run_string '\\include "/hello"'
1174
+ end
1175
+
1176
+ assert_equal "[input] No such file or directory @ rb_sysopen - /hello", error.message
1177
+ end
1178
+
1179
+ def test_escape_sequence
1180
+ tokens = [
1181
+ {:assignment=>{
1182
+ :variable=>slice('var', 1),
1183
+ :operator=>slice('=', 1),
1184
+ :value=>{:filters=>[], :string=>slice('"\\\\ \\"\\n\\s"', 1)}
1185
+ }},
1186
+ ]
1187
+
1188
+ o = SlideField::ObjectData.new :child, 'loc'
1189
+ @interpreter.interpret_tree tokens, o
1190
+
1191
+ assert_equal "\\ \"\ns", o.get(:var)
1192
+ assert_equal :string, o.var_type(:var)
1193
+ assert_equal 'line 1 char 3', o.var_loc(:var)
1194
+ end
1195
+
1196
+ def test_default_value
1197
+ o = SlideField::ObjectData.new :type, 'loc'
1198
+ @interpreter.interpret_tree [], o
1199
+
1200
+ assert_equal [0,0], o.get(:test)
1201
+ assert_equal :point, o.var_type(:test)
1202
+ assert_equal 'default', o.var_loc(:test)
1203
+ end
1204
+
1205
+ def test_default_value_parent
1206
+ p = SlideField::ObjectData.new :type, 'loc'
1207
+ p.set :test, [1,1], 'loc', :point
1208
+
1209
+ o = SlideField::ObjectData.new :type, 'loc'
1210
+ o.parent = p
1211
+
1212
+ @interpreter.interpret_tree [], o
1213
+
1214
+ assert_equal [1,1], o.get(:test)
1215
+ assert_equal :point, o.var_type(:test)
1216
+ assert_equal 'loc', o.var_loc(:test)
1217
+ end
1218
+
1219
+ def test_template
1220
+ tokens = [{
1221
+ :object=>{:template=>slice('&', 1), :type=>slice('var_name', 1)}
1222
+ }]
1223
+
1224
+ o = SlideField::ObjectData.new :parent, 'loc'
1225
+ o.set :var_name, {:type=>slice('child', 2)}, 'loc', :object
1226
+
1227
+ @interpreter.interpret_tree tokens, o
1228
+
1229
+ assert_equal 1, o[:child].count
1230
+ assert_equal 'line 1 char 2', o[:child].first.loc
1231
+ end
1232
+
1233
+ def test_template_upstream_body
1234
+ template = {
1235
+ :type=>slice('child', 1),
1236
+ :body=>[
1237
+ {:assignment=>{
1238
+ :variable=>slice('var', 1),
1239
+ :operator=>slice('=', 1),
1240
+ :value=>{:filters=>[], :integer=>slice('42', 1)}
1241
+ }},
1242
+ ]
1243
+ }
1244
+
1245
+ tokens = [{
1246
+ :object=>{
1247
+ :template=>slice('&', 2),
1248
+ :type=>slice('var_name', 2),
1249
+ }
1250
+ }]
1251
+
1252
+ o = SlideField::ObjectData.new :parent, 'loc'
1253
+ o.set :var_name, template, 'loc', :object
1254
+
1255
+ @interpreter.interpret_tree tokens, o
1256
+ copy = o[:child].first
1257
+
1258
+ assert_equal 42, copy.get(:var)
1259
+ assert_equal :integer, copy.var_type(:var)
1260
+ assert_equal 'line 2 char 1', copy.var_loc(:var)
1261
+ end
1262
+
1263
+ def test_template_downstream_body
1264
+ template = {
1265
+ :type=>slice('child', 1),
1266
+ }
1267
+
1268
+ tokens = [{
1269
+ :object=>{
1270
+ :template=>slice('&', 2),
1271
+ :type=>slice('var_name', 2),
1272
+ :body=>[
1273
+ {:assignment=>{
1274
+ :variable=>slice('var', 3),
1275
+ :operator=>slice('=', 3),
1276
+ :value=>{:filters=>[], :integer=>slice('42', 3)}
1277
+ }},
1278
+ ]
1279
+ }
1280
+ }]
1281
+
1282
+ o = SlideField::ObjectData.new :parent, 'loc'
1283
+ o.set :var_name, template, 'loc', :object
1284
+
1285
+ @interpreter.interpret_tree tokens, o
1286
+ copy = o[:child].first
1287
+
1288
+ assert_equal 42, copy.get(:var)
1289
+ assert_equal :integer, copy.var_type(:var)
1290
+ assert_equal 'line 3 char 3', copy.var_loc(:var)
1291
+ end
1292
+
1293
+ def test_template_merge_bodies
1294
+ template = {
1295
+ :type=>slice('child', 1),
1296
+ :body=>[
1297
+ {:assignment=>{
1298
+ :variable=>slice('var', 1),
1299
+ :operator=>slice('+=', 1),
1300
+ :value=>{:filters=>[], :integer=>slice('2', 1)}
1301
+ }},
1302
+ ]
1303
+ }
1304
+
1305
+ tokens = [{
1306
+ :object=>{
1307
+ :template=>slice('&', 2),
1308
+ :type=>slice('var_name', 2),
1309
+ :body=>[
1310
+ {:assignment=>{
1311
+ :variable=>slice('var', 3),
1312
+ :operator=>slice('=', 3),
1313
+ :value=>{:filters=>[], :integer=>slice('42', 3)}
1314
+ }},
1315
+ ]
1316
+ }
1317
+ }]
1318
+
1319
+ o = SlideField::ObjectData.new :parent, 'loc'
1320
+ o.set :var_name, template, 'loc', :object
1321
+
1322
+ @interpreter.interpret_tree tokens, o
1323
+ copy = o[:child].first
1324
+
1325
+ assert_equal 44, copy.get(:var)
1326
+ assert_equal :integer, copy.var_type(:var)
1327
+ assert_equal 'line 2 char 1', copy.var_loc(:var)
1328
+ end
1329
+
1330
+ def test_template_upstream_value
1331
+ template = {
1332
+ :type=>slice('value', 1),
1333
+ :value=>{:filters=>[], :integer=>slice('42', 1)}
1334
+ }
1335
+
1336
+ tokens = [{
1337
+ :object=>{
1338
+ :template=>slice('&', 2),
1339
+ :type=>slice('var_name', 2),
1340
+ }
1341
+ }]
1342
+
1343
+ o = SlideField::ObjectData.new :parent, 'loc'
1344
+ o.set :var_name, template, 'loc', :object
1345
+
1346
+ @interpreter.interpret_tree tokens, o
1347
+ copy = o[:value].first
1348
+
1349
+ assert_equal 42, copy.get(:num)
1350
+ assert_equal :integer, copy.var_type(:num)
1351
+ assert_equal 'line 2 char 1', copy.var_loc(:num)
1352
+ end
1353
+
1354
+ def test_template_downstream_value
1355
+ template = {
1356
+ :type=>slice('value', 1),
1357
+ }
1358
+
1359
+ tokens = [{
1360
+ :object=>{
1361
+ :template=>slice('&', 2),
1362
+ :type=>slice('var_name', 2),
1363
+ :value=>{:filters=>[], :integer=>slice('42', 2)}
1364
+ }
1365
+ }]
1366
+
1367
+ o = SlideField::ObjectData.new :parent, 'loc'
1368
+ o.set :var_name, template, 'loc', :object
1369
+
1370
+ @interpreter.interpret_tree tokens, o
1371
+ copy = o[:value].first
1372
+
1373
+ assert_equal 42, copy.get(:num)
1374
+ assert_equal :integer, copy.var_type(:num)
1375
+ assert_equal 'line 2 char 3', copy.var_loc(:num)
1376
+ end
1377
+
1378
+ def test_template_double_value
1379
+ template = {
1380
+ :type=>slice('value', 1),
1381
+ :value=>{:filters=>[], :integer=>slice('42', 1)}
1382
+ }
1383
+
1384
+ tokens = [{
1385
+ :object=>{
1386
+ :template=>slice('&', 2),
1387
+ :type=>slice('var_name', 2),
1388
+ :value=>{:filters=>[], :integer=>slice('42', 2)}
1389
+ }
1390
+ }]
1391
+
1392
+ o = SlideField::ObjectData.new :parent, 'loc'
1393
+ o.set :var_name, template, 'loc', :object
1394
+
1395
+ error = assert_raises SlideField::InterpreterError do
1396
+ @interpreter.interpret_tree tokens, o
1397
+ end
1398
+
1399
+ assert_equal "Variable 'num' is already defined at line 2 char 3", error.message
1400
+ end
1401
+
1402
+ def test_template_of_template
1403
+ tokens = [
1404
+ {:assignment=>{
1405
+ :variable=>slice('alias', 1),
1406
+ :operator=>slice('=', 1),
1407
+ :value=>{
1408
+ :filters=>[],
1409
+ :object=>{:template=>slice('&', 1), :type=>slice('template', 1)}
1410
+ }
1411
+ }},
1412
+ {:object=>{:template=>slice('&', 2), :type=>slice('alias', 2)}}
1413
+ ]
1414
+
1415
+ o = SlideField::ObjectData.new :parent, 'loc'
1416
+ o.set :template, {:type=>slice('child', 2)}, 'loc', :object
1417
+
1418
+ error = assert_raises SlideField::InterpreterError do
1419
+ @interpreter.interpret_tree tokens, o
1420
+ end
1421
+
1422
+ assert_equal "Unexpected template reference at line 1 char 4", error.message
1423
+ end
1424
+
1425
+ def test_undefined_template
1426
+ tokens = [{
1427
+ :object=>{:template=>slice('&', 1), :type=>slice('var_name', 1)}
1428
+ }]
1429
+
1430
+ o = SlideField::ObjectData.new :parent, 'loc'
1431
+
1432
+ error = assert_raises SlideField::InterpreterError do
1433
+ @interpreter.interpret_tree tokens, o
1434
+ end
1435
+
1436
+ assert_equal "Undefined variable 'var_name' at line 1 char 2", error.message
1437
+ end
1438
+
1439
+ def test_invalid_template
1440
+ tokens = [{
1441
+ :object=>{:template=>slice('&', 1), :type=>slice('var_name', 1)}
1442
+ }]
1443
+
1444
+ o = SlideField::ObjectData.new :parent, 'loc'
1445
+ o.set :var_name, 42, 'loc', :integer
1446
+
1447
+ error = assert_raises SlideField::InterpreterError do
1448
+ @interpreter.interpret_tree tokens, o
1449
+ end
1450
+
1451
+ assert_equal "Unexpected 'integer', expecting 'object' at line 1 char 2", error.message
1452
+ end
1453
+
1454
+ def test_filter_point_x
1455
+ tokens = [
1456
+ {:assignment=>{
1457
+ :variable=>slice('var', 1),
1458
+ :operator=>slice('=', 1),
1459
+ :value=>{
1460
+ :filters=>[{:name=>slice('x', 1)}],
1461
+ :point=>slice('12x34', 1)
1462
+ }
1463
+ }},
1464
+ ]
1465
+
1466
+ o = SlideField::ObjectData.new :child, 'loc'
1467
+ @interpreter.interpret_tree tokens, o
1468
+
1469
+ assert_equal :integer, o.var_type(:var)
1470
+ assert_equal 12, o.get(:var)
1471
+ assert_equal 'line 1 char 4', o.var_loc(:var)
1472
+ end
1473
+
1474
+ def test_filter_point_y
1475
+ tokens = [
1476
+ {:assignment=>{
1477
+ :variable=>slice('var', 1),
1478
+ :operator=>slice('=', 1),
1479
+ :value=>{
1480
+ :filters=>[{:name=>slice('y', 1)}],
1481
+ :point=>slice('12x34', 1)
1482
+ }
1483
+ }},
1484
+ ]
1485
+
1486
+ o = SlideField::ObjectData.new :child, 'loc'
1487
+ @interpreter.interpret_tree tokens, o
1488
+
1489
+ assert_equal :integer, o.var_type(:var)
1490
+ assert_equal 34, o.get(:var)
1491
+ assert_equal 'line 1 char 4', o.var_loc(:var)
1492
+ end
1493
+
1494
+ def test_filter_integer_x
1495
+ tokens = [
1496
+ {:assignment=>{
1497
+ :variable=>slice('var', 1),
1498
+ :operator=>slice('=', 1),
1499
+ :value=>{
1500
+ :filters=>[{:name=>slice('x', 1)}],
1501
+ :integer=>slice('1', 1)
1502
+ }
1503
+ }},
1504
+ ]
1505
+
1506
+ o = SlideField::ObjectData.new :child, 'loc'
1507
+ @interpreter.interpret_tree tokens, o
1508
+
1509
+ assert_equal :point, o.var_type(:var)
1510
+ assert_equal [1,0], o.get(:var)
1511
+ assert_equal 'line 1 char 4', o.var_loc(:var)
1512
+ end
1513
+
1514
+ def test_filter_integer_y
1515
+ tokens = [
1516
+ {:assignment=>{
1517
+ :variable=>slice('var', 1),
1518
+ :operator=>slice('=', 1),
1519
+ :value=>{
1520
+ :filters=>[{:name=>slice('y', 1)}],
1521
+ :integer=>slice('1', 1)
1522
+ }
1523
+ }},
1524
+ ]
1525
+
1526
+ o = SlideField::ObjectData.new :child, 'loc'
1527
+ @interpreter.interpret_tree tokens, o
1528
+
1529
+ assert_equal :point, o.var_type(:var)
1530
+ assert_equal [0,1], o.get(:var)
1531
+ assert_equal 'line 1 char 4', o.var_loc(:var)
1532
+ end
1533
+
1534
+ def test_filter_string_lines
1535
+ tokens = [
1536
+ {:assignment=>{
1537
+ :variable=>slice('var', 1),
1538
+ :operator=>slice('=', 1),
1539
+ :value=>{
1540
+ :filters=>[{:name=>slice('lines', 1)}],
1541
+ :string=>slice('first\\nsecond', 1)
1542
+ }
1543
+ }},
1544
+ ]
1545
+
1546
+ o = SlideField::ObjectData.new :child, 'loc'
1547
+ @interpreter.interpret_tree tokens, o
1548
+
1549
+ assert_equal :integer, o.var_type(:var)
1550
+ assert_equal 2, o.get(:var)
1551
+ assert_equal 'line 1 char 4', o.var_loc(:var)
1552
+ end
1553
+
1554
+ def test_filters_order
1555
+ tokens = [
1556
+ {:assignment=>{
1557
+ :variable=>slice('var', 1),
1558
+ :operator=>slice('=', 1),
1559
+ :value=>{
1560
+ :filters=>[
1561
+ {:name=>slice('y', 1)},
1562
+ {:name=>slice('x', 1)}
1563
+ ],
1564
+ :point=>slice('42x24', 1)
1565
+ }
1566
+ }},
1567
+ ]
1568
+
1569
+ o = SlideField::ObjectData.new :child, 'loc'
1570
+ @interpreter.interpret_tree tokens, o
1571
+
1572
+ assert_equal :point, o.var_type(:var)
1573
+ assert_equal [0,42], o.get(:var)
1574
+ assert_equal 'line 1 char 5', o.var_loc(:var)
1575
+ end
1576
+
1577
+ def test_filter_identifier
1578
+ tokens = [
1579
+ {:assignment=>{
1580
+ :variable=>slice('var', 1),
1581
+ :operator=>slice('=', 1),
1582
+ :value=>{
1583
+ :filters=>[{:name=>slice('x', 1)}],
1584
+ :identifier=>slice('test', 1)
1585
+ }
1586
+ }},
1587
+ ]
1588
+
1589
+ o = SlideField::ObjectData.new :child, 'loc'
1590
+ o.set :test, [12,21], 'loc', :point
1591
+
1592
+ @interpreter.interpret_tree tokens, o
1593
+
1594
+ assert_equal :integer, o.var_type(:var)
1595
+ assert_equal 12, o.get(:var)
1596
+ assert_equal 'line 1 char 4', o.var_loc(:var)
1597
+ end
1598
+
1599
+ def test_unknown_filter
1600
+ tokens = [
1601
+ {:assignment=>{
1602
+ :variable=>slice('var', 1),
1603
+ :operator=>slice('=', 1),
1604
+ :value=>{
1605
+ :filters=>[{:name=>slice('aaaa', 1)}],
1606
+ :integer=>slice('1', 1)
1607
+ }
1608
+ }},
1609
+ ]
1610
+
1611
+ o = SlideField::ObjectData.new :child, 'loc'
1612
+ error = assert_raises SlideField::InterpreterError do
1613
+ @interpreter.interpret_tree tokens, o
1614
+ end
1615
+
1616
+ assert_equal "Invalid filter 'aaaa' for type 'integer' at line 1 char 3", error.message
1617
+ end
1618
+
1619
+ def test_filter_lost_in_template
1620
+ template = {
1621
+ :type=>slice('child', 1),
1622
+ :body=>[
1623
+ {:assignment=>{
1624
+ :variable=>slice('var', 1),
1625
+ :operator=>slice('=', 1),
1626
+ :value=>{
1627
+ :filters=>[{:name=>slice('x', 1)}],
1628
+ :point=>slice('1x1', 1)
1629
+ }
1630
+ }},
1631
+ ]
1632
+ }
1633
+
1634
+ tokens = [
1635
+ {:object=>{
1636
+ :template=>slice('&', 2),
1637
+ :type=>slice('var_name', 2),
1638
+ }},
1639
+ {:object=>{
1640
+ :template=>slice('&', 3),
1641
+ :type=>slice('var_name', 3),
1642
+ }}
1643
+ ]
1644
+
1645
+ o = SlideField::ObjectData.new :parent, 'loc'
1646
+ o.set :var_name, template, 'loc', :object
1647
+
1648
+ @interpreter.interpret_tree tokens, o
1649
+
1650
+ assert_equal 2, o[:child].count
1651
+
1652
+ first = o[:child][0]
1653
+ second = o[:child][1]
1654
+
1655
+ assert_equal :integer, first.var_type(:var)
1656
+ assert_equal 1, first.get(:var)
1657
+ assert_equal 'line 2 char 1', first.var_loc(:var)
1658
+
1659
+ assert_equal :integer, second.var_type(:var)
1660
+ assert_equal 1, second.get(:var)
1661
+ assert_equal 'line 3 char 1', second.var_loc(:var)
1662
+ end
1663
+
1664
+ def test_debug
1665
+ tokens = [
1666
+ {:object=>{
1667
+ :type=>slice('debug', 1),
1668
+ :value=>{:filters=>[], :string=>slice('"i haz bugs"', 1)}
1669
+ }}
1670
+ ]
1671
+
1672
+ o = SlideField::ObjectData.new :child, 'loc'
1673
+ o.context = 'parent context'
1674
+
1675
+ pretty, err = capture_io do
1676
+ ap :type=>:string, :value=>'i haz bugs'
1677
+ end
1678
+
1679
+ assert_output "DEBUG in local context at line 1 char 1:\n#{pretty}\n" do
1680
+ @interpreter.interpret_tree tokens, o, nil, 'local context'
1681
+ end
1682
+
1683
+ assert_empty o[:debug]
1684
+ end
1685
+
1686
+ def test_parse_error
1687
+ error = assert_raises SlideField::ParseError do
1688
+ @interpreter.run_file @path + '/parse_error.sfp'
1689
+ end
1690
+
1691
+ assert_match /\A\[parse_error.sfp\] /, error.message
1692
+ end
1693
+
1694
+ def test_include_relative
1695
+ @interpreter.run_string '\\include "../../examples/minimal/main.sfp"', @path
1696
+ end
1697
+
1698
+ def test_include_absolute
1699
+ ex_path = File.expand_path '../examples', __dir__
1700
+ @interpreter.run_string '\\include "' + ex_path + '/minimal/main.sfp"'
1701
+ end
1702
+
1703
+ def test_include_parse_error
1704
+ error = assert_raises SlideField::ParseError do
1705
+ @interpreter.run_string '\\include "parse_error.sfp"', @path
1706
+ end
1707
+
1708
+ assert_match /\A\[input\] \[parse_error.sfp\] /, error.message
1709
+ refute_match /\\include/, error.message
1710
+ end
1711
+
1712
+ def test_reparse
1713
+ ex_path = File.expand_path '../examples', __dir__
1714
+ @interpreter.run_file ex_path + '/minimal/main.sfp'
1715
+
1716
+ error = assert_raises SlideField::InterpreterError do
1717
+ @interpreter.run_file ex_path + '/minimal/main.sfp'
1718
+ end
1719
+
1720
+ assert_equal "File already interpreted: '#{ex_path}/minimal/main.sfp'", error.message
1721
+ end
1722
+
1723
+ def test_recursive_include
1724
+ error = assert_raises SlideField::InterpreterError do
1725
+ @interpreter.run_file @path + '/recursive_include.sfp'
1726
+ end
1727
+
1728
+ assert_equal "[recursive_include.sfp] File already interpreted: '#{@path}/recursive_include.sfp'", error.message
1729
+ end
1730
+
1731
+ def test_include_parent_folder
1732
+ error = assert_raises SlideField::InterpreterError do
1733
+ @interpreter.run_file @path + '/sub/include_parent.sfp'
1734
+ end
1735
+
1736
+ assert_match /\A\[include_parent.sfp\] \[..\/unknown_object.sfp\] /, error.message
1737
+
1738
+ error = assert_raises SlideField::ParseError do
1739
+ @interpreter.run_file @path + '/parse_error.sfp'
1740
+ end
1741
+
1742
+ assert_match /\A\[parse_error.sfp\] /, error.message
1743
+ end
1744
+
1745
+ def test_include_subfolder
1746
+ error = assert_raises SlideField::InterpreterError do
1747
+ @interpreter.run_file @path + '/include_sub.sfp'
1748
+ end
1749
+
1750
+ assert_match /\A\[include_sub.sfp\] \[sub\/include_parent.sfp\] \[unknown_object.sfp\] /, error.message
1751
+ end
1752
+
1753
+ def test_include_wrong_template
1754
+ error = assert_raises SlideField::InterpreterError do
1755
+ @interpreter.run_string '\\include "wrong_template.sfp"; \\&wrong_template', @path
1756
+ end
1757
+
1758
+ assert_match /&wrong_template/, error.message
1759
+ end
1760
+
1761
+ def test_include_unclosed_object
1762
+ assert_raises SlideField::ParseError do
1763
+ @interpreter.run_string '\\include "unclosed_object.sfp"', @path
1764
+ end
1765
+ end
1766
+ end