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