iba 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +5 -2
- data/lib/iba.rb +51 -47
- data/test/analyse_test.rb +17 -1
- data/test/assert_test.rb +15 -8
- data/test/display_test.rb +11 -2
- metadata +4 -4
data/README.rdoc
CHANGED
@@ -39,8 +39,11 @@ to the contents of the block.
|
|
39
39
|
Current limits:
|
40
40
|
|
41
41
|
* Only single-expression blocks are supported.
|
42
|
-
* The expression must start with a method-like identifier
|
43
|
-
not 'Foo' or '23'). In practice,
|
42
|
+
* The expression must start with a method-like identifier or an instance
|
43
|
+
variable (like 'foo' or '@foo', but not 'Foo' or '23'). In practice,
|
44
|
+
this produces quite natural results.
|
45
|
+
* Local and instance variables whose names start with an underscore should
|
46
|
+
not be used inside the block.
|
44
47
|
|
45
48
|
Iba's implementation is inspired by Arlo[2], a generic combinator library
|
46
49
|
for Python.
|
data/lib/iba.rb
CHANGED
@@ -18,20 +18,16 @@ class Combinator
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def analyse
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
exprs = [lft, rgt].map {|e| display_subexpression e}.compact
|
30
|
-
str << "\n"
|
31
|
-
str << exprs.join(", ")
|
32
|
-
end
|
33
|
-
str
|
21
|
+
str = "#{self.to_s} is #{self.call.inspect}"
|
22
|
+
if expression.class == MethodCallExpression and expression._method == :==
|
23
|
+
b = @block.binding
|
24
|
+
lft = expression._reciever
|
25
|
+
rgt = expression._args.first
|
26
|
+
exprs = [lft, rgt].map {|e| display_subexpression e}.compact
|
27
|
+
str << "\n"
|
28
|
+
str << exprs.join(", ")
|
34
29
|
end
|
30
|
+
str
|
35
31
|
end
|
36
32
|
|
37
33
|
private
|
@@ -41,7 +37,7 @@ class Combinator
|
|
41
37
|
nil
|
42
38
|
else
|
43
39
|
str = expr._to_s
|
44
|
-
"#{str} is #{eval
|
40
|
+
"#{str} is #{eval(str, @block.binding).inspect}"
|
45
41
|
end
|
46
42
|
end
|
47
43
|
|
@@ -56,23 +52,42 @@ class EmptyExpression
|
|
56
52
|
b = blk.binding
|
57
53
|
|
58
54
|
vars = eval "local_variables", b
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
55
|
+
ivars = eval "instance_variables", b
|
56
|
+
|
57
|
+
_override_instance_variables ivars
|
58
|
+
|
59
|
+
_override_local_variables vars, b
|
64
60
|
|
65
61
|
result = self.instance_eval(&blk)
|
66
62
|
unless result.class == MethodCallExpression
|
67
63
|
result = LiteralExpression.new(result)
|
68
64
|
end
|
69
65
|
|
66
|
+
_restore_local_variables vars, b
|
67
|
+
|
68
|
+
result
|
69
|
+
end
|
70
|
+
|
71
|
+
def _override_instance_variables vars
|
72
|
+
vars.each do |v|
|
73
|
+
next if v =~ /^@_/
|
74
|
+
eval "#{v} = Iba::MethodCallExpression.new(Iba::EmptyExpression.new, :#{v}, [])"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def _override_local_variables vars, b
|
70
79
|
vars.each do |v|
|
71
80
|
next if v =~ /^_/
|
72
|
-
eval "#{v} =
|
81
|
+
eval "_#{v} = #{v}", b
|
82
|
+
eval "#{v} = Iba::MethodCallExpression.new(Iba::EmptyExpression.new, :#{v}, [])", b
|
73
83
|
end
|
84
|
+
end
|
74
85
|
|
75
|
-
|
86
|
+
def _restore_local_variables vars, b
|
87
|
+
vars.each do |v|
|
88
|
+
next if v =~ /^_/
|
89
|
+
eval "#{v} = _#{v}", b
|
90
|
+
end
|
76
91
|
end
|
77
92
|
|
78
93
|
def _to_s
|
@@ -86,49 +101,38 @@ class LiteralExpression
|
|
86
101
|
end
|
87
102
|
|
88
103
|
def _to_s
|
89
|
-
@value.
|
104
|
+
@value.inspect
|
90
105
|
end
|
91
106
|
end
|
92
107
|
|
93
108
|
class MethodCallExpression
|
94
|
-
|
95
|
-
def initialize reciever, methodname, args
|
96
|
-
@reciever = reciever
|
97
|
-
@method = methodname
|
98
|
-
@args = args.map {|a| _wrap(a)}
|
99
|
-
end
|
100
|
-
|
101
|
-
def _method
|
102
|
-
@method
|
103
|
-
end
|
104
|
-
|
105
|
-
def _reciever
|
106
|
-
@reciever
|
107
|
-
end
|
109
|
+
attr_reader :_method, :_reciever, :_args
|
108
110
|
|
109
|
-
def
|
110
|
-
@
|
111
|
+
def initialize reciever, methodname, args
|
112
|
+
@_reciever = reciever
|
113
|
+
@_method = methodname
|
114
|
+
@_args = args.map {|a| _wrap(a)}
|
111
115
|
end
|
112
116
|
|
113
117
|
def _to_s
|
114
|
-
rcv = @
|
115
|
-
args = @
|
118
|
+
rcv = @_reciever._to_s
|
119
|
+
args = @_args.map {|a| a.respond_to?(:_to_s) ? a._to_s : a.to_s }
|
116
120
|
|
117
|
-
if @
|
121
|
+
if @_method == :[]
|
118
122
|
"#{rcv}[#{args[0]}]"
|
119
123
|
elsif method_is_operator?
|
120
|
-
case @
|
124
|
+
case @_args.length
|
121
125
|
when 0
|
122
|
-
"#{@
|
126
|
+
"#{@_method.to_s.sub(/@$/, '')}#{rcv}"
|
123
127
|
when 1
|
124
|
-
"(#{rcv} #{@
|
128
|
+
"(#{rcv} #{@_method} #{args.first})"
|
125
129
|
else
|
126
130
|
raise NotImplementedError
|
127
131
|
end
|
128
132
|
else
|
129
133
|
str = rcv == "" ? "" : "#{rcv}."
|
130
|
-
str << @
|
131
|
-
unless @
|
134
|
+
str << @_method.to_s
|
135
|
+
unless @_args.empty?
|
132
136
|
str << "(#{args.join(', ')})"
|
133
137
|
end
|
134
138
|
str
|
@@ -141,7 +145,7 @@ class MethodCallExpression
|
|
141
145
|
end
|
142
146
|
|
143
147
|
def method_is_operator?
|
144
|
-
@
|
148
|
+
@_method.to_s !~ /^[a-z]/
|
145
149
|
end
|
146
150
|
|
147
151
|
def to_s
|
data/test/analyse_test.rb
CHANGED
@@ -3,7 +3,7 @@ require File.expand_path('test_helper.rb', File.dirname(__FILE__))
|
|
3
3
|
# Test how the combinator analyses the parsed block contents.
|
4
4
|
class AnalyseTest < Test::Unit::TestCase
|
5
5
|
def test_empty_block
|
6
|
-
assert_equal "
|
6
|
+
assert_equal "nil is nil", combinator { }.analyse
|
7
7
|
end
|
8
8
|
|
9
9
|
def test_variable
|
@@ -24,11 +24,22 @@ class AnalyseTest < Test::Unit::TestCase
|
|
24
24
|
combinator { foo == 23 }.analyse
|
25
25
|
end
|
26
26
|
|
27
|
+
def test_operator_equals_array_literal
|
28
|
+
foo = [1, "bar"]
|
29
|
+
assert_equal "(foo == [2, \"baz\"]) is false\nfoo is [1, \"bar\"]",
|
30
|
+
combinator { foo == [2, "baz"] }.analyse
|
31
|
+
end
|
32
|
+
|
27
33
|
def test_string_variable
|
28
34
|
foo = "blub"
|
29
35
|
assert_equal "foo is \"blub\"", combinator { foo }.analyse
|
30
36
|
end
|
31
37
|
|
38
|
+
def test_array_variable
|
39
|
+
foo = [1, 2]
|
40
|
+
assert_equal "foo is [1, 2]", combinator { foo }.analyse
|
41
|
+
end
|
42
|
+
|
32
43
|
def test_object_variable
|
33
44
|
foo = Object.new
|
34
45
|
insp = foo.inspect
|
@@ -38,5 +49,10 @@ class AnalyseTest < Test::Unit::TestCase
|
|
38
49
|
def test_literal
|
39
50
|
assert_equal "23 is 23", combinator { 23 }.analyse
|
40
51
|
end
|
52
|
+
|
53
|
+
def test_instance_variable
|
54
|
+
@foo = 23
|
55
|
+
assert_equal "@foo is 23", combinator { @foo }.analyse
|
56
|
+
end
|
41
57
|
end
|
42
58
|
|
data/test/assert_test.rb
CHANGED
@@ -6,23 +6,30 @@ class AssertTest < Test::Unit::TestCase
|
|
6
6
|
assert { true }
|
7
7
|
end
|
8
8
|
|
9
|
-
def
|
9
|
+
def failing_block_assertion_test message, &block
|
10
10
|
begin
|
11
|
-
assert
|
11
|
+
assert(&block)
|
12
12
|
rescue Exception => e
|
13
|
-
assert_equal
|
13
|
+
assert_equal message, e.message
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
+
def test_simple_failing_assert
|
18
|
+
failing_block_assertion_test("false is false.") { false }
|
19
|
+
end
|
20
|
+
|
17
21
|
def test_operator_equals_assert
|
18
22
|
foo = 24
|
19
|
-
|
20
|
-
assert { foo == 23 }
|
21
|
-
rescue Exception => e
|
22
|
-
assert_equal "(foo == 23) is false\nfoo is 24.", e.message
|
23
|
-
end
|
23
|
+
failing_block_assertion_test("(foo == 23) is false\nfoo is 24.") { foo == 23 }
|
24
24
|
end
|
25
25
|
|
26
|
+
def test_instance_variable_assert
|
27
|
+
@foo = 24
|
28
|
+
failing_block_assertion_test("(@foo == 23) is false\n@foo is 24.") { @foo == 23 }
|
29
|
+
end
|
30
|
+
|
31
|
+
# Special cases
|
32
|
+
|
26
33
|
def test_assert_with_custom_message
|
27
34
|
foo = false
|
28
35
|
begin
|
data/test/display_test.rb
CHANGED
@@ -3,13 +3,17 @@ require File.expand_path('test_helper.rb', File.dirname(__FILE__))
|
|
3
3
|
# Test how the combinator displays the parsed block contents.
|
4
4
|
class DisplayTest < Test::Unit::TestCase
|
5
5
|
def test_empty_combinator
|
6
|
-
assert_equal "", combinator { }.to_s
|
6
|
+
assert_equal "nil", combinator { }.to_s
|
7
7
|
end
|
8
8
|
|
9
|
-
def
|
9
|
+
def test_literal_number
|
10
10
|
assert_equal "23", combinator { 23 }.to_s
|
11
11
|
end
|
12
12
|
|
13
|
+
def test_literal_string
|
14
|
+
assert_equal "\"aa\"", combinator { "aa" }.to_s
|
15
|
+
end
|
16
|
+
|
13
17
|
def test_method_calls
|
14
18
|
assert_equal "foo", combinator { foo }.to_s
|
15
19
|
assert_equal "foo.foo", combinator { foo.foo }.to_s
|
@@ -45,4 +49,9 @@ class DisplayTest < Test::Unit::TestCase
|
|
45
49
|
def test_operator_if_wont_work
|
46
50
|
assert_equal "bar", combinator { foo ? bar : baz }.to_s
|
47
51
|
end
|
52
|
+
|
53
|
+
def test_defined_instance_variables
|
54
|
+
@foo = 1
|
55
|
+
assert_equal "@foo", combinator { @foo }.to_s
|
56
|
+
end
|
48
57
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: iba
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Matijs van Zuijlen
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-02-25 00:00:00 +01:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|