subaltern 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,64 @@
1
+ #--
2
+ # Copyright (c) 2011-2012, John Mettraux, jmettraux@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+ #++
22
+
23
+
24
+ module Subaltern
25
+
26
+ def self.kernel
27
+
28
+ {
29
+ 'loop' => LoopFunction.new
30
+ }
31
+ end
32
+
33
+ class LoopFunction < Function
34
+
35
+ def initialize
36
+ end
37
+
38
+ def call(context, tree)
39
+
40
+ return nil unless context['__block']
41
+ # a real Ruby would return an Enumerator instance
42
+
43
+ con = Context.new(context, {})
44
+
45
+ loop do
46
+
47
+ begin
48
+
49
+ r = context['__block'].call(con, [], false)
50
+ # new_context is false
51
+
52
+ rescue Command => c
53
+
54
+ case c.name
55
+ when 'break' then break c
56
+ when 'next' then next c
57
+ else raise c
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+
@@ -0,0 +1,28 @@
1
+ #--
2
+ # Copyright (c) 2011-2012, John Mettraux, jmettraux@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+ #++
22
+
23
+
24
+ module Subaltern
25
+
26
+ VERSION = '1.0.0'
27
+ end
28
+
@@ -0,0 +1,74 @@
1
+
2
+ require 'spec_helper'
3
+
4
+
5
+ describe Subaltern do
6
+
7
+ describe Array do
8
+
9
+ describe '[]' do
10
+
11
+ it 'returns the array' do
12
+
13
+ Subaltern.eval('[]').should == []
14
+ Subaltern.eval('[ 1, 2 ]').should == [ 1, 2 ]
15
+ end
16
+ end
17
+
18
+ describe 'standard array methods' do
19
+
20
+ it 'are accepted' do
21
+
22
+ Subaltern.eval('[ 1, 2, 3 ].length').should == 3
23
+ Subaltern.eval('[ 1, [ 2, 3 ] ].flatten').should == [ 1, 2, 3 ]
24
+ end
25
+ end
26
+
27
+ describe '#each' do
28
+
29
+ it 'works' do
30
+
31
+ Subaltern.eval(%[
32
+ sum = 0
33
+ [ 1, 2, 3, 4 ].each { |e| sum = sum + e }
34
+ sum
35
+ ]).should == 10
36
+ end
37
+ end
38
+
39
+ describe '#inject' do
40
+
41
+ it 'works' do
42
+
43
+ Subaltern.eval(%[
44
+ [ 1, 2, 3 ].inject(0) { |sum, e| sum + e }
45
+ ]).should == 6
46
+ end
47
+ end
48
+
49
+ describe '#collect' do
50
+
51
+ it 'works' do
52
+
53
+ Subaltern.eval(%[
54
+ [ 1, 2, 3 ].collect { |e| e + 1 }
55
+ ]).should == [ 2, 3, 4 ]
56
+ end
57
+ end
58
+
59
+ describe '#select' do
60
+
61
+ it 'works' do
62
+
63
+ Subaltern.eval(%[
64
+ [ 1, 2, 3 ].select { |e| true }
65
+ ]).should == [ 1, 2, 3 ]
66
+
67
+ #Subaltern.eval(%[
68
+ # [ 1, 2, 3, 4, 5, 6, 7, 8 ].select { |e| e.even? }
69
+ #]).should == [ 2, 4, 6, 8 ]
70
+ end
71
+ end
72
+ end
73
+ end
74
+
@@ -0,0 +1,125 @@
1
+
2
+ require 'spec_helper'
3
+
4
+
5
+ describe Subaltern do
6
+
7
+ describe 'bad syntax' do
8
+
9
+ it 'raises a Racc::ParseError' do
10
+
11
+ lambda {
12
+ Subaltern.eval('adsfad:12')
13
+ }.should raise_error(Racc::ParseError)
14
+ end
15
+ end
16
+
17
+ describe 'a literal, a string, or a boolean' do
18
+
19
+ it 'is returned as is' do
20
+
21
+ [
22
+ 1, "hello", 1.0, true, false, nil
23
+ ].each do |lit|
24
+ Subaltern.eval(lit.inspect).should == lit
25
+ end
26
+ end
27
+ end
28
+
29
+ describe 'ranges' do
30
+
31
+ it 'is returned as is' do
32
+
33
+ Subaltern.eval(%{
34
+ 1..5
35
+ }).should == (1..5)
36
+ end
37
+ end
38
+
39
+ describe '==' do
40
+
41
+ it 'returns true or false' do
42
+
43
+ Subaltern.eval(%{
44
+ [ true == false, true == true, false == true, false == false ]
45
+ }).should == [ false, true, false, true ]
46
+ end
47
+ end
48
+
49
+ describe 'a sequence of code' do
50
+
51
+ it 'is executed line by line' do
52
+
53
+ Subaltern.eval(%{
54
+ 1
55
+ 2
56
+ }).should == 2
57
+ end
58
+
59
+ it 'is executed line by line' do
60
+
61
+ Subaltern.eval(%{
62
+ 1; 2
63
+ }).should == 2
64
+ end
65
+ end
66
+
67
+ describe 'variable lookup' do
68
+
69
+ it 'works' do
70
+
71
+ Subaltern.eval('a', { 'a' => 1 }).should == 1
72
+ end
73
+ end
74
+
75
+ describe 'variable assignment' do
76
+
77
+ it 'works' do
78
+
79
+ Subaltern.eval(%{
80
+ a = 2; a
81
+ }).should == 2
82
+ end
83
+ end
84
+
85
+ describe 'using regular expressions' do
86
+
87
+ it 'works' do
88
+
89
+ Subaltern.eval(%{
90
+ /abc/.match('d')
91
+ }).should == nil
92
+
93
+ Subaltern.eval(%{
94
+ /abc/.match('myabcde')
95
+ }).class.should == MatchData
96
+
97
+ Subaltern.eval(%{
98
+ /(abc)/.match('abc')[1]
99
+ }).should == 'abc'
100
+ end
101
+ end
102
+
103
+ describe 'return' do
104
+
105
+ it 'is honored' do
106
+
107
+ Subaltern.eval(%{
108
+ 'a'
109
+ return 'A'
110
+ 'b'
111
+ }).should == 'A'
112
+ end
113
+ end
114
+
115
+ describe 'unary -' do
116
+
117
+ it 'works' do
118
+
119
+ Subaltern.eval(%{
120
+ [ 1 + -5, - 5 ]
121
+ }).should == [ -4, -5 ]
122
+ end
123
+ end
124
+ end
125
+
@@ -0,0 +1,129 @@
1
+
2
+ require 'spec_helper'
3
+
4
+
5
+ describe Subaltern do
6
+
7
+ describe 'true' do
8
+
9
+ it 'is returned as is' do
10
+
11
+ Subaltern.eval(%{
12
+ true
13
+ }).should == true
14
+ end
15
+ end
16
+
17
+ describe 'false' do
18
+
19
+ it 'is returned as is' do
20
+
21
+ Subaltern.eval(%{
22
+ false
23
+ }).should == false
24
+ end
25
+ end
26
+
27
+ describe 'not' do
28
+
29
+ it 'works' do
30
+
31
+ Subaltern.eval(%{
32
+ not true
33
+ }).should == false
34
+ end
35
+
36
+ it 'works (!)' do
37
+
38
+ Subaltern.eval(%{
39
+ ! true
40
+ }).should == false
41
+ end
42
+
43
+ it 'works (!!)' do
44
+
45
+ Subaltern.eval(%{
46
+ !! "nada"
47
+ }).should == true
48
+ end
49
+ end
50
+
51
+ describe 'or' do
52
+
53
+ it 'works' do
54
+
55
+ Subaltern.eval(%{
56
+ false or true
57
+ }).should == true
58
+ end
59
+
60
+ it 'works (||)' do
61
+
62
+ Subaltern.eval(%{
63
+ false || true
64
+ }).should == true
65
+ end
66
+ end
67
+
68
+ describe 'and' do
69
+
70
+ it 'works' do
71
+
72
+ Subaltern.eval(%{
73
+ true and true
74
+ }).should == true
75
+ end
76
+
77
+ it 'works (&&)' do
78
+
79
+ Subaltern.eval(%{
80
+ true && true
81
+ }).should == true
82
+ end
83
+ end
84
+
85
+ describe '==' do
86
+
87
+ it 'works' do
88
+
89
+ Subaltern.eval(%{
90
+ 1 == 1
91
+ }).should == true
92
+ end
93
+
94
+ it 'works (2)' do
95
+
96
+ Subaltern.eval(%{
97
+ 1 == 2
98
+ }).should == false
99
+ end
100
+ end
101
+
102
+ describe '!=' do
103
+
104
+ it 'works' do
105
+
106
+ Subaltern.eval(%{
107
+ 1 != 1
108
+ }).should == false
109
+ end
110
+
111
+ it 'works (2)' do
112
+
113
+ Subaltern.eval(%{
114
+ 1 != 2
115
+ }).should == true
116
+ end
117
+ end
118
+
119
+ describe '===' do
120
+
121
+ it 'works' do
122
+
123
+ Subaltern.eval(%{
124
+ String === ''
125
+ }).should == true
126
+ end
127
+ end
128
+ end
129
+
@@ -0,0 +1,23 @@
1
+
2
+ require 'spec_helper'
3
+
4
+
5
+ describe Subaltern do
6
+
7
+ describe Subaltern::Context do
8
+
9
+ describe '.new' do
10
+
11
+ it 'is OK not to pass initial variables' do
12
+
13
+ Subaltern::Context.new.eval('1 + 1').should == 2
14
+ end
15
+
16
+ it 'is OK to pass initial variables' do
17
+
18
+ Subaltern::Context.new('a' => 7).eval('a + 1').should == 8
19
+ end
20
+ end
21
+ end
22
+ end
23
+