fancy 0.3.2 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
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/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" . if_do: |idx| {
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" . if_do: |idx| {
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 if_do: |file| {
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? if_do: {
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 if_false: block {
21
- "Calls the block."
22
- block call
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
- "Calls the block."
27
- block call
21
+ block call: [self]
28
22
  }
29
23
 
30
- def nil? {
31
- "Returns true."
32
- true
24
+ def if_nil: then_block else: else_block {
25
+ then_block call: [self]
33
26
  }
34
27
 
35
- def false? {
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
- { true } while_true: {
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 if_false: block {
41
- "Calls the block."
42
- nil
38
+ def if_true: block {
39
+ "Calls the @block if @true? returns @true"
40
+ block call: [self]
43
41
  }
44
42
 
45
- def if_nil: block {
46
- "Returns nil."
47
- nil
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 nil? {
51
- "Returns nil."
48
+ def if_false: block {
49
+ "Calls the @block if @false? returns @true@"
52
50
  nil
53
51
  }
54
52
 
55
- def false? {
56
- "Returns nil."
57
- nil
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 true? {
61
- "Returns nil."
58
+ def if_nil: block {
59
+ "Calls the @block if @nil? returns @true@"
62
60
  nil
63
61
  }
64
62
 
65
- def if_do: block {
66
- "If the object is non-nil, it calls the given block with itself as argument."
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
- match self {
69
- case nil -> nil
70
- case false -> nil
71
- case _ -> block call: [self]
72
- }
68
+ def nil? {
69
+ "Returns @false."
70
+ false
73
71
  }
74
72
 
75
- def if_do: then_block else: else_block {
76
- """If the object is non-nil, it calls the given then_block with itself as argument.
77
- Otherwise it calls the given else_block."""
73
+ def false? {
74
+ "Returns @false."
75
+ false
76
+ }
78
77
 
79
- match self {
80
- case nil -> else_block call: [self]
81
- case false -> else_block call: [self]
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 || other {
109
- "Returns @ self if self is true-ish, otherwise returns @other"
110
- self if_do: {
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 && other {
118
- "Same as Object#and:"
119
- and: other
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 if_do: block
157
+ cond if_true: block
126
158
  """
127
- cond if_do: block
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 if_do: then_block else: else_block
165
+ cond if_true: then_block else: else_block
134
166
  """
135
- cond if_do: then_block else: else_block
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 if_do: { nil } else: block
191
+ cond if_true: { nil } else: block
160
192
  """
161
193
 
162
- cond if_do: { nil } else: block
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
  }