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/lib/iteration.fy
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
class Fancy {
|
2
|
+
class BreakIteration : StdError {
|
3
|
+
read_slots: ['return_value]
|
4
|
+
def initialize: @return_value {}
|
5
|
+
}
|
6
|
+
|
7
|
+
class NextIteration : StdError {
|
8
|
+
read_slots: ['return_value]
|
9
|
+
def initialize: @return_value {}
|
10
|
+
}
|
11
|
+
|
12
|
+
class StopIteration : StdError {
|
13
|
+
"""
|
14
|
+
Raised to stop the iteration, in particular by Enumerator#next.
|
15
|
+
It is rescued by Block#loop.
|
16
|
+
|
17
|
+
Example:
|
18
|
+
{
|
19
|
+
'Hello println
|
20
|
+
StopIteration new raise!
|
21
|
+
'World println
|
22
|
+
} loop
|
23
|
+
'Done! println
|
24
|
+
|
25
|
+
Produces:
|
26
|
+
|
27
|
+
Hello
|
28
|
+
Done!
|
29
|
+
"""
|
30
|
+
|
31
|
+
def initialize { @result = nil }
|
32
|
+
def initialize: @result { }
|
33
|
+
|
34
|
+
def result {
|
35
|
+
"""
|
36
|
+
Returns the return value of the iterator.
|
37
|
+
|
38
|
+
o = Object new
|
39
|
+
def o each: block {
|
40
|
+
block call: 1
|
41
|
+
block call: 2
|
42
|
+
block call: 3
|
43
|
+
100
|
44
|
+
}
|
45
|
+
|
46
|
+
e = o to_enum
|
47
|
+
e next p #=> 1
|
48
|
+
e next p #=> 2
|
49
|
+
e next p #=> 3
|
50
|
+
try {
|
51
|
+
e next
|
52
|
+
} catch Fancy StopIteration => ex {
|
53
|
+
ex result p #=> 100
|
54
|
+
}
|
55
|
+
"""
|
56
|
+
|
57
|
+
@result
|
58
|
+
}
|
59
|
+
}
|
60
|
+
}
|
data/lib/main.fy
CHANGED
@@ -39,7 +39,7 @@ ARGV for_option: "-e" do: |eval_string| {
|
|
39
39
|
}
|
40
40
|
|
41
41
|
ARGV for_option: "-c" do: {
|
42
|
-
ARGV index: "-c" .
|
42
|
+
ARGV index: "-c" . if_true: |idx| {
|
43
43
|
ARGV[[idx + 1, -1]] each: |filename| {
|
44
44
|
"Compiling " ++ filename println
|
45
45
|
Fancy Compiler compile_file: filename to: nil line: 1 print: false
|
@@ -49,7 +49,7 @@ ARGV for_option: "-c" do: {
|
|
49
49
|
}
|
50
50
|
|
51
51
|
ARGV for_option: "-cv" do: {
|
52
|
-
ARGV index: "-cv" .
|
52
|
+
ARGV index: "-cv" . if_true: |idx| {
|
53
53
|
ARGV[[idx + 1, -1]] each: |filename| {
|
54
54
|
"Compiling " ++ filename println
|
55
55
|
Fancy Compiler compile_file: filename to: nil line: 1 print: true
|
@@ -77,7 +77,7 @@ ARGV for_option: "list-packages" do: {
|
|
77
77
|
Fancy Package add_to_loadpath
|
78
78
|
|
79
79
|
# Load a source file, if any given:
|
80
|
-
ARGV first
|
80
|
+
ARGV first if_true: |file| {
|
81
81
|
try {
|
82
82
|
Fancy CodeLoader load_compiled_file: file
|
83
83
|
} catch Fancy Parser ParseError => e {
|
@@ -85,6 +85,6 @@ ARGV first if_do: |file| {
|
|
85
85
|
}
|
86
86
|
}
|
87
87
|
|
88
|
-
ARGV empty?
|
88
|
+
ARGV empty? if_true: {
|
89
89
|
require: "../bin/ifancy"
|
90
90
|
}
|
data/lib/nil_class.fy
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
class NilClass {
|
2
|
-
"NilClass. The class of the singleton nil value."
|
2
|
+
"NilClass. The class of the singleton @nil value."
|
3
3
|
|
4
4
|
def NilClass new {
|
5
5
|
# always return nil singleton object when trying to create a new
|
@@ -7,54 +7,46 @@ class NilClass {
|
|
7
7
|
nil
|
8
8
|
}
|
9
9
|
|
10
|
-
def if_true: then_block else: else_block {
|
11
|
-
"Calls else_block."
|
12
|
-
else_block call
|
13
|
-
}
|
14
|
-
|
15
10
|
def if_true: block {
|
16
|
-
"Returns nil."
|
11
|
+
"Returns @nil."
|
17
12
|
nil
|
18
13
|
}
|
19
14
|
|
20
|
-
def
|
21
|
-
"Calls
|
22
|
-
|
15
|
+
def if_true: then_block else: else_block {
|
16
|
+
"Calls @else_block."
|
17
|
+
else_block call
|
23
18
|
}
|
24
19
|
|
25
20
|
def if_nil: block {
|
26
|
-
|
27
|
-
block call
|
21
|
+
block call: [self]
|
28
22
|
}
|
29
23
|
|
30
|
-
def
|
31
|
-
|
32
|
-
true
|
24
|
+
def if_nil: then_block else: else_block {
|
25
|
+
then_block call: [self]
|
33
26
|
}
|
34
27
|
|
35
|
-
def
|
36
|
-
"Returns true."
|
28
|
+
def nil? {
|
29
|
+
"Returns @true."
|
37
30
|
true
|
38
31
|
}
|
39
32
|
|
40
|
-
def true? {
|
41
|
-
"Returns nil."
|
42
|
-
false
|
43
|
-
}
|
44
|
-
|
45
33
|
def to_s {
|
34
|
+
"Returns an empty @String@."
|
46
35
|
""
|
47
36
|
}
|
48
37
|
|
49
38
|
def to_a {
|
39
|
+
"Returns an empty @Array@."
|
50
40
|
[]
|
51
41
|
}
|
52
42
|
|
53
43
|
def not {
|
44
|
+
"Returns @true."
|
54
45
|
true
|
55
46
|
}
|
56
47
|
|
57
48
|
def inspect {
|
49
|
+
"Returns @nil as a @String@."
|
58
50
|
"nil"
|
59
51
|
}
|
60
52
|
}
|
data/lib/number.fy
CHANGED
@@ -5,6 +5,14 @@ class Number {
|
|
5
5
|
"""
|
6
6
|
|
7
7
|
def upto: num {
|
8
|
+
"""
|
9
|
+
@num @Number@ to create an @Array@ up to.
|
10
|
+
@return @Array@ containing numbers from @self to @num.
|
11
|
+
|
12
|
+
Returns an Array with Numbers starting at @self and going up to @num.
|
13
|
+
Expects @num to be greater or equal to @self.
|
14
|
+
"""
|
15
|
+
|
8
16
|
i = self
|
9
17
|
arr = []
|
10
18
|
while: { i <= num } do: {
|
@@ -14,7 +22,32 @@ class Number {
|
|
14
22
|
arr
|
15
23
|
}
|
16
24
|
|
25
|
+
def upto: num do: block {
|
26
|
+
"""
|
27
|
+
@num Maximum @Number@ to call @block with.
|
28
|
+
@block A @Block@ that should be called with each @Number@ between @self and @num.
|
29
|
+
@return @self
|
30
|
+
|
31
|
+
Calls @block with each @Number@ between @self and @num.
|
32
|
+
Expects @num to be greater or equal to @self.
|
33
|
+
"""
|
34
|
+
i = self
|
35
|
+
while: { i <= num } do: {
|
36
|
+
block call: [i]
|
37
|
+
i = i + 1
|
38
|
+
}
|
39
|
+
self
|
40
|
+
}
|
41
|
+
|
17
42
|
def downto: num {
|
43
|
+
"""
|
44
|
+
@num @Number@ to create an @Array@ down to.
|
45
|
+
@return @Array@ containing numbers from @self down to @num.
|
46
|
+
|
47
|
+
Returns an Array with Numbers starting at @self and going down to @num.
|
48
|
+
Expects @num to be smaller or equal to @self.
|
49
|
+
"""
|
50
|
+
|
18
51
|
i = self
|
19
52
|
arr = []
|
20
53
|
while: { i >= num } do: {
|
@@ -24,6 +57,24 @@ class Number {
|
|
24
57
|
arr
|
25
58
|
}
|
26
59
|
|
60
|
+
def downto: num do: block {
|
61
|
+
"""
|
62
|
+
@num Minimum @Number@ to call @block with.
|
63
|
+
@block A @Block@ that should be called with each @Number@ between @self and @num.
|
64
|
+
@return @self
|
65
|
+
|
66
|
+
Calls @block with each @Number@ between @self and @num.
|
67
|
+
Expects @num to be smaller or equal to @self.
|
68
|
+
"""
|
69
|
+
|
70
|
+
i = self
|
71
|
+
while: { i >= num } do: {
|
72
|
+
block call: [i]
|
73
|
+
i = i - 1
|
74
|
+
}
|
75
|
+
self
|
76
|
+
}
|
77
|
+
|
27
78
|
def squared {
|
28
79
|
"Returns the square of a Number."
|
29
80
|
|
data/lib/object.fy
CHANGED
@@ -17,9 +17,7 @@ class Object {
|
|
17
17
|
|
18
18
|
def loop: block {
|
19
19
|
"Infinitely calls the block (loops)."
|
20
|
-
|
21
|
-
block call
|
22
|
-
}
|
20
|
+
block loop
|
23
21
|
}
|
24
22
|
|
25
23
|
def println {
|
@@ -37,50 +35,49 @@ class Object {
|
|
37
35
|
self == other not
|
38
36
|
}
|
39
37
|
|
40
|
-
def
|
41
|
-
"Calls the block
|
42
|
-
|
38
|
+
def if_true: block {
|
39
|
+
"Calls the @block if @true? returns @true"
|
40
|
+
block call: [self]
|
43
41
|
}
|
44
42
|
|
45
|
-
def
|
46
|
-
"
|
47
|
-
|
43
|
+
def if_true: then_block else: else_block {
|
44
|
+
"Calls the @then_block if @true? returns @true - otherwise @else_block is called"
|
45
|
+
then_block call: [self]
|
48
46
|
}
|
49
47
|
|
50
|
-
def
|
51
|
-
"
|
48
|
+
def if_false: block {
|
49
|
+
"Calls the @block if @false? returns @true@"
|
52
50
|
nil
|
53
51
|
}
|
54
52
|
|
55
|
-
def
|
56
|
-
"
|
57
|
-
|
53
|
+
def if_false: then_block else: else_block {
|
54
|
+
"Calls the @then_block if @false? returns @true - otherwise @else_block is called"
|
55
|
+
else_block call
|
58
56
|
}
|
59
57
|
|
60
|
-
def
|
61
|
-
"
|
58
|
+
def if_nil: block {
|
59
|
+
"Calls the @block if @nil? returns @true@"
|
62
60
|
nil
|
63
61
|
}
|
64
62
|
|
65
|
-
def
|
66
|
-
"
|
63
|
+
def if_nil: then_block else: else_block {
|
64
|
+
"Calls the @then_block if @nil? returns @true - otherwise @else_block is called"
|
65
|
+
else_block call
|
66
|
+
}
|
67
67
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
case _ -> block call: [self]
|
72
|
-
}
|
68
|
+
def nil? {
|
69
|
+
"Returns @false."
|
70
|
+
false
|
73
71
|
}
|
74
72
|
|
75
|
-
def
|
76
|
-
"
|
77
|
-
|
73
|
+
def false? {
|
74
|
+
"Returns @false."
|
75
|
+
false
|
76
|
+
}
|
78
77
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
case _ -> then_block call: [self]
|
83
|
-
}
|
78
|
+
def true? {
|
79
|
+
"Returns @false."
|
80
|
+
false
|
84
81
|
}
|
85
82
|
|
86
83
|
def or_take: other {
|
@@ -105,34 +102,69 @@ class Object {
|
|
105
102
|
0
|
106
103
|
}
|
107
104
|
|
108
|
-
def
|
109
|
-
|
110
|
-
|
105
|
+
def to_enum {
|
106
|
+
FancyEnumerator new: self
|
107
|
+
}
|
108
|
+
|
109
|
+
def to_enum: iterator {
|
110
|
+
FancyEnumerator new: self with: iterator
|
111
|
+
}
|
112
|
+
|
113
|
+
def and: other {
|
114
|
+
"""
|
115
|
+
Boolean conjunction.
|
116
|
+
Returns @other if @self and @other are true-ish, otherwise @false.
|
117
|
+
"""
|
118
|
+
|
119
|
+
if_true: {
|
120
|
+
{ other = other call } if: (other is_a?: Block)
|
121
|
+
return other
|
122
|
+
}
|
123
|
+
return self
|
124
|
+
}
|
125
|
+
|
126
|
+
def or: other {
|
127
|
+
"""
|
128
|
+
Boolean disjunction.
|
129
|
+
Returns true if either @self or other is true, otherwise nil.
|
130
|
+
"""
|
131
|
+
if_true: {
|
111
132
|
return self
|
112
133
|
} else: {
|
134
|
+
{ other = other call } if: (other is_a?: Block)
|
113
135
|
return other
|
114
136
|
}
|
115
137
|
}
|
116
138
|
|
117
|
-
def
|
118
|
-
"
|
119
|
-
|
139
|
+
def or: other {
|
140
|
+
"""
|
141
|
+
Boolean disjunction.
|
142
|
+
Returns true if either @self or other is true, otherwise nil.
|
143
|
+
"""
|
144
|
+
unless: self do: {
|
145
|
+
{ other = other call } if: (other is_a?: Block)
|
146
|
+
return other
|
147
|
+
}
|
148
|
+
return self
|
120
149
|
}
|
121
150
|
|
151
|
+
alias_method: ':&& for: 'and:
|
152
|
+
alias_method: ':|| for: 'or:
|
153
|
+
|
122
154
|
def if: cond then: block {
|
123
155
|
"""
|
124
156
|
Same as:
|
125
|
-
cond
|
157
|
+
cond if_true: block
|
126
158
|
"""
|
127
|
-
cond
|
159
|
+
cond if_true: block
|
128
160
|
}
|
129
161
|
|
130
162
|
def if: cond then: then_block else: else_block {
|
131
163
|
"""
|
132
164
|
Same as:
|
133
|
-
cond
|
165
|
+
cond if_true: then_block else: else_block
|
134
166
|
"""
|
135
|
-
cond
|
167
|
+
cond if_true: then_block else: else_block
|
136
168
|
}
|
137
169
|
|
138
170
|
def while: cond_block do: body_block {
|
@@ -156,10 +188,10 @@ class Object {
|
|
156
188
|
def unless: cond do: block {
|
157
189
|
"""
|
158
190
|
Same as:
|
159
|
-
cond
|
191
|
+
cond if_true: { nil } else: block
|
160
192
|
"""
|
161
193
|
|
162
|
-
cond
|
194
|
+
cond if_true: { nil } else: block
|
163
195
|
}
|
164
196
|
|
165
197
|
def method: method_name {
|
@@ -204,6 +236,37 @@ class Object {
|
|
204
236
|
val
|
205
237
|
}
|
206
238
|
|
239
|
+
def if_responds? {
|
240
|
+
"""
|
241
|
+
@return RespondsToProxy for @self
|
242
|
+
|
243
|
+
Returns a @RespondsToProxy@ for @self that forwards any messages
|
244
|
+
only if @self responds to them.
|
245
|
+
|
246
|
+
Example usage:
|
247
|
+
|
248
|
+
# only send 'some_message: if object responds to it:
|
249
|
+
object if_responds? some_message: some_parameter
|
250
|
+
"""
|
251
|
+
|
252
|
+
RespondsToProxy new: self
|
253
|
+
}
|
254
|
+
|
255
|
+
def backtick: str {
|
256
|
+
"""
|
257
|
+
This is the default implementation for backtick: which gets called when using the backtick syntax.
|
258
|
+
For example:
|
259
|
+
`cat README`
|
260
|
+
Gets translated to the following message send:
|
261
|
+
self backtick: \"cat README\"
|
262
|
+
Which allows for custom implementations of the backtick: method, if needed.
|
263
|
+
This default implementation works the same way as in Ruby, Perl or Bash.
|
264
|
+
It returns the output of running the given string on the command line as a @String@.
|
265
|
+
"""
|
266
|
+
|
267
|
+
System pipe: str . read
|
268
|
+
}
|
269
|
+
|
207
270
|
def ? future {
|
208
271
|
future value
|
209
272
|
}
|
@@ -219,4 +282,24 @@ class Object {
|
|
219
282
|
def wait: seconds {
|
220
283
|
Fiber yield: [seconds]
|
221
284
|
}
|
285
|
+
|
286
|
+
def next {
|
287
|
+
"Skip to the next iteration"
|
288
|
+
Fancy NextIteration new raise!
|
289
|
+
}
|
290
|
+
|
291
|
+
def next: value {
|
292
|
+
"Return value for this iteration and skip to the next one"
|
293
|
+
(Fancy NextIteration new: value) raise!
|
294
|
+
}
|
295
|
+
|
296
|
+
def break {
|
297
|
+
"Stop iterating"
|
298
|
+
Fancy BreakIteration new raise!
|
299
|
+
}
|
300
|
+
|
301
|
+
def break: value {
|
302
|
+
"Return value from iteration"
|
303
|
+
(Fancy BreakIteration new: value) raise!
|
304
|
+
}
|
222
305
|
}
|