fancy 0.3.0
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/AUTHORS +7 -0
- data/LICENSE +19 -0
- data/README +173 -0
- data/Rakefile +255 -0
- data/bin/fancy +40 -0
- data/bin/fdoc +23 -0
- data/bin/fyi +22 -0
- data/bin/ifancy +46 -0
- data/boot/README +12 -0
- data/boot/code_loader.rb +165 -0
- data/boot/compile.fy +3 -0
- data/boot/fancy_ext.rb +13 -0
- data/boot/fancy_ext/block_env.rb +29 -0
- data/boot/fancy_ext/class.rb +26 -0
- data/boot/fancy_ext/kernel.rb +12 -0
- data/boot/fancy_ext/module.rb +89 -0
- data/boot/fancy_ext/object.rb +34 -0
- data/boot/fancy_ext/string_helper.rb +10 -0
- data/boot/load.rb +72 -0
- data/boot/rbx-compiler/README +12 -0
- data/boot/rbx-compiler/compiler.rb +24 -0
- data/boot/rbx-compiler/compiler/ast.rb +23 -0
- data/boot/rbx-compiler/compiler/ast/README +11 -0
- data/boot/rbx-compiler/compiler/ast/array_literal.rb +13 -0
- data/boot/rbx-compiler/compiler/ast/assign.rb +57 -0
- data/boot/rbx-compiler/compiler/ast/block.rb +70 -0
- data/boot/rbx-compiler/compiler/ast/class_def.rb +35 -0
- data/boot/rbx-compiler/compiler/ast/expression_list.rb +57 -0
- data/boot/rbx-compiler/compiler/ast/hash_literal.rb +11 -0
- data/boot/rbx-compiler/compiler/ast/identifier.rb +120 -0
- data/boot/rbx-compiler/compiler/ast/match.rb +81 -0
- data/boot/rbx-compiler/compiler/ast/message_send.rb +71 -0
- data/boot/rbx-compiler/compiler/ast/method_def.rb +116 -0
- data/boot/rbx-compiler/compiler/ast/node.rb +6 -0
- data/boot/rbx-compiler/compiler/ast/range_literal.rb +22 -0
- data/boot/rbx-compiler/compiler/ast/require.rb +20 -0
- data/boot/rbx-compiler/compiler/ast/return.rb +29 -0
- data/boot/rbx-compiler/compiler/ast/ruby_args.rb +35 -0
- data/boot/rbx-compiler/compiler/ast/script.rb +56 -0
- data/boot/rbx-compiler/compiler/ast/singleton_method_def.rb +39 -0
- data/boot/rbx-compiler/compiler/ast/string_literal.rb +14 -0
- data/boot/rbx-compiler/compiler/ast/super.rb +25 -0
- data/boot/rbx-compiler/compiler/ast/try_catch_block.rb +220 -0
- data/boot/rbx-compiler/compiler/ast/tuple_literal.rb +33 -0
- data/boot/rbx-compiler/compiler/command.rb +39 -0
- data/boot/rbx-compiler/compiler/compiler.rb +83 -0
- data/boot/rbx-compiler/compiler/stages.rb +99 -0
- data/boot/rbx-compiler/parser.rb +2 -0
- data/boot/rbx-compiler/parser/README +15 -0
- data/boot/rbx-compiler/parser/Rakefile +54 -0
- data/boot/rbx-compiler/parser/extconf.rb +3 -0
- data/boot/rbx-compiler/parser/fancy_parser.bundle +0 -0
- data/boot/rbx-compiler/parser/fancy_parser.c +46 -0
- data/boot/rbx-compiler/parser/fancy_parser.h +8 -0
- data/boot/rbx-compiler/parser/lexer.lex +180 -0
- data/boot/rbx-compiler/parser/parser.rb +356 -0
- data/boot/rbx-compiler/parser/parser.y +711 -0
- data/boot/rsexp_pretty_printer.rb +76 -0
- data/doc/api/fancy.css +93 -0
- data/doc/api/fancy.jsonp +1 -0
- data/doc/api/fdoc.js +187 -0
- data/doc/api/index.html +57 -0
- data/doc/api/underscore-min.js +18 -0
- data/doc/features.md +228 -0
- data/examples/argv.fy +8 -0
- data/examples/arithmetic.fy +7 -0
- data/examples/armstrong_numbers.fy +33 -0
- data/examples/array.fy +52 -0
- data/examples/blocks.fy +15 -0
- data/examples/boolean.fy +24 -0
- data/examples/call_with_receiver.fy +9 -0
- data/examples/class.fy +68 -0
- data/examples/closures.fy +24 -0
- data/examples/constant_access.fy +15 -0
- data/examples/default_args.fy +17 -0
- data/examples/define_methods.fy +15 -0
- data/examples/documentation.fy +57 -0
- data/examples/documentation_formatters.fy +25 -0
- data/examples/echo.fy +16 -0
- data/examples/empty_catch.fy +4 -0
- data/examples/exception.fy +9 -0
- data/examples/factorial.fy +12 -0
- data/examples/fibonacci.fy +16 -0
- data/examples/files.fy +23 -0
- data/examples/finally.fy +5 -0
- data/examples/game_of_life.fy +148 -0
- data/examples/hashes.fy +7 -0
- data/examples/hello_world.fy +6 -0
- data/examples/html_generator.fy +54 -0
- data/examples/implicit_return.fy +3 -0
- data/examples/matchers.fy +6 -0
- data/examples/methods.fy +29 -0
- data/examples/nested_classes.fy +27 -0
- data/examples/nested_try.fy +9 -0
- data/examples/numbers.fy +12 -0
- data/examples/pattern_matching.fy +40 -0
- data/examples/person.fy +65 -0
- data/examples/project-euler/01.fy +8 -0
- data/examples/project-euler/02.fy +21 -0
- data/examples/project-euler/28.fy +33 -0
- data/examples/rbx/and_or.fy +7 -0
- data/examples/rbx/blocks.fy +22 -0
- data/examples/rbx/classes.fy +32 -0
- data/examples/rbx/hello.fy +8 -0
- data/examples/rbx/include.fy +12 -0
- data/examples/rbx/inherit.fy +11 -0
- data/examples/rbx/methods.fy +15 -0
- data/examples/rbx/nested_classes.fy +9 -0
- data/examples/rbx/require.fy +3 -0
- data/examples/rbx/strings.fy +5 -0
- data/examples/regex.fy +7 -0
- data/examples/require.fy +7 -0
- data/examples/retry.fy +12 -0
- data/examples/return.fy +13 -0
- data/examples/ruby_require.fy +7 -0
- data/examples/ruby_send.fy +3 -0
- data/examples/singleton_methods.fy +21 -0
- data/examples/stupid_quicksort.fy +12 -0
- data/examples/threads.fy +18 -0
- data/examples/tuple.fy +8 -0
- data/examples/webserver/webserver.fy +18 -0
- data/lib/argv.fy +36 -0
- data/lib/array.fy +207 -0
- data/lib/block.fy +88 -0
- data/lib/boot.fy +41 -0
- data/lib/class.fy +106 -0
- data/lib/compiler.fy +14 -0
- data/lib/compiler/ast.fy +40 -0
- data/lib/compiler/ast/assign.fy +96 -0
- data/lib/compiler/ast/block.fy +84 -0
- data/lib/compiler/ast/class_def.fy +33 -0
- data/lib/compiler/ast/expression_list.fy +47 -0
- data/lib/compiler/ast/identifier.fy +113 -0
- data/lib/compiler/ast/literals.fy +122 -0
- data/lib/compiler/ast/match.fy +88 -0
- data/lib/compiler/ast/message_send.fy +110 -0
- data/lib/compiler/ast/method_def.fy +90 -0
- data/lib/compiler/ast/node.fy +7 -0
- data/lib/compiler/ast/range.fy +16 -0
- data/lib/compiler/ast/require.fy +15 -0
- data/lib/compiler/ast/return.fy +23 -0
- data/lib/compiler/ast/script.fy +52 -0
- data/lib/compiler/ast/singleton_method_def.fy +35 -0
- data/lib/compiler/ast/super.fy +17 -0
- data/lib/compiler/ast/try_catch.fy +176 -0
- data/lib/compiler/ast/tuple_literal.fy +34 -0
- data/lib/compiler/command.fy +51 -0
- data/lib/compiler/compiler.fy +73 -0
- data/lib/compiler/stages.fy +81 -0
- data/lib/directory.fy +17 -0
- data/lib/documentation.fy +115 -0
- data/lib/enumerable.fy +269 -0
- data/lib/eval.fy +31 -0
- data/lib/fancy_spec.fy +202 -0
- data/lib/fdoc.fy +359 -0
- data/lib/fdoc_hook.fy +10 -0
- data/lib/file.fy +54 -0
- data/lib/hash.fy +56 -0
- data/lib/main.fy +80 -0
- data/lib/method.fy +22 -0
- data/lib/nil_class.fy +56 -0
- data/lib/number.fy +87 -0
- data/lib/object.fy +170 -0
- data/lib/package.fy +61 -0
- data/lib/package/dependency.fy +24 -0
- data/lib/package/installer.fy +180 -0
- data/lib/package/specification.fy +55 -0
- data/lib/package/uninstaller.fy +15 -0
- data/lib/parser.fy +4 -0
- data/lib/parser/ext/README +15 -0
- data/lib/parser/ext/ext.c +42 -0
- data/lib/parser/ext/ext.h +8 -0
- data/lib/parser/ext/extconf.rb +3 -0
- data/lib/parser/ext/lexer.lex +187 -0
- data/lib/parser/ext/parser.y +744 -0
- data/lib/parser/methods.fy +297 -0
- data/lib/rbx.fy +37 -0
- data/lib/rbx/array.fy +237 -0
- data/lib/rbx/bignum.fy +23 -0
- data/lib/rbx/block.fy +9 -0
- data/lib/rbx/class.fy +129 -0
- data/lib/rbx/code_loader.fy +192 -0
- data/lib/rbx/console.fy +63 -0
- data/lib/rbx/directory.fy +46 -0
- data/lib/rbx/documentation.fy +64 -0
- data/lib/rbx/environment_variables.fy +3 -0
- data/lib/rbx/exception.fy +30 -0
- data/lib/rbx/false_class.fy +58 -0
- data/lib/rbx/fiber.fy +25 -0
- data/lib/rbx/file.fy +191 -0
- data/lib/rbx/fixnum.fy +25 -0
- data/lib/rbx/float.fy +14 -0
- data/lib/rbx/hash.fy +38 -0
- data/lib/rbx/integer.fy +15 -0
- data/lib/rbx/io.fy +30 -0
- data/lib/rbx/match_data.fy +9 -0
- data/lib/rbx/method.fy +22 -0
- data/lib/rbx/name_error.fy +3 -0
- data/lib/rbx/no_method_error.fy +15 -0
- data/lib/rbx/object.fy +117 -0
- data/lib/rbx/range.fy +15 -0
- data/lib/rbx/regexp.fy +9 -0
- data/lib/rbx/string.fy +63 -0
- data/lib/rbx/symbol.fy +12 -0
- data/lib/rbx/system.fy +37 -0
- data/lib/rbx/tcp_server.fy +6 -0
- data/lib/rbx/tcp_socket.fy +7 -0
- data/lib/rbx/thread.fy +75 -0
- data/lib/rbx/tuple.fy +37 -0
- data/lib/set.fy +61 -0
- data/lib/stack.fy +51 -0
- data/lib/string.fy +58 -0
- data/lib/struct.fy +13 -0
- data/lib/symbol.fy +23 -0
- data/lib/true_class.fy +43 -0
- data/lib/tuple.fy +68 -0
- data/lib/version.fy +6 -0
- data/tests/argv.fy +13 -0
- data/tests/array.fy +343 -0
- data/tests/assignment.fy +53 -0
- data/tests/block.fy +103 -0
- data/tests/class.fy +409 -0
- data/tests/control_flow.fy +79 -0
- data/tests/documentation.fy +24 -0
- data/tests/exception.fy +115 -0
- data/tests/file.fy +86 -0
- data/tests/hash.fy +101 -0
- data/tests/method.fy +131 -0
- data/tests/nil_class.fy +55 -0
- data/tests/number.fy +128 -0
- data/tests/object.fy +125 -0
- data/tests/parsing/sexp.fy +50 -0
- data/tests/pattern_matching.fy +82 -0
- data/tests/range.fy +11 -0
- data/tests/set.fy +10 -0
- data/tests/stack.fy +22 -0
- data/tests/string.fy +102 -0
- data/tests/symbol.fy +17 -0
- data/tests/true_class.fy +63 -0
- data/tests/tuple.fy +21 -0
- data/tools/fancy-mode.el +63 -0
- metadata +321 -0
data/tests/assignment.fy
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
FancySpec describe: "Assignment" with: {
|
2
|
+
it: "should correctly assign multiple values at once" when: {
|
3
|
+
x, y, z = 1, 10, 100
|
4
|
+
x should == 1
|
5
|
+
y should == 10
|
6
|
+
z should == 100
|
7
|
+
|
8
|
+
x, y, z = 'foo, 'bar
|
9
|
+
x should == 'foo
|
10
|
+
y should == 'bar
|
11
|
+
z should == nil
|
12
|
+
|
13
|
+
x = 'foo
|
14
|
+
y = 'bar
|
15
|
+
x, y = y, x
|
16
|
+
x should == 'bar
|
17
|
+
y should == 'foo
|
18
|
+
}
|
19
|
+
|
20
|
+
it: "should handle multiple assignment for any collection type implementing 'at:" when: {
|
21
|
+
x, y, z = (1, 2, 3)
|
22
|
+
x should == 1
|
23
|
+
y should == 2
|
24
|
+
z should == 3
|
25
|
+
|
26
|
+
a, b, c = ["a", "b", "c"]
|
27
|
+
a should == "a"
|
28
|
+
b should == "b"
|
29
|
+
c should == "c"
|
30
|
+
|
31
|
+
e, f = ([1,2], "foo")
|
32
|
+
e should == [1,2]
|
33
|
+
f should == "foo"
|
34
|
+
}
|
35
|
+
|
36
|
+
it: "should handle multiple assignment with splat-identifiers" when: {
|
37
|
+
x,y,z,*rest = [1,2,3,4,5,6,7]
|
38
|
+
x should == 1
|
39
|
+
y should == 2
|
40
|
+
z should == 3
|
41
|
+
rest should == [4,5,6,7]
|
42
|
+
|
43
|
+
a,b,*c,*d,e = [1,2,3,4,5,6,7,8]
|
44
|
+
a should == 1
|
45
|
+
b should == 2
|
46
|
+
c should == [3,4,5,6,7,8]
|
47
|
+
d should == [4,5,6,7,8]
|
48
|
+
e should == 5
|
49
|
+
|
50
|
+
_,_,*z = "hello, world!" # ignore first 2 characters
|
51
|
+
z should == "llo, world!"
|
52
|
+
}
|
53
|
+
}
|
data/tests/block.fy
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
FancySpec describe: Block with: {
|
2
|
+
it: "should return the value of the last expression" when: {
|
3
|
+
block = {
|
4
|
+
a = "a"
|
5
|
+
empty = " "
|
6
|
+
str = "String!"
|
7
|
+
a ++ empty ++ str
|
8
|
+
}
|
9
|
+
block call should == "a String!"
|
10
|
+
}
|
11
|
+
|
12
|
+
it: "should close over a value and change it internally" when: {
|
13
|
+
x = 0
|
14
|
+
{ x < 10 } while_true: {
|
15
|
+
x should be: |x| { x < 10 }
|
16
|
+
x = x + 1
|
17
|
+
}
|
18
|
+
x should == 10
|
19
|
+
}
|
20
|
+
|
21
|
+
it: "should return the argument count" for: 'argcount when: {
|
22
|
+
{ } argcount . should == 0
|
23
|
+
|x| { } argcount . should == 1
|
24
|
+
|x y z| { } argcount . should == 3
|
25
|
+
}
|
26
|
+
|
27
|
+
it: "should call a block while another is true" for: 'while_true: when: {
|
28
|
+
i = 0
|
29
|
+
{i < 10} while_true: {
|
30
|
+
i = i + 1
|
31
|
+
}
|
32
|
+
i should be: { i >= 10 }
|
33
|
+
}
|
34
|
+
|
35
|
+
it: "should call a block while another is not true (boolean false)" for: 'while_false: when: {
|
36
|
+
i = 0
|
37
|
+
{i == 10} while_false: {
|
38
|
+
i = i + 1
|
39
|
+
}
|
40
|
+
i should == 10
|
41
|
+
}
|
42
|
+
|
43
|
+
# again for while_nil
|
44
|
+
it: "should call a block while another is nil" for: 'while_nil: when: {
|
45
|
+
i = 0
|
46
|
+
{i == 10} while_nil: {
|
47
|
+
i = i + 1
|
48
|
+
}
|
49
|
+
i should == 10
|
50
|
+
}
|
51
|
+
|
52
|
+
it: "should call a block while another one is true-ish" for: 'while_do: when: {
|
53
|
+
x = 0
|
54
|
+
{ x < 10 } while_do: |val| {
|
55
|
+
val should == true
|
56
|
+
x = x + 1
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
it: "should call itself only when the argument is nil" for: 'unless: when: {
|
61
|
+
try {
|
62
|
+
{ StdError new: "got_run!" . raise! } unless: nil
|
63
|
+
StdError new: "didnt_run!" . raise!
|
64
|
+
} catch StdError => e {
|
65
|
+
e message should == "got_run!"
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
it: "should call itself only when the argument is true" for: 'if: when: {
|
70
|
+
try {
|
71
|
+
{ StdError new: "got_run!" . raise! } if: true
|
72
|
+
StdError new: "didnt_run!" . raise!
|
73
|
+
} catch StdError => e {
|
74
|
+
e message should == "got_run!"
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
it: "should also be able to take arguments seperated by comma" for: 'call: when: {
|
79
|
+
block = |x, y| { x + y }
|
80
|
+
block call: [1,2] . should == 3
|
81
|
+
}
|
82
|
+
|
83
|
+
it: "should evaluate the blocks in a short-circuiting manner" for: '&& when: {
|
84
|
+
{ false } && { false } should == false
|
85
|
+
{ true } && { false } should == false
|
86
|
+
{ false } && { true } should == false
|
87
|
+
{ true } && { true } should == true
|
88
|
+
|
89
|
+
{ false } || { false } should == false
|
90
|
+
{ false } || { true } should == true
|
91
|
+
{ true } || { false } should == true
|
92
|
+
{ true } || { true } should == true
|
93
|
+
|
94
|
+
# TODO: Add more useful tests here...
|
95
|
+
}
|
96
|
+
|
97
|
+
it: "should call the block as a partial block" when: {
|
98
|
+
[1,2,3] map: @{upto: 3} . should == [[1,2,3], [2,3], [3]]
|
99
|
+
[1,2,3] map: @{+ 3} . should == [4,5,6]
|
100
|
+
[1,2,3] map: @{to_s} . should == ["1", "2", "3"]
|
101
|
+
[1,2,3] map: @{to_s * 3} . should == ["111", "222", "333"]
|
102
|
+
}
|
103
|
+
}
|
data/tests/class.fy
ADDED
@@ -0,0 +1,409 @@
|
|
1
|
+
class Mixin {
|
2
|
+
def mixin_method {
|
3
|
+
'mixed_in_found
|
4
|
+
}
|
5
|
+
}
|
6
|
+
|
7
|
+
class ClassWithMixin {
|
8
|
+
def normal_method {
|
9
|
+
'normal_found
|
10
|
+
}
|
11
|
+
}
|
12
|
+
|
13
|
+
class ClassWithNoMixin {
|
14
|
+
read_slots: ['foo, 'bar, 'baz]
|
15
|
+
write_slots: ['hello, 'world]
|
16
|
+
read_write_slots: ['oh, 'noes]
|
17
|
+
|
18
|
+
def normal_method {
|
19
|
+
'new_normal_found
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
class ClassWithPrivate {
|
24
|
+
def public_method {
|
25
|
+
"public!"
|
26
|
+
}
|
27
|
+
|
28
|
+
def protected protected_method {
|
29
|
+
"protected!"
|
30
|
+
}
|
31
|
+
|
32
|
+
def private private_method {
|
33
|
+
"private!"
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
FancySpec describe: Class with: {
|
38
|
+
it: "should NOT find the method when not mixed-in" for: 'responds_to?: when: {
|
39
|
+
instance = ClassWithMixin new
|
40
|
+
instance normal_method . should == 'normal_found
|
41
|
+
instance responds_to?: 'normal_method . should == true
|
42
|
+
instance responds_to?: 'mixin_method . should == false
|
43
|
+
}
|
44
|
+
|
45
|
+
it: "should find the method when mixed-in" for: 'include: when: {
|
46
|
+
# => include Mixin into ClassWithMixin
|
47
|
+
class ClassWithMixin {
|
48
|
+
include: Mixin
|
49
|
+
}
|
50
|
+
|
51
|
+
instance = ClassWithMixin new
|
52
|
+
instance responds_to?: 'normal_method . should == true
|
53
|
+
instance responds_to?: 'mixin_method . should == true
|
54
|
+
instance normal_method . should == 'normal_found
|
55
|
+
instance mixin_method . should == 'mixed_in_found
|
56
|
+
}
|
57
|
+
|
58
|
+
it: "should rebind the old class name with ClassWithNoMixin and replace the old normal_method" when: {
|
59
|
+
instance = ClassWithMixin new
|
60
|
+
instance normal_method should == 'normal_found
|
61
|
+
# rebind the class to the other class
|
62
|
+
ClassWithMixin = ClassWithNoMixin
|
63
|
+
instance = ClassWithMixin new
|
64
|
+
instance normal_method should == 'new_normal_found
|
65
|
+
}
|
66
|
+
|
67
|
+
it: "should have dynamically generated getter methods" for: 'responds_to?: when: {
|
68
|
+
instance = ClassWithNoMixin new
|
69
|
+
instance responds_to?: 'foo . should == true
|
70
|
+
instance responds_to?: 'bar . should == true
|
71
|
+
instance responds_to?: 'baz . should == true
|
72
|
+
instance responds_to?: "hello:" . should == true
|
73
|
+
instance responds_to?: "world:" . should == true
|
74
|
+
instance responds_to?: 'oh . should == true
|
75
|
+
instance responds_to?: ":oh" . should == true
|
76
|
+
instance responds_to?: 'noes . should == true
|
77
|
+
instance responds_to?: "noes:" . should == true
|
78
|
+
}
|
79
|
+
|
80
|
+
it: "should find the instance variable correctly" when: {
|
81
|
+
class AClass {
|
82
|
+
def initialize: foo {
|
83
|
+
@foo = foo
|
84
|
+
}
|
85
|
+
def foo {
|
86
|
+
@foo
|
87
|
+
}
|
88
|
+
}
|
89
|
+
|
90
|
+
str = "instance value"
|
91
|
+
instance = AClass new: str
|
92
|
+
instance foo should == str
|
93
|
+
AClass new foo should == nil
|
94
|
+
}
|
95
|
+
|
96
|
+
it: "should find the class variable correctly" when: {
|
97
|
+
class AClass {
|
98
|
+
def foo: foo {
|
99
|
+
@@foo = foo
|
100
|
+
}
|
101
|
+
def foo {
|
102
|
+
@@foo
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
instance1 = AClass new
|
107
|
+
instance2 = AClass new
|
108
|
+
str = "class value"
|
109
|
+
instance1 foo: str
|
110
|
+
instance1 foo should == str
|
111
|
+
instance2 foo should == str
|
112
|
+
instance2 foo should == (instance1 foo)
|
113
|
+
|
114
|
+
str2 = "another value"
|
115
|
+
instance2 foo: str2
|
116
|
+
instance2 foo should == str2
|
117
|
+
instance1 foo should == str2
|
118
|
+
}
|
119
|
+
|
120
|
+
it: "should have correct method overloading for method names with and without an argument" when: {
|
121
|
+
class AClass {
|
122
|
+
def foo {
|
123
|
+
foo: "None!"
|
124
|
+
}
|
125
|
+
|
126
|
+
def foo: bar {
|
127
|
+
"In AClass#foo: with bar = " ++ bar
|
128
|
+
}
|
129
|
+
}
|
130
|
+
|
131
|
+
instance = AClass new
|
132
|
+
instance foo should == "In AClass#foo: with bar = None!"
|
133
|
+
instance foo: "Test!" . should == "In AClass#foo: with bar = Test!"
|
134
|
+
}
|
135
|
+
|
136
|
+
# it: "should call superclass method by calling super" when: {
|
137
|
+
# class SuperClass {
|
138
|
+
# read_slots: ['name]
|
139
|
+
# def initialize: name {
|
140
|
+
# @name = name
|
141
|
+
# }
|
142
|
+
# }
|
143
|
+
# class SubClass : SuperClass {
|
144
|
+
# read_slots: ['age]
|
145
|
+
|
146
|
+
# def initialize: age {
|
147
|
+
# super initialize: "SubClass"
|
148
|
+
# @age = age
|
149
|
+
# }
|
150
|
+
# def initialize {
|
151
|
+
# super initialize: "SubClass"
|
152
|
+
# @age = 0
|
153
|
+
# }
|
154
|
+
# }
|
155
|
+
|
156
|
+
# sub = SubClass new: 42
|
157
|
+
# sub name should == "SubClass"
|
158
|
+
# sub age should == 42
|
159
|
+
|
160
|
+
# sub2 = SubClass new
|
161
|
+
# sub2 name should == "SubClass"
|
162
|
+
# sub2 age should == 0
|
163
|
+
# }
|
164
|
+
|
165
|
+
it: "should return its superclass" when: {
|
166
|
+
Fixnum superclass should == Integer
|
167
|
+
Symbol superclass should == Object
|
168
|
+
StdError superclass should == Exception
|
169
|
+
Class superclass should == Module
|
170
|
+
Object superclass should == nil
|
171
|
+
|
172
|
+
IOError superclass should == StandardError
|
173
|
+
NoMethodError superclass should == NameError
|
174
|
+
}
|
175
|
+
|
176
|
+
# it: "should create a new Class dynamically" when: {
|
177
|
+
# x = Class new
|
178
|
+
# x is_a?: Class . should == true
|
179
|
+
# x new is_a?: x . should == true
|
180
|
+
# x new is_a?: Object . should == true
|
181
|
+
# x new class should == x
|
182
|
+
|
183
|
+
# # Symbol as superclass
|
184
|
+
# y = Class new: Symbol
|
185
|
+
# y is_a?: Class . should == true
|
186
|
+
# y new is_a?: Symbol . should == true
|
187
|
+
# y new is_a?: Object . should == true
|
188
|
+
# }
|
189
|
+
|
190
|
+
it: "should only be able to call the public method from outside the Class" when: {
|
191
|
+
x = ClassWithPrivate new
|
192
|
+
x public_method should == "public!"
|
193
|
+
try {
|
194
|
+
x private_method should == nil # should fail
|
195
|
+
} catch NoMethodError => e {
|
196
|
+
e method_name should == "private_method"
|
197
|
+
}
|
198
|
+
try {
|
199
|
+
x protected_method should == nil # should fail
|
200
|
+
} catch NoMethodError => e {
|
201
|
+
e method_name should == "protected_method"
|
202
|
+
}
|
203
|
+
}
|
204
|
+
|
205
|
+
it: "should be a subclass of another Class" for: 'subclass?: when: {
|
206
|
+
class Super {
|
207
|
+
}
|
208
|
+
class Sub : Super {
|
209
|
+
}
|
210
|
+
|
211
|
+
Super subclass?: Object . should == true
|
212
|
+
Sub subclass?: Object . should == true
|
213
|
+
Sub subclass?: Super . should == true
|
214
|
+
Super subclass?: Sub . should == nil
|
215
|
+
}
|
216
|
+
|
217
|
+
# it: "should dynamically create a subclass of another class" for: 'is_a?: when: {
|
218
|
+
# subclass = String subclass: {
|
219
|
+
# def foo {
|
220
|
+
# "hello, world!"
|
221
|
+
# }
|
222
|
+
# }
|
223
|
+
# subclass is_a?: Class . should == true
|
224
|
+
# subclass subclass?: String . should == true
|
225
|
+
# subclass new is_a?: subclass . should == true
|
226
|
+
# subclass new foo should == "hello, world!"
|
227
|
+
|
228
|
+
# # now the same with Class##new:body:
|
229
|
+
# subclass2 = Class superclass: Symbol body: {
|
230
|
+
# def foo {
|
231
|
+
# "hello, world, again!"
|
232
|
+
# }
|
233
|
+
# }
|
234
|
+
# subclass2 is_a?: Class . should == true
|
235
|
+
# subclass2 subclass?: String . should == true
|
236
|
+
# subclass2 new is_a?: subclass2 . should == true
|
237
|
+
# subclass2 new foo should == "hello, world, again!"
|
238
|
+
# }
|
239
|
+
|
240
|
+
it: "should undefine an instance method" for: 'undefine_method: when: {
|
241
|
+
class Foo {
|
242
|
+
def instance_method {
|
243
|
+
"instance method!"
|
244
|
+
}
|
245
|
+
}
|
246
|
+
f = Foo new
|
247
|
+
f instance_method should == "instance method!"
|
248
|
+
Foo undefine_method: 'instance_method
|
249
|
+
try {
|
250
|
+
f instance_method should == nil # should not get here
|
251
|
+
} catch NoMethodError => e {
|
252
|
+
e method_name should == "instance_method"
|
253
|
+
}
|
254
|
+
}
|
255
|
+
|
256
|
+
it: "should undefine a class method" for: 'undefine_class_method: when: {
|
257
|
+
class Foo {
|
258
|
+
def self class_method {
|
259
|
+
"class method!"
|
260
|
+
}
|
261
|
+
}
|
262
|
+
Foo class_method should == "class method!"
|
263
|
+
|
264
|
+
try {
|
265
|
+
Foo undefine_method: 'class_method
|
266
|
+
true should == nil # should not happen
|
267
|
+
} catch NameError {
|
268
|
+
true should == true
|
269
|
+
}
|
270
|
+
|
271
|
+
Foo undefine_class_method: 'class_method
|
272
|
+
|
273
|
+
try {
|
274
|
+
Foo class_method should == nil # should not get here
|
275
|
+
} catch NoMethodError => e {
|
276
|
+
e method_name should == "class_method"
|
277
|
+
}
|
278
|
+
}
|
279
|
+
|
280
|
+
# it: "should have nested classes" when: {
|
281
|
+
# class Outer {
|
282
|
+
# class Inner {
|
283
|
+
# class InnerMost {
|
284
|
+
# def foobar {
|
285
|
+
# "foobar!"
|
286
|
+
# }
|
287
|
+
# }
|
288
|
+
# }
|
289
|
+
# }
|
290
|
+
# Outer is_a?: Class . should == true
|
291
|
+
# Outer::Inner is_a?: Class . should == true
|
292
|
+
# Outer::Inner::InnerMost is_a?: Class . should == true
|
293
|
+
# obj = Outer::Inner::InnerMost new
|
294
|
+
# obj foobar should == "foobar!"
|
295
|
+
|
296
|
+
# # change InnerMost#foobar
|
297
|
+
# class Outer::Inner::InnerMost {
|
298
|
+
# def foobar {
|
299
|
+
# "oh no!"
|
300
|
+
# }
|
301
|
+
# }
|
302
|
+
# obj foobar . should == "oh no!"
|
303
|
+
# }
|
304
|
+
|
305
|
+
it: "should not override existing classes with the same name in a nested class" when: {
|
306
|
+
StdArray = Array
|
307
|
+
class NameSpace {
|
308
|
+
class Array {
|
309
|
+
def Array what_am_i {
|
310
|
+
"not the same as the standard Array class"
|
311
|
+
}
|
312
|
+
}
|
313
|
+
}
|
314
|
+
|
315
|
+
NameSpace::Array what_am_i . should == "not the same as the standard Array class"
|
316
|
+
NameSpace::Array should_not == Array
|
317
|
+
}
|
318
|
+
|
319
|
+
# it: "should return all nested classes of a class" for: 'nested_classes when: {
|
320
|
+
# class Outer {
|
321
|
+
# }
|
322
|
+
# Outer nested_classes should == []
|
323
|
+
|
324
|
+
# class Outer {
|
325
|
+
# class Inner1 {
|
326
|
+
# }
|
327
|
+
# }
|
328
|
+
# Outer nested_classes should == [Outer::Inner1]
|
329
|
+
|
330
|
+
# class Outer {
|
331
|
+
# class Inner2 {
|
332
|
+
# }
|
333
|
+
# }
|
334
|
+
# Outer nested_classes should == [Outer::Inner1, Outer::Inner2]
|
335
|
+
# }
|
336
|
+
|
337
|
+
it: "should find other nested classes in the same parent class" when: {
|
338
|
+
class MyOuter {
|
339
|
+
class Inner1 {
|
340
|
+
def method1 {
|
341
|
+
'method_1
|
342
|
+
}
|
343
|
+
}
|
344
|
+
class Inner2 {
|
345
|
+
include: Inner1
|
346
|
+
def method2 {
|
347
|
+
'method_2
|
348
|
+
}
|
349
|
+
}
|
350
|
+
}
|
351
|
+
|
352
|
+
MyOuter::Inner1 new method1 should == 'method_1
|
353
|
+
MyOuter::Inner2 new method1 should == 'method_1
|
354
|
+
MyOuter::Inner2 new method2 should == 'method_2
|
355
|
+
}
|
356
|
+
|
357
|
+
it: "should find itself in it's own methods, even if nested into another class" when: {
|
358
|
+
class MyOuter {
|
359
|
+
class MyInner1 {
|
360
|
+
def method1 {
|
361
|
+
MyInner1
|
362
|
+
}
|
363
|
+
def self class_method1 {
|
364
|
+
MyInner1
|
365
|
+
}
|
366
|
+
}
|
367
|
+
class MyInner2 {
|
368
|
+
def method2 {
|
369
|
+
[MyInner1, MyInner2]
|
370
|
+
}
|
371
|
+
def self class_method2 {
|
372
|
+
[MyInner1, MyInner2]
|
373
|
+
}
|
374
|
+
}
|
375
|
+
}
|
376
|
+
|
377
|
+
MyOuter::MyInner1 new method1 should == MyOuter::MyInner1
|
378
|
+
MyOuter::MyInner2 new method2 should == [MyOuter::MyInner1, MyOuter::MyInner2]
|
379
|
+
MyOuter::MyInner1 class_method1 should == MyOuter::MyInner1
|
380
|
+
MyOuter::MyInner2 class_method2 should == [MyOuter::MyInner1, MyOuter::MyInner2]
|
381
|
+
}
|
382
|
+
|
383
|
+
it: "should have an alias method as defined" for: 'alias_method:for: when: {
|
384
|
+
class AClass {
|
385
|
+
def foo {
|
386
|
+
"in foo!"
|
387
|
+
}
|
388
|
+
|
389
|
+
alias_method: 'bar for: 'foo
|
390
|
+
}
|
391
|
+
|
392
|
+
obj = AClass new
|
393
|
+
obj foo should == "in foo!"
|
394
|
+
obj bar should == "in foo!"
|
395
|
+
}
|
396
|
+
|
397
|
+
it: "should have the correct list of ancestors" for: 'ancestors when: {
|
398
|
+
class A {
|
399
|
+
}
|
400
|
+
class B : A {
|
401
|
+
}
|
402
|
+
class C : B {
|
403
|
+
}
|
404
|
+
|
405
|
+
A ancestors should == [A, Object, Kernel]
|
406
|
+
B ancestors should == [B, A, Object, Kernel]
|
407
|
+
C ancestors should == [C, B, A, Object, Kernel]
|
408
|
+
}
|
409
|
+
}
|