delorean_lang 0.5.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +5 -5
  2. data/.gitlab-ci.yml +1 -2
  3. data/.rubocop.yml +45 -5
  4. data/.rubocop_todo.yml +1 -634
  5. data/Gemfile +3 -1
  6. data/README.md +22 -0
  7. data/Rakefile +3 -1
  8. data/delorean.gemspec +18 -17
  9. data/lib/delorean/abstract_container.rb +4 -2
  10. data/lib/delorean/base.rb +30 -27
  11. data/lib/delorean/cache.rb +2 -0
  12. data/lib/delorean/cache/adapters.rb +2 -0
  13. data/lib/delorean/cache/adapters/base.rb +2 -0
  14. data/lib/delorean/cache/adapters/ruby_cache.rb +5 -0
  15. data/lib/delorean/const.rb +5 -3
  16. data/lib/delorean/debug.rb +6 -5
  17. data/lib/delorean/delorean.rb +466 -147
  18. data/lib/delorean/delorean.treetop +13 -1
  19. data/lib/delorean/engine.rb +61 -50
  20. data/lib/delorean/error.rb +2 -1
  21. data/lib/delorean/model.rb +12 -9
  22. data/lib/delorean/nodes.rb +130 -67
  23. data/lib/delorean/ruby.rb +2 -0
  24. data/lib/delorean/ruby/whitelists.rb +2 -0
  25. data/lib/delorean/ruby/whitelists/base.rb +7 -3
  26. data/lib/delorean/ruby/whitelists/default.rb +6 -6
  27. data/lib/delorean/ruby/whitelists/empty.rb +3 -2
  28. data/lib/delorean/ruby/whitelists/matchers.rb +2 -0
  29. data/lib/delorean/ruby/whitelists/matchers/arguments.rb +2 -0
  30. data/lib/delorean/ruby/whitelists/matchers/method.rb +5 -2
  31. data/lib/delorean/ruby/whitelists/whitelist_error.rb +2 -0
  32. data/lib/delorean/version.rb +3 -1
  33. data/lib/delorean_lang.rb +3 -1
  34. data/spec/cache_spec.rb +4 -2
  35. data/spec/dev_spec.rb +68 -69
  36. data/spec/eval_spec.rb +824 -729
  37. data/spec/func_spec.rb +172 -176
  38. data/spec/parse_spec.rb +516 -522
  39. data/spec/ruby/whitelist_spec.rb +6 -3
  40. data/spec/spec_helper.rb +26 -23
  41. metadata +27 -27
@@ -1,838 +1,832 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
4
 
3
- describe "Delorean" do
4
- let(:sset) {
5
+ describe 'Delorean' do
6
+ let(:sset) do
5
7
  TestContainer.new(
6
- "AAA" =>
7
- defn("X:",
8
- " a = 123",
9
- " b = a",
10
- )
11
- )
12
- }
8
+ 'AAA' =>
9
+ defn('X:',
10
+ ' a = 123',
11
+ ' b = a',
12
+ )
13
+ )
14
+ end
13
15
 
14
- let(:engine) {
15
- Delorean::Engine.new "YYY", sset
16
- }
16
+ let(:engine) do
17
+ Delorean::Engine.new 'YYY', sset
18
+ end
17
19
 
18
- it "can parse very simple calls" do
19
- engine.parse defn("X:",
20
- " a = 123",
21
- " b = a",
22
- )
20
+ it 'can parse very simple calls' do
21
+ engine.parse defn('X:',
22
+ ' a = 123',
23
+ ' b = a',
24
+ )
23
25
  end
24
26
 
25
- it "can parse simple expressions - 1" do
26
- engine.parse defn("A:",
27
- " a = 123",
28
- " x = -(a*2)",
29
- " b = -(a + 1)",
30
- )
27
+ it 'can parse simple expressions - 1' do
28
+ engine.parse defn('A:',
29
+ ' a = 123',
30
+ ' x = -(a*2)',
31
+ ' b = -(a + 1)',
32
+ )
31
33
  end
32
34
 
33
- it "can parse simple expressions - 2" do
34
- engine.parse defn("A:",
35
- " a = 1 + 2 * -3 - -4",
36
- )
35
+ it 'can parse simple expressions - 2' do
36
+ engine.parse defn('A:',
37
+ ' a = 1 + 2 * -3 - -4',
38
+ )
37
39
  end
38
40
 
39
- it "can parse params" do
40
- engine.parse defn("A:",
41
- " a =?",
42
- " b =? a*2",
43
- )
41
+ it 'can parse params' do
42
+ engine.parse defn('A:',
43
+ ' a =?',
44
+ ' b =? a*2',
45
+ )
44
46
  end
45
47
 
46
- it "can parse indexing" do
47
- engine.parse defn("A:",
48
- " b = [1,2,3][1]",
49
- )
48
+ it 'can parse indexing' do
49
+ engine.parse defn('A:',
50
+ ' b = [1,2,3][1]',
51
+ )
50
52
  end
51
53
 
52
- it "can parse indexing with getattr" do
53
- engine.parse defn("A:",
54
+ it 'can parse indexing with getattr' do
55
+ engine.parse defn('A:',
54
56
  " a = {'x': [1,2,3]}",
55
- " b = a.x[1]",
56
- )
57
+ ' b = a.x[1]',
58
+ )
57
59
  end
58
60
 
59
- it "should accept default param definitions" do
61
+ it 'should accept default param definitions' do
60
62
  lambda {
61
- engine.parse defn("A:",
62
- " a =? 0.0123",
63
- " b =? 0",
64
- " c =? -1.1",
65
- " d = b + c",
66
- )
63
+ engine.parse defn('A:',
64
+ ' a =? 0.0123',
65
+ ' b =? 0',
66
+ ' c =? -1.1',
67
+ ' d = b + c',
68
+ )
67
69
  }.should_not raise_error
