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/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
|
}
|