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
@@ -168,7 +168,7 @@ class Fancy Package {
168
168
  If no @.fancypack file is found, raise an error.
169
169
  """
170
170
 
171
- Dir glob(installed_path ++ "/*.fancypack") first if_do: |fpackfile| {
171
+ Dir glob(installed_path ++ "/*.fancypack") first if_true: |fpackfile| {
172
172
  require: fpackfile
173
173
  }
174
174
 
@@ -23,6 +23,7 @@ hex_lit 0[xX]{hexdigit}+
23
23
  bin_lit 0[bB]{bindigit}+
24
24
  oct_lit 0[oO]{octdigit}+
25
25
  string_lit L?\"(\\.|[^\\"])*\"
26
+ backtick_lit L?`(\\.|[^`])*`
26
27
  multiline_string L?\"\"\"(\\.|[^\\"])*\"\"\"
27
28
  lparen \(
28
29
  rparen \)
@@ -56,7 +57,7 @@ identifier @?@?({lower}|[_&*])({letter}|{digit}|{special_under})*
56
57
  selector ({letter}|[_&*])({letter}|{digit}|{special_under})*":"
57
58
  constant {capital}({letter}|{digit}|{special_under})*
58
59
  nested_constant ({constant}::)+{constant}
59
- symbol_lit \'({identifier}|{operator}|:|"[]")+
60
+ symbol_lit \'({identifier}|{operator}|{constant}|:|"[]")+
60
61
  ruby_send_open {identifier}{lparen}
61
62
  ruby_oper_open {operator}{lparen}
62
63
  regexp_lit "/".*"/"
@@ -100,6 +101,10 @@ escaped_newline "\\".*\n
100
101
  yylval.object = rb_str_new2(yytext);
101
102
  return STRING_LITERAL;
102
103
  }
104
+ {backtick_lit} {
105
+ yylval.object = rb_str_new2(yytext);
106
+ return BACKTICK_LITERAL;
107
+ }
103
108
  {multiline_string} {
104
109
  yylval.object = rb_str_new2(yytext);
105
110
  return MULTI_STRING_LITERAL;
@@ -73,6 +73,7 @@ extern char *yytext;
73
73
  %token SYMBOL_LITERAL
74
74
  %token REGEX_LITERAL
75
75
  %token OPERATOR
76
+ %token BACKTICK_LITERAL
76
77
 
77
78
  %left DOT
78
79
  %right DOLLAR
@@ -159,6 +160,8 @@ extern char *yytext;
159
160
  %type <object> match_body
160
161
  %type <object> match_clause
161
162
 
163
+ %type <object> backtick_literal
164
+
162
165
  %%
163
166
 
164
167
  programm: /*empty*/
@@ -360,6 +363,9 @@ method_args: method_arg {
360
363
  | method_args method_args_default {
361
364
  $$ = rb_funcall(self, rb_intern("ast:concat:into:"), 3, INT2NUM(yylineno), $2, $1);
362
365
  }
366
+ | method_args_default {
367
+ $$ = rb_funcall(self, rb_intern("ast:concat:"), 2, INT2NUM(yylineno), $1);
368
+ }
363
369
  ;
364
370
 
365
371
  method_arg_default: selector identifier LPAREN space exp space RPAREN {
@@ -534,6 +540,12 @@ ruby_send: exp ruby_send_open ruby_args {
534
540
  | ruby_send_open ruby_args {
535
541
  $$ = rb_funcall(self, rb_intern("ast:send:to:ruby:"), 4, INT2NUM(yylineno), $1, Qnil, $2);
536
542
  }
543
+ | exp FUTURE_SEND ruby_send_open ruby_args {
544
+ $$ = rb_funcall(self, rb_intern("ast:future_send:to:ruby:"), 4, INT2NUM(yylineno), $3, $1, $4);
545
+ }
546
+ | exp ASYNC_SEND ruby_send_open ruby_args {
547
+ $$ = rb_funcall(self, rb_intern("ast:async_send:to:ruby:"), 4, INT2NUM(yylineno), $3, $1, $4);
548
+ }
537
549
  ;
538
550
 
539
551
  /*
@@ -659,6 +671,7 @@ literal_value: integer_literal
659
671
  | block_literal
660
672
  | tuple_literal
661
673
  | range_literal
674
+ | backtick_literal
662
675
  ;
663
676
 
664
677
  array_literal: empty_array {
@@ -714,6 +727,11 @@ range_literal: LPAREN exp DOT DOT exp RPAREN {
714
727
  }
715
728
  ;
716
729
 
730
+ backtick_literal: BACKTICK_LITERAL {
731
+ $$ = fy_terminal_node(self, "ast:backtick:");
732
+ }
733
+ ;
734
+
717
735
  block_args: block_args_with_comma
718
736
  | block_args_without_comma
719
737
  ;
@@ -97,6 +97,13 @@ class Fancy {
97
97
  ast: line string: (string from: 2 to: -3)
98
98
  }
99
99
 
100
+ def ast: line backtick: backtick_string {
101
+ str = ast: line string: backtick_string
102
+ selector = (ast: line identifier: "backtick:")
103
+ args = AST MessageArgs new: line args: [str]
104
+ AST MessageSend new: line message: selector to: (AST Self new: line) args: args
105
+ }
106
+
100
107
  def ast: line array: expr_ary {
101
108
  AST ArrayLiteral new: line array: expr_ary
102
109
  }
@@ -140,7 +147,7 @@ class Fancy {
140
147
  }
141
148
 
142
149
  def ast: line assign: rvalue to: lvalue many: many (false) {
143
- ast = many if_do: { AST MultipleAssignment } else: { AST Assignment }
150
+ ast = many if_true: { AST MultipleAssignment } else: { AST Assignment }
144
151
  ast new: line var: lvalue value: rvalue
145
152
  }
146
153
 
@@ -168,7 +175,7 @@ class Fancy {
168
175
  }
169
176
 
170
177
  def ast: line send: message to: receiver (AST Self new: line) ruby: ruby (nil) {
171
- args = ruby if_do: {
178
+ args = ruby if_true: {
172
179
  unless: receiver do: {
173
180
  receiver = AST Self new: line
174
181
  }
@@ -211,6 +218,10 @@ class Fancy {
211
218
  (margs size - idx) times: |pos| {
212
219
  required = margs from: 0 to: (idx + pos - 1)
213
220
  default = margs from: (idx + pos) to: -1
221
+ only_default_args = default size == (margs size)
222
+ if: only_default_args then: {
223
+ required = []
224
+ }
214
225
  params = required map: |r| { r variable() } . + $ default map: |d| { d default() }
215
226
 
216
227
  forward = AST MessageSend new: line \
@@ -220,6 +231,13 @@ class Fancy {
220
231
 
221
232
  doc = AST StringLiteral new: line value: ("Forward to message " ++ target)
222
233
  body = AST ExpressionList new: line list: [doc, forward]
234
+
235
+ # use base method name (e.g. "foo:" -> "foo") for the method to be generated
236
+ # if there are no more arguments left (only default args left)
237
+ if: only_default_args then: {
238
+ required = AST Identifier from: (margs first selector() string from: 0 to: -2) line: line
239
+ }
240
+
223
241
  block call: [required, body]
224
242
  }
225
243
  }
data/lib/proxy.fy CHANGED
@@ -8,9 +8,26 @@ class ProxyReceiver : BasicObject {
8
8
  }
9
9
 
10
10
  def unknown_message: msg with_params: params {
11
- @proxy send: msg params: params
12
- @obj send: msg params: params
11
+ @proxy send_message: msg with_params: params
12
+ @obj send_message: msg with_params: params
13
13
  }
14
14
  }
15
15
 
16
- Proxy = ProxyReceiver
16
+ Proxy = ProxyReceiver
17
+
18
+ class RespondsToProxy : BasicObject {
19
+ """
20
+ A RespondsToProxy is a Proxy that forwards any message sent to it to it's @target instance variable
21
+ only if it responds to that message. Any messages that @target doesn't respond to simply won't be sent
22
+ and @nil will be returned.
23
+ """
24
+
25
+ def initialize: @target {
26
+ }
27
+
28
+ def unknown_message: msg with_params: params {
29
+ if: (@target responds_to?: msg) then: {
30
+ @target send_message: msg with_params: params
31
+ }
32
+ }
33
+ }
data/lib/rbx.fy CHANGED
@@ -11,7 +11,6 @@ require: "rbx/class"
11
11
  require: "rbx/console"
12
12
  require: "rbx/array"
13
13
  require: "rbx/hash"
14
- require: "rbx/false_class"
15
14
  require: "rbx/string"
16
15
  require: "rbx/symbol"
17
16
  require: "rbx/integer"
data/lib/rbx/array.fy CHANGED
@@ -10,6 +10,7 @@ class Array {
10
10
  ruby_alias: 'last
11
11
  ruby_alias: 'shuffle
12
12
  ruby_alias: 'inspect
13
+ ruby_alias: 'shift
13
14
 
14
15
  def Array new: size with: default {
15
16
  "Creates a new Array with a given size and default-value."
@@ -17,49 +18,12 @@ class Array {
17
18
  Array new(size, default)
18
19
  }
19
20
 
20
- def Array new: size {
21
- "Creates a new Array with a given size (default value is nil)."
22
-
23
- Array new: size with: nil
24
- }
25
-
26
- def append: arr {
27
- "Appends another Array onto this one."
28
-
29
- arr each: |x| {
30
- self << x
31
- }
32
- self
33
- }
34
-
35
21
  def includes?: obj {
36
22
  "Indicates, if an Array includes a given value."
37
23
 
38
24
  include?(obj)
39
25
  }
40
26
 
41
- def clone {
42
- "Clones (shallow copy) the Array."
43
- new = []
44
- each: |x| {
45
- new << x
46
- }
47
- new
48
- }
49
-
50
- def each: block {
51
- """
52
- @block @Block@ to be called for each element in @self.
53
- @return Return value of calling @block on the last item in @self.
54
-
55
- Calls a given @Block@ with each element in the @Array@.
56
- """
57
-
58
- val = nil
59
- each() |x| { val = block call: [x] }
60
- val
61
- }
62
-
63
27
  def remove_at: index {
64
28
  """
65
29
  Removes an element at a given index.
@@ -94,7 +58,7 @@ class Array {
94
58
  Returns the element in the @Array@ at a given index.
95
59
  """
96
60
 
97
- ruby: '[] args: [idx]
61
+ at(idx)
98
62
  }
99
63
 
100
64
  def at: idx put: obj {
@@ -105,24 +69,9 @@ class Array {
105
69
 
106
70
  Inserts a given object at a given index (position) in the Array.
107
71
  """
108
-
109
72
  ruby: '[]= args: [idx, obj]
110
73
  }
111
74
 
112
- def each_with_index: block {
113
- """
114
- @block @Block@ to be called with each element and its inde in the @Array@.
115
-
116
- Iterate over all elements in Array. Calls a given Block with each element and its index.
117
- """
118
-
119
- i = 0
120
- each: |x| {
121
- block call: [x, i]
122
- i = i + 1
123
- }
124
- }
125
-
126
75
  def index: item {
127
76
  """
128
77
  @item Item/Value for which the index is requested within an @Array@.
@@ -133,44 +82,6 @@ class Array {
133
82
  index(item)
134
83
  }
135
84
 
136
- def indices_of: item {
137
- """
138
- @item Item/Value for which a list of indices is requested within an @Array@.
139
- @return @Array@ of all indices for a given value within an @Array@ (possibly empty).
140
-
141
- Returns an Array of all indices of this item. Empty Array if item does not occur.
142
- """
143
-
144
- tmp = []
145
- each_with_index: |obj, idx| {
146
- if: (item == obj) then: {
147
- tmp << idx
148
- }
149
- }
150
- tmp
151
- }
152
-
153
- def from: from to: to {
154
- """
155
- @from Start index for sub-array.
156
- @to End index ofr sub-array.
157
-
158
- Returns sub-array starting at from: and going to to:
159
- """
160
-
161
- if: (from < 0) then: {
162
- from = size + from
163
- }
164
- if: (to < 0) then: {
165
- to = size + to
166
- }
167
- subarr = []
168
- from upto: to do_each: |i| {
169
- subarr << (at: i)
170
- }
171
- subarr
172
- }
173
-
174
85
  def last: count {
175
86
  """
176
87
  @count Number of last elements to get from an @Array@.
@@ -201,39 +112,6 @@ class Array {
201
112
  all?(&block)
202
113
  }
203
114
 
204
- def select: block {
205
- """
206
- @block Predicate @Block@ to be used as filter.
207
- @return @Array@ of all the elements for which @block doesn't yield @false or @nil.
208
-
209
- Returns a new Array with all the elements in self that yield a
210
- true-ish value when called with the given Block.
211
- """
212
-
213
- tmp = []
214
- each: |x| {
215
- if: (block call: [x]) then: {
216
- tmp << x
217
- }
218
- }
219
- return tmp
220
- }
221
-
222
- def select_with_index: block {
223
- """
224
- Same as select:, just gets also called with an additional argument
225
- for each element's index value.
226
- """
227
-
228
- tmp = []
229
- each_with_index: |obj idx| {
230
- if: (block call: [obj, idx]) then: {
231
- tmp << [obj, idx]
232
- }
233
- }
234
- tmp
235
- }
236
-
237
115
  def reject: block {
238
116
  """
239
117
  Returns a new Array with all the elements which yield nil or false
@@ -257,19 +135,7 @@ class Array {
257
135
  join(join_str)
258
136
  }
259
137
 
260
- def sum {
261
- """
262
- Calculates the sum of all the elements in the Enumerable
263
- (assuming them to be Numbers (implementing '+' & '*')).
264
- """
265
-
266
- reduce: |x y| { x + y } init_val: 0
267
- }
268
-
269
- def product {
270
- """Calculates the product of all the elements in the Enumerable
271
- (assuming them to be Numbers (implementing '+' & '*'))."""
272
-
273
- reduce: |x y| { x * y } init_val: 1
138
+ def unshift: value {
139
+ unshift(value)
274
140
  }
275
141
  }
data/lib/rbx/block.fy CHANGED
@@ -30,6 +30,30 @@ class Block {
30
30
  """
31
31
  @top_scope receiver: recv
32
32
  }
33
+
34
+ def call_with_receiver: receiver {
35
+ call_under(receiver, method() scope())
36
+ }
37
+
38
+ def call: args with_receiver: receiver {
39
+ call_under(receiver, method() scope(), *args)
40
+ }
41
+
42
+ def loop {
43
+ wrapper = {
44
+ try {
45
+ call
46
+ } catch (Fancy NextIteration) => ex {
47
+ ex return_value
48
+ }
49
+ }
50
+
51
+ try {
52
+ loop(&wrapper)
53
+ } catch (Fancy BreakIteration) => ex {
54
+ return ex return_value
55
+ }
56
+ }
33
57
  }
34
58
 
35
59
  class Rubinius VariableScope {
@@ -40,4 +64,4 @@ class Rubinius VariableScope {
40
64
  def receiver: recv {
41
65
  @self = recv
42
66
  }
43
- }
67
+ }
data/lib/rbx/class.fy CHANGED
@@ -44,6 +44,20 @@ class Class {
44
44
  new(superclass, &body_block)
45
45
  }
46
46
 
47
+ def initialize {
48
+ """
49
+ Initializes a @Class@ with @Object@ set as superclass (default superclass).
50
+ """
51
+ initialize: Object
52
+ }
53
+
54
+ def initialize: superclass {
55
+ """
56
+ Initializes a @Class@ with a superclass.
57
+ """
58
+ initialize(superclass)
59
+ }
60
+
47
61
  def define_method: name with: block {
48
62
  """
49
63
  @name Name of the method to be defined.
@@ -128,4 +142,11 @@ class Class {
128
142
 
129
143
  alias_method(message_name: new_method_name, message_name: old_method_name)
130
144
  }
145
+
146
+ def alias_method: new_method_name for_ruby: ruby_method_name {
147
+ """
148
+ Creates a method alias for a Ruby method.
149
+ """
150
+ alias_method(message_name: new_method_name, ruby_method_name)
151
+ }
131
152
  }