68
70
  end
69
71
 
70
- it "gives errors with attrs not in node" do
72
+ it 'gives errors with attrs not in node' do
71
73
  lambda {
72
- engine.parse defn("a = 123",
73
- "b = a * 2",
74
- )
74
+ engine.parse defn('a = 123',
75
+ 'b = a * 2',
76
+ )
75
77
  }.should raise_error(Delorean::ParseError)
76
78
  end
77
79
 
78
- it "should disallow .<digits> literals" do
80
+ it 'should disallow .<digits> literals' do
79
81
  lambda {
80
- engine.parse defn("A:",
81
- " a = .123",
82
- )
82
+ engine.parse defn('A:',
83
+ ' a = .123',
84
+ )
83
85
  }.should raise_error(Delorean::ParseError)
84
86
  end
85
87
 
86
- it "should disallow leading 0s in numbers" do
88
+ it 'should disallow leading 0s in numbers' do
87
89
  lambda {
88
- engine.parse defn("A:",
89
- " a = 00.123",
90
- )
90
+ engine.parse defn('A:',
91
+ ' a = 00.123',
92
+ )
91
93
  }.should raise_error(Delorean::ParseError)
92
94
  end
93
95
 
94
- it "should disallow leading 0s in numbers (2)" do
96
+ it 'should disallow leading 0s in numbers (2)' do
95
97
  lambda {
96
- engine.parse defn("A:",
97
- " a = 0123",
98
- )
98
+ engine.parse defn('A:',
99
+ ' a = 0123',
100
+ )
99
101
  }.should raise_error(Delorean::ParseError)
100
102
  end
101
103
 
102
- it "should disallow bad attr names" do
104
+ it 'should disallow bad attr names' do
103
105
  lambda {
104
- engine.parse defn("A:",
105
- " B = 1",
106
- )
106
+ engine.parse defn('A:',
107
+ ' B = 1',
108
+ )
107
109
  }.should raise_error(Delorean::ParseError)
108
110
 
109
111
  engine.reset
110
112
 
111
113
  lambda {
112
- engine.parse defn("A:",
113
- " _b = 1",
114
- )
114
+ engine.parse defn('A:',
115
+ ' _b = 1',
116
+ )
115
117
  }.should raise_error(Delorean::ParseError)
116
118
  end
117
119
 
118
- it "should disallow bad node names" do
120
+ it 'should disallow bad node names' do
119
121
  lambda {
120
- engine.parse defn("a:",
121
- )
122
+ engine.parse defn('a:',
123
+ )
122
124
  }.should raise_error(Delorean::ParseError)
123
125
 
124
126
  engine.reset
125
127
 
126
128
  lambda {
127
- engine.parse defn("_A:",
128
- )
129
+ engine.parse defn('_A:',
130
+ )
129
131
  }.should raise_error(Delorean::ParseError)
130
132
  end
131
133
 
132
- it "should disallow recursion" do
134
+ it 'should disallow recursion' do
133
135
  lambda {
134
- engine.parse defn("A:",
135
- " a = 1",
136
- "B: A",
137
- " a = a + 1",
138
- )
136
+ engine.parse defn('A:',
137
+ ' a = 1',
138
+ 'B: A',
139
+ ' a = a + 1',
140
+ )
139
141
  }.should raise_error(Delorean::RecursionError)
140
142
 
141
143
  engine.reset
142
144
 
143
145
  lambda {
144
- engine.parse defn("A:",
145
- " a = 1",
146
- "B: A",
147
- " b = a",
148
- " a = b",
149
- )
146
+ engine.parse defn('A:',
147
+ ' a = 1',
148
+ 'B: A',
149
+ ' b = a',
150
+ ' a = b',
151
+ )
150
152
  }.should raise_error(Delorean::RecursionError)
151
-
152
153
  end
153
154
 
154
- it "should allow getattr in expressions" do
155
- engine.parse defn("A:",
156
- " a = 1",
157
- " b = A.a * A.a - A.a",
158
- )
155
+ it 'should allow getattr in expressions' do
156
+ engine.parse defn('A:',
157
+ ' a = 1',
158
+ ' b = A.a * A.a - A.a',
159
+ )
159
160
  end
160
161
 
161
- it "should allow in expressions" do
162
- engine.parse defn("A:",
163
- " int =? 1",
164
- " a = if int>1 then int*2 else int/2",
165
- " b = int in [1,2,3]",
166
- )
162
+ it 'should allow in expressions' do
163
+ engine.parse defn('A:',
164
+ ' int =? 1',
165
+ ' a = if int>1 then int*2 else int/2',
166
+ ' b = int in [1,2,3]',
167
+ )
167
168
  end
168
169
 
169
- it "should allow non-recursive code 1" do
170
+ it 'should allow non-recursive code 1' do
170
171
  # this is not a recursion error
