trxl 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ --colour
2
+ --loadby random
3
+ --format specdoc
4
+ --backtrace
@@ -0,0 +1,28 @@
1
+ require "rubygems"
2
+ require "treetop"
3
+ require "pathname"
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+
8
+ SPEC_ROOT = Pathname(__FILE__).dirname.expand_path
9
+
10
+ require SPEC_ROOT.parent + 'lib/trxl'
11
+
12
+ module Trxl
13
+ module SpecHelper
14
+
15
+ # raise unless successful
16
+ def parse(expression)
17
+ @parser.parse(expression)
18
+ end
19
+
20
+ # raise if an exception is raised during parsing
21
+ # raise if an exception is raised during evaluation
22
+ def eval(expression, env = Environment.new)
23
+ env = Trxl::Environment.new(env) if env.is_a?(Hash)
24
+ ast = parse(expression)
25
+ ast.eval(env)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,391 @@
1
+ require 'spec_helper'
2
+
3
+ Infinity = 1.0 / 0
4
+
5
+ describe "When evaluating addition expressions, the language" do
6
+
7
+ include Trxl::SpecHelper
8
+
9
+ before(:each) do
10
+ @parser = Trxl::Calculator.new
11
+ end
12
+
13
+ it "should allow integers as operands" do
14
+ eval("0+0").should == 0 + 0
15
+ eval("0+1").should == 0 + 1
16
+ eval("1+0").should == 1 + 0
17
+ eval("1+1").should == 1 + 1
18
+ eval("2+2").should == 2 + 2
19
+ eval("2+-2").should == 2 + -2
20
+ end
21
+
22
+ it "should allow floats as operands" do
23
+ eval("0.0+0.0").should == 0.0 + 0.0
24
+ eval("0.1+1").should == 0.1 + 1
25
+ eval("1.34+0.23456789").should == 1.34 + 0.23456789
26
+ eval("1.000+1.87").should == 1.000 + 1.87
27
+ eval("2.0+2.01").should == 2.0 + 2.01
28
+ eval("2.0+-2.01").should == 2.0 + -2.01
29
+ end
30
+
31
+ it "should allow arbitrary spacing" do
32
+ eval("4 + 2").should == 4 + 2
33
+ eval("4 +2").should == 4 + 2
34
+ eval("4+ 2").should == 4 + 2
35
+ eval(" 4 + 2").should == 4 + 2
36
+ eval("4 + 2 ").should == 4 + 2
37
+ eval(" 4 + 2 ").should == 4 + 2
38
+ end
39
+
40
+ it "should allow chained expressions" do
41
+ eval("1 + 1 + 1").should == 1 + 1 + 1
42
+ eval("1 + 1 + 1 + 1").should == 1 + 1 + 1 + 1
43
+ end
44
+
45
+ end
46
+
47
+
48
+ describe "When evaluating subtraction expressions, the language" do
49
+
50
+ include Trxl::SpecHelper
51
+
52
+ before(:each) do
53
+ @parser = Trxl::Calculator.new
54
+ end
55
+
56
+ it "should allow integers as operands" do
57
+ eval("0-0").should == 0 - 0
58
+ eval("0-2").should == 0 - 2
59
+ eval("2-2").should == 2 - 2
60
+ eval("5-2").should == 5 - 2
61
+ eval("5--2").should == 5--2
62
+ end
63
+
64
+
65
+ it "should allow floats as operands" do
66
+ eval("0.0-0.0").should == 0.0 - 0.0
67
+ eval("0.1-2.34").should == 0.1 - 2.34
68
+ eval("2.12-2.34").should == 2.12 - 2.34
69
+ eval("5.45678-2.456789").should == 5.45678 - 2.456789
70
+ eval("5.45678--2.456789").should == 5.45678 - -2.456789
71
+ end
72
+
73
+ it "should allow arbitrary spacing" do
74
+ eval("4 - 2").should == 4 - 2
75
+ eval("4 -2").should == 4 - 2
76
+ eval("4- 2").should == 4 - 2
77
+ eval(" 4 - 2").should == 4 - 2
78
+ eval("4 - 2 ").should == 4 - 2
79
+ eval(" 4 - 2 ").should == 4 - 2
80
+ end
81
+
82
+ it "should perform left associative evaluation in chained expressions" do
83
+ eval("16 - 4 - 2").should == (16 - 4 - 2)
84
+ eval("16 - 4 - 2 - 2").should == (16 - 4 - 2 - 2)
85
+ end
86
+
87
+ it "should allow to override operator precedence with parentheses" do
88
+ eval("(16 - 4) - 2").should == (16 - 4) - 2
89
+ eval("16 - (4 - 2)").should == 16 - (4 - 2)
90
+ eval("(16 - 4) - (2 - 2)").should == (16 - 4) - (2 - 2)
91
+ eval("16 - (4 - 2) - 2").should == 16 - (4 - 2) - 2
92
+ end
93
+
94
+ end
95
+
96
+
97
+ describe "When evaluating multiplication expressions, the language" do
98
+
99
+ include Trxl::SpecHelper
100
+
101
+ before(:each) do
102
+ @parser = Trxl::Calculator.new
103
+ end
104
+
105
+ it "should allow integers as operands" do
106
+ eval("0*0").should == 0 * 0
107
+ eval("0*1").should == 0 * 1
108
+ eval("1*0").should == 1 * 0
109
+ eval("1*1").should == 1 * 1
110
+ eval("2*2").should == 2 * 2
111
+ eval("3*4").should == 3 * 4
112
+ eval("3*-4").should == 3 * -4
113
+ end
114
+
115
+
116
+ it "should allow floats as operands" do
117
+ eval("0.0*0.0").should == 0.0 * 0.0
118
+ eval("0.1*1.0").should == 0.1 * 1.0
119
+ eval("1.345*0.987").should == 1.345 * 0.987
120
+ eval("1.23*1.45").should == 1.23 * 1.45
121
+ eval("2.5*2").should == 2.5 * 2
122
+ eval("3.45*4.45").should == 3.45 * 4.45
123
+ eval("3.45*-4.45").should == 3.45 * -4.45
124
+ end
125
+
126
+ it "should allow arbitrary spacing" do
127
+ eval("4 * 2").should == 4 * 2
128
+ eval("4 *2").should == 4 * 2
129
+ eval("4* 2").should == 4 * 2
130
+ eval(" 4 * 2").should == 4 * 2
131
+ eval("4 * 2 ").should == 4 * 2
132
+ eval(" 4 * 2 ").should == 4 * 2
133
+ end
134
+
135
+ it "should allow chained expressions" do
136
+ eval("1 * 2 * 3").should == 1 * 2 * 3
137
+ eval("1 * 2 * 3 * 4").should == 1 * 2 * 3 * 4
138
+ end
139
+
140
+ end
141
+
142
+
143
+ describe "When evaluating division expressions, the language" do
144
+
145
+ include Trxl::SpecHelper
146
+
147
+ before(:each) do
148
+ @parser = Trxl::Calculator.new
149
+ end
150
+
151
+ it "should allow integers as operands" do
152
+ eval("1/1").should == 1.0 / 1
153
+ eval("0/1").should == 0.0 / 1
154
+ eval("1/2").should == 1.0 / 2
155
+ eval("4/2").should == 4.0 / 2
156
+ eval("3/2").should == 3.0 / 2
157
+ eval("3/-2").should == 3.0 / -2
158
+
159
+ # test division by zero
160
+ lambda { eval("1/0") }.should raise_error(Trxl::DivisionByZeroError)
161
+ end
162
+
163
+ it "should allow floats as operands" do
164
+ eval("1.0/1.0").should == 1.0 / 1.0
165
+ eval("0.0/1.0").should == 0.0 / 1.0
166
+ eval("1.23/2.34").should == 1.23 / 2.34
167
+ eval("4.2345678/2").should == 4.2345678 / 2
168
+ eval("3/2.123456").should == 3 / 2.123456
169
+ eval("3/-2.123456").should == 3 / -2.123456
170
+
171
+ # TODO think about DivisonByZero vs. Infinity
172
+ end
173
+
174
+ it "should allow arbitrary spacing" do
175
+ eval("4 / 2").should == 4 / 2
176
+ eval("4 /2").should == 4 / 2
177
+ eval("4/ 2").should == 4 / 2
178
+ eval(" 4 / 2").should == 4 / 2
179
+ eval("4 / 2 ").should == 4 / 2
180
+ eval(" 4 / 2 ").should == 4 / 2
181
+ end
182
+
183
+ it "should perform left associative evaluation in chained expressions" do
184
+ eval("16 / 4 / 2").should == (16 / 4 / 2)
185
+ eval("16 / 4 / 2 / 2").should == (16 / 4 / 2 / 2)
186
+ end
187
+
188
+ it "should allow to override operator precedence with parentheses" do
189
+ eval("(16 / 4) / 2").should == (16 / 4) / 2
190
+ eval("16 / (4 / 2)").should == 16 / (4 / 2)
191
+ eval("(16 / 4) / (2 / 2)").should == (16 / 4) / (2 / 2)
192
+ eval("16 / (4 / 2) / 2").should == 16 / (4 / 2) / 2
193
+ end
194
+
195
+ end
196
+
197
+
198
+ describe "When evaluating modulo expressions, the language" do
199
+
200
+ include Trxl::SpecHelper
201
+
202
+ before(:each) do
203
+ @parser = Trxl::Calculator.new
204
+ end
205
+
206
+ it "should allow integers as operands" do
207
+ eval("1%1").should == 1 % 1
208
+ eval("4%2").should == 4 % 2
209
+ eval("8%3").should == 8 % 3
210
+ eval("8%-3").should == 8 % -3
211
+
212
+ # test division by zero
213
+ lambda { eval("1%0") }.should raise_error(Trxl::DivisionByZeroError)
214
+ end
215
+
216
+
217
+ it "should allow floats as operands" do
218
+ eval("1.0%1.0").should == 1.0 % 1.0
219
+ eval("4.0%2.0").should == 4.0 % 2.0
220
+ eval("8.0%3.2").should == 8.0 % 3.2
221
+ eval("8.0%-3.2").should == 8.0 % -3.2
222
+
223
+ # TODO think about DivisonByZero vs. Infinity
224
+ end
225
+
226
+ it "should allow arbitrary spacing" do
227
+ eval("4 % 2").should == 4 % 2
228
+ eval("4 %2").should == 4 % 2
229
+ eval("4% 2").should == 4 % 2
230
+ eval(" 4 % 2").should == 4 % 2
231
+ eval("4 % 2 ").should == 4 % 2
232
+ eval(" 4 % 2 ").should == 4 % 2
233
+ end
234
+
235
+ it "should perform left associative evaluation in chained expressions" do
236
+ eval("15 % 5 % 3").should == (15 % 5 % 3)
237
+ eval("16 % 9 % 4 % 2").should == (16 % 9 % 4 % 2)
238
+ end
239
+
240
+ it "should allow to override operator precedence with parentheses" do
241
+ eval("(16 % 4) % 2").should == (16 % 4) % 2
242
+ eval("16 % (5 % 3)").should == 16 % (5 % 3)
243
+ eval("(16 % 4) % (5 % 3)").should == (16 % 4) % (5 % 3)
244
+ eval("16 % (5 % 3) % 2").should == 16 % (5 % 3) % 2
245
+ end
246
+
247
+ end
248
+
249
+ describe "When evaluating exponential expressions, the language" do
250
+
251
+ include Trxl::SpecHelper
252
+
253
+ before(:each) do
254
+ @parser = Trxl::Calculator.new
255
+ end
256
+
257
+ it "should allow integers as operands" do
258
+ eval("1^1").should == 1 ** 1
259
+ eval("4^2").should == 4 ** 2
260
+ eval("8^3").should == 8 ** 3
261
+ eval("8^-3").should == 8 ** -3
262
+ end
263
+
264
+
265
+ it "should allow floats as operands" do
266
+ eval("1.0^1.0").should == 1.0 ** 1.0
267
+ eval("4.0^2.0").should == 4.0 ** 2.0
268
+ eval("8.0^3.2").should == 8.0 ** 3.2
269
+ eval("8.0^-3.2").should == 8.0 ** -3.2
270
+ end
271
+
272
+ it "should allow arbitrary spacing" do
273
+ eval("4 ^ 2").should == 4 ** 2
274
+ eval("4 ^2").should == 4 ** 2
275
+ eval("4^ 2").should == 4 ** 2
276
+ eval(" 4 ^ 2").should == 4 ** 2
277
+ eval("4 ^ 2 ").should == 4 ** 2
278
+ eval(" 4 ^ 2 ").should == 4 ** 2
279
+ end
280
+
281
+ it "should perform left associative evaluation in chained expressions" do
282
+ eval("2 ^ 2 ^ 2").should == (2 ** 2 ** 2)
283
+ eval("2 ^ 2 ^ 2 ^ 2").should == (2 ** 2 ** 2 ** 2)
284
+ end
285
+
286
+ end
287
+
288
+
289
+ describe "When evaluating arbitrary arithmetic expressions, the language" do
290
+
291
+ include Trxl::SpecHelper
292
+
293
+ before(:each) do
294
+ @parser = Trxl::Calculator.new
295
+ end
296
+
297
+ it "should respect arithmetic operator precedence" do
298
+ eval("2 + 4 * 2 + 2").should == 2 + 4 * 2 + 2
299
+ eval("2 + 4 / 2 + 2").should == 2 + 4 / 2 + 2
300
+ eval("2 + 5 % 3 + 2").should == 2 + 5 % 3 + 2
301
+ eval("2 + 4 ^ 2 + 2").should == 2 + 4 ** 2 + 2
302
+
303
+ eval("2 - 4 * 2 - 2").should == 2 - 4 * 2 - 2
304
+ eval("2 - 4 / 2 - 2").should == 2 - 4 / 2 - 2
305
+ eval("2 - 5 % 3 - 2").should == 2 - 5 % 3 - 2
306
+ eval("2 - 4 ^ 2 - 2").should == 2 - 4 ** 2 - 2
307
+
308
+ eval("2 * 4 * 2 - 2").should == 2 * 4 * 2 - 2
309
+ eval("8 / 4 / 2 - 2").should == 8 / 4 / 2 - 2
310
+ eval("8 % 4 % 2 - 2").should == 8 % 4 % 2 - 2
311
+ eval("2 ^ 2 ^ 2 - 2").should == 2 ** 2 ** 2 - 2
312
+
313
+ eval("2 * 4 * 2 - 2 * 3").should == 2 * 4 * 2 - 2 * 3
314
+ eval("8 / 4 / 2 - 4 / 2").should == 8 / 4 / 2 - 4 / 2
315
+ eval("8 % 4 % 2 - 5 % 3").should == 8 % 4 % 2 - 5 % 3
316
+ eval("2 ^ 2 ^ 2 - 2 ^ 2").should == 2 ** 2 ** 2 - 2 ** 2
317
+
318
+ eval("4 / 2 + 2 * 4 * 2 - 2 * 3").should == 4 / 2 + 2 * 4 * 2 - 2 * 3
319
+ eval("2 * 2 + 8 / 4 / 2 - 4 / 2").should == 2 * 2 + 8 / 4 / 2 - 4 / 2
320
+ eval("2 + 4 + 8 % 4 % 2 - 5 % 3").should == 2 + 4 + 8 % 4 % 2 - 5 % 3
321
+ eval("2 * 2 + 2 ^ 2 ^ 2 - 2 ^ 2").should == 2 * 2 + 2 ** 2 ** 2 - 2 ** 2
322
+
323
+ eval("4 + 2 - 2").should == 4 + 2 - 2
324
+ eval("4 * 2 / 2").should == 4 * 2 / 2
325
+ eval("4 * 2 % 2").should == 4 * 2 % 2
326
+
327
+ eval("4 - 2 + 2").should == 4 - 2 + 2
328
+ eval("4 / 2 * 2").should == 4 / 2 * 2
329
+ eval("4 % 2 * 2").should == 4 % 2 * 2
330
+ eval("4 ^ 2 * 2").should == 4 ** 2 * 2
331
+
332
+ end
333
+
334
+ it "should allow to override operator precedence using parentheses" do
335
+ eval("(2 + 4) * (2 + 2)").should == (2 + 4) * (2 + 2)
336
+ eval("(2 + 4) / (2 + 2)").should == (2 + 4).to_f / (2 + 2)
337
+ eval("(2 + 4) % (2 + 2)").should == (2 + 4) % (2 + 2)
338
+ eval("(2 + 4) ^ (2 + 2)").should == (2 + 4) ** (2 + 2)
339
+
340
+ eval("(2 - 4) * (2 - 2)").should == (2 - 4) * (2 - 2)
341
+ eval("(2 - 4) / (4 - 2)").should == (2 - 4).to_f / (4 - 2)
342
+ eval("(2 - 4) % (4 - 2)").should == (2 - 4) % (4 - 2)
343
+ eval("(2 - 4) ^ (2 - 2)").should == (2 - 4) ** (2 - 2)
344
+
345
+ eval("2 * 4 * (2 - 2)").should == 2 * 4 * (2 - 2)
346
+ eval("8 / (4 / 2) - 2").should == 8 / (4 / 2) - 2
347
+ eval("8 / (8 / 2 - 2)").should == 8 / (8 / 2 - 2)
348
+ eval("8 % (5 % 3) - 2").should == 8 % (5 % 3) - 2
349
+ eval("8 % (4 % 2 - 2)").should == 8 % (4 % 2 - 2)
350
+ eval("2 ^ (2 ^ 2) - 2").should == 2 ** (2 ** 2) - 2
351
+ eval("2 ^ (2 ^ 2 - 2)").should == 2 ** (2 ** 2 - 2)
352
+
353
+ eval("2 * 4 * (2 - 2) * 3").should == 2 * 4 * (2 - 2) * 3
354
+ eval("2 * 4 * (2 - 2 * 3)").should == 2 * 4 * (2 - 2 * 3)
355
+ eval("8 / 4 / (2 - 4) / 2").should == 8.0 / 4 / (2 - 4) / 2
356
+ eval("8 / 4 / (2 - 8 / 2)").should == 8.0 / 4 / (2 - 8 / 2)
357
+ eval("8 % 4 % (2 - 6) % 3").should == 8 % 4 % (2 - 6) % 3
358
+ eval("8 % 4 % (2 - 6 % 3)").should == 8 % 4 % (2 - 6 % 3)
359
+ eval("2 ^ 2 ^ (2 - 2) ^ 2").should == 2 ** 2 ** (2 - 2) ** 2
360
+ eval("2 ^ 2 ^ (2 - 2 ^ 2)").should == 2 ** 2 ** (2 - 2 ** 2)
361
+
362
+ eval("4 / (2 + 2 * 4) * (2 - 2) * 3").should == 4 / (2 + 2 * 4) * (2 - 2) * 3
363
+ eval("2 * (2 + 8 / 4 / 2 - 4) / 2").should == 2 * (2 + 8 / 4 / 2 - 4) / 2
364
+ eval("(2 + 4 + 8 % 4) % 2 - (5 % 3)").should == (2 + 4 + 8 % 4) % 2 - (5 % 3)
365
+ eval("(2 * 2 + 2) ^ (2 ^ 2) - 2 ^ 2").should == (2 * 2 + 2) ** (2 ** 2) - 2 ** 2
366
+ end
367
+
368
+
369
+ it "should allow to use variables as operands" do
370
+ env = { :a => 5, :b => 2, :foo => 3 }
371
+ eval("(((1 + 2 * a) - b * foo) * 2 + a) / foo", env).should == (((1 + 2 * env[:a]) - env[:b] * env[:foo]) * 2 + env[:a]) / env[:foo]
372
+ end
373
+
374
+ it "should allow to use function applications as operands" do
375
+ program = <<-PROGRAM
376
+ sum = fun(a,b) { a + b };
377
+ (2 * 2 + sum(2,4)) / 2
378
+ PROGRAM
379
+ eval(program).should == 5
380
+ end
381
+
382
+ it "should allow to use function applications and variables as operands" do
383
+ program = <<-PROGRAM
384
+ x = 2; y = 4;
385
+ sum = fun(a,b) { a + b };
386
+ (x * 2 + sum(x,y)) / 2
387
+ PROGRAM
388
+ eval(program).should == 5
389
+ end
390
+
391
+ end
@@ -0,0 +1,163 @@
1
+ require 'spec_helper'
2
+
3
+ describe "For working with Arrays, the language" do
4
+
5
+ include Trxl::SpecHelper
6
+
7
+ before(:each) do
8
+ @parser = Trxl::Calculator.new
9
+ end
10
+
11
+
12
+ it "should resolve positive offsets within arrays" do
13
+ env = { :foo => [ 1, 2, 3 ] }
14
+ eval("foo[0]", env).should == 1
15
+ eval("foo[1]", env).should == 2
16
+ eval("foo[2]", env).should == 3
17
+ eval("foo[3]", env).should be_nil
18
+ end
19
+
20
+ it "should recognize primary expressions as offset specifiers" do
21
+ env = { :foo => [ 1, 2, 3 ] }
22
+ eval("a = 0; foo[a]", env).should == 1
23
+ eval("foo[fun(x){x}(0)]", env).should == 1
24
+ end
25
+
26
+ it "should resolve negative offsets within arrays" do
27
+ env = { :foo => [ 1, 2, 3 ] }
28
+ eval("foo[-1]", env).should == 3
29
+ eval("foo[-2]", env).should == 2
30
+ eval("foo[-3]", env).should == 1
31
+ eval("foo[-4]", env).should be_nil
32
+ end
33
+
34
+ it "should resolve exact matching expressions" do
35
+ env = { :foo => [ 1, 2, 2, 3, 3, 3 ] }
36
+
37
+ eval("foo[=1]", env).should == [1]
38
+ eval("foo[=2]", env).should == [2,2]
39
+ eval("foo[=3]", env).should == [3,3,3]
40
+ eval("foo[=4]", env).should == []
41
+
42
+ env = { :foo => [ "foo", "foo", "bar" ] }
43
+
44
+ eval("foo[='foo']", env).should == [ "foo", "foo" ]
45
+ eval("foo[='bar']", env).should == [ "bar" ]
46
+ eval("foo[='baz']", env).should == []
47
+
48
+ env = { :foo => [ "foo", "foo", "bar" ], :a => "foo", :b => "bar", :c => "baz" }
49
+
50
+ eval("foo[=a]", env).should == [ "foo", "foo" ]
51
+ eval("foo[=b]", env).should == [ "bar" ]
52
+ eval("foo[=c]", env).should == []
53
+ end
54
+
55
+ it "should resolve exact matching expressions followed by offset access expressions" do
56
+ env = { :foo => [ 1, 2, 2, 3, 3, 3 ] }
57
+ eval("foo[=1][0]", env).should == 1
58
+ eval("foo[=2][0]", env).should == 2
59
+ eval("foo[=2][1]", env).should == 2
60
+ eval("foo[=3][0]", env).should == 3
61
+ eval("foo[=3][1]", env).should == 3
62
+ eval("foo[=3][2]", env).should == 3
63
+ eval("foo[=4][0]", env).should be_nil
64
+ end
65
+
66
+ it "should allow array variable definitions" do
67
+ eval("a = []").should == []
68
+ eval("a = []; a;").should == []
69
+ eval("a = [ 1, 2, 3 ]").should == [ 1, 2, 3 ]
70
+ eval("a = [ 1, 2, 3 ]; a;").should == [ 1, 2, 3 ]
71
+ end
72
+
73
+ it "should allow nested array variable definitions" do
74
+ eval("a = [[]]").should == [[]]
75
+ eval("a = [[]]; a;").should == [[]]
76
+ eval("a = [ [1, 2], [3, 4] ]").should == [ [1, 2], [3, 4] ]
77
+ eval("a = [ [1, 2], [3, 4] ]; a;").should == [ [1, 2], [3, 4] ]
78
+ end
79
+
80
+ it "should allow arbitrary expressions in array literal" do
81
+ eval("x = 1; foo = fun(x) {x}; arr = [ x, fun(){2}(), foo(3) ]").should == [ 1, 2, 3 ]
82
+ end
83
+
84
+ it "should be able to perform offset access expressions on user defined array variables" do
85
+ eval("a = [1,2,3]; a[0]").should == 1
86
+ eval("a = [1,2,3]; a[1]").should == 2
87
+ eval("a = [1,2,3]; a[2]").should == 3
88
+
89
+ eval("a = []; a[0]").should be_nil
90
+ eval("a = [[]]; a[0]").should == []
91
+ end
92
+
93
+ it "should be able to perform multiple offset access expressions on nested array variables" do
94
+ eval("a = [[]][0]").should == []
95
+ eval("a = [ [1, 2], [3, 4] ]; a[0]").should == [1, 2]
96
+ eval("a = [ [1, 2], [3, 4] ]; a[0][0];").should == 1
97
+ eval("a = [ [1, 2], [3, 4] ]; a[0][1];").should == 2
98
+ end
99
+
100
+ it "should return arrays for array literal expressions" do
101
+ eval("[1,2,3]").should == [ 1, 2, 3 ]
102
+ eval("[ 1, fun(){2}(), fun(x){x}(3) ]").should == [ 1, 2, 3 ]
103
+ end
104
+
105
+ it "should be able to perform offset access expressions on array literals" do
106
+ eval("[1,2,3][0]").should == 1
107
+ eval("[1,2,3][1]").should == 2
108
+ eval("[1,2,3][2]").should == 3
109
+ eval("[1,2,3][-1]").should == 3
110
+ eval("[1,2,3][-2]").should == 2
111
+ eval("[1,2,3][-3]").should == 1
112
+ end
113
+
114
+ it "should be able to calculate the size of any given Array or String" do
115
+ eval("a = [ 1, 2, 3 ]; SIZE(a);").should == 3
116
+ eval("SIZE(a = [ 1, 2, 3 ])").should == 3
117
+ eval("SIZE([ 1, 2, 3 ])").should == 3
118
+
119
+ eval("s = 'Test String'; SIZE(s);").should == "Test String".size
120
+ eval("SIZE(a = 'Test String')").should == "Test String".size
121
+ eval("SIZE('Test String')").should == "Test String".size
122
+
123
+ lambda { eval("SIZE(1)") }.should raise_error(Trxl::InvalidOperationException)
124
+ lambda { eval("SIZE(fun(){3}())") }.should raise_error(Trxl::InvalidOperationException)
125
+ end
126
+
127
+ it "should allow to push values into an already existing Array" do
128
+ eval("a = []; a << 1;").should == [ 1 ]
129
+ eval("a = []; a << 1; a;").should == [ 1 ]
130
+ eval("a = [1]; a << 2;").should == [ 1, 2 ]
131
+ eval("a = [1]; a << 2; a;").should == [ 1, 2 ]
132
+ lambda { eval("a = 1; a << 2;") }.should raise_error(Trxl::InvalidOperationException)
133
+
134
+ #eval("a = [[]]; a[0] << 1;").should == [ [1] ]
135
+ eval("a = [[]]; a[0] << 1; a;").should == [ [1] ]
136
+ eval("a = [1]; a << [2];").should == [ 1, [ 2 ] ]
137
+ eval("a = [1]; a << [2]; a;").should == [ 1, [ 2 ] ]
138
+ lambda { eval("a = [1]; a[0] << 2;") }.should raise_error(Trxl::InvalidOperationException)
139
+ end
140
+
141
+ it "should allow to add two Arrays" do
142
+ eval("[1,2,3] + []").should == [1,2,3]
143
+ eval("[] + [4,5,6]").should == [4,5,6]
144
+ eval("[1,2,3] + [4,5,6]").should == [1,2,3,4,5,6]
145
+
146
+ eval("[[1,2],3] + []").should == [[1,2],3]
147
+ eval("[[]] + [4,5,6]").should == [[],4,5,6]
148
+ eval("[[1,2],3] + [[4,5],6]").should == [[1,2],3,[4,5],6]
149
+ end
150
+
151
+ it "should allow to subtract two Arrays" do
152
+ eval("[1,2,3] - []").should == [1,2,3]
153
+ eval("[] - [4,5,6]").should == []
154
+ eval("[1,2,3] - [4,5,6]").should == [1,2,3]
155
+ eval("[1,2,3,4,5,6] - [4,5,6]").should == [1,2,3]
156
+
157
+ eval("[[1,2],3] - []").should == [[1,2],3]
158
+ eval("[[]] - [4,5,6]").should == [[]]
159
+ eval("[[1,2],3] - [4,5,6]").should == [[1,2],3]
160
+ eval("[1,2,3,[4],5,[6]] - [4,5,6]").should == [1,2,3,[4],[6]]
161
+ end
162
+
163
+ end