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
@@ -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
|