171
- engine.parse defn("A:",
172
- " a = 1",
173
- " b = 2",
174
- "B: A",
175
- " a = A.b",
176
- " b = a",
177
- )
178
-
179
- end
180
-
181
- it "should allow non-recursive code 2" do
182
- engine.parse defn("A:",
183
- " a = 1",
184
- " b = 2",
185
- "B: A",
186
- " a = A.b",
187
- " b = A.b + B.a",
188
- )
189
- end
190
-
191
- it "should allow non-recursive code 3" do
192
- engine.parse defn("A:",
193
- " b = 2",
194
- " a = A.b + A.b",
195
- " c = a + b + a + b",
196
- )
197
- end
198
-
199
- it "should check for recursion with default params 1" do
200
- lambda {
201
- engine.parse defn("A:",
202
- " a =? a",
203
- )
172
+ engine.parse defn('A:',
173
+ ' a = 1',
174
+ ' b = 2',
175
+ 'B: A',
176
+ ' a = A.b',
177
+ ' b = a',
178
+ )
179
+ end
180
+
181
+ it 'should allow non-recursive code 2' do
182
+ engine.parse defn('A:',
183
+ ' a = 1',
184
+ ' b = 2',
185
+ 'B: A',
186
+ ' a = A.b',
187
+ ' b = A.b + B.a',
188
+ )
189
+ end
190
+
191
+ it 'should allow non-recursive code 3' do
192
+ engine.parse defn('A:',
193
+ ' b = 2',
194
+ ' a = A.b + A.b',
195
+ ' c = a + b + a + b',
196
+ )
197
+ end
198
+
199
+ it 'should check for recursion with default params 1' do
200
+ lambda {
201
+ engine.parse defn('A:',
202
+ ' a =? a',
203
+ )
204
204
  }.should raise_error(Delorean::UndefinedError)
205
205
  end
206
206
 
207
- it "should check for recursion with default params 2" do
207
+ it 'should check for recursion with default params 2' do
208
208
  lambda {
209
- engine.parse defn("A:",
210
- " a = 1",
211
- "B: A",
212
- " b =? a",
213
- " a =? b",
214
- )
209
+ engine.parse defn('A:',
210
+ ' a = 1',
211
+ 'B: A',
212
+ ' b =? a',
213
+ ' a =? b',
214
+ )
215
215
  }.should raise_error(Delorean::RecursionError)
216
216
  end
217
217
 
218
- it "gives errors for attrs defined more than once in a node" do
218
+ it 'gives errors for attrs defined more than once in a node' do
219
219
  lambda {
220
- engine.parse defn("B:",
221
- " b = 1 + 1",
222
- " b = 123",
223
- )
220
+ engine.parse defn('B:',
221
+ ' b = 1 + 1',
222
+ ' b = 123',
223
+ )
224
224
  }.should raise_error(Delorean::RedefinedError)
225
225
 
226
226
  engine.reset
227
227
 
228
228
  lambda {
229
- engine.parse defn("B:",
230
- " b =?",
231
- " b = 123",
232
- )
229
+ engine.parse defn('B:',
230
+ ' b =?',
231
+ ' b = 123',
232
+ )
233
233
  }.should raise_error(Delorean::RedefinedError)
234
234
 
235
235
  engine.reset
236
236
 
237
237
  lambda {
238
- engine.parse defn("B:",
239
- " b =? 22",
240
- " b = 123",
241
- )
238
+ engine.parse defn('B:',
239
+ ' b =? 22',
240
+ ' b = 123',
241
+ )
242
242
  }.should raise_error(Delorean::RedefinedError)
243
243
  end
244
244
 
245
- it "should raise error for nodes defined more than once" do
245
+ it 'should raise error for nodes defined more than once' do
246
246
  lambda {
247
- engine.parse defn("B:",
248
- " b =?",
249
- "B:",
250
- )
247
+ engine.parse defn('B:',
248
+ ' b =?',
249
+ 'B:',
250
+ )
251
251
  }.should raise_error(Delorean::RedefinedError)
252
252
 
253
253
  engine.reset
254
254
 
255
255
  lambda {
256
- engine.parse defn("B:",
257
- "A:",
258
- "B:",
259
- )
256
+ engine.parse defn('B:',
257
+ 'A:',
258
+ 'B:',
259
+ )
260
260
  }.should raise_error(Delorean::RedefinedError)
261
261
  end
262
262
 
263
- it "should not be valid to derive from undefined nodes" do
263
+ it 'should not be valid to derive from undefined nodes' do
264
264
  lambda {
265
- engine.parse defn("A: B",
266
- " a = 456 * 123",
267
- )
265
+ engine.parse defn('A: B',
266
+ ' a = 456 * 123',
267
+ )
268
268
  }.should raise_error(Delorean::UndefinedError)
269
269
  end
270
270
 
271
- it "should not be valid to use an undefined attr" do
271
+ it 'should not be valid to use an undefined attr' do
272
272
  lambda {
273
- engine.parse defn("A:",
274
- " a = 456 * 123",
275
- "B: A",
276
- " b = a",
277
- " c = d",
278
- )
273
+ engine.parse defn('A:',
274
+ ' a = 456 * 123',
275
+ 'B: A',
276
+ ' b = a',
277
+ ' c = d',
278
+ )
279
279
  }.should raise_error(Delorean::UndefinedError)
280
280
  end
281
281
 
282
- it "should not be possible to use a forward definition in hash" do
282
+ it 'should not be possible to use a forward definition in hash' do
283
283
  lambda {
284
- engine.parse defn("A:",
284
+ engine.parse defn('A:',
285
285
  " c = {'b': 1, 'd' : d}",
286
- " d = 789",
287
- )
286
+ ' d = 789',
287
+ )
288
288
  }.should raise_error(Delorean::UndefinedError)
289
289
  end
290
290
 
291
- it "should not be possible to use a forward definition in node call" do
291
+ it 'should not be possible to use a forward definition in node call' do
292
292
  lambda {
293
- engine.parse defn("A:",
294
- " c = A(b=1, d=d)",
295
- " d = 789",
296
- )
293
+ engine.parse defn('A:',
294
+ ' c = A(b=1, d=d)',
295
+ ' d = 789',
296
+ )
297
297
  }.should raise_error(Delorean::UndefinedError)
298
298
  end
299
299
 
300
- it "should not be possible to use a forward definition in array" do
300
+ it 'should not be possible to use a forward definition in array' do
301
301
  lambda {
302
- engine.parse defn("A:",
303
- " c = [123, 456, d]",
304
- " d = 789",
305
- )
302
+ engine.parse defn('A:',
303
+ ' c = [123, 456, d]',
304
+ ' d = 789',
305
+ )
306
306
  }.should raise_error(Delorean::UndefinedError)
307
307
  end
308
308
 
309
- it "should be able to use ruby keywords as identifier" do
309
+ it 'should be able to use ruby keywords as identifier' do
310
310
  lambda {
311
- engine.parse defn("A:",
312
- " in = 123",
313
- )
311
+ engine.parse defn('A:',
312
+ ' in = 123',
313
+ )
314
314
  }.should_not raise_error
315
315
 
316
316
  engine.reset
317
317
 
318
318
  lambda {
319
- engine.parse defn("B:",
320
- " in1 = 123",
321
- )
319
+ engine.parse defn('B:',
320
+ ' in1 = 123',
321
+ )
322
322
  }.should_not raise_error
323
323
 
324
324
  engine.reset
325
325
 
326
326
  lambda {
327
- engine.parse defn("C:",
328
- " ifx = 123",
329
- " elsey = ifx + 1",
330
- )
327
+ engine.parse defn('C:',
328
+ ' ifx = 123',
329
+ ' elsey = ifx + 1',
330
+ )
331
331
  }.should_not raise_error
332
332
 
333
333
  engine.reset
334
334
 
335
335
  lambda {
336
- engine.parse defn("D:",
337
- " true = false",
338
- )
336
+ engine.parse defn('D:',
337
+ ' true = false',
338
+ )
339
339
  }.should_not raise_error
340
340
 
341
341
  engine.reset
342
342
 
343
343
  lambda {
344
- engine.parse defn("E:",
345
- " a = 1",
346
- " return=a",
347
- )
344
+ engine.parse defn('E:',
345
+ ' a = 1',
346
+ ' return=a',
347
+ )
348
348
  }.should_not raise_error
349
349
 
350
350
  engine.reset
351
351
 
352
- skip "need to fix"
352
+ skip 'need to fix'
353
353
 
354
354
  lambda {
355
- engine.parse defn("D:",
356
- " true_1 = false",
357
- " false_1 = true_1",
358
- " nil_1 = false_1",
359
- )
355
+ engine.parse defn('D:',
356
+ ' true_1 = false',
357
+ ' false_1 = true_1',
358
+ ' nil_1 = false_1',
359
+ )
360
360
  }.should_not raise_error
361
361
 
362
362
  engine.reset
363
363
  end
364
364
 
365
- it "should parse calls followed by getattr" do
365
+ it 'should parse calls followed by getattr' do
366
366
  lambda {
367
- engine.parse defn("A:",
368
- " a = -1",
369
- " b = A().a",
370
- )
367
+ engine.parse defn('A:',
368
+ ' a = -1',
369
+ ' b = A().a',
370
+ )
371
371
  }.should_not raise_error
372
372
  end
373
373
 
374
- it "should be able to chain method calls on model functions" do
374
+ it 'should be able to chain method calls on model functions' do
375
375
  lambda {
376
- engine.parse defn("A:",
376
+ engine.parse defn('A:',
377
377
  " b = Dummy.i_just_met_you('CRJ', 123).name"
378
- )
378
+ )
379
379
  }.should_not raise_error
380
380
  end
381
381
 
382
- it "should be able to pass model class to model functions" do
382
+ it 'should be able to pass model class to model functions' do
383
383
  lambda {
384
- engine.parse defn("A:",
385
- " b = Dummy.i_just_met_you(Dummy, 1)"
386
- )
384
+ engine.parse defn('A:',
385
+ ' b = Dummy.i_just_met_you(Dummy, 1)'
386
+ )
387
387
  }.should_not raise_error
388
388
  end
389
389
 
390
- it "should be able to call class methods on ActiveRecord classes" do
391
- engine.parse defn("A:",
392
- " b = Dummy.call_me_maybe()",
393
- )
390
+ it 'should be able to call class methods on ActiveRecord classes' do
391
+ engine.parse defn('A:',
392
+ ' b = Dummy.call_me_maybe()',
393
+ )
394
394
  end
395
395
 
396
- it "should get exception on arg count to class method call" do
396
+ it 'should get exception on arg count to class method call' do
397
397
  lambda {
398
- engine.parse defn("A:",
398
+ engine.parse defn('A:',
399
399
  ' b = Dummy.i_just_met_you(1, 2, 3)',
400
- )
400
+ )
401
401
  }.should raise_error(Delorean::BadCallError)
402
402
  end
403
403
 
404
404
  it "shouldn't be able to call ActiveRecord methods without signature" do
405
405
  lambda {
406
- engine.parse defn("A:",
407
- " b = Dummy.this_is_crazy()",
408
- )
406
+ engine.parse defn('A:',
407
+ ' b = Dummy.this_is_crazy()',
408
+ )
409
409
  }.should raise_error(Delorean::UndefinedFunctionError)
410
410
  end
411
411
 
412
- it "should be able to call class methods on ActiveRecord classes in modules" do
413
- engine.parse defn("A:",
414
- " b = M::LittleDummy.heres_my_number(867, 5309)",
415
- )
412
+ it 'should be able to call class methods on ActiveRecord classes in modules' do
413
+ engine.parse defn('A:',
414
+ ' b = M::LittleDummy.heres_my_number(867, 5309)',
415
+ )
416
416
  end
417
417
 
418
- it "should be able to override parameters with attribute definitions" do
419
- engine.parse defn("A:",
420
- " b =? 22",
421
- "B: A",
422
- " b = 123",
423
- "C: B",
424
- " b =? 11",
425
- )
418
+ it 'should be able to override parameters with attribute definitions' do
419
+ engine.parse defn('A:',
420
+ ' b =? 22',
421
+ 'B: A',
422
+ ' b = 123',
423
+ 'C: B',
424
+ ' b =? 11',
425
+ )
426
426
  end
427
427
 
428
- it "should be able to access derived attrs" do
429
- engine.parse defn("A:",
430
- " b =? 22",
431
- "B: A",
432
- " c = b * 123",
433
- "C: B",
434
- " d =? c * b + 11",
435
- )
428
+ it 'should be able to access derived attrs' do
429
+ engine.parse defn('A:',
430
+ ' b =? 22',
431
+ 'B: A',
432
+ ' c = b * 123',
433
+ 'C: B',
434
+ ' d =? c * b + 11',
435
+ )
436
436
  end
437
437
 
438
- it "should not be able to access attrs not defined in ancestors" do
438
+ it 'should not be able to access attrs not defined in ancestors' do
439
439
  lambda {
440
- engine.parse defn("A:",
441
- " b =? 22",
442
- "B: A",
443
- " c = b * 123",
444
- "C: A",
445
- " d =? c * b + 11",
446
- )
440
+ engine.parse defn('A:',
441
+ ' b =? 22',
442
+ 'B: A',
443
+ ' c = b * 123',
444
+ 'C: A',
445
+ ' d =? c * b + 11',
446
+ )
447
447
  }.should raise_error(Delorean::UndefinedError)
448
448
  end
449
449
 
450
- it "should be able to access specific node attrs " do
451
- engine.parse defn("A:",
452
- " b = 123",
453
- " c = A.b",
454
- )
450
+ it 'should be able to access specific node attrs ' do
451
+ engine.parse defn('A:',
452
+ ' b = 123',
453
+ ' c = A.b',
454
+ )
455
455
 
456
456
  engine.reset
457
457
 
458
- engine.parse defn("A:",
459
- " b = 123",
460
- "B: A",
461
- " b = 111",
462
- " c = A.b * 123",
463
- " d = B.b",
464
- )
458
+ engine.parse defn('A:',
459
+ ' b = 123',
460
+ 'B: A',
461
+ ' b = 111',
462
+ ' c = A.b * 123',
463
+ ' d = B.b',
464
+ )
465
465
  end
466
466
 
467
- it "should be able to perform arbitrary getattr" do
468
- engine.parse defn("A:",
469
- " b = 22",
470
- " c = b.x.y.z",
471
- )
467
+ it 'should be able to perform arbitrary getattr' do
468
+ engine.parse defn('A:',
469
+ ' b = 22',
470
+ ' c = b.x.y.z',
471
+ )
472
472
 
473
473
  engine.reset
474
474
 
475
475
  lambda {
476
- engine.parse defn("B:",
477
- " c = b.x.y.z",
478
- )
476
+ engine.parse defn('B:',
477
+ ' c = b.x.y.z',
478
+ )
479
479
  }.should raise_error(Delorean::UndefinedError)
480
-
481
480
  end
482
481
 
483
- it "should handle lines with comments" do
484
- engine.parse defn("A: # kaka",
485
- " b = 22 # testing #",
486
- " c = b",
487
- )
482
+ it 'should handle lines with comments' do
483
+ engine.parse defn('A: # kaka',
484
+ ' b = 22 # testing #',
485
+ ' c = b',
486
+ )
488
487
  end
489
488
 
490
- it "should be able to report error line during parse" do
489
+ it 'should be able to report error line during parse' do
491
490
  begin
492
- engine.parse defn("A:",
493
- " b = 123",
494
- "B: .A",
495
- )
496
- rescue => exc
491
+ engine.parse defn('A:',
492
+ ' b = 123',
493
+ 'B: .A',
494
+ )
495
+ rescue StandardError => exc
497
496
  end
498
497
 
499
- exc.module_name.should == "YYY"
498
+ exc.module_name.should == 'YYY'
500
499
  exc.line.should == 3
501
500
 
502
501
  engine.reset
503
502
 
504
503
  begin
505
- engine.parse defn("A:",
506
- " b = 3 % b",
507
- )
508
- rescue => exc
504
+ engine.parse defn('A:',
505
+ ' b = 3 % b',
506
+ )
507
+ rescue StandardError => exc
509
508
  end
510
509
 
511
- exc.module_name.should == "YYY"
510
+ exc.module_name.should == 'YYY'
512
511
  exc.line.should == 2
513
512
  end
514
513
 
515
- it "correctly report error line during parse" do
514
+ it 'correctly report error line during parse' do
516
515
  begin
517
- engine.parse defn("A:",
518
- " b = [yyy",
519
- " ]",
520
- "B:",
521
- )
522
- rescue => exc
516
+ engine.parse defn('A:',
517
+ ' b = [yyy',
518
+ ' ]',
519
+ 'B:',
520
+ )
521
+ rescue StandardError => exc
523
522
  end
524
523
 
525
- exc.module_name.should == "YYY"
524
+ exc.module_name.should == 'YYY'
526
525
  exc.line.should == 2
527
526
  end
528
527
 
529
- it "should raise error on malformed string" do
528
+ it 'should raise error on malformed string' do
530
529
  lambda {
531
- engine.parse defn("A:",
530
+ engine.parse defn('A:',
532
531
  ' d = "testing"" ',
533
- )
532
+ )
534
533
  }.should raise_error(Delorean::ParseError)
535
534
  end
536
535
 
537
- it "should not allow inherited ruby methods as attrs" do
536
+ it 'should not allow inherited ruby methods as attrs' do
538
537
  lambda {
539
- engine.parse defn("A:",
540
- " a = name",
541
- )
538
+ engine.parse defn('A:',
539
+ ' a = name',
540
+ )
542
541
  }.should raise_error(Delorean::UndefinedError)
543
542
 
544
543
  engine.reset
545
544
 
546
545
  lambda {
547
- engine.parse defn("A:",
548
- " a = new",
549
- )
546
+ engine.parse defn('A:',
547
+ ' a = new',
548
+ )
550
549
  }.should raise_error(Delorean::UndefinedError)
551
550
  end
552
551
 
553
- it "should be able to parse lists" do
554
- engine.parse defn("A:",
555
- " b = []",
556
- " c = [1,2,3]",
552
+ it 'should be able to parse lists' do
553
+ engine.parse defn('A:',
554
+ ' b = []',
555
+ ' c = [1,2,3]',
557
556
  " d = [b, c, b, c, 1, 2, '123', 1.1]",
558
- " e = [1, 1+1, 1+1+1]",
559
- )
557
+ ' e = [1, 1+1, 1+1+1]',
558
+ )
560
559
 
561
560
  engine.reset
562
561
 
563
562
  lambda {
564
- engine.parse defn("A:",
565
- " a = [",
566
- )
563
+ engine.parse defn('A:',
564
+ ' a = [',
565
+ )
567
566
  }.should raise_error(Delorean::ParseError)
568
567
 
569
568
  engine.reset
570
569
 
571
570
  lambda {
572
- engine.parse defn("A:",
573
- " a = []-",
574
- )
571
+ engine.parse defn('A:',
572
+ ' a = []-',
573
+ )
575
574
  }.should raise_error(Delorean::ParseError)
576
-
577
575
  end
578
576
 
579
577
  it "should handle trailing ',' with lists" do
580
- engine.parse defn("A:",
581
- " b = [1,2,3,]",
582
- )
578
+ engine.parse defn('A:',
579
+ ' b = [1,2,3,]',
580
+ )
583
581
 
584
582
  engine.reset
585
583
 
586
584
  lambda {
587
- engine.parse defn("A:",
588
- " a = [,]",
589
- )
585
+ engine.parse defn('A:',
586
+ ' a = [,]',
587
+ )
590
588
  }.should raise_error(Delorean::ParseError)
591
589
 
592
590
  engine.reset
593
591
 
594
592
  lambda {
595
- engine.parse defn("A:",
596
- " a = [1,2,,]",
597
- )
593
+ engine.parse defn('A:',
594
+ ' a = [1,2,,]',
595
+ )
598
596
  }.should raise_error(Delorean::ParseError)
599
597
  end
600
598
 
601
- it "should be able to parse hashes" do
602
- engine.parse defn("A:",
603
- " b = {}",
599
+ it 'should be able to parse hashes' do
600
+ engine.parse defn('A:',
601
+ ' b = {}',
604
602
  " c = {'a':1, 'b': 2, 'c':-3}",
605
- " d = [{1:11}, {2: 22}]",
606
- )
603
+ ' d = [{1:11}, {2: 22}]',
604
+ )
607
605
 
608
606
  engine.reset
609
607
 
610
608
  lambda {
611
- engine.parse defn("A:",
612
- " a = {",
613
- )
609
+ engine.parse defn('A:',
610
+ ' a = {',
611
+ )
614
612
  }.should raise_error(Delorean::ParseError)
615
613
 
616
614
  engine.reset
617
615
 
618
616
  lambda {
619
- engine.parse defn("A:",
620
- " a = {}+",
621
- )
617
+ engine.parse defn('A:',
618
+ ' a = {}+',
619
+ )
622
620
  }.should raise_error(Delorean::ParseError)
623
621
  end
624
622
 
625
- it "should be able to parse conditional hash literals" do
626
- engine.parse defn("A:",
627
- " a = {}",
623
+ it 'should be able to parse conditional hash literals' do
624
+ engine.parse defn('A:',
625
+ ' a = {}',
628
626
  " c = {'a':a if a, 'b': 2, 'c':-3 if 123}",
629
- )
627
+ )
630
628
  end
631
629
 
632
630
  it "should handle trailing ',' with hashes" do
633
- engine.parse defn("A:",
634
- " b = {-1:1,}",
635
- )
631
+ engine.parse defn('A:',
632
+ ' b = {-1:1,}',
633
+ )
636
634
 
637
635
  engine.reset
638
636
 
639
637
  lambda {
640
- engine.parse defn("A:",
641
- " a = {,}",
642
- )
638
+ engine.parse defn('A:',
639
+ ' a = {,}',
640
+ )
643
641
  }.should raise_error(Delorean::ParseError)
644
642
 
645
643
  engine.reset
646
644
 
647
645
  lambda {
648
- engine.parse defn("A:",
649
- " a = {-1:1,,}",
650
- )
646
+ engine.parse defn('A:',
647
+ ' a = {-1:1,,}',
648
+ )
651
649
  }.should raise_error(Delorean::ParseError)
652
650
  end
653
651
 
654
- it "should be able to parse list operations " do
655
- engine.parse defn("A:",
656
- " b = [] + []",
657
- )
652
+ it 'should be able to parse list operations ' do
653
+ engine.parse defn('A:',
654
+ ' b = [] + []',
655
+ )
658
656
  end
659
657
 
660
- it "should parse list comprehension" do
661
- engine.parse defn("A:",
662
- " b = [123 for i in 123]",
663
- )
664
-
658
+ it 'should parse list comprehension' do
659
+ engine.parse defn('A:',
660
+ ' b = [123 for i in 123]',
661
+ )
665
662
  end
666
663
 
667
- it "should parse list comprehension (2)" do
668
- engine.parse defn("A:",
669
- " b = [i+1 for i in [1,2,3]]",
670
- )
671
-
664
+ it 'should parse list comprehension (2)' do
665
+ engine.parse defn('A:',
666
+ ' b = [i+1 for i in [1,2,3]]',
667
+ )
672
668
  end
673
669
 
674
- it "should parse nested list comprehension" do
675
- engine.parse defn("A:",
676
- " b = [[a+c for c in [4,5]] for a in [1,2,3]]",
677
- )
678
-
670
+ it 'should parse nested list comprehension' do
671
+ engine.parse defn('A:',
672
+ ' b = [[a+c for c in [4,5]] for a in [1,2,3]]',
673
+ )
679
674
  end
680
675
 
681
- xit "should parse cross list comprehension" do
682
- engine.parse defn("A:",
683
- " b = [a+c for c in [4,5] for a in [1,2,3]]",
684
- )
685
-
676
+ xit 'should parse cross list comprehension' do
677
+ engine.parse defn('A:',
678
+ ' b = [a+c for c in [4,5] for a in [1,2,3]]',
679
+ )
686
680
  end
687
681
 
688
- it "should accept list comprehension variable override" do
689
- engine.parse defn("A:",
690
- " b = [b+1 for b in [1,2,3]]",
691
- )
682
+ it 'should accept list comprehension variable override' do
683
+ engine.parse defn('A:',
684
+ ' b = [b+1 for b in [1,2,3]]',
685
+ )
692
686
  end
693
687
 
694
- it "should accept list comprehension variable override (2)" do
695
- engine.parse defn("A:",
696
- " a = 1",
697
- " b = [a+1 for a in [1,2,3]]",
698
- )
688
+ it 'should accept list comprehension variable override (2)' do
689
+ engine.parse defn('A:',
690
+ ' a = 1',
691
+ ' b = [a+1 for a in [1,2,3]]',
692
+ )
699
693
  end
700
694
 
701
- it "errors out on bad list comprehension" do
695
+ it 'errors out on bad list comprehension' do
702
696
  lambda {
703
- engine.parse defn("A:",
704
- " b = [i+1 for x in [1,2,3]]",
705
- )
697
+ engine.parse defn('A:',
698
+ ' b = [i+1 for x in [1,2,3]]',
699
+ )
706
700
  }.should raise_error(Delorean::UndefinedError)
707
701
  engine.reset
708
702
 
709
703
  lambda {
710
- engine.parse defn("A:",
711
- " a = [123 for b in b]",
712
- )
704
+ engine.parse defn('A:',
705
+ ' a = [123 for b in b]',
706
+ )
713
707
  }.should raise_error(Delorean::UndefinedError)
714
708
  engine.reset
715
709
 
716
710
  # disallow nested comprehension var reuse
717
711
  lambda {
718
- engine.parse defn("A:",
719
- " b = [[a+1 for a in [4,5]] for a in [1,2,3]]",
720
- )
712
+ engine.parse defn('A:',
713
+ ' b = [[a+1 for a in [4,5]] for a in [1,2,3]]',
714
+ )
721
715
  }.should raise_error(Delorean::RedefinedError)
722
716
  engine.reset
723
717
  end
724
718
 
725
- it "should handle nested comprehension variables" do
726
- engine.parse defn("A:",
727
- " b = [ a+b for a, b in [] ]",
728
- )
719
+ it 'should handle nested comprehension variables' do
720
+ engine.parse defn('A:',
721
+ ' b = [ a+b for a, b in [] ]',
722
+ )
729
723
  end
730
724
 
731
- it "should allow nodes as values" do
732
- engine.parse defn("A:",
733
- " a = 123",
734
- "B:",
735
- " a = A",
736
- )
725
+ it 'should allow nodes as values' do
726
+ engine.parse defn('A:',
727
+ ' a = 123',
728
+ 'B:',
729
+ ' a = A',
730
+ )
737
731
  end
738
732
 
739
- it "should parse module calls" do
740
- engine.parse defn("A:",
741
- " a = 123",
742
- " b = 456 + a",
733
+ it 'should parse module calls' do
734
+ engine.parse defn('A:',
735
+ ' a = 123',
736
+ ' b = 456 + a',
743
737
  " n = 'A'",
744
- " c = nil(x = 123, y = 456)",
745
- " d = n(x = 123,",
746
- " y = 456,",
747
- " )",
748
- )
738
+ ' c = nil(x = 123, y = 456)',
739
+ ' d = n(x = 123,',
740
+ ' y = 456,',
741
+ ' )',
742
+ )
749
743
  end
750
744
 
751
- it "should parse module calls by node name" do
752
- engine.parse defn("A:",
753
- " a = 123",
754
- " d = A()",
755
- )
745
+ it 'should parse module calls by node name' do
746
+ engine.parse defn('A:',
747
+ ' a = 123',
748
+ ' d = A()',
749
+ )
756
750
  end
757
751
 
758
- it "should allow positional args to node calls" do
759
- engine.parse defn("A:",
760
- " d = A(1, 2, 3, a=123, b=456)",
761
- )
752
+ it 'should allow positional args to node calls' do
753
+ engine.parse defn('A:',
754
+ ' d = A(1, 2, 3, a=123, b=456)',
755
+ )
762
756
  end
763
757
 
764
- it "should allow node calls to attrs" do
765
- engine.parse defn("A:",
766
- " x=?",
767
- " a = A(x=123)",
768
- " d = a(x=456).x",
769
- )
758
+ it 'should allow node calls to attrs' do
759
+ engine.parse defn('A:',
760
+ ' x=?',
761
+ ' a = A(x=123)',
762
+ ' d = a(x=456).x',
763
+ )
770
764
  end
771
765
 
772
- it "allow conditional args to node calls" do
773
- engine.parse defn("A:",
774
- " d = A(a=1, b=4 if true, c=4 if false)",
775
- )
766
+ it 'allow conditional args to node calls' do
767
+ engine.parse defn('A:',
768
+ ' d = A(a=1, b=4 if true, c=4 if false)',
769
+ )
776
770
  end
777
771
 
778
- it "allow double splats in node calls" do
779
- engine.parse defn("A:",
780
- " a =?",
781
- " d = A(**a, **(a+a), a=123, b=456)",
782
- )
772
+ it 'allow double splats in node calls' do
773
+ engine.parse defn('A:',
774
+ ' a =?',
775
+ ' d = A(**a, **(a+a), a=123, b=456)',
776
+ )
783
777
  end
784
778
 
785
- it "allow double splats in literal hashes" do
786
- engine.parse defn("A:",
787
- " a =?",
779
+ it 'allow double splats in literal hashes' do
780
+ engine.parse defn('A:',
781
+ ' a =?',
788
782
  " d = {'a':1, 2:2, **a, **(a+a)}",
789
- )
783
+ )
790
784
  end
791
785
 
792
- it "should parse instance calls" do
793
- engine.parse defn("A:",
794
- " a = [1,2,[4]].flatten(1)",
795
- )
786
+ it 'should parse instance calls' do
787
+ engine.parse defn('A:',
788
+ ' a = [1,2,[4]].flatten(1)',
789
+ )
796
790
  end
797
791
 
798
- it "should parse multiline attr defs" do
799
- engine.parse defn("A:",
800
- " a = [1,",
801
- " 2,",
802
- " 3]",
803
- " b = 456",
804
- )
792
+ it 'should parse multiline attr defs' do
793
+ engine.parse defn('A:',
794
+ ' a = [1,',
795
+ ' 2,',
796
+ ' 3]',
797
+ ' b = 456',
798
+ )
805
799
  end
806
800
 
807
- xit "should parse multiline empty list" do
808
- engine.parse defn("A:",
809
- " a = [",
810
- " ]",
811
- )
801
+ xit 'should parse multiline empty list' do
802
+ engine.parse defn('A:',
803
+ ' a = [',
804
+ ' ]',
805
+ )
812
806
  end
813
807
 
814
- it "should give proper errors on parse multiline attr defs" do
808
+ it 'should give proper errors on parse multiline attr defs' do
815
809
  begin
816
- engine.parse defn("A:",
817
- " a = [1,",
818
- " 2,",
819
- " 3];",
820
- " b = 456",
821
- )
822
- fail
810
+ engine.parse defn('A:',
811
+ ' a = [1,',
812
+ ' 2,',
813
+ ' 3];',
814
+ ' b = 456',
815
+ )
816
+ raise
823
817
  rescue Delorean::ParseError => exc
824
818
  exc.line.should == 2
825
819
  end
826
820
  end
827
821
 
828
- it "should give proper errors when multiline error falls off the end" do
822
+ it 'should give proper errors when multiline error falls off the end' do
829
823
  begin
830
- engine.parse defn("A:",
831
- " x = 123",
832
- " a = 1 +",
833
- " 2 +",
834
- )
835
- fail
824
+ engine.parse defn('A:',
825
+ ' x = 123',
826
+ ' a = 1 +',
827
+ ' 2 +',
828
+ )
829
+ raise
836
830
  rescue Delorean::ParseError => exc
837
831
  exc.line.should == 3
838
832
  end
@@ -840,69 +834,69 @@ describe "Delorean" do
840
834
 
841
835
  it "should give proper errors when multiline doesn't end properly" do
842
836
  begin
843
- engine.parse defn("A:",
844
- " a = 1",
845
- " b = [a+1",
846
- " for a in [1,2,3]",
847
- "B:",
848
- )
849
- fail
837
+ engine.parse defn('A:',
838
+ ' a = 1',
839
+ ' b = [a+1',
840
+ ' for a in [1,2,3]',
841
+ 'B:',
842
+ )
843
+ raise
850
844
  rescue Delorean::ParseError => exc
851
845
  exc.line.should == 3
852
846
  end
853
847
  end
854
848
 
855
- it "should error on multiline not properly spaced" do
849
+ it 'should error on multiline not properly spaced' do
856
850
  begin
857
- engine.parse defn("A:",
858
- " a = [1,",
859
- " 2]",
860
- " b = 456",
861
- )
862
- fail
851
+ engine.parse defn('A:',
852
+ ' a = [1,',
853
+ ' 2]',
854
+ ' b = 456',
855
+ )
856
+ raise
863
857
  rescue Delorean::ParseError => exc
864
858
  exc.line.should == 2
865
859
  end
866
860
  end
867
861
 
868
862
  # this is a parsing limitation which should go away
869
- it "should not parse interpolated strings" do
863
+ it 'should not parse interpolated strings' do
870
864
  begin
871
- engine.parse defn("A:",
865
+ engine.parse defn('A:',
872
866
  ' d = "#{this is a test}"',
873
- )
874
- fail
867
+ )
868
+ raise
875
869
  rescue Delorean::ParseError => exc
876
870
  exc.line.should == 2
877
871
  end
878
872
  end
879
873
 
880
- it "should parse imports" do
881
- engine.parse defn("import AAA",
882
- "A:",
883
- " b = 456",
884
- "B: AAA::X",
885
- )
874
+ it 'should parse imports' do
875
+ engine.parse defn('import AAA',
876
+ 'A:',
877
+ ' b = 456',
878
+ 'B: AAA::X',
879
+ )
886
880
  end
887
881
 
888
- xit "should parse ERR()" do
882
+ xit 'should parse ERR()' do
889
883
  # pending ... wrapping with parens -- (ERR()) works
890
- engine.parse defn("A:",
891
- " b = ERR() && 123",
892
- )
884
+ engine.parse defn('A:',
885
+ ' b = ERR() && 123',
886
+ )
893
887
  end
894
888
 
895
- it "should disallow import loops" do
889
+ it 'should disallow import loops' do
896
890
  skip 'not implemented yet'
897
891
  sset.merge(
898
- "BBB" =>
899
- defn("import AAA",
900
- "import CCC",
901
- ),
902
- "CCC" =>
903
- defn("import BBB",
904
- ),
905
- )
906
- sset.get_engine("CCC")
892
+ 'BBB' =>
893
+ defn('import AAA',
894
+ 'import CCC',
895
+ ),
896
+ 'CCC' =>
897
+ defn('import BBB',
898
+ ),
899
+ )
900
+ sset.get_engine('CCC')
907
901
  end
908
902
  end