fancy 0.3.3 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +14 -14
- data/Rakefile +16 -4
- data/bin/fancy +3 -0
- data/bin/fspec +20 -0
- data/bin/fyi +27 -11
- data/bin/ifancy +1 -1
- data/boot/fancy_ext.rb +1 -0
- data/boot/fancy_ext/block_env.rb +1 -9
- data/boot/fancy_ext/delegator.rb +64 -0
- data/boot/fancy_ext/object.rb +4 -0
- data/boot/fancy_ext/thread.rb +4 -0
- data/boot/load.rb +5 -1
- data/boot/rbx-compiler/compiler/ast.rb +0 -1
- data/boot/rbx-compiler/compiler/ast/class_def.rb +2 -0
- data/boot/rbx-compiler/compiler/ast/method_def.rb +2 -0
- data/boot/rbx-compiler/compiler/ast/node.rb +10 -0
- data/boot/rbx-compiler/compiler/ast/ruby_args.rb +12 -0
- data/boot/rbx-compiler/compiler/ast/singleton_method_def.rb +2 -0
- data/boot/rbx-compiler/parser/fancy_parser.bundle +0 -0
- data/boot/rbx-compiler/parser/lexer.lex +5 -11
- data/boot/rbx-compiler/parser/parser.rb +16 -5
- data/boot/rbx-compiler/parser/parser.y +39 -24
- data/doc/api/fancy.css +1 -1
- data/doc/api/fancy.jsonp +1 -1
- data/doc/api/fdoc.js +22 -4
- data/doc/api/index.html +5 -6
- data/doc/api/jquery-ui.min.js +401 -0
- data/doc/api/jquery.tools.min.js +192 -0
- data/doc/api/themeswitchertool.js +250 -0
- data/doc/features.md +17 -0
- data/examples/actor_bunnies.fy +32 -0
- data/examples/actors.fy +26 -0
- data/examples/actors_primitive.fy +27 -0
- data/examples/actors_ring.fy +37 -0
- data/examples/armstrong_numbers.fy +1 -1
- data/examples/array.fy +7 -9
- data/examples/async_send.fy +1 -2
- data/examples/blocks.fy +4 -4
- data/examples/call_with_receiver.fy +1 -1
- data/examples/class.fy +1 -1
- data/examples/default_args.fy +4 -1
- data/examples/define_methods.fy +2 -2
- data/examples/echo.fy +1 -1
- data/examples/factorial.fy +1 -1
- data/examples/future_composition.fy +2 -2
- data/examples/futures.fy +0 -5
- data/examples/game_of_life.fy +1 -1
- data/examples/person.fy +1 -1
- data/lib/argv.fy +7 -2
- data/lib/array.fy +109 -42
- data/lib/block.fy +39 -14
- data/lib/boot.fy +2 -0
- data/lib/class.fy +2 -0
- data/lib/compiler/ast.fy +2 -1
- data/lib/compiler/ast/assign.fy +2 -3
- data/lib/compiler/ast/async_send.fy +1 -15
- data/lib/compiler/ast/class_def.fy +2 -1
- data/lib/compiler/ast/expression_list.fy +4 -5
- data/lib/compiler/ast/future_send.fy +1 -10
- data/lib/compiler/ast/goto.fy +46 -0
- data/lib/compiler/ast/identifier.fy +9 -7
- data/lib/compiler/ast/literals.fy +8 -1
- data/lib/compiler/ast/match.fy +14 -4
- data/lib/compiler/ast/message_send.fy +34 -6
- data/lib/compiler/ast/method_def.fy +6 -6
- data/lib/compiler/ast/node.fy +3 -3
- data/lib/compiler/ast/range.fy +1 -0
- data/lib/compiler/ast/script.fy +0 -2
- data/lib/compiler/ast/singleton_method_def.fy +2 -4
- data/lib/compiler/ast/string_interpolation.fy +17 -0
- data/lib/compiler/ast/super.fy +5 -4
- data/lib/compiler/ast/try_catch.fy +8 -6
- data/lib/compiler/ast/tuple_literal.fy +3 -2
- data/lib/compiler/command.fy +0 -1
- data/lib/compiler/compiler.fy +1 -5
- data/lib/compiler/stages.fy +6 -14
- data/lib/documentation.fy +57 -46
- data/lib/enumerable.fy +257 -23
- data/lib/enumerator.fy +122 -15
- data/lib/false_class.fy +10 -1
- data/lib/fancy_spec.fy +263 -61
- data/lib/fdoc.fy +11 -25
- data/lib/fiber.fy +11 -0
- data/lib/file.fy +8 -11
- data/lib/future.fy +84 -5
- data/lib/hash.fy +65 -14
- data/lib/integer.fy +35 -0
- data/lib/iteration.fy +54 -29
- data/lib/message.fy +6 -0
- data/lib/method.fy +0 -16
- data/lib/nil_class.fy +58 -8
- data/lib/number.fy +49 -22
- data/lib/object.fy +371 -65
- data/lib/package.fy +24 -1
- data/lib/package/installer.fy +5 -9
- data/lib/package/specification.fy +2 -2
- data/lib/parser/ext/lexer.lex +15 -11
- data/lib/parser/ext/parser.y +70 -23
- data/lib/parser/methods.fy +33 -14
- data/lib/proxy.fy +33 -3
- data/lib/range.fy +28 -0
- data/lib/rbx.fy +3 -1
- data/lib/rbx/actor.fy +53 -0
- data/lib/rbx/alpha.fy +31 -0
- data/lib/rbx/array.fy +21 -12
- data/lib/rbx/bignum.fy +6 -2
- data/lib/rbx/block.fy +23 -26
- data/lib/rbx/class.fy +54 -2
- data/lib/rbx/code_loader.fy +8 -4
- data/lib/rbx/date.fy +9 -0
- data/lib/rbx/directory.fy +18 -0
- data/lib/rbx/environment_variables.fy +1 -0
- data/lib/rbx/exception.fy +9 -2
- data/lib/rbx/fiber.fy +22 -4
- data/lib/rbx/file.fy +5 -5
- data/lib/rbx/fixnum.fy +5 -0
- data/lib/rbx/float.fy +11 -3
- data/lib/rbx/hash.fy +31 -16
- data/lib/rbx/integer.fy +1 -0
- data/lib/rbx/io.fy +17 -7
- data/lib/rbx/match_data.fy +15 -4
- data/lib/rbx/method.fy +40 -7
- data/lib/rbx/name_error.fy +4 -0
- data/lib/rbx/object.fy +92 -24
- data/lib/rbx/range.fy +20 -6
- data/lib/rbx/regexp.fy +11 -3
- data/lib/rbx/string.fy +51 -1
- data/lib/rbx/stringio.fy +17 -0
- data/lib/rbx/symbol.fy +15 -1
- data/lib/rbx/system.fy +20 -2
- data/lib/rbx/tcp_server.fy +4 -1
- data/lib/rbx/tcp_socket.fy +11 -0
- data/lib/rbx/time.fy +6 -0
- data/lib/rbx/tuple.fy +14 -5
- data/lib/set.fy +144 -29
- data/lib/stack.fy +42 -11
- data/lib/string.fy +118 -8
- data/lib/struct.fy +13 -3
- data/lib/symbol.fy +21 -2
- data/lib/thread_pool.fy +2 -1
- data/lib/true_class.fy +45 -7
- data/lib/tuple.fy +27 -9
- data/lib/version.fy +2 -2
- data/ruby_lib/fancy +43 -0
- data/ruby_lib/fdoc +23 -0
- data/ruby_lib/fspec +3 -0
- data/ruby_lib/fyi +3 -0
- data/ruby_lib/ifancy +3 -0
- data/tests/argv.fy +5 -9
- data/tests/array.fy +323 -196
- data/tests/assignment.fy +29 -29
- data/tests/block.fy +72 -59
- data/tests/class.fy +227 -138
- data/tests/control_flow.fy +83 -51
- data/tests/documentation.fy +8 -8
- data/tests/enumerable.fy +8 -0
- data/tests/enumerator.fy +47 -29
- data/tests/exception.fy +49 -32
- data/tests/file.fy +28 -28
- data/tests/fixnum.fy +170 -0
- data/tests/future.fy +24 -7
- data/tests/hash.fy +55 -38
- data/tests/method.fy +50 -43
- data/tests/nil_class.fy +37 -37
- data/tests/object.fy +152 -70
- data/tests/pattern_matching.fy +67 -31
- data/tests/range.fy +6 -6
- data/tests/set.fy +101 -4
- data/tests/stack.fy +14 -5
- data/tests/string.fy +115 -61
- data/tests/stringio.fy +18 -0
- data/tests/struct.fy +27 -0
- data/tests/symbol.fy +19 -6
- data/tests/true_class.fy +34 -34
- data/tests/tuple.fy +30 -12
- metadata +103 -81
- data/boot/rbx-compiler/compiler/ast/require.rb +0 -20
- data/examples/actor.fy +0 -37
- data/examples/curl_async.fy +0 -37
- data/lib/compiler/ast/require.fy +0 -15
- data/tests/number.fy +0 -135
- data/tests/parsing/sexp.fy +0 -50
data/tests/assignment.fy
CHANGED
@@ -1,53 +1,53 @@
|
|
1
1
|
FancySpec describe: "Assignment" with: {
|
2
|
-
it: "
|
2
|
+
it: "correctly assigns multiple values at once" when: {
|
3
3
|
x, y, z = 1, 10, 100
|
4
|
-
x
|
5
|
-
y
|
6
|
-
z
|
4
|
+
x is: 1
|
5
|
+
y is: 10
|
6
|
+
z is: 100
|
7
7
|
|
8
8
|
x, y, z = 'foo, 'bar
|
9
|
-
x
|
10
|
-
y
|
11
|
-
z
|
9
|
+
x is: 'foo
|
10
|
+
y is: 'bar
|
11
|
+
z is: nil
|
12
12
|
|
13
13
|
x = 'foo
|
14
14
|
y = 'bar
|
15
15
|
x, y = y, x
|
16
|
-
x
|
17
|
-
y
|
16
|
+
x is: 'bar
|
17
|
+
y is: 'foo
|
18
18
|
}
|
19
19
|
|
20
|
-
it: "
|
20
|
+
it: "handles multiple assignment for any collection type implementing 'at:" when: {
|
21
21
|
x, y, z = (1, 2, 3)
|
22
|
-
x
|
23
|
-
y
|
24
|
-
z
|
22
|
+
x is: 1
|
23
|
+
y is: 2
|
24
|
+
z is: 3
|
25
25
|
|
26
26
|
a, b, c = ["a", "b", "c"]
|
27
|
-
a
|
28
|
-
b
|
29
|
-
c
|
27
|
+
a is: "a"
|
28
|
+
b is: "b"
|
29
|
+
c is: "c"
|
30
30
|
|
31
31
|
e, f = ([1,2], "foo")
|
32
|
-
e
|
33
|
-
f
|
32
|
+
e is: [1,2]
|
33
|
+
f is: "foo"
|
34
34
|
}
|
35
35
|
|
36
|
-
it: "
|
36
|
+
it: "handles multiple assignment with splat-identifiers" when: {
|
37
37
|
x,y,z,*rest = [1,2,3,4,5,6,7]
|
38
|
-
x
|
39
|
-
y
|
40
|
-
z
|
41
|
-
rest
|
38
|
+
x is: 1
|
39
|
+
y is: 2
|
40
|
+
z is: 3
|
41
|
+
rest is: [4,5,6,7]
|
42
42
|
|
43
43
|
a,b,*c,*d,e = [1,2,3,4,5,6,7,8]
|
44
|
-
a
|
45
|
-
b
|
46
|
-
c
|
47
|
-
d
|
48
|
-
e
|
44
|
+
a is: 1
|
45
|
+
b is: 2
|
46
|
+
c is: [3,4,5,6,7,8]
|
47
|
+
d is: [4,5,6,7,8]
|
48
|
+
e is: 5
|
49
49
|
|
50
50
|
_,_,*z = "hello, world!" # ignore first 2 characters
|
51
|
-
z
|
51
|
+
z is: "llo, world!"
|
52
52
|
}
|
53
53
|
}
|
data/tests/block.fy
CHANGED
@@ -1,146 +1,146 @@
|
|
1
1
|
FancySpec describe: Block with: {
|
2
|
-
it: "
|
2
|
+
it: "returns the value of the last expression" when: {
|
3
3
|
block = {
|
4
4
|
a = "a"
|
5
5
|
empty = " "
|
6
6
|
str = "String!"
|
7
7
|
a ++ empty ++ str
|
8
8
|
}
|
9
|
-
block call
|
9
|
+
block call is: "a String!"
|
10
10
|
}
|
11
11
|
|
12
|
-
it: "
|
12
|
+
it: "closes over a value and change it internally" when: {
|
13
13
|
x = 0
|
14
14
|
{ x < 10 } while_true: {
|
15
|
-
x
|
15
|
+
x is be: |x| { x < 10 }
|
16
16
|
x = x + 1
|
17
17
|
}
|
18
|
-
x
|
18
|
+
x is: 10
|
19
19
|
}
|
20
20
|
|
21
|
-
it: "
|
22
|
-
{ }
|
23
|
-
|x| { }
|
24
|
-
|x y z| { }
|
21
|
+
it: "returns the argument count" with: 'arity when: {
|
22
|
+
{ } arity . is: 0
|
23
|
+
|x| { } arity . is: 1
|
24
|
+
|x y z| { } arity . is: 3
|
25
25
|
}
|
26
26
|
|
27
|
-
it: "
|
27
|
+
it: "calls a block while another is true" with: 'while_true: when: {
|
28
28
|
i = 0
|
29
29
|
{i < 10} while_true: {
|
30
30
|
i = i + 1
|
31
31
|
}
|
32
|
-
i
|
32
|
+
i is be: { i >= 10 }
|
33
33
|
}
|
34
34
|
|
35
|
-
it: "
|
35
|
+
it: "calls a block while another is not true (boolean false)" with: 'while_false: when: {
|
36
36
|
i = 0
|
37
37
|
{i == 10} while_false: {
|
38
38
|
i = i + 1
|
39
39
|
}
|
40
|
-
i
|
40
|
+
i is: 10
|
41
41
|
}
|
42
42
|
|
43
43
|
# again for while_nil
|
44
|
-
it: "
|
44
|
+
it: "calls a block while another is nil" with: 'while_nil: when: {
|
45
45
|
i = 0
|
46
46
|
{i == 10} while_nil: {
|
47
47
|
i = i + 1
|
48
48
|
}
|
49
|
-
i
|
49
|
+
i is: 10
|
50
50
|
}
|
51
51
|
|
52
|
-
it: "
|
52
|
+
it: "calls a block while another one is true-ish" with: 'while_do: when: {
|
53
53
|
x = 0
|
54
54
|
{ x < 10 } while_do: |val| {
|
55
|
-
val
|
55
|
+
val is: true
|
56
56
|
x = x + 1
|
57
57
|
}
|
58
58
|
}
|
59
59
|
|
60
|
-
it: "
|
60
|
+
it: "calls another block while a block yields false" with: 'until_do: when: {
|
61
61
|
i = 0
|
62
|
-
{ i > 10 } until_do: { i <= 10
|
63
|
-
i
|
62
|
+
{ i > 10 } until_do: { i <= 10 is: true; i = i + 1 }
|
63
|
+
i is: 11
|
64
64
|
}
|
65
65
|
|
66
|
-
it: "
|
66
|
+
it: "calls a block until another yields true" with: 'until: when: {
|
67
67
|
i = 0
|
68
|
-
{ i <= 10
|
69
|
-
i
|
68
|
+
{ i <= 10 is: true; i = i + 1 } until: { i > 10 }
|
69
|
+
i is: 11
|
70
70
|
}
|
71
71
|
|
72
|
-
it: "
|
72
|
+
it: "calls itself only when the argument is nil" with: 'unless: when: {
|
73
73
|
try {
|
74
74
|
{ StdError new: "got_run!" . raise! } unless: nil
|
75
75
|
StdError new: "didnt_run!" . raise!
|
76
76
|
} catch StdError => e {
|
77
|
-
e message
|
77
|
+
e message is: "got_run!"
|
78
78
|
}
|
79
79
|
}
|
80
80
|
|
81
|
-
it: "
|
81
|
+
it: "calls itself only when the argument is true" with: 'if: when: {
|
82
82
|
try {
|
83
83
|
{ StdError new: "got_run!" . raise! } if: true
|
84
84
|
StdError new: "didnt_run!" . raise!
|
85
85
|
} catch StdError => e {
|
86
|
-
e message
|
86
|
+
e message is: "got_run!"
|
87
87
|
}
|
88
88
|
}
|
89
89
|
|
90
|
-
it: "
|
90
|
+
it: "also is able to take arguments seperated by comma" with: 'call: when: {
|
91
91
|
block = |x, y| { x + y }
|
92
|
-
block call: [1,2] .
|
92
|
+
block call: [1,2] . is: 3
|
93
93
|
}
|
94
94
|
|
95
|
-
it: "
|
96
|
-
{ false } && { false }
|
97
|
-
{ true } && { false }
|
98
|
-
{ false } && { true }
|
99
|
-
{ true } && { true }
|
95
|
+
it: "evaluates the blocks in a short-circuiting manner" with: '&& when: {
|
96
|
+
{ false } && { false } is: false
|
97
|
+
{ true } && { false } is: false
|
98
|
+
{ false } && { true } is: false
|
99
|
+
{ true } && { true } is: true
|
100
100
|
|
101
|
-
{ false } || { false }
|
102
|
-
{ false } || { true }
|
103
|
-
{ true } || { false }
|
104
|
-
{ true } || { true }
|
101
|
+
{ false } || { false } is: false
|
102
|
+
{ false } || { true } is: true
|
103
|
+
{ true } || { false } is: true
|
104
|
+
{ true } || { true } is: true
|
105
105
|
|
106
106
|
# TODO: Add more useful tests here...
|
107
107
|
}
|
108
108
|
|
109
|
-
it: "
|
110
|
-
[1,2,3] map: @{upto: 3} .
|
111
|
-
[1,2,3] map: @{+ 3} .
|
112
|
-
[1,2,3] map: @{to_s} .
|
113
|
-
[1,2,3] map: @{to_s * 3} .
|
109
|
+
it: "calls the block as a partial block" when: {
|
110
|
+
[1,2,3] map: @{upto: 3} . is: [[1,2,3], [2,3], [3]]
|
111
|
+
[1,2,3] map: @{+ 3} . is: [4,5,6]
|
112
|
+
[1,2,3] map: @{to_s} . is: ["1", "2", "3"]
|
113
|
+
[1,2,3] map: @{to_s * 3} . is: ["111", "222", "333"]
|
114
114
|
}
|
115
115
|
|
116
|
-
it: "
|
116
|
+
it: "executes a match clause if the block returns a true-ish value" with: '=== when: {
|
117
117
|
def do_match: val {
|
118
118
|
match val {
|
119
119
|
case |x| { x even? } -> "yup, it's even"
|
120
120
|
case _ -> "nope, not even"
|
121
121
|
}
|
122
122
|
}
|
123
|
-
do_match: 2 .
|
124
|
-
do_match: 1 .
|
123
|
+
do_match: 2 . is: "yup, it's even"
|
124
|
+
do_match: 1 . is: "nope, not even"
|
125
125
|
}
|
126
126
|
|
127
|
-
it: "
|
127
|
+
it: "returns the receiver of a block" with: 'receiver when: {
|
128
128
|
class Foo { def foo { { self } } } # return block
|
129
129
|
f = Foo new
|
130
|
-
f foo receiver
|
130
|
+
f foo receiver is: f
|
131
131
|
}
|
132
132
|
|
133
|
-
it: "
|
133
|
+
it: "sets the receiver correctly to a new value" with: 'receiver: when: {
|
134
134
|
b = { "hey" }
|
135
135
|
|
136
136
|
b receiver: 10
|
137
|
-
b receiver
|
137
|
+
b receiver is: 10
|
138
138
|
|
139
139
|
b receiver: "Hello, World!"
|
140
|
-
b receiver
|
140
|
+
b receiver is: "Hello, World!"
|
141
141
|
}
|
142
142
|
|
143
|
-
it: "
|
143
|
+
it: "calls a block with a different receiver" with: 'call_with_receiver: when: {
|
144
144
|
class ClassA {
|
145
145
|
def inspect {
|
146
146
|
"in ClassA#inspect"
|
@@ -157,12 +157,12 @@ FancySpec describe: Block with: {
|
|
157
157
|
block = {
|
158
158
|
self inspect
|
159
159
|
}
|
160
|
-
block call
|
161
|
-
block call_with_receiver: (ClassA new) .
|
162
|
-
block call_with_receiver: (ClassB new) .
|
160
|
+
block call is: "in self#inspect"
|
161
|
+
block call_with_receiver: (ClassA new) . is: "in ClassA#inspect"
|
162
|
+
block call_with_receiver: (ClassB new) . is: "in ClassB#inspect"
|
163
163
|
}
|
164
164
|
|
165
|
-
it: "
|
165
|
+
it: "calls a block with arguments and a different receiver" with: 'call:with_receiver: when: {
|
166
166
|
class ClassC {
|
167
167
|
def inspect: x {
|
168
168
|
"in ClassC#inspect: #{x}"
|
@@ -179,8 +179,21 @@ FancySpec describe: Block with: {
|
|
179
179
|
block = |arg| {
|
180
180
|
self inspect: arg
|
181
181
|
}
|
182
|
-
block call: [42] .
|
183
|
-
block call: [42] with_receiver: (ClassC new) .
|
184
|
-
block call: [42] with_receiver: (ClassD new) .
|
182
|
+
block call: [42] . is: "in self#inspect: 42"
|
183
|
+
block call: [42] with_receiver: (ClassC new) . is: "in ClassC#inspect: 42"
|
184
|
+
block call: [42] with_receiver: (ClassD new) . is: "in ClassD#inspect: 42"
|
185
|
+
}
|
186
|
+
|
187
|
+
it: "calls a block using the ruby-send syntax" with: 'call: when: {
|
188
|
+
b = |x y| {
|
189
|
+
x + y
|
190
|
+
}
|
191
|
+
|
192
|
+
b call: [2,3] . is: 5
|
193
|
+
b(2,3) . is: 5
|
194
|
+
|
195
|
+
b2 = |x| { x * 5 }
|
196
|
+
b2("hello") is: ("hello" * 5)
|
197
|
+
b2("foo") is: (b2 call: ["foo"])
|
185
198
|
}
|
186
199
|
}
|
data/tests/class.fy
CHANGED
@@ -25,98 +25,100 @@ class ClassWithPrivate {
|
|
25
25
|
"public!"
|
26
26
|
}
|
27
27
|
|
28
|
-
def
|
28
|
+
def protected_method {
|
29
29
|
"protected!"
|
30
30
|
}
|
31
|
+
protected: 'protected_method
|
31
32
|
|
32
|
-
def
|
33
|
+
def private_method {
|
33
34
|
"private!"
|
34
35
|
}
|
36
|
+
private: 'private_method
|
35
37
|
}
|
36
38
|
|
37
39
|
FancySpec describe: Class with: {
|
38
|
-
it: "
|
40
|
+
it: "does NOT find the method when not mixed-in" with: 'responds_to?: when: {
|
39
41
|
instance = ClassWithMixin new
|
40
|
-
instance normal_method .
|
41
|
-
instance responds_to?: 'normal_method .
|
42
|
-
instance responds_to?: 'mixin_method .
|
42
|
+
instance normal_method . is: 'normal_found
|
43
|
+
instance responds_to?: 'normal_method . is: true
|
44
|
+
instance responds_to?: 'mixin_method . is: false
|
43
45
|
}
|
44
46
|
|
45
|
-
it: "
|
47
|
+
it: "finds the method when mixed-in" with: 'include: when: {
|
46
48
|
# => include Mixin into ClassWithMixin
|
47
49
|
class ClassWithMixin {
|
48
50
|
include: Mixin
|
49
51
|
}
|
50
52
|
|
51
53
|
instance = ClassWithMixin new
|
52
|
-
instance responds_to?: 'normal_method .
|
53
|
-
instance responds_to?: 'mixin_method .
|
54
|
-
instance normal_method .
|
55
|
-
instance mixin_method .
|
54
|
+
instance responds_to?: 'normal_method . is: true
|
55
|
+
instance responds_to?: 'mixin_method . is: true
|
56
|
+
instance normal_method . is: 'normal_found
|
57
|
+
instance mixin_method . is: 'mixed_in_found
|
56
58
|
}
|
57
59
|
|
58
|
-
it: "
|
60
|
+
it: "rebinds the old class name with ClassWithNoMixin and replace the old normal_method" when: {
|
59
61
|
instance = ClassWithMixin new
|
60
|
-
instance normal_method
|
62
|
+
instance normal_method is: 'normal_found
|
61
63
|
# rebind the class to the other class
|
62
64
|
ClassWithMixin = ClassWithNoMixin
|
63
65
|
instance = ClassWithMixin new
|
64
|
-
instance normal_method
|
66
|
+
instance normal_method is: 'new_normal_found
|
65
67
|
}
|
66
68
|
|
67
|
-
it: "
|
69
|
+
it: "has dynamically generated getter and setter methods" with: 'responds_to?: when: {
|
68
70
|
instance = ClassWithNoMixin new
|
69
|
-
instance responds_to?: 'foo .
|
70
|
-
instance responds_to?: 'bar .
|
71
|
-
instance responds_to?: 'baz .
|
72
|
-
instance responds_to?: "hello:" .
|
73
|
-
instance responds_to?: "world:" .
|
74
|
-
instance responds_to?: 'oh .
|
75
|
-
instance responds_to?: ":oh" .
|
76
|
-
instance responds_to?: 'noes .
|
77
|
-
instance responds_to?: "noes:" .
|
78
|
-
}
|
79
|
-
|
80
|
-
it: "
|
71
|
+
instance responds_to?: 'foo . is: true
|
72
|
+
instance responds_to?: 'bar . is: true
|
73
|
+
instance responds_to?: 'baz . is: true
|
74
|
+
instance responds_to?: "hello:" . is: true
|
75
|
+
instance responds_to?: "world:" . is: true
|
76
|
+
instance responds_to?: 'oh . is: true
|
77
|
+
instance responds_to?: ":oh" . is: true
|
78
|
+
instance responds_to?: 'noes . is: true
|
79
|
+
instance responds_to?: "noes:" . is: true
|
80
|
+
}
|
81
|
+
|
82
|
+
it: "defines getter methods for single slots" with: 'read_slot: when: {
|
81
83
|
class Getters {
|
82
84
|
read_slot: 'foo
|
83
85
|
read_slot: 'bar
|
84
86
|
}
|
85
87
|
|
86
88
|
g = Getters new
|
87
|
-
g responds_to?: 'foo .
|
88
|
-
g responds_to?: 'foo: .
|
89
|
-
g responds_to?: 'bar .
|
90
|
-
g responds_to?: 'bar: .
|
89
|
+
g responds_to?: 'foo . is: true
|
90
|
+
g responds_to?: 'foo: . is: false
|
91
|
+
g responds_to?: 'bar . is: true
|
92
|
+
g responds_to?: 'bar: . is: false
|
91
93
|
}
|
92
94
|
|
93
|
-
it: "
|
95
|
+
it: "defines setter methods for single slots" with: 'write_slot: when: {
|
94
96
|
class Setters {
|
95
97
|
write_slot: 'foo
|
96
98
|
write_slot: 'bar
|
97
99
|
}
|
98
100
|
|
99
101
|
s = Setters new
|
100
|
-
s responds_to?: 'foo .
|
101
|
-
s responds_to?: 'foo: .
|
102
|
-
s responds_to?: 'bar .
|
103
|
-
s responds_to?: 'bar: .
|
102
|
+
s responds_to?: 'foo . is: false
|
103
|
+
s responds_to?: 'foo: . is: true
|
104
|
+
s responds_to?: 'bar . is: false
|
105
|
+
s responds_to?: 'bar: . is: true
|
104
106
|
}
|
105
107
|
|
106
|
-
it: "
|
108
|
+
it: "defines getter & setter methods for single slots" with: 'read_write_slot: when: {
|
107
109
|
class GettersAndSetters {
|
108
110
|
read_write_slot: 'foo
|
109
111
|
read_write_slot: 'bar
|
110
112
|
}
|
111
113
|
|
112
114
|
gs = GettersAndSetters new
|
113
|
-
gs responds_to?: 'foo .
|
114
|
-
gs responds_to?: 'foo: .
|
115
|
-
gs responds_to?: 'bar .
|
116
|
-
gs responds_to?: 'bar: .
|
115
|
+
gs responds_to?: 'foo . is: true
|
116
|
+
gs responds_to?: 'foo: . is: true
|
117
|
+
gs responds_to?: 'bar . is: true
|
118
|
+
gs responds_to?: 'bar: . is: true
|
117
119
|
}
|
118
120
|
|
119
|
-
it: "
|
121
|
+
it: "finds the instance variable correctly" when: {
|
120
122
|
class AClass {
|
121
123
|
def initialize: foo {
|
122
124
|
@foo = foo
|
@@ -128,11 +130,11 @@ FancySpec describe: Class with: {
|
|
128
130
|
|
129
131
|
str = "instance value"
|
130
132
|
instance = AClass new: str
|
131
|
-
instance foo
|
132
|
-
AClass new foo
|
133
|
+
instance foo is: str
|
134
|
+
AClass new foo is: nil
|
133
135
|
}
|
134
136
|
|
135
|
-
it: "
|
137
|
+
it: "finds the class variable correctly" when: {
|
136
138
|
class AClass {
|
137
139
|
def foo: foo {
|
138
140
|
@@foo = foo
|
@@ -146,17 +148,17 @@ FancySpec describe: Class with: {
|
|
146
148
|
instance2 = AClass new
|
147
149
|
str = "class value"
|
148
150
|
instance1 foo: str
|
149
|
-
instance1 foo
|
150
|
-
instance2 foo
|
151
|
-
instance2 foo
|
151
|
+
instance1 foo is: str
|
152
|
+
instance2 foo is: str
|
153
|
+
instance2 foo is: (instance1 foo)
|
152
154
|
|
153
155
|
str2 = "another value"
|
154
156
|
instance2 foo: str2
|
155
|
-
instance2 foo
|
156
|
-
instance1 foo
|
157
|
+
instance2 foo is: str2
|
158
|
+
instance1 foo is: str2
|
157
159
|
}
|
158
160
|
|
159
|
-
it: "
|
161
|
+
it: "has correct method overloading for method names with and without an argument" when: {
|
160
162
|
class AClass {
|
161
163
|
def foo {
|
162
164
|
foo: "None!"
|
@@ -168,11 +170,11 @@ FancySpec describe: Class with: {
|
|
168
170
|
}
|
169
171
|
|
170
172
|
instance = AClass new
|
171
|
-
instance foo
|
172
|
-
instance foo: "Test!" .
|
173
|
+
instance foo is: "In AClass#foo: with bar = None!"
|
174
|
+
instance foo: "Test!" . is: "In AClass#foo: with bar = Test!"
|
173
175
|
}
|
174
176
|
|
175
|
-
it: "
|
177
|
+
it: "calls a superclass method by using super" when: {
|
176
178
|
class SuperClass {
|
177
179
|
read_slots: ['name]
|
178
180
|
def initialize: name {
|
@@ -193,76 +195,76 @@ FancySpec describe: Class with: {
|
|
193
195
|
}
|
194
196
|
|
195
197
|
sub = SubClass new: 42
|
196
|
-
sub name
|
197
|
-
sub age
|
198
|
+
sub name is: "SubClass"
|
199
|
+
sub age is: 42
|
198
200
|
|
199
201
|
sub2 = SubClass new
|
200
|
-
sub2 name
|
201
|
-
sub2 age
|
202
|
+
sub2 name is: "SubClass"
|
203
|
+
sub2 age is: 0
|
202
204
|
}
|
203
205
|
|
204
|
-
it: "
|
205
|
-
Fixnum superclass
|
206
|
-
Symbol superclass
|
207
|
-
StdError superclass
|
208
|
-
Class superclass
|
209
|
-
Object superclass
|
206
|
+
it: "returns its superclass" when: {
|
207
|
+
Fixnum superclass is: Integer
|
208
|
+
Symbol superclass is: Object
|
209
|
+
StdError superclass is: Exception
|
210
|
+
Class superclass is: Module
|
211
|
+
Object superclass is: nil
|
210
212
|
|
211
|
-
IOError superclass
|
212
|
-
NoMethodError superclass
|
213
|
+
IOError superclass is: StandardError
|
214
|
+
NoMethodError superclass is: NameError
|
213
215
|
}
|
214
216
|
|
215
|
-
it: "
|
217
|
+
it: "creates a new Class dynamically" when: {
|
216
218
|
x = Class new
|
217
|
-
x is_a?: Class .
|
218
|
-
x new is_a?: x .
|
219
|
-
x new is_a?: Object .
|
220
|
-
x new class
|
219
|
+
x is_a?: Class . is: true
|
220
|
+
x new is_a?: x . is: true
|
221
|
+
x new is_a?: Object . is: true
|
222
|
+
x new class is: x
|
221
223
|
|
222
224
|
# Symbol as superclass
|
223
225
|
y = Class new: String
|
224
|
-
y is_a?: Class .
|
225
|
-
y new is_a?: String .
|
226
|
-
|
226
|
+
y is_a?: Class . is: true
|
227
|
+
y new is_a?: String . is: true
|
228
|
+
y new is_a?: Object . is: true
|
227
229
|
}
|
228
230
|
|
229
|
-
it: "
|
231
|
+
it: "only is able to call the public method from outside the Class" when: {
|
230
232
|
x = ClassWithPrivate new
|
231
|
-
x public_method
|
233
|
+
x public_method is: "public!"
|
232
234
|
try {
|
233
|
-
x private_method
|
235
|
+
x private_method is: nil # is fail
|
234
236
|
} catch NoMethodError => e {
|
235
|
-
e method_name
|
237
|
+
e method_name is: 'private_method
|
236
238
|
}
|
237
239
|
try {
|
238
|
-
x protected_method
|
240
|
+
x protected_method is: nil # is fail
|
239
241
|
} catch NoMethodError => e {
|
240
|
-
e method_name
|
242
|
+
e method_name is: 'protected_method
|
241
243
|
}
|
242
244
|
}
|
243
245
|
|
244
|
-
it: "
|
246
|
+
it: "is a subclass of another Class" with: 'subclass?: when: {
|
245
247
|
class Super {
|
246
248
|
}
|
247
249
|
class Sub : Super {
|
248
250
|
}
|
249
251
|
|
250
|
-
Super subclass?: Object .
|
251
|
-
Sub subclass?: Object .
|
252
|
-
Sub subclass?: Super .
|
253
|
-
Super subclass?: Sub .
|
252
|
+
Super subclass?: Object . is: true
|
253
|
+
Sub subclass?: Object . is: true
|
254
|
+
Sub subclass?: Super . is: true
|
255
|
+
Super subclass?: Sub . is: nil
|
254
256
|
}
|
255
257
|
|
256
|
-
it: "
|
258
|
+
it: "dynamically creates a subclass of another class" with: 'is_a?: when: {
|
257
259
|
subclass = String subclass: {
|
258
260
|
def foo {
|
259
261
|
"hello, world!"
|
260
262
|
}
|
261
263
|
}
|
262
|
-
subclass is_a?: Class .
|
263
|
-
subclass subclass?: String .
|
264
|
-
subclass new is_a?: subclass .
|
265
|
-
subclass new foo
|
264
|
+
subclass is_a?: Class . is: true
|
265
|
+
subclass subclass?: String . is: true
|
266
|
+
subclass new is_a?: subclass . is: true
|
267
|
+
subclass new foo is: "hello, world!"
|
266
268
|
|
267
269
|
# now the same with Class##new:body:
|
268
270
|
subclass2 = Class superclass: String body: {
|
@@ -270,53 +272,53 @@ FancySpec describe: Class with: {
|
|
270
272
|
"hello, world, again!"
|
271
273
|
}
|
272
274
|
}
|
273
|
-
subclass2 is_a?: Class .
|
274
|
-
subclass2 subclass?: String .
|
275
|
-
subclass2 new is_a?: subclass2 .
|
276
|
-
subclass2 new foo
|
275
|
+
subclass2 is_a?: Class . is: true
|
276
|
+
subclass2 subclass?: String . is: true
|
277
|
+
subclass2 new is_a?: subclass2 . is: true
|
278
|
+
subclass2 new foo is: "hello, world, again!"
|
277
279
|
}
|
278
280
|
|
279
|
-
it: "
|
281
|
+
it: "undefines an instance method" with: 'undefine_method: when: {
|
280
282
|
class Foo {
|
281
283
|
def instance_method {
|
282
284
|
"instance method!"
|
283
285
|
}
|
284
286
|
}
|
285
287
|
f = Foo new
|
286
|
-
f instance_method
|
288
|
+
f instance_method is: "instance method!"
|
287
289
|
Foo undefine_method: 'instance_method
|
288
290
|
try {
|
289
|
-
f instance_method
|
291
|
+
f instance_method is: nil # is not get here
|
290
292
|
} catch NoMethodError => e {
|
291
|
-
e method_name
|
293
|
+
e method_name is: 'instance_method
|
292
294
|
}
|
293
295
|
}
|
294
296
|
|
295
|
-
it: "
|
297
|
+
it: "undefines a class method" with: 'undefine_class_method: when: {
|
296
298
|
class Foo {
|
297
299
|
def self class_method {
|
298
300
|
"class method!"
|
299
301
|
}
|
300
302
|
}
|
301
|
-
Foo class_method
|
303
|
+
Foo class_method is: "class method!"
|
302
304
|
|
303
305
|
try {
|
304
306
|
Foo undefine_method: 'class_method
|
305
|
-
true
|
307
|
+
true is: nil # is not happen
|
306
308
|
} catch NameError {
|
307
|
-
true
|
309
|
+
true is: true
|
308
310
|
}
|
309
311
|
|
310
312
|
Foo undefine_class_method: 'class_method
|
311
313
|
|
312
314
|
try {
|
313
|
-
Foo class_method
|
315
|
+
Foo class_method is: nil # is not get here
|
314
316
|
} catch NoMethodError => e {
|
315
|
-
e method_name
|
317
|
+
e method_name is: 'class_method
|
316
318
|
}
|
317
319
|
}
|
318
320
|
|
319
|
-
it: "
|
321
|
+
it: "has nested classes" when: {
|
320
322
|
class Outer {
|
321
323
|
class Inner {
|
322
324
|
class InnerMost {
|
@@ -326,11 +328,11 @@ FancySpec describe: Class with: {
|
|
326
328
|
}
|
327
329
|
}
|
328
330
|
}
|
329
|
-
Outer is_a?: Class .
|
330
|
-
Outer
|
331
|
-
Outer
|
332
|
-
obj = Outer
|
333
|
-
obj foobar
|
331
|
+
Outer is_a?: Class . is: true
|
332
|
+
Outer Inner is_a?: Class . is: true
|
333
|
+
Outer Inner InnerMost is_a?: Class . is: true
|
334
|
+
obj = Outer Inner InnerMost new
|
335
|
+
obj foobar is: "foobar!"
|
334
336
|
|
335
337
|
# change InnerMost#foobar
|
336
338
|
class Outer::Inner::InnerMost {
|
@@ -338,10 +340,10 @@ FancySpec describe: Class with: {
|
|
338
340
|
"oh no!"
|
339
341
|
}
|
340
342
|
}
|
341
|
-
obj foobar
|
343
|
+
obj foobar is: "oh no!"
|
342
344
|
}
|
343
345
|
|
344
|
-
it: "
|
346
|
+
it: "does not override existing classes with the same name in a nested class" when: {
|
345
347
|
StdArray = Array
|
346
348
|
class NameSpace {
|
347
349
|
class Array {
|
@@ -351,29 +353,29 @@ FancySpec describe: Class with: {
|
|
351
353
|
}
|
352
354
|
}
|
353
355
|
|
354
|
-
NameSpace
|
355
|
-
NameSpace
|
356
|
+
NameSpace Array what_am_i is: "not the same as the standard Array class"
|
357
|
+
NameSpace Array is_not: Array
|
356
358
|
}
|
357
359
|
|
358
|
-
# it: "
|
360
|
+
# it: "returns all nested classes of a class" with: 'nested_classes when: {
|
359
361
|
# class Outer {
|
360
362
|
# }
|
361
|
-
# Outer nested_classes
|
363
|
+
# Outer nested_classes is: []
|
362
364
|
|
363
365
|
# class Outer {
|
364
366
|
# class Inner1 {
|
365
367
|
# }
|
366
368
|
# }
|
367
|
-
# Outer nested_classes
|
369
|
+
# Outer nested_classes is: [Outer::Inner1]
|
368
370
|
|
369
371
|
# class Outer {
|
370
372
|
# class Inner2 {
|
371
373
|
# }
|
372
374
|
# }
|
373
|
-
# Outer nested_classes
|
375
|
+
# Outer nested_classes is: [Outer Inner1, Outer Inner2]
|
374
376
|
# }
|
375
377
|
|
376
|
-
it: "
|
378
|
+
it: "finds other nested classes in the same parent class" when: {
|
377
379
|
class MyOuter {
|
378
380
|
class Inner1 {
|
379
381
|
def method1 {
|
@@ -388,12 +390,12 @@ FancySpec describe: Class with: {
|
|
388
390
|
}
|
389
391
|
}
|
390
392
|
|
391
|
-
MyOuter
|
392
|
-
MyOuter
|
393
|
-
MyOuter
|
393
|
+
MyOuter Inner1 new method1 is: 'method_1
|
394
|
+
MyOuter Inner2 new method1 is: 'method_1
|
395
|
+
MyOuter Inner2 new method2 is: 'method_2
|
394
396
|
}
|
395
397
|
|
396
|
-
it: "
|
398
|
+
it: "finds itself in it's own methods, even if nested into another class" when: {
|
397
399
|
class MyOuter {
|
398
400
|
class MyInner1 {
|
399
401
|
def method1 {
|
@@ -413,13 +415,13 @@ FancySpec describe: Class with: {
|
|
413
415
|
}
|
414
416
|
}
|
415
417
|
|
416
|
-
MyOuter
|
417
|
-
MyOuter
|
418
|
-
MyOuter
|
419
|
-
MyOuter
|
418
|
+
MyOuter MyInner1 new method1 is: MyOuter MyInner1
|
419
|
+
MyOuter MyInner2 new method2 is: [MyOuter MyInner1, MyOuter MyInner2]
|
420
|
+
MyOuter MyInner1 class_method1 is: MyOuter MyInner1
|
421
|
+
MyOuter MyInner2 class_method2 is: [MyOuter MyInner1, MyOuter MyInner2]
|
420
422
|
}
|
421
423
|
|
422
|
-
it: "
|
424
|
+
it: "has an alias method as defined" with: 'alias_method:for: when: {
|
423
425
|
class AClass {
|
424
426
|
def foo {
|
425
427
|
"in foo!"
|
@@ -429,25 +431,25 @@ FancySpec describe: Class with: {
|
|
429
431
|
}
|
430
432
|
|
431
433
|
obj = AClass new
|
432
|
-
obj foo
|
433
|
-
obj bar
|
434
|
+
obj foo is: "in foo!"
|
435
|
+
obj bar is: "in foo!"
|
434
436
|
}
|
435
437
|
|
436
|
-
it: "
|
438
|
+
it: "has an alias method for a ruby method defined" with: 'alias_method:for_ruby: when: {
|
437
439
|
try {
|
438
|
-
[] equal?: [1,2] .
|
440
|
+
[] equal?: [1,2] . is: true # is fail
|
439
441
|
} catch NoMethodError => e {
|
440
|
-
e method_name
|
442
|
+
e method_name is: 'equal?:
|
441
443
|
}
|
442
444
|
|
443
445
|
class Array {
|
444
446
|
alias_method: 'equal?: for_ruby: 'equal?
|
445
447
|
}
|
446
448
|
|
447
|
-
[] equal?: [1,2] .
|
449
|
+
[] equal?: [1,2] . is: false
|
448
450
|
}
|
449
451
|
|
450
|
-
it: "
|
452
|
+
it: "has the correct list of ancestors" with: 'ancestors when: {
|
451
453
|
class A {
|
452
454
|
}
|
453
455
|
class B : A {
|
@@ -455,8 +457,95 @@ FancySpec describe: Class with: {
|
|
455
457
|
class C : B {
|
456
458
|
}
|
457
459
|
|
458
|
-
A ancestors
|
459
|
-
B ancestors
|
460
|
-
C ancestors
|
460
|
+
A ancestors is: [A, Object, Kernel]
|
461
|
+
B ancestors is: [B, A, Object, Kernel]
|
462
|
+
C ancestors is: [C, B, A, Object, Kernel]
|
463
|
+
}
|
464
|
+
|
465
|
+
it: "makes methods private" with: 'private: when: {
|
466
|
+
class AClassWithPrivateMethods {
|
467
|
+
def a {
|
468
|
+
"in a"
|
469
|
+
}
|
470
|
+
def b {
|
471
|
+
"in b"
|
472
|
+
}
|
473
|
+
private: ['a, 'b]
|
474
|
+
}
|
475
|
+
|
476
|
+
x = AClassWithPrivateMethods new
|
477
|
+
{ x a } raises: NoMethodError
|
478
|
+
{ x b } raises: NoMethodError
|
479
|
+
AClassWithPrivateMethods instance_method: 'a . private? is: true
|
480
|
+
AClassWithPrivateMethods instance_method: 'b . private? is: true
|
481
|
+
}
|
482
|
+
|
483
|
+
it: "makes methods protected" with: 'protected: when: {
|
484
|
+
class AClassWithProtectedMethods {
|
485
|
+
def a {
|
486
|
+
"in a"
|
487
|
+
}
|
488
|
+
def b {
|
489
|
+
"in b"
|
490
|
+
}
|
491
|
+
protected: ['a, 'b]
|
492
|
+
}
|
493
|
+
|
494
|
+
x = AClassWithProtectedMethods new
|
495
|
+
{ x a } raises: NoMethodError
|
496
|
+
{ x b } raises: NoMethodError
|
497
|
+
AClassWithProtectedMethods instance_method: 'a . private? is: false
|
498
|
+
AClassWithProtectedMethods instance_method: 'b . private? is: false
|
499
|
+
AClassWithProtectedMethods instance_method: 'a . protected? is: true
|
500
|
+
AClassWithProtectedMethods instance_method: 'b . protected? is: true
|
501
|
+
}
|
502
|
+
|
503
|
+
it: "makes methods public" with: 'public: when: {
|
504
|
+
class AClassWithPublicMethods {
|
505
|
+
def a {
|
506
|
+
"in a"
|
507
|
+
}
|
508
|
+
def b {
|
509
|
+
"in b"
|
510
|
+
}
|
511
|
+
private: ['a, 'b]
|
512
|
+
public: ['a, 'b] # making sure Class#public: works.
|
513
|
+
}
|
514
|
+
|
515
|
+
x = AClassWithPublicMethods new
|
516
|
+
{ x a } does_not raise: NoMethodError
|
517
|
+
{ x b } does_not raise: NoMethodError
|
518
|
+
AClassWithPublicMethods instance_method: 'a . private? is: false
|
519
|
+
AClassWithPublicMethods instance_method: 'b . private? is: false
|
520
|
+
AClassWithPublicMethods instance_method: 'a . protected? is: false
|
521
|
+
AClassWithPublicMethods instance_method: 'b . protected? is: false
|
522
|
+
AClassWithPublicMethods instance_method: 'a . public? is: true
|
523
|
+
AClassWithPublicMethods instance_method: 'b . public? is: true
|
524
|
+
}
|
525
|
+
|
526
|
+
it: "defines a class without a body" when: {
|
527
|
+
class Foo
|
528
|
+
Foo is_a?: Class . is: true
|
529
|
+
Foo new is_a?: Foo . is: true
|
530
|
+
|
531
|
+
class FooNew : Foo
|
532
|
+
FooNew is_a?: Class . is: true
|
533
|
+
FooNew ancestors includes?: Foo . is: true
|
534
|
+
FooNew new is_a?: Foo . is: true
|
535
|
+
}
|
536
|
+
|
537
|
+
it: "defines a class with empty methods" when: {
|
538
|
+
class Foo
|
539
|
+
class Bar : Foo {
|
540
|
+
def initialize: @bar
|
541
|
+
def empty_method
|
542
|
+
def to_s {
|
543
|
+
@bar + "bar"
|
544
|
+
}
|
545
|
+
}
|
546
|
+
|
547
|
+
b = Bar new: "foo"
|
548
|
+
b to_s is: "foobar"
|
549
|
+
b empty_method is: nil
|
461
550
|
}
|
462
551
|
}
|