fancy 0.3.2 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- 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/lib/package/installer.fy
CHANGED
@@ -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
|
171
|
+
Dir glob(installed_path ++ "/*.fancypack") first if_true: |fpackfile| {
|
172
172
|
require: fpackfile
|
173
173
|
}
|
174
174
|
|
data/lib/parser/ext/lexer.lex
CHANGED
@@ -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;
|
data/lib/parser/ext/parser.y
CHANGED
@@ -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
|
;
|
data/lib/parser/methods.fy
CHANGED
@@ -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
|
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
|
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
|
12
|
-
@obj
|
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
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
|
-
|
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
|
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
|
}
|