fancy 0.3.2 → 0.3.3
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.md +4 -1
- data/Rakefile +8 -0
- data/bin/fyi +25 -20
- data/bin/ifancy +39 -5
- data/{extconf.rb → boot/extconf.rb} +1 -1
- data/boot/fancy_ext/block_env.rb +0 -14
- data/boot/fancy_ext/kernel.rb +6 -2
- data/boot/rbx-compiler/parser/fancy_parser.bundle +0 -0
- data/examples/actor.fy +37 -0
- data/examples/armstrong_numbers.fy +1 -1
- data/examples/curl_async.fy +37 -0
- data/examples/echo.fy +1 -1
- data/examples/factorial.fy +1 -1
- data/examples/future_composition.fy +20 -0
- data/examples/game_of_life.fy +2 -2
- data/examples/person.fy +4 -8
- data/examples/rbx/blocks.fy +1 -1
- data/examples/return.fy +1 -1
- data/examples/struct.fy +9 -0
- data/lib/argv.fy +2 -2
- data/lib/array.fy +157 -0
- data/lib/block.fy +18 -1
- data/lib/boot.fy +5 -1
- data/lib/compiler/ast/class_def.fy +1 -1
- data/lib/compiler/ast/identifier.fy +2 -2
- data/lib/compiler/ast/message_send.fy +2 -2
- data/lib/compiler/ast/method_def.fy +2 -2
- data/lib/compiler/ast/try_catch.fy +5 -1
- data/lib/documentation.fy +1 -1
- data/lib/enumerable.fy +3 -7
- data/lib/enumerator.fy +77 -0
- data/lib/false_class.fy +52 -0
- data/lib/fancy_spec.fy +40 -12
- data/lib/fdoc.fy +2 -2
- data/lib/file.fy +8 -1
- data/lib/future.fy +23 -2
- data/lib/iteration.fy +60 -0
- data/lib/main.fy +4 -4
- data/lib/nil_class.fy +14 -22
- data/lib/number.fy +51 -0
- data/lib/object.fy +126 -43
- data/lib/package/installer.fy +1 -1
- data/lib/parser/ext/lexer.lex +6 -1
- data/lib/parser/ext/parser.y +18 -0
- data/lib/parser/methods.fy +20 -2
- data/lib/proxy.fy +20 -3
- data/lib/rbx.fy +0 -1
- data/lib/rbx/array.fy +4 -138
- data/lib/rbx/block.fy +25 -1
- data/lib/rbx/class.fy +21 -0
- data/lib/rbx/exception.fy +1 -0
- data/lib/rbx/fiber.fy +1 -0
- data/lib/rbx/file.fy +8 -0
- data/lib/rbx/integer.fy +0 -8
- data/lib/rbx/method.fy +34 -7
- data/lib/rbx/no_method_error.fy +8 -1
- data/lib/rbx/object.fy +3 -32
- data/lib/rbx/range.fy +13 -1
- data/lib/rbx/regexp.fy +3 -0
- data/lib/rbx/string.fy +6 -1
- data/lib/rbx/system.fy +20 -2
- data/lib/set.fy +2 -2
- data/lib/string.fy +1 -1
- data/lib/struct.fy +15 -12
- data/lib/symbol.fy +2 -2
- data/lib/true_class.fy +16 -20
- data/lib/version.fy +1 -1
- data/tests/argv.fy +1 -0
- data/tests/array.fy +33 -2
- data/tests/block.fy +44 -0
- data/tests/class.fy +102 -88
- data/tests/control_flow.fy +131 -8
- data/tests/enumerator.fy +85 -0
- data/tests/exception.fy +13 -13
- data/tests/file.fy +4 -13
- data/tests/future.fy +26 -0
- data/tests/method.fy +83 -72
- data/tests/nil_class.fy +20 -13
- data/tests/number.fy +16 -9
- data/tests/object.fy +39 -20
- data/tests/string.fy +7 -0
- data/tests/true_class.fy +4 -4
- data/tools/fancy-mode.el +1 -1
- metadata +15 -20
- data/boot/compiler/parser/ext/fancy_parser.bundle +0 -0
- data/boot/rbx-compiler/parser/Makefile +0 -162
- data/boot/rbx-compiler/parser/lexer.c +0 -2316
- data/boot/rbx-compiler/parser/lexer.h +0 -315
- data/boot/rbx-compiler/parser/parser.c +0 -3105
- data/boot/rbx-compiler/parser/parser.h +0 -114
- data/lib/lazy_array.fy +0 -23
- data/lib/parser/ext/Makefile +0 -162
- data/lib/parser/ext/fancy_parser.bundle +0 -0
- data/lib/parser/ext/lexer.c +0 -2360
- data/lib/parser/ext/lexer.h +0 -315
- data/lib/parser/ext/parser.c +0 -3382
- data/lib/parser/ext/parser.h +0 -118
- data/lib/rbx/false_class.fy +0 -58
data/tests/enumerator.fy
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
FancySpec describe: FancyEnumerator with: {
|
2
|
+
it: "iterates with 'next" for: 'new: when: {
|
3
|
+
enum = FancyEnumerator new: (42..50)
|
4
|
+
enum next should == 42
|
5
|
+
enum next should == 43
|
6
|
+
}
|
7
|
+
|
8
|
+
it: "peeks to find next element" for: 'peek when: {
|
9
|
+
enum = FancyEnumerator new: (42..50)
|
10
|
+
enum peek should == 42
|
11
|
+
enum peek should == 42
|
12
|
+
enum next should == 42
|
13
|
+
|
14
|
+
enum peek should == 43
|
15
|
+
enum peek should == 43
|
16
|
+
enum next should == 43
|
17
|
+
}
|
18
|
+
|
19
|
+
it: "turns an object with 'each: into an FancyEnumerator" for: 'to_enum when: {
|
20
|
+
enum = (42..45) to_enum
|
21
|
+
enum next should == 42
|
22
|
+
}
|
23
|
+
|
24
|
+
it: "turns an object with given method into an FancyEnumerator" for: 'to_enum: when: {
|
25
|
+
o = {}
|
26
|
+
def o iter: block {
|
27
|
+
1 upto: 10 do: block
|
28
|
+
}
|
29
|
+
enum = o to_enum: 'iter:
|
30
|
+
enum next should == 1
|
31
|
+
}
|
32
|
+
|
33
|
+
it: "rewinds to the beginning of the iteration" for: 'rewind when: {
|
34
|
+
enum = (42..45) to_enum
|
35
|
+
check = {
|
36
|
+
enum peek should == 42
|
37
|
+
enum next should == 42
|
38
|
+
enum peek should == 43
|
39
|
+
enum next should == 43
|
40
|
+
}
|
41
|
+
|
42
|
+
check call
|
43
|
+
enum rewind
|
44
|
+
check call
|
45
|
+
}
|
46
|
+
|
47
|
+
it: "raises Fancy StopIteration when out of values" for: 'next when: {
|
48
|
+
o = Object new
|
49
|
+
def o each: block { block call: [1] }
|
50
|
+
e = o to_enum
|
51
|
+
|
52
|
+
e next should == 1
|
53
|
+
try {
|
54
|
+
e next
|
55
|
+
"We should not reach this line" should == true
|
56
|
+
} catch (Fancy StopIteration) => ex {
|
57
|
+
ex result should == nil
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
it: "sets result on Fancy StopIteration when out of values" for: 'next when: {
|
62
|
+
o = Object new
|
63
|
+
def o each: block {
|
64
|
+
block call: [1]
|
65
|
+
42
|
66
|
+
}
|
67
|
+
e = o to_enum
|
68
|
+
|
69
|
+
e next should == 1
|
70
|
+
try {
|
71
|
+
e next
|
72
|
+
"We should not reach this line" should == true
|
73
|
+
} catch (Fancy StopIteration) => ex {
|
74
|
+
ex result should == 42
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
it: "iterates with an object" for: 'with:each: when: {
|
79
|
+
enum = (42..45) to_enum
|
80
|
+
result = enum with: [] each: |val, obj| { obj << val }
|
81
|
+
result should == [42, 43, 44, 45]
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
# => [:each, :each_with_index, :each_with_object, :with_index, :with_object, :next_values, :peek_values, :next, :peek, :feed, :rewind, :inspect]
|
data/tests/exception.fy
CHANGED
@@ -70,20 +70,20 @@ FancySpec describe: StdError with: {
|
|
70
70
|
}
|
71
71
|
}
|
72
72
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
73
|
+
it: "should raise and catch a custom exception correctly" for: 'raise! when: {
|
74
|
+
class MyError : StdError{
|
75
|
+
def initialize {
|
76
|
+
initialize: "MyError message"
|
77
|
+
}
|
78
|
+
}
|
79
79
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
80
|
+
try {
|
81
|
+
MyError new raise!
|
82
|
+
nil should == true # will fail
|
83
|
+
} catch MyError => e {
|
84
|
+
e message should == "MyError message"
|
85
|
+
}
|
86
|
+
}
|
87
87
|
|
88
88
|
it: "should restart itself after being fixed in a catch clause" when: {
|
89
89
|
y = 0
|
data/tests/file.fy
CHANGED
@@ -12,12 +12,9 @@ FancySpec describe: File with: {
|
|
12
12
|
file open? should == false
|
13
13
|
}
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
# file close
|
19
|
-
# file open? should == nil
|
20
|
-
# }
|
15
|
+
it: "should be closed when not correctly opened" for: 'open? when: {
|
16
|
+
{ file = File new } should raise: ArgumentError
|
17
|
+
}
|
21
18
|
|
22
19
|
it: "should write and read from a file correctly" for: 'writeln: when: {
|
23
20
|
filename = "/tmp/read_write_test.txt"
|
@@ -43,13 +40,7 @@ FancySpec describe: File with: {
|
|
43
40
|
}
|
44
41
|
|
45
42
|
it: "should raise an IOError exception when trying to open an invalid file" when: {
|
46
|
-
|
47
|
-
file = File open: "/foo/bar/baz" modes: ['read]
|
48
|
-
nil should == true # this shouldn't execute
|
49
|
-
} catch IOError => e {
|
50
|
-
#e filename should == "/foo/bar/baz"
|
51
|
-
#e modes should == ['read]
|
52
|
-
}
|
43
|
+
{ file = File open: "/foo/bar/baz" modes: ['read] } should raise: IOError
|
53
44
|
}
|
54
45
|
|
55
46
|
it: "should rename a File" when: {
|
data/tests/future.fy
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
FancySpec describe: Future with: {
|
2
|
+
it: "should compose Futures to create execution pipelines" for: '&& when: {
|
3
|
+
def some_computation: num {
|
4
|
+
num upto: (num ** num ** num)
|
5
|
+
}
|
6
|
+
|
7
|
+
f = self @ some_computation: 2 && @{select: 'even?} && 'size
|
8
|
+
f is_a?: Future . should == true
|
9
|
+
f value is_a?: Fixnum . should == true
|
10
|
+
}
|
11
|
+
}
|
12
|
+
|
13
|
+
FancySpec describe: FutureCollection with: {
|
14
|
+
it: "should execute a block for each future in the collection when it's ready" for: 'each: when: {
|
15
|
+
futures = 0 upto: 10 . map: |i| {
|
16
|
+
i ** i @ ** i
|
17
|
+
}
|
18
|
+
|
19
|
+
fc = FutureCollection new: futures
|
20
|
+
fc each: |val| {
|
21
|
+
val is_a?: Integer . should == true
|
22
|
+
}
|
23
|
+
|
24
|
+
fc await_all
|
25
|
+
}
|
26
|
+
}
|
data/tests/method.fy
CHANGED
@@ -14,57 +14,57 @@ FancySpec describe: Method with: {
|
|
14
14
|
# x give_me_the_sender! should == self
|
15
15
|
# }
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
17
|
+
it: "should return the amount of arguments a Method takes" for: 'argcount when: {
|
18
|
+
class Foo {
|
19
|
+
def no_args {
|
20
|
+
}
|
21
|
+
def one_arg: yo {
|
22
|
+
}
|
23
|
+
def two: a args: b {
|
24
|
+
}
|
25
|
+
def three: a args: b ok: c {
|
26
|
+
}
|
27
|
+
}
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
29
|
+
Foo instance_method: 'no_args . arity should == 0
|
30
|
+
Foo instance_method: "one_arg:" . arity should == 1
|
31
|
+
Foo instance_method: "two:args:" . arity should == 2
|
32
|
+
Foo instance_method: "three:args:ok:" . arity should == 3
|
33
|
+
}
|
34
34
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
35
|
+
it: "should return the return value" when: {
|
36
|
+
def foo: bar {
|
37
|
+
return "returning!"
|
38
|
+
bar # will never get executed
|
39
|
+
}
|
40
40
|
|
41
|
-
|
41
|
+
foo: "yay" . should == "returning!"
|
42
42
|
|
43
|
-
|
43
|
+
# another example
|
44
44
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
45
|
+
def f: x {
|
46
|
+
x < 10 if_true: {
|
47
|
+
return 100
|
48
|
+
}
|
49
|
+
0
|
50
|
+
}
|
51
51
|
|
52
|
-
|
53
|
-
|
52
|
+
f: 10 . should == 0
|
53
|
+
f: 9 . should == 100
|
54
54
|
|
55
|
-
|
55
|
+
# and another one
|
56
56
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
57
|
+
def foo {
|
58
|
+
10 times: |i| {
|
59
|
+
i == 8 if_true: {
|
60
|
+
return i # nested return
|
61
|
+
}
|
62
|
+
}
|
63
|
+
return 0
|
64
|
+
}
|
65
65
|
|
66
|
-
|
67
|
-
|
66
|
+
foo should == 8
|
67
|
+
}
|
68
68
|
|
69
69
|
it: "should return only from block-scope not from method-scope" when: {
|
70
70
|
def self foo {
|
@@ -75,42 +75,42 @@ FancySpec describe: Method with: {
|
|
75
75
|
}
|
76
76
|
0
|
77
77
|
}
|
78
|
-
|
78
|
+
foo should == 8
|
79
79
|
}
|
80
80
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
81
|
+
it: "should return locally (from block-scope not from method-scope" when: {
|
82
|
+
def self foo {
|
83
|
+
[1,2,3] select: |x| { return_local x != 3 }
|
84
|
+
}
|
85
|
+
foo should == [1,2]
|
86
|
+
}
|
87
87
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
88
|
+
class Foo {
|
89
|
+
def bar {
|
90
|
+
}
|
91
|
+
def private private_bar {
|
92
|
+
}
|
93
|
+
def protected protected_bar {
|
94
|
+
}
|
95
|
+
}
|
96
96
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
97
|
+
it: "should be public" for: 'public? when: {
|
98
|
+
Foo instance_method: 'bar . public? should == true
|
99
|
+
Foo instance_method: 'private_bar . public? should == false
|
100
|
+
Foo instance_method: 'protected_bar . public? should == false
|
101
|
+
}
|
102
102
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
103
|
+
it: "should be private" for: 'private? when: {
|
104
|
+
Foo instance_method: 'bar . private? should == false
|
105
|
+
Foo instance_method: 'private_bar . private? should == true
|
106
|
+
Foo instance_method: 'protected_bar . private? should == false
|
107
|
+
}
|
108
108
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
109
|
+
it: "should be protected" for: 'protected? when: {
|
110
|
+
Foo instance_method: 'bar . protected? should == false
|
111
|
+
Foo instance_method: 'private_bar . protected? should == false
|
112
|
+
Foo instance_method: 'protected_bar . protected? should == true
|
113
|
+
}
|
114
114
|
|
115
115
|
it: "should set the default values for optional argument, when not passed in" when: {
|
116
116
|
def foo: arg1 bar: arg2 ("foo") baz: arg3 (nil) {
|
@@ -122,6 +122,17 @@ FancySpec describe: Method with: {
|
|
122
122
|
foo: "hello" . should == "hellofoo"
|
123
123
|
}
|
124
124
|
|
125
|
+
it: "should have default values for all arguments, if none given" when: {
|
126
|
+
def a: arg1 ("foo") b: arg2 ("bar") c: arg3 ("baz") {
|
127
|
+
[arg1, arg2, arg3]
|
128
|
+
}
|
129
|
+
|
130
|
+
a: "hello" b: "world" c: "!" . should == ["hello", "world", "!"]
|
131
|
+
a: "hello" b: "world" . should == ["hello", "world", "baz"]
|
132
|
+
a: "hello" . should == ["hello", "bar", "baz"]
|
133
|
+
a should == ["foo", "bar", "baz"]
|
134
|
+
}
|
135
|
+
|
125
136
|
it: "should return multiple values (as a Tuple)" when: {
|
126
137
|
def multiple_return_values: x {
|
127
138
|
(x, x + x, x + x + x)
|
data/tests/nil_class.fy
CHANGED
@@ -1,23 +1,30 @@
|
|
1
1
|
FancySpec describe: NilClass with: {
|
2
2
|
it: "should be false for calling and: with any value" for: 'and: when: {
|
3
|
-
nil and: true . should ==
|
4
|
-
nil and: 'foo . should ==
|
5
|
-
nil and: nil . should ==
|
3
|
+
nil and: true . should == nil
|
4
|
+
nil and: 'foo . should == nil
|
5
|
+
nil and: nil . should == nil
|
6
|
+
false and: true . should == false
|
7
|
+
false and: 'foo . should == false
|
8
|
+
false and: nil . should == false
|
6
9
|
}
|
7
10
|
|
8
|
-
it: "should be false for calling && with any value" for: '&& when: {
|
9
|
-
(nil && true) should ==
|
10
|
-
(nil && 'foo) should ==
|
11
|
-
(nil && nil) should ==
|
11
|
+
it: "should be nil/false for calling && with any value" for: '&& when: {
|
12
|
+
(nil && true) should == nil
|
13
|
+
(nil && 'foo) should == nil
|
14
|
+
(nil && nil) should == nil
|
15
|
+
(false && true) should == false
|
16
|
+
(false && 'foo) should == false
|
17
|
+
(false && nil) should == false
|
12
18
|
}
|
13
19
|
|
14
20
|
it: "should be true for calling or: with any non-nil value" for: 'or: when: {
|
15
21
|
nil or: true . should == true
|
16
|
-
nil or: 'foo . should ==
|
22
|
+
nil or: 'foo . should == 'foo
|
17
23
|
}
|
18
24
|
|
19
|
-
it: "should be nil for calling or: with a nil value" for: 'or: when: {
|
20
|
-
nil or: nil . should ==
|
25
|
+
it: "should be nil/false for calling or: with a nil/false value" for: 'or: when: {
|
26
|
+
nil or: nil . should == nil
|
27
|
+
nil or: false . should == false
|
21
28
|
}
|
22
29
|
|
23
30
|
it: "should be true for calling || with any non-nil value" for: '|| when: {
|
@@ -33,8 +40,8 @@ FancySpec describe: NilClass with: {
|
|
33
40
|
nil if_true: { 'then } . should == nil
|
34
41
|
}
|
35
42
|
|
36
|
-
it: "should call the block" for: 'if_false: when: {
|
37
|
-
nil if_false: { 'false } . should ==
|
43
|
+
it: "should not call the block" for: 'if_false: when: {
|
44
|
+
nil if_false: { 'false } . should == nil
|
38
45
|
}
|
39
46
|
|
40
47
|
it: "should be nil" for: 'nil? when: {
|
@@ -42,7 +49,7 @@ FancySpec describe: NilClass with: {
|
|
42
49
|
}
|
43
50
|
|
44
51
|
it: "should be false" for: 'false? when: {
|
45
|
-
nil false? should ==
|
52
|
+
nil false? should == false
|
46
53
|
}
|
47
54
|
|
48
55
|
it: "should NOT be true" for: 'true? when: {
|
data/tests/number.fy
CHANGED
@@ -24,12 +24,7 @@ FancySpec describe: Number with: {
|
|
24
24
|
}
|
25
25
|
|
26
26
|
it: "should raise an exception when dividing by zero" when: {
|
27
|
-
|
28
|
-
10 / 0
|
29
|
-
"This should not happen!" should == nil
|
30
|
-
} catch ZeroDivisionError => err {
|
31
|
-
err message should == "divided by 0"
|
32
|
-
}
|
27
|
+
{ 10 / 0 } should raise: ZeroDivisionError
|
33
28
|
}
|
34
29
|
|
35
30
|
it: "should calculate the correct modulo value" for: 'modulo: when: {
|
@@ -62,15 +57,27 @@ FancySpec describe: Number with: {
|
|
62
57
|
0 upto: 10 . should == [0,1,2,3,4,5,6,7,8,9,10]
|
63
58
|
}
|
64
59
|
|
60
|
+
it: "should iterate from 1 upto 10" for: 'upto:do: when: {
|
61
|
+
sum = 0
|
62
|
+
1 upto: 10 do: |n| { sum = sum + n }
|
63
|
+
sum should == 55
|
64
|
+
}
|
65
|
+
|
65
66
|
it: "should return an array from 10 downto 0" for: 'downto: when: {
|
66
67
|
10 downto: 0 . should == [10,9,8,7,6,5,4,3,2,1,0]
|
67
68
|
}
|
68
69
|
|
70
|
+
it: "should iterate from 10 downto 1" for: 'downto:do: when: {
|
71
|
+
sum = 0
|
72
|
+
10 downto: 1 do: |n| { sum = sum + n }
|
73
|
+
sum should == 55
|
74
|
+
}
|
75
|
+
|
69
76
|
it: "should calculate the given power of itself" for: '** when: {
|
70
77
|
2 ** 3 should == 8
|
71
78
|
2 ** 0 should == 1
|
72
79
|
2 ** 1 should == 2
|
73
|
-
0 upto: 10
|
80
|
+
0 upto: 10 do: |i| {
|
74
81
|
i ** 0 should == 1
|
75
82
|
i ** 1 should == i
|
76
83
|
i ** 2 should == (i squared)
|
@@ -80,7 +87,7 @@ FancySpec describe: Number with: {
|
|
80
87
|
it: "should be the square of self" for: 'squared when: {
|
81
88
|
5 squared should == 25
|
82
89
|
10 squared should == 100
|
83
|
-
20 upto: 50
|
90
|
+
20 upto: 50 do: |i| {
|
84
91
|
i squared should == (i * i)
|
85
92
|
}
|
86
93
|
}
|
@@ -88,7 +95,7 @@ FancySpec describe: Number with: {
|
|
88
95
|
it: "should be the double value of self" for: 'doubled when: {
|
89
96
|
5 doubled should == 10
|
90
97
|
10 doubled should == 20
|
91
|
-
20 upto: 50
|
98
|
+
20 upto: 50 do: |i| {
|
92
99
|
i doubled should == (i + i)
|
93
100
|
}
|
94
101
|
}
|