trxl 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +24 -0
- data/README +143 -0
- data/Rakefile +41 -0
- data/VERSION +1 -0
- data/lib/trxl.rb +5 -0
- data/lib/trxl/trxl.rb +585 -0
- data/lib/trxl/trxl_grammar.rb +8583 -0
- data/lib/trxl/trxl_grammar.treetop +1394 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +28 -0
- data/spec/trxl/arithmetics_spec.rb +391 -0
- data/spec/trxl/arrays_spec.rb +163 -0
- data/spec/trxl/booleans_spec.rb +138 -0
- data/spec/trxl/builtins_spec.rb +268 -0
- data/spec/trxl/closures_spec.rb +244 -0
- data/spec/trxl/comments_spec.rb +35 -0
- data/spec/trxl/common_spec.rb +22 -0
- data/spec/trxl/conditionals_spec.rb +454 -0
- data/spec/trxl/constants_spec.rb +23 -0
- data/spec/trxl/environment_spec.rb +117 -0
- data/spec/trxl/hashes_spec.rb +62 -0
- data/spec/trxl/numbers_spec.rb +27 -0
- data/spec/trxl/ranges_spec.rb +81 -0
- data/spec/trxl/require_spec.rb +50 -0
- data/spec/trxl/stdlib_spec.rb +370 -0
- data/spec/trxl/strings_spec.rb +1 -0
- data/spec/trxl/variables_spec.rb +45 -0
- data/trxl.gemspec +90 -0
- metadata +119 -0
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -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
|