iba 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/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
|
|