trxl 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe "The language" do
4
+
5
+ include Trxl::SpecHelper
6
+
7
+ before(:each) do
8
+ @parser = Trxl::Calculator.new
9
+ end
10
+
11
+ it "should evaluate the constant 'NULL' to nil" do
12
+ eval("NULL").should be_nil
13
+ end
14
+
15
+ it "should evaluate the constant 'TRUE' to true" do
16
+ eval("TRUE").should be_true
17
+ end
18
+
19
+ it "should evaluate the constant 'FALSE' to false" do
20
+ eval("FALSE").should be_false
21
+ end
22
+
23
+ end
@@ -0,0 +1,117 @@
1
+ require 'spec_helper'
2
+
3
+ describe "A newly created environment" do
4
+
5
+ before :each do
6
+ @env = Trxl::Environment.new
7
+ end
8
+
9
+ it "should be empty" do
10
+ @env.should be_empty
11
+ end
12
+
13
+ it "should have a depth of 1 (one)" do
14
+ @env.depth.should == 1
15
+ end
16
+
17
+ end
18
+
19
+ describe "For storing variables" do
20
+
21
+ before :each do
22
+ @env = Trxl::Environment.new
23
+ end
24
+
25
+ it "should allow to bind variables to any given value" do
26
+ @env[:a] = "foo"
27
+ @env[:a].should == "foo"
28
+ end
29
+
30
+ it "should allow to test if it's empty" do
31
+ @env.should be_empty
32
+ @env[:a] = "foo"
33
+ @env.should_not be_empty
34
+ end
35
+
36
+ it "should allow to assign new values to already initialized variables" do
37
+ @env[:a] = "foo"
38
+ @env[:a].should == "foo"
39
+ @env[:a] = "bar"
40
+ @env[:a].should == "bar"
41
+ end
42
+
43
+ end
44
+
45
+ describe "For scoping variables" do
46
+
47
+ before :each do
48
+ @env = Trxl::Environment.new({
49
+ :a => "foo",
50
+ :b => "bar"
51
+ })
52
+ end
53
+
54
+ it "should allow to enter a new scope" do
55
+ @env.enter_scope
56
+ @env.depth.should == 2
57
+ end
58
+
59
+ it "should allow to pop any nested scope" do
60
+ @env.enter_scope
61
+ @env.exit_scope
62
+ @env.depth.should == 1
63
+ end
64
+
65
+ it "should not allow to pop the toplevel scope" do
66
+ lambda { @env.exit_scope }.should raise_error
67
+ end
68
+
69
+ it "should override any existing variable in a new scope" do
70
+ @env.enter_scope
71
+ @env[:a] = "bam"
72
+ @env[:a].should == "bam"
73
+ @env.exit_scope
74
+ @env[:a].should == "foo"
75
+ end
76
+
77
+ it "should allow to merge an existing environment into the current local one" do
78
+ other_env = { :c => "c", :d => "d" }
79
+ @env.merge!(other_env)
80
+ @env.local[:c].should == "c"
81
+ @env.local[:a].should == "foo"
82
+ @env.local[:b].should == "bar"
83
+ @env[:c].should == "c"
84
+ @env[:a].should == "foo"
85
+ @env[:b].should == "bar"
86
+
87
+ other_env = { :a => "a", :c => "c" }
88
+ @env.merge!(other_env)
89
+ @env.local[:a].should == "a"
90
+ @env.local[:b].should == "bar"
91
+ @env.local[:c].should == "c"
92
+ @env[:a].should == "a"
93
+ @env[:b].should == "bar"
94
+ @env[:c].should == "c"
95
+ end
96
+
97
+ it "should allow to return a new merged environment leaving the original intact" do
98
+ other_env = { :c => "c", :d => "d" }
99
+ env = @env.merge(other_env)
100
+ env.local[:c].should == "c"
101
+ env.local[:a].should == "foo"
102
+ env.local[:b].should == "bar"
103
+ env[:c].should == "c"
104
+ env[:a].should == "foo"
105
+ env[:b].should == "bar"
106
+
107
+ other_env = { :a => "a", :c => "c" }
108
+ env = @env.merge(other_env)
109
+ env.local[:a].should == "a"
110
+ env.local[:b].should == "bar"
111
+ env.local[:c].should == "c"
112
+ env[:a].should == "a"
113
+ env[:b].should == "bar"
114
+ env[:c].should == "c"
115
+ end
116
+
117
+ end
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ describe "For working with Hashes, the Trxl::Calculator" do
4
+
5
+ include Trxl::SpecHelper
6
+
7
+ before(:each) do
8
+ @parser = Trxl::Calculator.new
9
+ end
10
+
11
+
12
+ it "should evaluate hash literal expressions" do
13
+ eval("{}").should == {}
14
+ eval("{ 1 => 2 }").should == { 1 => 2 }
15
+ eval("{ 1 => 2, 3 => 4 }").should == { 1 => 2, 3 => 4 }
16
+ end
17
+
18
+ it "should allow hash variable definitions" do
19
+ eval("a = {}").should == {}
20
+ eval("a = {}; a;").should == {}
21
+ eval("a = { 1 => 2 }").should == { 1 => 2 }
22
+ eval("a = { 1 => 2 }; a;").should == { 1 => 2 }
23
+ eval("a = { 1 => 2, 3 => 4 }; a;").should == { 1 => 2, 3 => 4 }
24
+ end
25
+
26
+ it "should allow nested hash variable definitions" do
27
+ eval("a = { 1 => { 2 => 3 } }").should == { 1 => { 2 => 3 } }
28
+ eval("a = { 1 => { 2 => 3 }, 4 => 5 }").should == { 1 => { 2 => 3 }, 4 => 5 }
29
+ end
30
+
31
+ it "should allow arbitrary expressions in hash literal" do
32
+ eval("x = 1; foo = fun(x) {x}; h = { fun(){2}() => foo(3) }").should == { 2 => 3 }
33
+ end
34
+
35
+ it "should be able to index hashes by their keys" do
36
+ eval("h = { 1 => 2 }; h[0]").should == nil
37
+ eval("h = { 1 => 2 }; h[1]").should == 2
38
+ eval("h = { 1 => 2 }; h[2]").should == nil
39
+ end
40
+
41
+ it "should recognize primary expressions as hash offset specifiers" do
42
+ eval("h = { 1 => 2 }; h[fun(x){x}(0)]").should == nil
43
+ eval("h = { 1 => 2 }; h[fun(x){x}(1)]").should == 2
44
+ eval("h = { 1 => 2 }; h[fun(x){x}(2)]").should == nil
45
+ end
46
+
47
+ it "should resolve exact matching expressions" do
48
+ env = { :foo => { :a => "bar", :b => "bar", :c => "baz" } }
49
+ eval("foo[='bar']", env).should == [ [:a, "bar"], [:b, "bar"] ]
50
+ eval("foo[='baz']", env).should == [ [:c, "baz"] ]
51
+ eval("foo[='bam']", env).should == []
52
+ end
53
+
54
+ it "should resolve exact matching expressions followed by offset access expressions" do
55
+ env = { :foo => { :a => "bar", :b => "bar", :c => "baz" } }
56
+ eval("foo[='bar'][0]", env).should == [ :a, "bar" ]
57
+ eval("foo[='bar'][1]", env).should == [ :b, "bar" ]
58
+ eval("foo[='baz'][0]", env).should == [ :c, "baz" ]
59
+ eval("foo[='bam'][0]", env).should be_nil
60
+ end
61
+
62
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe "The calculation grammar" do
4
+
5
+ include Trxl::SpecHelper
6
+
7
+ before(:each) do
8
+ @parser = Trxl::Calculator.new
9
+ end
10
+
11
+ it "should evaluate a given positive integer number to itself" do
12
+ eval("7").should == 7
13
+ end
14
+
15
+ it "should evaluate a given negative integer number to itself" do
16
+ eval("-7").should == -7
17
+ end
18
+
19
+ it "should evaluate a given positive real number to itself" do
20
+ eval("7.0").should == 7.0
21
+ end
22
+
23
+ it "should evaluate a given negative real number to itself" do
24
+ eval("-7.0").should == -7.0
25
+ end
26
+
27
+ end
@@ -0,0 +1,81 @@
1
+ require 'spec_helper'
2
+
3
+ describe "When working with Ranges, the Trxl::Calculator" do
4
+
5
+ include Trxl::SpecHelper
6
+
7
+ before(:each) do
8
+ @parser = Trxl::Calculator.new
9
+ end
10
+
11
+ it "should return arrays for range literal expressions" do
12
+ eval("0..0").should == [ 0 ]
13
+ eval("0..-1").should == [ ]
14
+ eval("0...0").should == [ ]
15
+ eval("0...-1").should == [ ]
16
+
17
+ eval("1..5").should == [ 1, 2, 3, 4, 5 ]
18
+ eval("1 .. 5").should == [ 1, 2, 3, 4, 5 ]
19
+ eval("a = 1; b = 5; a..b").should == [ 1, 2, 3, 4, 5 ]
20
+ eval("1...5").should == [ 1, 2, 3, 4 ]
21
+ eval("1 ... 5").should == [ 1, 2, 3, 4 ]
22
+ eval("a = 1; b = 5; a...b").should == [ 1, 2, 3, 4 ]
23
+
24
+ eval("\"a\"..\"a\"").should == [ "a" ]
25
+ eval("\"a\"..\"c\"").should == [ "a", "b", "c" ]
26
+ eval("\"a\" .. \"c\"").should == [ "a", "b", "c" ]
27
+ eval("\"a\"...\"c\"").should == [ "a", "b" ]
28
+ eval("\"a\" ... \"c\"").should == [ "a", "b" ]
29
+
30
+ eval("'a'..'a'").should == [ "a" ]
31
+ eval("'a'..'c'").should == [ "a", "b", "c" ]
32
+ eval("'a' .. 'c'").should == [ "a", "b", "c" ]
33
+ eval("'a'...'c'").should == [ "a", "b" ]
34
+ eval("'a' ... 'c'").should == [ "a", "b" ]
35
+
36
+ eval("'aa'..'aa'").should == [ "aa" ]
37
+ eval("'aa'..'ac'").should == [ "aa", "ab", "ac" ]
38
+ eval("'aa'...'ac'").should == [ "aa", "ab" ]
39
+
40
+ eval("1..5 == [ 1, 2, 3, 4, 5 ]").should be_true
41
+ eval("1...5 == [ 1, 2, 3, 4 ]").should be_true
42
+
43
+ eval("SIZE(1..5)").should == 5
44
+
45
+ eval("a..b == [ 1, 2 ]", { :a => 1, :b => 2 }).should be_true
46
+ eval("a..c", { :a => 1, :b => nil, :c => 2 }).should == [ 1, 2]
47
+
48
+ lambda { eval("a..b", { :a => nil, :b => nil }) }.should raise_error
49
+
50
+ end
51
+
52
+ it "should store ranges as arrays" do
53
+ eval("a = 1..5; a;").should == [ 1, 2, 3, 4, 5 ]
54
+ eval("a = 1 .. 5; a;").should == [ 1, 2, 3, 4, 5 ]
55
+ eval("a = 1; b = 5; c = a..b; c;").should == [ 1, 2, 3, 4, 5 ]
56
+ eval("a = 1...5; a;").should == [ 1, 2, 3, 4 ]
57
+ eval("a = 1 ... 5; a;").should == [ 1, 2, 3, 4 ]
58
+ eval("a = 1; b = 5; c = a...b; c;").should == [ 1, 2, 3, 4 ]
59
+ end
60
+
61
+ end
62
+
63
+ describe "When working with Strings, the Trxl::Calculator" do
64
+
65
+ include Trxl::SpecHelper
66
+
67
+ before(:each) do
68
+ @parser = Trxl::Calculator.new
69
+ end
70
+
71
+ it "should evaluate string literals to strings using double quotes (\"\")" do
72
+ eval("\"Test String\"").should == "Test String"
73
+ eval("s = \"Test String\"; s;").should == "Test String"
74
+ end
75
+
76
+ it "should evaluate string literals to strings using single quotes ('')" do
77
+ eval("'Test String'").should == "Test String"
78
+ eval("s = 'Test String'; s;").should == "Test String"
79
+ end
80
+
81
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ describe "For defining Trxl::StdLib, the Trxl::Calculator" do
4
+
5
+ include Trxl::SpecHelper
6
+
7
+ before(:each) do
8
+ @parser = Trxl::Calculator.new
9
+ end
10
+
11
+ it "should be able to require trxl code snippets and merge them into the current env" do
12
+ program = "require 'stdlib'"
13
+ env_after_require = eval(program)
14
+ env_after_require.should have_key(:foreach_in)
15
+ env_after_require.should have_key(:_foreach_in_)
16
+ env_after_require.should have_key(:inject)
17
+ env_after_require.should have_key(:_inject_)
18
+ env_after_require.should have_key(:map)
19
+ env_after_require.should have_key(:ratio)
20
+ end
21
+
22
+ it "should be able to require scoped trxl code snippets and merge them into the current env" do
23
+ program = "require 'stdlib/foreach_in'"
24
+ env_after_require = eval(program)
25
+ env_after_require.should have_key(:foreach_in)
26
+
27
+ program = "require 'stdlib/inject'"
28
+ env_after_require = eval(program)
29
+ env_after_require.should have_key(:inject)
30
+ end
31
+
32
+ it "should be able to require scoped trxl code snippets and merge them into the current env" do
33
+ program = "require 'stdlib/foreach_in'"
34
+ env_after_require = eval(program)
35
+ env_after_require.should have_key(:foreach_in)
36
+
37
+ program = "require 'stdlib/inject'"
38
+ env_after_require = eval(program)
39
+ env_after_require.should have_key(:inject)
40
+ end
41
+
42
+ it "should ignore a require statement if the library has already been loaded" do
43
+ program = "require 'stdlib/inject'"
44
+ program = "require 'stdlib/map'"
45
+ env_after_require = eval(program)
46
+ env_after_require.should have_key(:inject)
47
+ env_after_require.should have_key(:map)
48
+ end
49
+
50
+ end
@@ -0,0 +1,370 @@
1
+ require 'spec_helper'
2
+
3
+ describe "The Trxl::StdLib" do
4
+
5
+ include Trxl::SpecHelper
6
+
7
+ before(:each) do
8
+ @parser = Trxl::Calculator.new
9
+ end
10
+
11
+ it "should be able to parse the whole Trxl::StdLib code" do
12
+ lambda { parse(Trxl::Calculator.stdlib) }.should_not raise_error
13
+ end
14
+
15
+ it "should define a foreach function with read access to the outer env" do
16
+ program = <<-PROGRAM
17
+ require 'stdlib/foreach_in';
18
+ foreach_in(1..3, fun(c) { c });
19
+ PROGRAM
20
+ eval(program).should == 3
21
+ end
22
+
23
+ it "should define a foreach function with write access to the outer env" do
24
+ program = <<-PROGRAM
25
+ require 'stdlib/foreach_in';
26
+ sum = 0;
27
+ a = 1..10;
28
+ foreach_in(a, fun(e) {
29
+ sum = sum + e
30
+ });
31
+ sum;
32
+ PROGRAM
33
+ eval(program).should == 55
34
+ end
35
+
36
+ it "should define an inject function with read access to the outer env" do
37
+ program = <<-PROGRAM
38
+ require 'stdlib/inject';
39
+ inject(0, 1..6, fun(memo, val) { memo + val });
40
+ PROGRAM
41
+ eval(program).should == 21
42
+ end
43
+
44
+ it "should define an inject function with write access to the outer env" do
45
+ program = <<-PROGRAM
46
+ require 'stdlib/inject';
47
+ ratio = fun(values) {
48
+ base = 0;
49
+ positives = inject(0, values, fun(memo, val) {
50
+ if(ENV[val] == "yes")
51
+ base = base + 1;
52
+ memo + 1
53
+ elsif(ENV[val] == "no")
54
+ base = base + 1;
55
+ memo
56
+ else
57
+ memo
58
+ end
59
+ });
60
+ if(base > 0)
61
+ ROUND((ROUND(positives, 10) / base) * 100, 2)
62
+ else
63
+ 0
64
+ end
65
+ };
66
+ ratio('a'..'c');
67
+ PROGRAM
68
+ eval(program, { :a => 'yes', :b => 'no', :c => 'n/a' }).should == 50
69
+ end
70
+
71
+ it "should define a map function with read access to the outer env" do
72
+ program = <<-PROGRAM
73
+ require 'stdlib/map';
74
+ map([[1,2],[3,4],[5,6]], fun(a) { a[1]; });
75
+ PROGRAM
76
+ eval(program).should == [2,4,6]
77
+ end
78
+
79
+ it "should define a map function with write access to the outer env" do
80
+ program = <<-PROGRAM
81
+ require 'stdlib/map';
82
+ a = [];
83
+ map([[1,2],[3,4],[5,6]], fun(x) { a << x[1]; });
84
+ a;
85
+ PROGRAM
86
+ eval(program).should == [2,4,6]
87
+
88
+ program = <<-PROGRAM
89
+ require 'stdlib/map';
90
+ sum = 0;
91
+ map([[1,2],[3,4],[5,6]], fun(x) { sum = sum + x[1]; });
92
+ sum;
93
+ PROGRAM
94
+ eval(program).should == 12
95
+ end
96
+
97
+ it "should define a 'select' function for any enumerable collection" do
98
+ program = <<-PROGRAM
99
+ require 'stdlib/select';
100
+ select([ 1, 2, 3, 4 ], fun(e) { e % 2 == 0 });
101
+ PROGRAM
102
+ eval(program).should == [ 2, 4 ]
103
+
104
+ program = <<-PROGRAM
105
+ require 'stdlib/select';
106
+ select(1..4, fun(e) { e % 2 == 0 });
107
+ PROGRAM
108
+ eval(program).should == [ 2, 4 ]
109
+ end
110
+
111
+ it "should define a 'reject' function for any enumerable collection" do
112
+ program = <<-PROGRAM
113
+ require 'stdlib/reject';
114
+ reject([ 1, 2, 3, 4 ], fun(e) { e % 2 == 0 });
115
+ PROGRAM
116
+ eval(program).should == [ 1, 3 ]
117
+
118
+ program = <<-PROGRAM
119
+ require 'stdlib/reject';
120
+ reject(1..4, fun(e) { e % 2 == 0 });
121
+ PROGRAM
122
+ eval(program).should == [ 1, 3 ]
123
+ end
124
+
125
+ it "should define a 'ratio' function for any enumerable collection" do
126
+ env = {
127
+ :a => "Ja",
128
+ :b => "Ja",
129
+ :c => "Ja",
130
+ :d => "Ja"
131
+ }
132
+ req_stmt = "require 'stdlib/ratio';"
133
+ eval("#{req_stmt} ratio('a'..'d', 'Ja', 'keine Angabe');", env).should == 100
134
+
135
+ env = {
136
+ :a => "Ja",
137
+ :b => "Ja",
138
+ :c => "Nein",
139
+ :d => "Nein"
140
+ }
141
+ req_stmt = "require 'stdlib/ratio';"
142
+ eval("#{req_stmt} ratio('a'..'d', 'Ja', 'keine Angabe');", env).should == 50
143
+
144
+ env = {
145
+ :a => "Nein",
146
+ :b => "Nein",
147
+ :c => "Nein",
148
+ :d => "Nein"
149
+ }
150
+ req_stmt = "require 'stdlib/ratio';"
151
+ eval("#{req_stmt} ratio('a'..'d', 'Ja', 'keine Angabe');", env).should == 0
152
+
153
+ env = {
154
+ :a => "Ja",
155
+ :b => "Nein",
156
+ :c => "Nein",
157
+ :d => "Nein",
158
+ :e => "keine Angabe"
159
+ }
160
+ req_stmt = "require 'stdlib/ratio';"
161
+ eval("#{req_stmt} ratio('a'..'e', 'Ja', 'keine Angabe');", env).should == 25
162
+
163
+ env = {
164
+ :a => "keine Angabe"
165
+ }
166
+ req_stmt = "require 'stdlib/ratio';"
167
+ eval("#{req_stmt} ratio(['a'], 'Ja', 'keine Angabe');", env).should be_nil
168
+
169
+ env = {
170
+ :a => "keine Angabe",
171
+ :b => "keine Angabe",
172
+ :c => "keine Angabe"
173
+ }
174
+ req_stmt = "require 'stdlib/ratio';"
175
+ eval("#{req_stmt} ratio('a'..'c', 'Ja', 'keine Angabe');", env).should be_nil
176
+
177
+ env = {
178
+ :a => "Ja",
179
+ :b => "keine Angabe"
180
+ }
181
+ req_stmt = "require 'stdlib/ratio';"
182
+ eval("#{req_stmt} ratio('a'..'b', 'Ja', 'keine Angabe');", env).should == 100
183
+
184
+ env = {
185
+ :a => "Nein",
186
+ :b => "keine Angabe"
187
+ }
188
+ req_stmt = "require 'stdlib/ratio';"
189
+ eval("#{req_stmt} ratio('a'..'b', 'Ja', 'keine Angabe');", env).should == 0
190
+ end
191
+
192
+ it "should define a 'in_groups_of' function for any enumerable collection" do
193
+ program = <<-PROGRAM
194
+ require 'stdlib/in_groups_of';
195
+ in_groups_of(2, [ 1, 2, 3, 4 ], fun(group) { group });
196
+ PROGRAM
197
+ eval(program).should == [ [ 1, 2 ], [ 3, 4 ] ]
198
+
199
+ program = <<-PROGRAM
200
+ require 'stdlib/in_groups_of';
201
+ in_groups_of(2, 1..4, fun(group) { group });
202
+ PROGRAM
203
+ eval(program).should == [ [ 1, 2 ], [ 3, 4 ] ]
204
+
205
+ program = <<-PROGRAM
206
+ require 'stdlib/inject';
207
+ require 'stdlib/in_groups_of';
208
+ in_groups_of(2, 1..4, fun(group) { SUM(group) });
209
+ PROGRAM
210
+ eval(program).should == [ 3, 7 ]
211
+
212
+ program = <<-PROGRAM
213
+ require 'stdlib/in_groups_of';
214
+ in_groups_of(2, 'a'..'d', fun(group) { group });
215
+ PROGRAM
216
+ eval(program).should == [ [ 'a', 'b' ], [ 'c', 'd' ] ]
217
+
218
+ env = Trxl::Environment.new({
219
+ :a => {
220
+ 1 => "Building 1",
221
+ 2 => "Building 2",
222
+ 3 => "Building 3"
223
+ },
224
+ :b => {
225
+ 1 => "Feuerwehrgebäude",
226
+ 2 => "Schulgebäude",
227
+ 3 => "Wohngebäude"
228
+ },
229
+ :c => { 1 => 100, 2 => 200, 3 => 300 },
230
+ :d => { 1 => 100, 2 => 200, 3 => 300 },
231
+ :e => { 1 => 100, 2 => 200, 3 => 300 },
232
+ :f => { 1 => 100, 2 => 200, 3 => 300 },
233
+ :g => { 1 => 100, 2 => 200, 3 => 300 },
234
+ :h => { 1 => 100, 2 => 200, 3 => 300 },
235
+ :i => { 1 => 100, 2 => 200, 3 => 300 },
236
+ :j => { 1 => 100, 2 => 200, 3 => 300 },
237
+ :k => { 1 => 100, 2 => 200, 3 => 300 },
238
+ :l => { 1 => 100, 2 => 200, 3 => 300 },
239
+ :m => { 1 => 100, 2 => 200, 3 => 300 },
240
+ :n => { 1 => 100, 2 => 200, 3 => 300 },
241
+ :o => { 1 => 100, 2 => 200, 3 => 300 },
242
+ :p => { 1 => 100, 2 => 200, 3 => 300 },
243
+ :q => { 1 => 100, 2 => 200, 3 => 300 },
244
+ :r => { 1 => 100, 2 => 200, 3 => 300 },
245
+ :s => { 1 => 100, 2 => 200, 3 => 300 },
246
+ :t => { 1 => 100, 2 => 200, 3 => 300 },
247
+ :u => {
248
+ 1 => [ 15, 15, 15 ],
249
+ 1 => [ 20, 20, 20 ],
250
+ 1 => [ 30, 30, 30 ]
251
+ }
252
+ })
253
+ end
254
+
255
+ it "should allow recursive functions as accumulator in 'in_groups_of' function calls" do
256
+ program = <<-PROGRAM
257
+ require 'stdlib/inject';
258
+ require 'stdlib/in_groups_of';
259
+ in_groups_of(2, 1..4, fun(group) {
260
+ inject(0, group, fun(sum, e) {
261
+ sum + e
262
+ });
263
+ });
264
+ PROGRAM
265
+ eval(program).should == [ 3, 7 ]
266
+ end
267
+
268
+ it "should define a 'sum_of_type' function" do
269
+ env = {
270
+ :types => {
271
+ 1 => "Feuerwehrgebäude",
272
+ 2 => "Schulgebäude",
273
+ 3 => "Sonstige",
274
+ },
275
+ :values => {
276
+ 1 => [ 100, 100, 100 ],
277
+ 2 => [ 200, 200, 200 ],
278
+ 3 => [ 300, 300, 300 ]
279
+ }
280
+ }
281
+ req_stmt = "require 'stdlib/sum_of_type';"
282
+ eval("#{req_stmt} sum_of_type('Feuerwehrgebäude', types, values);", env).should == 300
283
+ eval("#{req_stmt} sum_of_type('Schulgebäude', types, values);", env).should == 600
284
+ eval("#{req_stmt} sum_of_type('Sonstige', types, values);", env).should == 900
285
+ end
286
+
287
+ it "should define a 'avg_sum_of_type' function" do
288
+ env = {
289
+ :types => {
290
+ 1 => "Feuerwehrgebäude",
291
+ 2 => "Schulgebäude",
292
+ 3 => "Sonstige",
293
+ },
294
+ :values => {
295
+ 1 => [ 100, 100, 100 ],
296
+ 2 => [ 200, 200, 200 ],
297
+ 3 => [ 300, 300, 300 ]
298
+ }
299
+ }
300
+ req_stmt = "require 'stdlib/avg_sum_of_type';"
301
+ eval("#{req_stmt} avg_sum_of_type('Feuerwehrgebäude', types, values);", env).should == 100
302
+ eval("#{req_stmt} avg_sum_of_type('Schulgebäude', types, values);", env).should == 200
303
+ eval("#{req_stmt} avg_sum_of_type('Sonstige', types, values);", env).should == 300
304
+ end
305
+
306
+ it "should define a 'total_range_sum_of_type' function" do
307
+ env = {
308
+ :types => {
309
+ 1 => "Feuerwehrgebäude",
310
+ 2 => "Schulgebäude",
311
+ 3 => "Sonstige",
312
+ },
313
+ :a => {
314
+ 1 => [ 100, 100, 100 ],
315
+ 2 => [ 200, 200, 200 ],
316
+ 3 => [ 300, 300, 300 ]
317
+ },
318
+ :b => {
319
+ 1 => [ 100, 100, 100 ],
320
+ 2 => [ 200, 200, 200 ],
321
+ 3 => [ 300, 300, 300 ]
322
+ }
323
+ }
324
+ req_stmt = "require 'stdlib/total_range_sum_of_type';"
325
+ eval("#{req_stmt} total_range_sum_of_type('Feuerwehrgebäude', types, 'a'..'b');", env).should == 600
326
+ eval("#{req_stmt} total_range_sum_of_type('Schulgebäude', types, 'a'..'b');", env).should == 1200
327
+ eval("#{req_stmt} total_range_sum_of_type('Sonstige', types, 'a'..'b');", env).should == 1800
328
+ end
329
+
330
+ it "should define a 'avg_range_sum_of_type' function" do
331
+ env = {
332
+ :types => {
333
+ 1 => "Feuerwehrgebäude",
334
+ 2 => "Schulgebäude",
335
+ 3 => "Sonstige",
336
+ },
337
+ :a => {
338
+ 1 => [ 100, 100, 100 ],
339
+ 2 => [ 200, 200, 200 ],
340
+ 3 => [ 300, 300, 300 ]
341
+ },
342
+ :b => {
343
+ 1 => [ 100, 100, 100 ],
344
+ 2 => [ 200, 200, 200 ],
345
+ 3 => [ 300, 300, 300 ]
346
+ }
347
+ }
348
+ req_stmt = "require 'stdlib/avg_range_sum_of_type';"
349
+ eval("#{req_stmt} avg_range_sum_of_type('Feuerwehrgebäude', types, 'a'..'b');", env).should == 200
350
+ eval("#{req_stmt} avg_range_sum_of_type('Schulgebäude', types, 'a'..'b');", env).should == 400
351
+ eval("#{req_stmt} avg_range_sum_of_type('Sonstige', types, 'a'..'b');", env).should == 600
352
+ end
353
+
354
+ it "should define a 'year_from_date' function" do
355
+ req_stmt = "require 'stdlib/year_from_date';"
356
+ eval("#{req_stmt} year_from_date('01/1999');").should == 1999
357
+ eval("#{req_stmt} year_from_date('12/1999');").should == 1999
358
+ eval("#{req_stmt} year_from_date('12/2008');").should == 2008
359
+ eval("#{req_stmt} year_from_date('12/2008');").should == 2008
360
+ end
361
+
362
+ it "should define a 'month_from_date' function" do
363
+ req_stmt = "require 'stdlib/month_from_date';"
364
+ eval("#{req_stmt} month_from_date('01/1999');").should == 1
365
+ eval("#{req_stmt} month_from_date('12/1999');").should == 12
366
+ eval("#{req_stmt} month_from_date('1/2008');").should == 1
367
+ eval("#{req_stmt} month_from_date('12/2008');").should == 12
368
+ end
369
+
370
+ end