trxl 0.1.5
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.
- 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
|