obtuse 0.0.1 → 0.0.2
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/.travis.yml +7 -0
- data/README.md +27 -16
- data/Rakefile +6 -0
- data/lib/obtuse.rb +2 -0
- data/lib/obtuse/ast/lambda.rb +11 -0
- data/lib/obtuse/evaluator.rb +205 -9
- data/lib/obtuse/parser.rb +11 -3
- data/lib/obtuse/transform.rb +5 -0
- data/lib/obtuse/version.rb +1 -1
- data/spec/examples_spec.rb +19 -0
- data/spec/obtuse_spec.rb +338 -21
- data/spec/spec_helper.rb +13 -4
- metadata +6 -2
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,29 +1,40 @@
|
|
1
|
-
# Obtuse
|
1
|
+
# Obtuse [](https://travis-ci.org/utkarshkukreti/obtuse)
|
2
2
|
|
3
|
-
|
3
|
+
Obtuse is a stack-oriented programming language, optimized for brevity.
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
7
|
-
|
7
|
+
### Using Git (recommended)
|
8
8
|
|
9
|
-
|
9
|
+
```
|
10
|
+
$ git clone https://github.com/utkarshkukreti/obtuse.git
|
11
|
+
$ cd obtuse
|
12
|
+
$ bundle install
|
13
|
+
$ rake install
|
14
|
+
```
|
10
15
|
|
11
|
-
|
16
|
+
### Using RubyGems
|
12
17
|
|
13
|
-
|
18
|
+
```
|
19
|
+
$ gem install obtuse
|
20
|
+
```
|
14
21
|
|
15
|
-
|
22
|
+
## Usage
|
16
23
|
|
17
|
-
|
24
|
+
Run
|
18
25
|
|
19
|
-
|
26
|
+
```
|
27
|
+
$ obtuse
|
28
|
+
```
|
29
|
+
|
30
|
+
to start the interactive REPL.
|
31
|
+
|
32
|
+
## Documentation
|
33
|
+
|
34
|
+
Check out `spec/obtuse_spec.rb` for all functions and their outputs.
|
20
35
|
|
21
|
-
|
36
|
+
## License
|
22
37
|
|
23
|
-
|
38
|
+
The MIT License.
|
24
39
|
|
25
|
-
|
26
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
-
5. Create new Pull Request
|
40
|
+
Copyright (c) 2012, Utkarsh Kukreti.
|
data/Rakefile
CHANGED
data/lib/obtuse.rb
CHANGED
data/lib/obtuse/evaluator.rb
CHANGED
@@ -1,26 +1,209 @@
|
|
1
1
|
module Obtuse
|
2
2
|
class Evaluator
|
3
|
-
|
3
|
+
attr_accessor :stdin
|
4
|
+
attr_reader :stack, :stash
|
4
5
|
|
5
6
|
def initialize
|
6
7
|
@stack = []
|
8
|
+
@stash = []
|
9
|
+
@stdin = $stdin
|
7
10
|
@parser = Parser.new
|
8
11
|
@transform = Transform.new
|
9
12
|
end
|
10
13
|
|
11
|
-
def eval(input)
|
12
|
-
|
14
|
+
def eval(input, parsed = false)
|
15
|
+
if parsed == false
|
16
|
+
input = @transform.apply(@parser.parse(input))
|
17
|
+
end
|
18
|
+
|
19
|
+
input.each do |atom|
|
13
20
|
case atom
|
14
|
-
when Integer, String
|
21
|
+
when Integer, String, Array, AST::Lambda
|
15
22
|
push atom
|
16
23
|
when :+, :-, :*, :/, :%, :^
|
17
24
|
atom = :** if atom == :^
|
18
|
-
|
19
|
-
if Integer === x && Integer === y
|
20
|
-
String === x && String === y
|
25
|
+
x, y = pop 2
|
26
|
+
if Integer === x && Integer === y
|
21
27
|
push x.send(atom, y)
|
28
|
+
elsif String === x && Integer === y
|
29
|
+
case atom
|
30
|
+
when :+
|
31
|
+
push x + y.to_s
|
32
|
+
when :*
|
33
|
+
push x * y
|
34
|
+
when :%
|
35
|
+
push x % y
|
36
|
+
end
|
37
|
+
elsif String === x && String === y
|
38
|
+
case atom
|
39
|
+
when :+
|
40
|
+
push x + y
|
41
|
+
when :-
|
42
|
+
push (x.chars.to_a - y.chars.to_a).join
|
43
|
+
when :*
|
44
|
+
push x.chars.to_a.join(y)
|
45
|
+
end
|
46
|
+
elsif String === x && Array === y
|
47
|
+
case atom
|
48
|
+
when :%
|
49
|
+
push x % y
|
50
|
+
end
|
51
|
+
elsif Array === x
|
52
|
+
case atom
|
53
|
+
when :+
|
54
|
+
push x + Array(y)
|
55
|
+
when :-
|
56
|
+
push x - Array(y)
|
57
|
+
when :*
|
58
|
+
if Integer === y
|
59
|
+
push x * y
|
60
|
+
elsif String === y
|
61
|
+
push x.join(y)
|
62
|
+
elsif Array === y
|
63
|
+
first = x.shift
|
64
|
+
push x.reduce([first]) {|fold, el| fold + y + [el] }
|
65
|
+
elsif AST::Lambda === y
|
66
|
+
push x.shift
|
67
|
+
x.each do |el|
|
68
|
+
push el
|
69
|
+
eval y.expression, true
|
70
|
+
end
|
71
|
+
end
|
72
|
+
when :%
|
73
|
+
if AST::Lambda === y
|
74
|
+
stash
|
75
|
+
x.each do |el|
|
76
|
+
push el
|
77
|
+
eval y.expression, true
|
78
|
+
end
|
79
|
+
stack = @stack
|
80
|
+
unstash
|
81
|
+
push stack
|
82
|
+
end
|
83
|
+
end
|
84
|
+
else
|
85
|
+
end
|
86
|
+
when :"#"
|
87
|
+
x = pop
|
88
|
+
if Integer === x
|
89
|
+
push [*0...x]
|
90
|
+
elsif String === x || Array === x
|
91
|
+
push x.length
|
92
|
+
end
|
93
|
+
when :"$"
|
94
|
+
x = pop
|
95
|
+
if Integer === x
|
96
|
+
push @stack[-x - 1] if @stack[-x - 1]
|
97
|
+
elsif String === x
|
98
|
+
push x.chars.sort.join
|
99
|
+
elsif Array === x
|
100
|
+
push x.sort
|
101
|
+
elsif AST::Lambda === x
|
102
|
+
y = x
|
103
|
+
x = pop
|
104
|
+
case x
|
105
|
+
when String, Array
|
106
|
+
stash
|
107
|
+
array = String === x ? x.chars.to_a : x
|
108
|
+
array.sort_by! do |el|
|
109
|
+
@stack = []
|
110
|
+
push el
|
111
|
+
eval y.expression, true
|
112
|
+
@stack
|
113
|
+
end
|
114
|
+
unstash
|
115
|
+
push String === x ? array.join : array
|
116
|
+
end
|
117
|
+
end
|
118
|
+
when :~
|
119
|
+
x = pop
|
120
|
+
case x
|
121
|
+
when String
|
122
|
+
eval x
|
123
|
+
when Array
|
124
|
+
@stack += x
|
125
|
+
when AST::Lambda
|
126
|
+
eval x.expression, true
|
127
|
+
end
|
128
|
+
when :!
|
129
|
+
push truthy?(pop) ? 0 : 1
|
130
|
+
when :"@"
|
131
|
+
x, y, z = pop 3
|
132
|
+
push y; push z; push x
|
133
|
+
when :"."
|
134
|
+
x = peek
|
135
|
+
push x if x
|
136
|
+
when :";"
|
137
|
+
pop
|
138
|
+
when :"["
|
139
|
+
stash
|
140
|
+
when :"]"
|
141
|
+
stack = @stack
|
142
|
+
unstash
|
143
|
+
push stack
|
144
|
+
when :"=", :<, :>
|
145
|
+
atom = :== if atom == :"="
|
146
|
+
x, y = pop 2
|
147
|
+
if Integer === x && Integer === y ||
|
148
|
+
String === x && String === y ||
|
149
|
+
Array === x && Array === y
|
150
|
+
push x.send(atom, y) ? 1 : 0
|
151
|
+
end
|
152
|
+
when :"\\"
|
153
|
+
x, y = pop 2
|
154
|
+
push y; push x;
|
155
|
+
when :I
|
156
|
+
x, y, z = pop 3
|
157
|
+
if AST::Lambda === x
|
158
|
+
eval x.expression, true
|
159
|
+
if truthy?(pop)
|
160
|
+
AST::Lambda === y ? eval(y.expression, true) : push(y)
|
161
|
+
else
|
162
|
+
AST::Lambda === z ? eval(z.expression, true) : push(z)
|
163
|
+
end
|
22
164
|
else
|
165
|
+
if truthy?(x)
|
166
|
+
AST::Lambda === y ? eval(y.expression, true) : push(y)
|
167
|
+
else
|
168
|
+
AST::Lambda === z ? eval(z.expression, true) : push(z)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
when :W
|
172
|
+
x, y = pop 2
|
173
|
+
if AST::Lambda === x && AST::Lambda === y
|
174
|
+
loop do
|
175
|
+
eval x.expression, true
|
176
|
+
break unless truthy?(pop)
|
177
|
+
eval y.expression, true
|
178
|
+
end
|
179
|
+
end
|
180
|
+
when :Ic
|
181
|
+
push pop.to_i.chr
|
182
|
+
when :Sg
|
183
|
+
x, y, z = pop 3
|
184
|
+
if (Integer === x || String === x) &&
|
185
|
+
(Integer === y || String === y) &&
|
186
|
+
(Integer === z || String === z)
|
187
|
+
push x.to_s.gsub(y.to_s, z.to_s)
|
23
188
|
end
|
189
|
+
when :Sl
|
190
|
+
push pop.to_s.downcase
|
191
|
+
when :Su
|
192
|
+
push pop.to_s.upcase
|
193
|
+
when :Sc
|
194
|
+
push pop.to_s.capitalize
|
195
|
+
when :So
|
196
|
+
push pop.to_s.ord
|
197
|
+
when :Si
|
198
|
+
x, y = pop 2
|
199
|
+
push x.to_s.include?(y.to_s) ? 1 : 0
|
200
|
+
when :St
|
201
|
+
x, y, z = pop 3
|
202
|
+
push x.to_s.tr(y.to_s, z.to_s)
|
203
|
+
when :Ra
|
204
|
+
push stdin.read.chomp
|
205
|
+
when :Rl
|
206
|
+
push stdin.gets.chomp
|
24
207
|
end
|
25
208
|
end
|
26
209
|
end
|
@@ -29,12 +212,25 @@ module Obtuse
|
|
29
212
|
@stack << object
|
30
213
|
end
|
31
214
|
|
32
|
-
def pop
|
33
|
-
@stack.pop
|
215
|
+
def pop(n = nil)
|
216
|
+
n ? @stack.pop(n) : @stack.pop
|
34
217
|
end
|
35
218
|
|
36
219
|
def peek
|
37
220
|
@stack.last
|
38
221
|
end
|
222
|
+
|
223
|
+
def stash
|
224
|
+
@stash << @stack
|
225
|
+
@stack = []
|
226
|
+
end
|
227
|
+
|
228
|
+
def unstash
|
229
|
+
@stack = @stash.pop
|
230
|
+
end
|
231
|
+
|
232
|
+
def truthy?(x)
|
233
|
+
!(x.nil? || x == 0 || x == "" || x == [])
|
234
|
+
end
|
39
235
|
end
|
40
236
|
end
|
data/lib/obtuse/parser.rb
CHANGED
@@ -4,9 +4,10 @@ module Obtuse
|
|
4
4
|
rule(:spaces?) { spaces.maybe }
|
5
5
|
rule(:digit) { match["0-9"] }
|
6
6
|
rule(:digits) { match["0-9"].repeat(1) }
|
7
|
+
rule(:minus) { str("-") }
|
7
8
|
|
8
9
|
rule :integer do
|
9
|
-
digits.as(:integer) >> spaces?
|
10
|
+
(minus.maybe >> digits).as(:integer) >> spaces?
|
10
11
|
end
|
11
12
|
|
12
13
|
rule :string do
|
@@ -15,12 +16,19 @@ module Obtuse
|
|
15
16
|
end
|
16
17
|
|
17
18
|
rule :function do
|
18
|
-
%w{+ - * / % ^
|
19
|
+
%w{+ - * / % ^ # $ ~ ! @ . ; [ ] = < > \\
|
20
|
+
W Ic I Sg Sl Su Sc So Si St Ra Rl}.
|
21
|
+
map { |name| str name }.reduce(:|).
|
19
22
|
as(:function) >> spaces?
|
20
23
|
end
|
21
24
|
|
25
|
+
rule :lambda do
|
26
|
+
str("{") >> spaces? >> expression.as(:expression).as(:lambda) >>
|
27
|
+
str("}") >> spaces?
|
28
|
+
end
|
29
|
+
|
22
30
|
rule :expression do
|
23
|
-
spaces? >> (string |
|
31
|
+
spaces? >> (integer | string | function | lambda).repeat >> spaces?
|
24
32
|
end
|
25
33
|
|
26
34
|
root :expression
|
data/lib/obtuse/transform.rb
CHANGED
data/lib/obtuse/version.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Obtuse do
|
4
|
+
describe "GCD" do
|
5
|
+
# From http://www.golfscript.com/golfscript/examples.html
|
6
|
+
e '13483 74205 {.}{.@\%}W;', 13483.gcd(74205)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "LCM" do
|
10
|
+
e '13483 74205 .@.@{.}{.@\%}W;\@*\/', 13483.lcm(74205)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "Project Euler" do
|
14
|
+
describe "Problem #6: Find the difference between the sum of the squares" +
|
15
|
+
" of the first one hundred natural numbers and the square of the sum." do
|
16
|
+
e '101#{+}*2^101#{2^}%{+}*-', 25164150
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/spec/obtuse_spec.rb
CHANGED
@@ -5,31 +5,348 @@ describe Obtuse do
|
|
5
5
|
Obtuse::VERSION.should be_a String
|
6
6
|
end
|
7
7
|
|
8
|
-
describe "
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
e "10 20 *", 200
|
15
|
-
e "2 3/", 0
|
16
|
-
e "10 20 /", 0
|
17
|
-
e "2 3%", 2
|
18
|
-
e "10 20 %", 10
|
19
|
-
e "2 3^", 8
|
20
|
-
e "10 20 ^", 10 ** 20
|
8
|
+
describe "Primitives" do
|
9
|
+
describe "Integer" do
|
10
|
+
e "2", 2
|
11
|
+
e "100", 100
|
12
|
+
e "-10", -10
|
13
|
+
end
|
21
14
|
|
22
|
-
|
23
|
-
|
15
|
+
describe "String" do
|
16
|
+
e %q{"a \n b \n c \t\td\na"}, "a \n b \n c \t\td\na"
|
17
|
+
end
|
24
18
|
end
|
25
19
|
|
26
|
-
describe "
|
27
|
-
|
20
|
+
describe "Functions" do
|
21
|
+
describe "+" do
|
22
|
+
describe "Integer Integer" do
|
23
|
+
e "2 1+", 3
|
24
|
+
e "10 20 +", 30
|
25
|
+
e "2 -3+", -1
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "String Integer" do
|
29
|
+
e %q{"foo: "42+}, "foo: 42"
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "String String" do
|
33
|
+
e '"foo""bar"+', "foobar"
|
34
|
+
e '"foo" "bar"+', "foobar"
|
35
|
+
e '"foo\\"" "bar"+', 'foo"bar'
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "Array Object" do
|
39
|
+
e %q{[1 2] 1 +}, [1, 2, 1]
|
40
|
+
e %q{[1 2] "1" +}, [1, 2, "1"]
|
41
|
+
e %q{[1] [] +}, [1]
|
42
|
+
e %q{[1 2] [3 4] +}, [1, 2, 3, 4]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "-" do
|
47
|
+
describe "Integer Integer" do
|
48
|
+
e "2 3-", -1
|
49
|
+
e "10 20 -", -10
|
50
|
+
e "-10 -20-", 10
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "String String" do
|
54
|
+
e %q{"aaa""a"-}, ""
|
55
|
+
e %q{"cabc""b"-}, "cac"
|
56
|
+
e %q{"cabc""cb"-}, "a"
|
57
|
+
e %q{"cabc""cab"-}, ""
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "Array Object" do
|
61
|
+
e %q{[1 2] 1 -}, [2]
|
62
|
+
e %q{[1 2] "1" -}, [1, 2]
|
63
|
+
e %q{[1] [] -}, [1]
|
64
|
+
e %q{[1 2 3 3 1 4 4] [3 4] -}, [1, 2, 1]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "*" do
|
69
|
+
describe "Integer Integer" do
|
70
|
+
e "2 3*", 6
|
71
|
+
e "10 20 *", 200
|
72
|
+
e "-5 5*", -25
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "(String | Array) Integer" do
|
76
|
+
e %q{"foobar "3*}, "foobar foobar foobar "
|
77
|
+
e %q{[1 2 3] 3*}, [1, 2, 3, 1, 2, 3, 1, 2, 3]
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "String String" do
|
81
|
+
e %q{"foobar" " 3 "*}, "f 3 o 3 o 3 b 3 a 3 r"
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "Array String" do
|
85
|
+
e %q{[1 2 3] ", "*}, "1, 2, 3"
|
86
|
+
e %q{[1 . 3] ", "*}, "1, 1, 3"
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "Array Array" do
|
90
|
+
e %q{[1 2 3] [1] *}, [1, 1, 2, 1, 3]
|
91
|
+
e %q{[1 2 3] [0 1] *}, [1, 0, 1, 2, 0, 1, 3]
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "Array Lambda (Fold)" do
|
95
|
+
e %q{[1 2 3] {+} *}, 6
|
96
|
+
e %q{[1 2 3] {-} *}, -4
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "/" do
|
101
|
+
describe "Integer Integer" do
|
102
|
+
e "2 3/", 0
|
103
|
+
e "10 20 /", 0
|
104
|
+
e "10 -2/", -5
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "%" do
|
109
|
+
describe "Integer Integer" do
|
110
|
+
e "2 3%", 2
|
111
|
+
e "10 20 %", 10
|
112
|
+
e "5 -3%", -1
|
113
|
+
end
|
114
|
+
|
115
|
+
describe "String Integer" do
|
116
|
+
e %q{"%05d" 123%}, "00123"
|
117
|
+
end
|
118
|
+
|
119
|
+
describe "String Array" do
|
120
|
+
e %q{"%02d %03d %04d"4#%}, "00 001 0002"
|
121
|
+
e %q{"%02d %03d %04d"[0 1 2 3 4 5]%}, "00 001 0002"
|
122
|
+
end
|
123
|
+
|
124
|
+
describe "Array Lambda (Map)" do
|
125
|
+
e %q{[1 2 3 4] {..} %}, [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4]
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe "^" do
|
130
|
+
describe "Integer Integer" do
|
131
|
+
e "2 3^", 8
|
132
|
+
e "10 20 ^", 10 ** 20
|
133
|
+
e "-3 3^", -27
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe "#" do
|
138
|
+
describe "Integer" do
|
139
|
+
e "3#", [0, 1, 2]
|
140
|
+
end
|
141
|
+
|
142
|
+
describe "String" do
|
143
|
+
e %q{"foo bar"#}, 7
|
144
|
+
end
|
145
|
+
|
146
|
+
describe "Array" do
|
147
|
+
e "10##", 10
|
148
|
+
e "[1 2]#", 2
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
describe "$" do
|
153
|
+
describe "Integer" do
|
154
|
+
e %q{5 $}, [], stack: true
|
155
|
+
e %q{1 0 $}, [1, 1], stack: true
|
156
|
+
e %q{5#~ 3 $}, [0, 1, 2, 3, 4, 1], stack: true
|
157
|
+
end
|
158
|
+
|
159
|
+
describe "String" do
|
160
|
+
e %q{"abcdcba"$}, "aabbccd"
|
161
|
+
end
|
162
|
+
|
163
|
+
describe "Array" do
|
164
|
+
e %q{[1 4 3] $}, [1, 3, 4]
|
165
|
+
end
|
166
|
+
|
167
|
+
describe "(String | Array) Lambda (Sort by)" do
|
168
|
+
e %q{"abca" {.} $}, "aabc"
|
169
|
+
e %q{[1 4 3] {-1 *} $}, [4, 3, 1]
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
describe "~" do
|
174
|
+
describe "String" do
|
175
|
+
e %q{"123"~}, 123
|
176
|
+
e %q{"1 2 3 + -"~}, -4
|
177
|
+
end
|
178
|
+
|
179
|
+
describe "Array" do
|
180
|
+
e %q{4#~+++}, 6
|
181
|
+
e %q{[1 2]~+}, 3
|
182
|
+
end
|
183
|
+
|
184
|
+
describe "Lambda" do
|
185
|
+
e '{1 1 +}~', 2
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
describe "!" do
|
190
|
+
describe "" do
|
191
|
+
e "!", 1
|
192
|
+
end
|
193
|
+
|
194
|
+
describe "Integer" do
|
195
|
+
e "1!", 0
|
196
|
+
e "0!", 1
|
197
|
+
end
|
198
|
+
|
199
|
+
describe "String" do
|
200
|
+
e %q{""!}, 1
|
201
|
+
e %q{"foo"!}, 0
|
202
|
+
end
|
203
|
+
|
204
|
+
describe "Array" do
|
205
|
+
e "1#!", 0
|
206
|
+
e "0#!", 1
|
207
|
+
e "[]!", 1
|
208
|
+
e "[1]!", 0
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
describe "@" do
|
213
|
+
describe "Object Object Object" do
|
214
|
+
e %q{"abc" 10 4# @}, [10, [0, 1, 2, 3], "abc"], stack: true
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
describe "." do
|
219
|
+
describe "" do
|
220
|
+
e %q{1 2 .}, [1, 2, 2], stack: true
|
221
|
+
e %q{.}, [], stack: true
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
describe ";" do
|
226
|
+
describe "" do
|
227
|
+
e %q{1 2;}, [1], stack: true
|
228
|
+
e %q{2;}, [], stack: true
|
229
|
+
e %q{;}, [], stack: true
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
describe "[]" do
|
234
|
+
e %q{[1 . 2 . + . [1 . .]]}, [1, 1, 4, 4, [1, 1, 1]]
|
235
|
+
end
|
236
|
+
|
237
|
+
describe "=" do
|
238
|
+
describe "Object Object" do
|
239
|
+
e %q{12 12 =}, 1
|
240
|
+
e %q{"foo" "foo " =}, 0
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
describe "<" do
|
245
|
+
describe "Object Object" do
|
246
|
+
e %q{5 3 <}, 0
|
247
|
+
e %q{"bar" "foo" <}, 1
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
describe ">" do
|
252
|
+
describe "Object Object" do
|
253
|
+
e %q{5 3 >}, 1
|
254
|
+
e %q{"bar" "foo" >}, 0
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
describe "\\" do
|
259
|
+
describe "Object Object" do
|
260
|
+
e %q{1 2 \\}, [2, 1], stack: true
|
261
|
+
e %q{[] [1] \\}, [[1], []], stack: true
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
describe "I" do
|
266
|
+
describe "Object Object Object" do
|
267
|
+
e '0 1 2 I', 2
|
268
|
+
e '1 1 2 I', 1
|
269
|
+
e '0 1 {...} {.}I', [0, 0, 0, 0], stack: true
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
describe "W" do
|
274
|
+
describe "Lambda Lambda" do
|
275
|
+
e '3{.}{1-}W', 0
|
276
|
+
e '5{.}{1-.}W', [4, 3, 2, 1, 0, 0], stack: true
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
describe "Ic" do
|
281
|
+
describe "Integer" do
|
282
|
+
e "97 Ic", "a"
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
describe "Sg" do
|
287
|
+
describe "(Integer | String) (Integer | String) (Integer | String)" do
|
288
|
+
e %q{123 1 2 Sg}, "223"
|
289
|
+
e %q{"123" 1 "s" Sg}, "s23"
|
290
|
+
e %q{123 1 "s" Sg}, "s23"
|
291
|
+
e %q{"foo bar" "f" "b" Sg}, "boo bar"
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
describe "Sl" do
|
296
|
+
describe "String" do
|
297
|
+
e %q{"Foo Bar!" Sl}, "foo bar!"
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
describe "Su" do
|
302
|
+
describe "String" do
|
303
|
+
e %q{"Foo Bar!" Su}, "FOO BAR!"
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
describe "Sc" do
|
308
|
+
describe "String" do
|
309
|
+
e %q{"foo bar!" Sc}, "Foo bar!"
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
describe "So" do
|
314
|
+
describe "String" do
|
315
|
+
e %q{"a" So}, 97
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
describe "Si" do
|
320
|
+
describe "(Integer | String) (Integer | String)" do
|
321
|
+
e %q{123 11 Si}, 0
|
322
|
+
e %q{123 "11" Si}, 0
|
323
|
+
e %q{"foo bar" "o b" Si}, 1
|
324
|
+
e %q{"444" 4 Si}, 1
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
describe "St" do
|
329
|
+
describe "(Integer | String) (Integer | String) (Integer | String)" do
|
330
|
+
e %q{123 13 98 St}, "928"
|
331
|
+
e %q{"123" "13" 98 St}, "928"
|
332
|
+
e %q{"hello" "a-y" "b-z" St}, "ifmmp"
|
333
|
+
e %q{"hello" "^aeiou" 0 St}, "0e00o"
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
describe "Ra" do
|
338
|
+
e "Ra", "abc\nbcd", stdin: "abc\nbcd"
|
339
|
+
end
|
340
|
+
|
341
|
+
describe "Rl" do
|
342
|
+
e "Rl", "abc", stdin: "abc\nbcd"
|
343
|
+
end
|
28
344
|
end
|
29
345
|
|
30
|
-
describe "
|
31
|
-
e
|
32
|
-
e
|
33
|
-
e
|
346
|
+
describe "Mixture" do
|
347
|
+
e "1 2+3-", 0
|
348
|
+
e "5 1 4 5 2 3 4 +-+-+-", 0
|
349
|
+
e "1-2-3-+", 2
|
350
|
+
e "1-2- 3+", 6
|
34
351
|
end
|
35
352
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,16 +1,25 @@
|
|
1
1
|
require "bundler/setup"
|
2
2
|
require "simplecov"
|
3
3
|
SimpleCov.start do
|
4
|
-
add_group
|
4
|
+
add_group "Libraries", "/lib"
|
5
|
+
add_filter "/lib/obtuse/cli.rb"
|
5
6
|
end
|
6
7
|
require "obtuse"
|
7
8
|
|
8
9
|
RSpec.configure do |config|
|
9
|
-
def e(input, output)
|
10
|
-
|
10
|
+
def e(input, output, options = {})
|
11
|
+
stdin = options[:stdin]
|
12
|
+
stdin = String === stdin ? StringIO.new(stdin) : $stdin
|
13
|
+
|
14
|
+
it "should evaluate `#{input}` to `#{output}`" do
|
11
15
|
evaluator = Obtuse::Evaluator.new
|
16
|
+
evaluator.stdin = stdin
|
12
17
|
evaluator.eval(input)
|
13
|
-
|
18
|
+
if options[:stack]
|
19
|
+
evaluator.stack.should eq output
|
20
|
+
else
|
21
|
+
evaluator.peek.should eq output
|
22
|
+
end
|
14
23
|
end
|
15
24
|
end
|
16
25
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: obtuse
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-12-
|
12
|
+
date: 2012-12-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: parslet
|
@@ -101,6 +101,7 @@ extra_rdoc_files: []
|
|
101
101
|
files:
|
102
102
|
- .gitignore
|
103
103
|
- .rspec
|
104
|
+
- .travis.yml
|
104
105
|
- Gemfile
|
105
106
|
- Guardfile
|
106
107
|
- LICENSE.txt
|
@@ -108,12 +109,14 @@ files:
|
|
108
109
|
- Rakefile
|
109
110
|
- bin/obtuse
|
110
111
|
- lib/obtuse.rb
|
112
|
+
- lib/obtuse/ast/lambda.rb
|
111
113
|
- lib/obtuse/cli.rb
|
112
114
|
- lib/obtuse/evaluator.rb
|
113
115
|
- lib/obtuse/parser.rb
|
114
116
|
- lib/obtuse/transform.rb
|
115
117
|
- lib/obtuse/version.rb
|
116
118
|
- obtuse.gemspec
|
119
|
+
- spec/examples_spec.rb
|
117
120
|
- spec/obtuse_spec.rb
|
118
121
|
- spec/spec_helper.rb
|
119
122
|
homepage: https://github.com/utkarshkukreti/obtuse
|
@@ -141,6 +144,7 @@ signing_key:
|
|
141
144
|
specification_version: 3
|
142
145
|
summary: A Stack-oriented programming language, optimized for brevity.
|
143
146
|
test_files:
|
147
|
+
- spec/examples_spec.rb
|
144
148
|
- spec/obtuse_spec.rb
|
145
149
|
- spec/spec_helper.rb
|
146
150
|
has_rdoc:
|