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.
Files changed (98) hide show
  1. data/README.md +4 -1
  2. data/Rakefile +8 -0
  3. data/bin/fyi +25 -20
  4. data/bin/ifancy +39 -5
  5. data/{extconf.rb → boot/extconf.rb} +1 -1
  6. data/boot/fancy_ext/block_env.rb +0 -14
  7. data/boot/fancy_ext/kernel.rb +6 -2
  8. data/boot/rbx-compiler/parser/fancy_parser.bundle +0 -0
  9. data/examples/actor.fy +37 -0
  10. data/examples/armstrong_numbers.fy +1 -1
  11. data/examples/curl_async.fy +37 -0
  12. data/examples/echo.fy +1 -1
  13. data/examples/factorial.fy +1 -1
  14. data/examples/future_composition.fy +20 -0
  15. data/examples/game_of_life.fy +2 -2
  16. data/examples/person.fy +4 -8
  17. data/examples/rbx/blocks.fy +1 -1
  18. data/examples/return.fy +1 -1
  19. data/examples/struct.fy +9 -0
  20. data/lib/argv.fy +2 -2
  21. data/lib/array.fy +157 -0
  22. data/lib/block.fy +18 -1
  23. data/lib/boot.fy +5 -1
  24. data/lib/compiler/ast/class_def.fy +1 -1
  25. data/lib/compiler/ast/identifier.fy +2 -2
  26. data/lib/compiler/ast/message_send.fy +2 -2
  27. data/lib/compiler/ast/method_def.fy +2 -2
  28. data/lib/compiler/ast/try_catch.fy +5 -1
  29. data/lib/documentation.fy +1 -1
  30. data/lib/enumerable.fy +3 -7
  31. data/lib/enumerator.fy +77 -0
  32. data/lib/false_class.fy +52 -0
  33. data/lib/fancy_spec.fy +40 -12
  34. data/lib/fdoc.fy +2 -2
  35. data/lib/file.fy +8 -1
  36. data/lib/future.fy +23 -2
  37. data/lib/iteration.fy +60 -0
  38. data/lib/main.fy +4 -4
  39. data/lib/nil_class.fy +14 -22
  40. data/lib/number.fy +51 -0
  41. data/lib/object.fy +126 -43
  42. data/lib/package/installer.fy +1 -1
  43. data/lib/parser/ext/lexer.lex +6 -1
  44. data/lib/parser/ext/parser.y +18 -0
  45. data/lib/parser/methods.fy +20 -2
  46. data/lib/proxy.fy +20 -3
  47. data/lib/rbx.fy +0 -1
  48. data/lib/rbx/array.fy +4 -138
  49. data/lib/rbx/block.fy +25 -1
  50. data/lib/rbx/class.fy +21 -0
  51. data/lib/rbx/exception.fy +1 -0
  52. data/lib/rbx/fiber.fy +1 -0
  53. data/lib/rbx/file.fy +8 -0
  54. data/lib/rbx/integer.fy +0 -8
  55. data/lib/rbx/method.fy +34 -7
  56. data/lib/rbx/no_method_error.fy +8 -1
  57. data/lib/rbx/object.fy +3 -32
  58. data/lib/rbx/range.fy +13 -1
  59. data/lib/rbx/regexp.fy +3 -0
  60. data/lib/rbx/string.fy +6 -1
  61. data/lib/rbx/system.fy +20 -2
  62. data/lib/set.fy +2 -2
  63. data/lib/string.fy +1 -1
  64. data/lib/struct.fy +15 -12
  65. data/lib/symbol.fy +2 -2
  66. data/lib/true_class.fy +16 -20
  67. data/lib/version.fy +1 -1
  68. data/tests/argv.fy +1 -0
  69. data/tests/array.fy +33 -2
  70. data/tests/block.fy +44 -0
  71. data/tests/class.fy +102 -88
  72. data/tests/control_flow.fy +131 -8
  73. data/tests/enumerator.fy +85 -0
  74. data/tests/exception.fy +13 -13
  75. data/tests/file.fy +4 -13
  76. data/tests/future.fy +26 -0
  77. data/tests/method.fy +83 -72
  78. data/tests/nil_class.fy +20 -13
  79. data/tests/number.fy +16 -9
  80. data/tests/object.fy +39 -20
  81. data/tests/string.fy +7 -0
  82. data/tests/true_class.fy +4 -4
  83. data/tools/fancy-mode.el +1 -1
  84. metadata +15 -20
  85. data/boot/compiler/parser/ext/fancy_parser.bundle +0 -0
  86. data/boot/rbx-compiler/parser/Makefile +0 -162
  87. data/boot/rbx-compiler/parser/lexer.c +0 -2316
  88. data/boot/rbx-compiler/parser/lexer.h +0 -315
  89. data/boot/rbx-compiler/parser/parser.c +0 -3105
  90. data/boot/rbx-compiler/parser/parser.h +0 -114
  91. data/lib/lazy_array.fy +0 -23
  92. data/lib/parser/ext/Makefile +0 -162
  93. data/lib/parser/ext/fancy_parser.bundle +0 -0
  94. data/lib/parser/ext/lexer.c +0 -2360
  95. data/lib/parser/ext/lexer.h +0 -315
  96. data/lib/parser/ext/parser.c +0 -3382
  97. data/lib/parser/ext/parser.h +0 -118
  98. 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
- # it: "should call superclass method by calling 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]
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
- # def initialize: age {
186
- # super initialize: "SubClass"
187
- # @age = age
188
- # }
189
- # def initialize {
190
- # super initialize: "SubClass"
191
- # @age = 0
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
- # sub = SubClass new: 42
196
- # sub name should == "SubClass"
197
- # sub age should == 42
195
+ sub = SubClass new: 42
196
+ sub name should == "SubClass"
197
+ sub age should == 42
198
198
 
199
- # sub2 = SubClass new
200
- # sub2 name should == "SubClass"
201
- # sub2 age should == 0
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
- # 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: Symbol
224
- # y is_a?: Class . should == true
225
- # y new is_a?: Symbol . should == true
226
- # y new is_a?: Object . should == true
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 == "private_method"
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 == "protected_method"
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
- # 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: Symbol 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
- # }
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 == "instance_method"
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 == "class_method"
315
+ e method_name should == 'class_method
316
316
  }
317
317
  }
318
318
 
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
- # }
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
  }
@@ -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: 'if_do: when: {
47
- 1 if_do: |num| {
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 if_do: {
51
+ nil if_true: {
52
52
  "nope"
53
53
  } . should == nil
54
54
 
55
- false if_do: {
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: 'if_do:else: when: {
61
- 1 if_do: |num| {
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 if_do: {
67
+ nil if_true: {
68
68
  "nope"
69
69
  } else: {
70
70
  "yup"
71
71
  } . should == "yup"
72
72
 
73
- false if_do: {
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
  }