fancy 0.3.2 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- 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/block.fy
CHANGED
@@ -139,4 +139,48 @@ FancySpec describe: Block with: {
|
|
139
139
|
b receiver: "Hello, World!"
|
140
140
|
b receiver should == "Hello, World!"
|
141
141
|
}
|
142
|
+
|
143
|
+
it: "should call a block with a different receiver" for: 'call_with_receiver when: {
|
144
|
+
class ClassA {
|
145
|
+
def inspect {
|
146
|
+
"in ClassA#inspect"
|
147
|
+
}
|
148
|
+
}
|
149
|
+
class ClassB {
|
150
|
+
def inspect {
|
151
|
+
"in ClassB#inspect"
|
152
|
+
}
|
153
|
+
}
|
154
|
+
def self inspect {
|
155
|
+
"in self#inspect"
|
156
|
+
}
|
157
|
+
block = {
|
158
|
+
self inspect
|
159
|
+
}
|
160
|
+
block call should == "in self#inspect"
|
161
|
+
block call_with_receiver: (ClassA new) . should == "in ClassA#inspect"
|
162
|
+
block call_with_receiver: (ClassB new) . should == "in ClassB#inspect"
|
163
|
+
}
|
164
|
+
|
165
|
+
it: "should call a block with arguments and a different receiver" for: 'call:with_receiver: when: {
|
166
|
+
class ClassC {
|
167
|
+
def inspect: x {
|
168
|
+
"in ClassC#inspect: #{x}"
|
169
|
+
}
|
170
|
+
}
|
171
|
+
class ClassD {
|
172
|
+
def inspect: x {
|
173
|
+
"in ClassD#inspect: #{x}"
|
174
|
+
}
|
175
|
+
}
|
176
|
+
def self inspect: x {
|
177
|
+
"in self#inspect: #{x}"
|
178
|
+
}
|
179
|
+
block = |arg| {
|
180
|
+
self inspect: arg
|
181
|
+
}
|
182
|
+
block call: [42] . should == "in self#inspect: 42"
|
183
|
+
block call: [42] with_receiver: (ClassC new) . should == "in ClassC#inspect: 42"
|
184
|
+
block call: [42] with_receiver: (ClassD new) . should == "in ClassD#inspect: 42"
|
185
|
+
}
|
142
186
|
}
|
data/tests/class.fy
CHANGED
@@ -172,34 +172,34 @@ FancySpec describe: Class with: {
|
|
172
172
|
instance foo: "Test!" . should == "In AClass#foo: with bar = Test!"
|
173
173
|
}
|
174
174
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
175
|
+
it: "should call superclass method by using super" when: {
|
176
|
+
class SuperClass {
|
177
|
+
read_slots: ['name]
|
178
|
+
def initialize: name {
|
179
|
+
@name = name
|
180
|
+
}
|
181
|
+
}
|
182
|
+
class SubClass : SuperClass {
|
183
|
+
read_slots: ['age]
|
184
184
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
185
|
+
def initialize: age {
|
186
|
+
super initialize: "SubClass"
|
187
|
+
@age = age
|
188
|
+
}
|
189
|
+
|
190
|
+
def initialize {
|
191
|
+
initialize: 0
|
192
|
+
}
|
193
|
+
}
|
194
194
|
|
195
|
-
|
196
|
-
|
197
|
-
|
195
|
+
sub = SubClass new: 42
|
196
|
+
sub name should == "SubClass"
|
197
|
+
sub age should == 42
|
198
198
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
199
|
+
sub2 = SubClass new
|
200
|
+
sub2 name should == "SubClass"
|
201
|
+
sub2 age should == 0
|
202
|
+
}
|
203
203
|
|
204
204
|
it: "should return its superclass" when: {
|
205
205
|
Fixnum superclass should == Integer
|
@@ -212,19 +212,19 @@ FancySpec describe: Class with: {
|
|
212
212
|
NoMethodError superclass should == NameError
|
213
213
|
}
|
214
214
|
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
215
|
+
it: "should create a new Class dynamically" when: {
|
216
|
+
x = Class new
|
217
|
+
x is_a?: Class . should == true
|
218
|
+
x new is_a?: x . should == true
|
219
|
+
x new is_a?: Object . should == true
|
220
|
+
x new class should == x
|
221
|
+
|
222
|
+
# Symbol as superclass
|
223
|
+
y = Class new: String
|
224
|
+
y is_a?: Class . should == true
|
225
|
+
y new is_a?: String . should == true
|
226
|
+
# y new is_a?: Object . should == true
|
227
|
+
}
|
228
228
|
|
229
229
|
it: "should only be able to call the public method from outside the Class" when: {
|
230
230
|
x = ClassWithPrivate new
|
@@ -232,12 +232,12 @@ FancySpec describe: Class with: {
|
|
232
232
|
try {
|
233
233
|
x private_method should == nil # should fail
|
234
234
|
} catch NoMethodError => e {
|
235
|
-
e method_name should ==
|
235
|
+
e method_name should == 'private_method
|
236
236
|
}
|
237
237
|
try {
|
238
238
|
x protected_method should == nil # should fail
|
239
239
|
} catch NoMethodError => e {
|
240
|
-
e method_name should ==
|
240
|
+
e method_name should == 'protected_method
|
241
241
|
}
|
242
242
|
}
|
243
243
|
|
@@ -253,28 +253,28 @@ FancySpec describe: Class with: {
|
|
253
253
|
Super subclass?: Sub . should == nil
|
254
254
|
}
|
255
255
|
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
256
|
+
it: "should dynamically create a subclass of another class" for: 'is_a?: when: {
|
257
|
+
subclass = String subclass: {
|
258
|
+
def foo {
|
259
|
+
"hello, world!"
|
260
|
+
}
|
261
|
+
}
|
262
|
+
subclass is_a?: Class . should == true
|
263
|
+
subclass subclass?: String . should == true
|
264
|
+
subclass new is_a?: subclass . should == true
|
265
|
+
subclass new foo should == "hello, world!"
|
266
|
+
|
267
|
+
# now the same with Class##new:body:
|
268
|
+
subclass2 = Class superclass: String body: {
|
269
|
+
def foo {
|
270
|
+
"hello, world, again!"
|
271
|
+
}
|
272
|
+
}
|
273
|
+
subclass2 is_a?: Class . should == true
|
274
|
+
subclass2 subclass?: String . should == true
|
275
|
+
subclass2 new is_a?: subclass2 . should == true
|
276
|
+
subclass2 new foo should == "hello, world, again!"
|
277
|
+
}
|
278
278
|
|
279
279
|
it: "should undefine an instance method" for: 'undefine_method: when: {
|
280
280
|
class Foo {
|
@@ -288,7 +288,7 @@ FancySpec describe: Class with: {
|
|
288
288
|
try {
|
289
289
|
f instance_method should == nil # should not get here
|
290
290
|
} catch NoMethodError => e {
|
291
|
-
e method_name should ==
|
291
|
+
e method_name should == 'instance_method
|
292
292
|
}
|
293
293
|
}
|
294
294
|
|
@@ -312,34 +312,34 @@ FancySpec describe: Class with: {
|
|
312
312
|
try {
|
313
313
|
Foo class_method should == nil # should not get here
|
314
314
|
} catch NoMethodError => e {
|
315
|
-
e method_name should ==
|
315
|
+
e method_name should == 'class_method
|
316
316
|
}
|
317
317
|
}
|
318
318
|
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
319
|
+
it: "should have nested classes" when: {
|
320
|
+
class Outer {
|
321
|
+
class Inner {
|
322
|
+
class InnerMost {
|
323
|
+
def foobar {
|
324
|
+
"foobar!"
|
325
|
+
}
|
326
|
+
}
|
327
|
+
}
|
328
|
+
}
|
329
|
+
Outer is_a?: Class . should == true
|
330
|
+
Outer::Inner is_a?: Class . should == true
|
331
|
+
Outer::Inner::InnerMost is_a?: Class . should == true
|
332
|
+
obj = Outer::Inner::InnerMost new
|
333
|
+
obj foobar should == "foobar!"
|
334
|
+
|
335
|
+
# change InnerMost#foobar
|
336
|
+
class Outer::Inner::InnerMost {
|
337
|
+
def foobar {
|
338
|
+
"oh no!"
|
339
|
+
}
|
340
|
+
}
|
341
|
+
obj foobar . should == "oh no!"
|
342
|
+
}
|
343
343
|
|
344
344
|
it: "should not override existing classes with the same name in a nested class" when: {
|
345
345
|
StdArray = Array
|
@@ -433,6 +433,20 @@ FancySpec describe: Class with: {
|
|
433
433
|
obj bar should == "in foo!"
|
434
434
|
}
|
435
435
|
|
436
|
+
it: "should have an alias method for a ruby method defined" for: 'alias_method:for_ruby: when: {
|
437
|
+
try {
|
438
|
+
[] equal?: [1,2] . should == true # should fail
|
439
|
+
} catch NoMethodError => e {
|
440
|
+
e method_name should == 'equal?:
|
441
|
+
}
|
442
|
+
|
443
|
+
class Array {
|
444
|
+
alias_method: 'equal?: for_ruby: 'equal?
|
445
|
+
}
|
446
|
+
|
447
|
+
[] equal?: [1,2] . should == false
|
448
|
+
}
|
449
|
+
|
436
450
|
it: "should have the correct list of ancestors" for: 'ancestors when: {
|
437
451
|
class A {
|
438
452
|
}
|
data/tests/control_flow.fy
CHANGED
@@ -43,37 +43,160 @@ FancySpec describe: "Control Flow" with: {
|
|
43
43
|
}
|
44
44
|
}
|
45
45
|
|
46
|
-
it: "should only call the block if it's a true-ish value" for: '
|
47
|
-
1
|
46
|
+
it: "should only call the block if it's a true-ish value" for: 'if_true: when: {
|
47
|
+
1 if_true: |num| {
|
48
48
|
num * 10
|
49
49
|
} . should == 10
|
50
50
|
|
51
|
-
nil
|
51
|
+
nil if_true: {
|
52
52
|
"nope"
|
53
53
|
} . should == nil
|
54
54
|
|
55
|
-
false
|
55
|
+
false if_true: {
|
56
56
|
"nope again"
|
57
57
|
} . should == nil
|
58
58
|
}
|
59
59
|
|
60
|
-
it: "should call the then_block if it's a true-ish value and call the else_block otherwise" for: '
|
61
|
-
1
|
60
|
+
it: "should call the then_block if it's a true-ish value and call the else_block otherwise" for: 'if_true:else: when: {
|
61
|
+
1 if_true: |num| {
|
62
62
|
num * 10
|
63
63
|
} else: {
|
64
64
|
nil
|
65
65
|
} . should == 10
|
66
66
|
|
67
|
-
nil
|
67
|
+
nil if_true: {
|
68
68
|
"nope"
|
69
69
|
} else: {
|
70
70
|
"yup"
|
71
71
|
} . should == "yup"
|
72
72
|
|
73
|
-
false
|
73
|
+
false if_true: {
|
74
74
|
"nope again"
|
75
75
|
} else: {
|
76
76
|
"yup again"
|
77
77
|
} . should == "yup again"
|
78
78
|
}
|
79
|
+
|
80
|
+
it: "should be possible to override the if_true:else: method and work accordingly in conditionals" when: {
|
81
|
+
class AClasThatIsLikeFalse {
|
82
|
+
def if_true: block else: another_block {
|
83
|
+
another_block call
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
obj = AClasThatIsLikeFalse new
|
88
|
+
if: obj then: {
|
89
|
+
'fail
|
90
|
+
} else: {
|
91
|
+
'success
|
92
|
+
} . should == 'success
|
93
|
+
|
94
|
+
# let's get rid of this custom if_true:else: method
|
95
|
+
AClasThatIsLikeFalse undefine_method: 'if_true:else:
|
96
|
+
|
97
|
+
if: obj then: {
|
98
|
+
'now_this_is_success
|
99
|
+
} else: {
|
100
|
+
'fail
|
101
|
+
} . should == 'now_this_is_success
|
102
|
+
}
|
103
|
+
|
104
|
+
it: "should break from an iteration" for: 'break when: {
|
105
|
+
x = 0
|
106
|
+
until: { x == 10 } do: {
|
107
|
+
x = x + 1
|
108
|
+
{ break } if: (x == 5)
|
109
|
+
}
|
110
|
+
x == 5 should == true
|
111
|
+
}
|
112
|
+
|
113
|
+
it: "should break from an iteration with return value" for: 'break: when: {
|
114
|
+
x = 0
|
115
|
+
y = until: { x == 10 } do: {
|
116
|
+
x = x + 1
|
117
|
+
{ break: 42 } if: (x == 5)
|
118
|
+
}
|
119
|
+
|
120
|
+
x should == 5
|
121
|
+
y should == 42
|
122
|
+
}
|
123
|
+
|
124
|
+
it: "should skip an iteration over a Range" for: 'next when: {
|
125
|
+
total = 0
|
126
|
+
(1..10) each: |i| {
|
127
|
+
{ next } if: (i == 5)
|
128
|
+
total = total + i
|
129
|
+
}
|
130
|
+
total should == 50
|
131
|
+
}
|
132
|
+
|
133
|
+
it: "should skip an iteration over an Array" for: 'next when: {
|
134
|
+
total = 0
|
135
|
+
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] each: |i| {
|
136
|
+
{ next } if: (i == 5)
|
137
|
+
total = total + i
|
138
|
+
}
|
139
|
+
total should == 50
|
140
|
+
}
|
141
|
+
|
142
|
+
it: "should skip an iteration over an Hash" for: 'next when: {
|
143
|
+
total = 0
|
144
|
+
<['a => 1, 'b => 2, 'c => 3, 'd => 4, 'e => 5, 'f => 6]> each: |k v| {
|
145
|
+
{ next } if: (k == 'd)
|
146
|
+
total = total + v
|
147
|
+
}
|
148
|
+
total should == 17
|
149
|
+
}
|
150
|
+
|
151
|
+
it: "stops any loop type at the correct spot" for: 'break when: {
|
152
|
+
i = 0
|
153
|
+
loop: {
|
154
|
+
{ break } if: (i == 3)
|
155
|
+
i = i + 1
|
156
|
+
}
|
157
|
+
i should == 3
|
158
|
+
|
159
|
+
i = 0
|
160
|
+
while: { i < 5 } do: {
|
161
|
+
{ break } if: (i == 3)
|
162
|
+
i = i + 1
|
163
|
+
}
|
164
|
+
i should == 3
|
165
|
+
|
166
|
+
i = 0
|
167
|
+
0 upto: 5 do: |n| {
|
168
|
+
i = n
|
169
|
+
{ break } if: (n == 3)
|
170
|
+
}
|
171
|
+
i should == 3
|
172
|
+
}
|
173
|
+
|
174
|
+
it: "stops any loop type at the correct spot" for: 'break: when: {
|
175
|
+
i = 0
|
176
|
+
loop: {
|
177
|
+
{ break: i } if: (i == 2)
|
178
|
+
i = i + 1
|
179
|
+
} . should == 2
|
180
|
+
|
181
|
+
i = 0
|
182
|
+
while: { i < 5 } do: {
|
183
|
+
{ break: i } if: (i == 2)
|
184
|
+
i = i + 1
|
185
|
+
} . should == 2
|
186
|
+
|
187
|
+
i = 0
|
188
|
+
0 upto: 5 do: |n| {
|
189
|
+
i = n
|
190
|
+
{ break: n } if: (n == 2)
|
191
|
+
}
|
192
|
+
i should == 2
|
193
|
+
}
|
194
|
+
|
195
|
+
it: "should allow empty try blocks" when: {
|
196
|
+
x = "foo"
|
197
|
+
try {
|
198
|
+
} finally {
|
199
|
+
x should == "foo"
|
200
|
+
}
|
201
|
+
}
|
79
202
|
}
|