fancy 0.4.0 → 0.5.0
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.
- data/README.md +1 -0
- data/bin/fspec +3 -1
- data/boot/code_loader.rb +5 -1
- data/boot/compiler/parser/ext/fancy_parser.bundle +0 -0
- data/boot/fancy_ext.rb +2 -0
- data/boot/fancy_ext/bootstrap.rb +6 -0
- data/boot/fancy_ext/symbol.rb +9 -0
- data/boot/fancy_ext/thread.rb +22 -1
- data/boot/load.rb +1 -0
- data/boot/rbx-compiler/parser/Makefile +156 -0
- data/boot/rbx-compiler/parser/fancy_parser.bundle +0 -0
- data/boot/rbx-compiler/parser/lexer.c +2310 -0
- data/boot/rbx-compiler/parser/lexer.h +315 -0
- data/boot/rbx-compiler/parser/parser.c +2946 -0
- data/boot/rbx-compiler/parser/parser.h +151 -0
- data/doc/api/fancy.jsonp +1 -1
- data/doc/features.md +8 -0
- data/examples/actors.fy +5 -9
- data/examples/actors_primitive.fy +4 -3
- data/examples/actors_ring.fy +15 -14
- data/examples/dynamic.fy +8 -0
- data/examples/dynamic_output.fy +15 -0
- data/examples/parsing.fy +1 -0
- data/examples/person.fy +1 -2
- data/lib/array.fy +49 -11
- data/lib/block.fy +18 -24
- data/lib/boot.fy +1 -1
- data/lib/class.fy +6 -6
- data/lib/compiler/ast.fy +0 -1
- data/lib/compiler/ast/assign.fy +25 -0
- data/lib/compiler/ast/block.fy +1 -0
- data/lib/compiler/ast/identifier.fy +16 -0
- data/lib/compiler/ast/literals.fy +4 -0
- data/lib/compiler/ast/message_send.fy +16 -1
- data/lib/enumerable.fy +45 -18
- data/lib/enumerator.fy +15 -15
- data/lib/false_class.fy +8 -0
- data/lib/fancy_spec.fy +20 -20
- data/lib/future.fy +35 -18
- data/lib/hash.fy +2 -2
- data/lib/integer.fy +1 -17
- data/lib/iteration.fy +36 -36
- data/lib/object.fy +65 -30
- data/lib/package.fy +2 -2
- data/lib/package/installer.fy +6 -0
- data/lib/parser/ext/Makefile +156 -0
- data/lib/parser/ext/fancy_parser.bundle +0 -0
- data/lib/parser/ext/lexer.c +2392 -0
- data/lib/parser/ext/lexer.h +315 -0
- data/lib/parser/ext/lexer.lex +0 -10
- data/lib/parser/ext/parser.c +3251 -0
- data/lib/parser/ext/parser.h +161 -0
- data/lib/parser/ext/parser.y +0 -22
- data/lib/parser/methods.fy +1 -13
- data/lib/range.fy +3 -3
- data/lib/rbx.fy +1 -0
- data/lib/rbx/actor.fy +4 -4
- data/lib/rbx/alpha.fy +6 -0
- data/lib/rbx/array.fy +5 -44
- data/lib/rbx/bignum.fy +1 -12
- data/lib/rbx/block.fy +25 -0
- data/lib/rbx/class.fy +1 -7
- data/lib/rbx/date.fy +1 -5
- data/lib/rbx/file.fy +1 -4
- data/lib/rbx/fixnum.fy +4 -16
- data/lib/rbx/float.fy +1 -10
- data/lib/rbx/integer.fy +14 -2
- data/lib/rbx/io.fy +1 -5
- data/lib/rbx/mutex.fy +30 -0
- data/lib/rbx/object.fy +5 -11
- data/lib/rbx/process.fy +13 -0
- data/lib/rbx/range.fy +1 -5
- data/lib/rbx/string.fy +4 -11
- data/lib/rbx/thread.fy +9 -0
- data/lib/rbx/time.fy +1 -7
- data/lib/stack.fy +1 -1
- data/lib/string.fy +9 -9
- data/lib/symbol.fy +12 -7
- data/lib/tuple.fy +18 -3
- data/lib/vars.fy +3 -0
- data/ruby_lib/fspec +2 -2
- data/ruby_lib/fyi +2 -2
- data/ruby_lib/ifancy +2 -2
- data/tests/array.fy +25 -1
- data/tests/assignment.fy +55 -0
- data/tests/future.fy +28 -0
- data/tests/set.fy +20 -0
- data/tests/stack.fy +46 -0
- data/tests/string.fy +1 -1
- data/tests/tuple.fy +22 -0
- data/tools/fancy-mode.el +1 -1
- metadata +26 -8
- data/lib/compiler/ast/goto.fy +0 -46
- data/lib/message.fy +0 -6
data/lib/block.fy
CHANGED
@@ -16,13 +16,14 @@ class Block {
|
|
16
16
|
|
17
17
|
def while_false: block {
|
18
18
|
"""
|
19
|
-
Executes a given Block while self evals to nil
|
19
|
+
Executes a given @Block@ while self evals to @nil or @false.
|
20
|
+
|
20
21
|
Example:
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
i = 0
|
23
|
+
{ i >= 10 } while_false: {
|
24
|
+
i println
|
25
|
+
i = i + 1
|
26
|
+
}
|
26
27
|
"""
|
27
28
|
|
28
29
|
{ call not } while_true: block
|
@@ -30,26 +31,19 @@ class Block {
|
|
30
31
|
|
31
32
|
alias_method: 'while_nil: for: 'while_false:
|
32
33
|
|
33
|
-
def while_true:
|
34
|
+
def while_true: block {
|
34
35
|
"""
|
35
|
-
@
|
36
|
+
@block @Block@ to call while @self yields @true.
|
36
37
|
|
37
|
-
Calls @
|
38
|
+
Calls @block while calling @self yields a @true-ish value.
|
38
39
|
"""
|
39
40
|
|
40
41
|
try {
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
ex result
|
47
|
-
}
|
48
|
-
}
|
49
|
-
} catch Fancy BreakIteration => ex {
|
50
|
-
return ex result
|
51
|
-
} catch Fancy StopIteration => ex {
|
52
|
-
return ex result
|
42
|
+
while_true_impl: block
|
43
|
+
} catch Fancy BreakIteration => b {
|
44
|
+
return b result
|
45
|
+
} catch Fancy StopIteration => s {
|
46
|
+
return s result
|
53
47
|
}
|
54
48
|
}
|
55
49
|
|
@@ -90,7 +84,7 @@ class Block {
|
|
90
84
|
Short-circuiting || (boolean OR).
|
91
85
|
"""
|
92
86
|
|
93
|
-
|
87
|
+
call if_true: |val| {
|
94
88
|
return val
|
95
89
|
} else: other_block
|
96
90
|
}
|
@@ -102,7 +96,7 @@ class Block {
|
|
102
96
|
Calls @self if @obj is true-ish.
|
103
97
|
"""
|
104
98
|
|
105
|
-
|
99
|
+
obj if_true: self
|
106
100
|
}
|
107
101
|
|
108
102
|
def unless: obj {
|
@@ -112,7 +106,7 @@ class Block {
|
|
112
106
|
Opposite of Block#if:. Calls @self if @obj is false-ish.
|
113
107
|
"""
|
114
108
|
|
115
|
-
|
109
|
+
obj if_true: { nil } else: self
|
116
110
|
}
|
117
111
|
|
118
112
|
def === val {
|
data/lib/boot.fy
CHANGED
@@ -30,7 +30,6 @@ require: "integer"
|
|
30
30
|
require: "enumerator"
|
31
31
|
require: "file"
|
32
32
|
require: "directory"
|
33
|
-
require: "fancy_spec"
|
34
33
|
require: "hash"
|
35
34
|
require: "set"
|
36
35
|
require: "symbol"
|
@@ -46,6 +45,7 @@ require: "struct"
|
|
46
45
|
# version holds fancy's version number
|
47
46
|
require: "version"
|
48
47
|
require: "argv"
|
48
|
+
require: "vars"
|
49
49
|
|
50
50
|
require: "documentation"
|
51
51
|
|
data/lib/class.fy
CHANGED
@@ -14,9 +14,9 @@ class Class {
|
|
14
14
|
|
15
15
|
Defines a slot reader method with a given name.
|
16
16
|
E.g. for a slotname @count it will define the following method:
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
def count {
|
18
|
+
get_slot: 'count
|
19
|
+
}
|
20
20
|
"""
|
21
21
|
|
22
22
|
define_method: slotname with: {
|
@@ -30,9 +30,9 @@ class Class {
|
|
30
30
|
|
31
31
|
Defines a slot writer method with a given name.
|
32
32
|
E.g. for a slotname @count it will define the following method:
|
33
|
-
|
34
|
-
|
35
|
-
|
33
|
+
def count: c {
|
34
|
+
set_slot: 'count value: c
|
35
|
+
}
|
36
36
|
"""
|
37
37
|
|
38
38
|
define_method: (slotname to_s + ":") with: |val| {
|
data/lib/compiler/ast.fy
CHANGED
data/lib/compiler/ast/assign.fy
CHANGED
@@ -92,4 +92,29 @@ class Fancy AST {
|
|
92
92
|
Rubinius AST ConstantAssignment new(@line, name, value) bytecode(g)
|
93
93
|
}
|
94
94
|
}
|
95
|
+
|
96
|
+
class DynamicVariable {
|
97
|
+
def bytecode: g assign: value {
|
98
|
+
pos(g)
|
99
|
+
var = DynamicVariable new: @line string: @string
|
100
|
+
dva = DynamicVariableAssign new: @line varname: var value: value in: (NilLiteral new: @line)
|
101
|
+
dva bytecode: g
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
class DynamicVariableAssign : Node {
|
106
|
+
def initialize: @line varname: @varname value: @value in: @block {
|
107
|
+
@varname = @varname varname
|
108
|
+
}
|
109
|
+
|
110
|
+
def bytecode: g {
|
111
|
+
pos(g)
|
112
|
+
|
113
|
+
ms = MessageSend new: @line \
|
114
|
+
message: (Identifier from: "let:be:in:" line: @line) \
|
115
|
+
to: (Self new: @line) \
|
116
|
+
args: (MessageArgs new: @line args: [@varname, @value, @block])
|
117
|
+
ms bytecode: g
|
118
|
+
}
|
119
|
+
}
|
95
120
|
}
|
data/lib/compiler/ast/block.fy
CHANGED
@@ -48,6 +48,7 @@ class Fancy AST {
|
|
48
48
|
case /^[A-Z]/ -> Constant
|
49
49
|
case /^@@/ -> ClassVariable
|
50
50
|
case /^@/ -> InstanceVariable
|
51
|
+
case /^\*/ -> DynamicVariable
|
51
52
|
case _ -> Identifier
|
52
53
|
}
|
53
54
|
type new: line string: string
|
@@ -118,4 +119,19 @@ class Fancy AST {
|
|
118
119
|
scoped bytecode(g)
|
119
120
|
}
|
120
121
|
}
|
122
|
+
|
123
|
+
class DynamicVariable : Identifier {
|
124
|
+
read_slot: 'varname
|
125
|
+
def initialize: @line string: @string {
|
126
|
+
@varname = SymbolLiteral new: @line value: @string
|
127
|
+
}
|
128
|
+
|
129
|
+
def bytecode: g {
|
130
|
+
thread = Identifier from: "Thread" line: @line
|
131
|
+
thread bytecode: g
|
132
|
+
g send('current, 0, false)
|
133
|
+
@varname bytecode: g
|
134
|
+
g send(':[], 1, false)
|
135
|
+
}
|
136
|
+
}
|
121
137
|
}
|
@@ -2,6 +2,16 @@ class Fancy AST {
|
|
2
2
|
class MessageSend : Node {
|
3
3
|
read_write_slots: ['name, 'receiver, 'args]
|
4
4
|
|
5
|
+
# fast instructions to be used if possible
|
6
|
+
FastOps = <[
|
7
|
+
':+ => 'meta_send_op_plus,
|
8
|
+
':- => 'meta_send_op_minus,
|
9
|
+
':== => 'meta_send_op_equal,
|
10
|
+
':=== => 'meta_send_op_tequal,
|
11
|
+
':< => 'meta_send_op_lt,
|
12
|
+
':> => 'meta_send_op_gt
|
13
|
+
]>
|
14
|
+
|
5
15
|
def initialize: @line message: @name to: @receiver (Self new: @line) args: @args (MessageArgs new: @line) {
|
6
16
|
}
|
7
17
|
|
@@ -49,7 +59,12 @@ class Fancy AST {
|
|
49
59
|
if: ruby_block? then: {
|
50
60
|
g send_with_block(sym, @args size, false)
|
51
61
|
} else: {
|
52
|
-
|
62
|
+
# use fast instruction, if available.
|
63
|
+
if: (FastOps[sym]) then: |op| {
|
64
|
+
g __send__(op, g find_literal(sym))
|
65
|
+
} else: {
|
66
|
+
g send(sym, @args size, false)
|
67
|
+
}
|
53
68
|
}
|
54
69
|
}
|
55
70
|
}
|
data/lib/enumerable.fy
CHANGED
@@ -34,7 +34,7 @@ class FancyEnumerable {
|
|
34
34
|
|
35
35
|
Joins a collection with a @String@ between each element, returning a new @String@.
|
36
36
|
|
37
|
-
|
37
|
+
\"hello, world\" join: \"-\" # => \"h-e-l-l-o-,- -w-o-r-l-d\"
|
38
38
|
"""
|
39
39
|
|
40
40
|
s = ""
|
@@ -59,13 +59,15 @@ class FancyEnumerable {
|
|
59
59
|
return true
|
60
60
|
}
|
61
61
|
}
|
62
|
-
|
62
|
+
false
|
63
63
|
}
|
64
64
|
|
65
65
|
def all?: condition {
|
66
66
|
"""
|
67
|
-
|
68
|
-
|
67
|
+
@block Predicate @Block@ to be called for each element until it returns @false for any one of them.
|
68
|
+
@return @true if all elements in @self yield @true for @block, @false otherwise.
|
69
|
+
|
70
|
+
Takes condition-block and returns @true if all elements meet it.
|
69
71
|
"""
|
70
72
|
|
71
73
|
each: |x| {
|
@@ -162,7 +164,7 @@ class FancyEnumerable {
|
|
162
164
|
as long as they meet the given condition block.
|
163
165
|
|
164
166
|
Example:
|
165
|
-
|
167
|
+
[1,2,3,4,5] take_while: |x| { x < 4 } # => [1,2,3]
|
166
168
|
"""
|
167
169
|
|
168
170
|
coll = []
|
@@ -183,7 +185,7 @@ class FancyEnumerable {
|
|
183
185
|
as long as they meet the given condition block.
|
184
186
|
|
185
187
|
Example:
|
186
|
-
|
188
|
+
[1,2,3,4,5] drop_while: |x| { x < 4 } # => [4,5]
|
187
189
|
"""
|
188
190
|
|
189
191
|
coll = []
|
@@ -210,7 +212,7 @@ class FancyEnumerable {
|
|
210
212
|
@return First @amount elements of @self in an @Array@.
|
211
213
|
|
212
214
|
Example:
|
213
|
-
|
215
|
+
[1,2,3,4] take: 2 # => [1,2]
|
214
216
|
"""
|
215
217
|
|
216
218
|
i = 0
|
@@ -226,7 +228,7 @@ class FancyEnumerable {
|
|
226
228
|
@return An @Array@ of all but the first @amount elements in @self.
|
227
229
|
|
228
230
|
Example:
|
229
|
-
|
231
|
+
[1,2,3,4,5] drop: 2 # => [3,4,5]
|
230
232
|
"""
|
231
233
|
|
232
234
|
i = 0
|
@@ -242,7 +244,7 @@ class FancyEnumerable {
|
|
242
244
|
value and an initial value.
|
243
245
|
|
244
246
|
Example:
|
245
|
-
|
247
|
+
[1,2,3] reduce: |sum val| { sum + val } init_val: 0 # => 6
|
246
248
|
"""
|
247
249
|
|
248
250
|
acc = init_val
|
@@ -258,7 +260,7 @@ class FancyEnumerable {
|
|
258
260
|
and the reducing block as second parameter.
|
259
261
|
|
260
262
|
Example:
|
261
|
-
|
263
|
+
[1,2,3] inject: 0 into: |sum val| { sum + val } # => 6
|
262
264
|
"""
|
263
265
|
|
264
266
|
reduce: block init_val: val
|
@@ -271,7 +273,7 @@ class FancyEnumerable {
|
|
271
273
|
Returns a new Array with all unique values (double entries are skipped).
|
272
274
|
|
273
275
|
Example:
|
274
|
-
|
276
|
+
[1,2,1,2,3] uniq # => [1,2,3]
|
275
277
|
"""
|
276
278
|
|
277
279
|
uniq_vals = []
|
@@ -339,7 +341,7 @@ class FancyEnumerable {
|
|
339
341
|
Returns a new @Array@ with all values removed that are @nil ( return @true on @nil? ).
|
340
342
|
|
341
343
|
Example:
|
342
|
-
|
344
|
+
[1,2,nil,3,nil] compact # => [1,2,3]
|
343
345
|
"""
|
344
346
|
|
345
347
|
reject: |x| { x nil? }
|
@@ -357,10 +359,10 @@ class FancyEnumerable {
|
|
357
359
|
@selection_block defaults to @identity.
|
358
360
|
|
359
361
|
Examples:
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
362
|
+
[1,2,5,3,4] superior_by: '> # => 5
|
363
|
+
[1,2,5,3,4] superior_by: '< # => 1
|
364
|
+
[[1,2], [2,3,4], [], [1]] superior_by: '> taking: 'size # => [2,3,4]
|
365
|
+
[[1,2], [2,3,4], [-1]] superior_by: '< taking: 'first # => [-1]
|
364
366
|
"""
|
365
367
|
|
366
368
|
|
@@ -430,7 +432,7 @@ class FancyEnumerable {
|
|
430
432
|
@return @Array@ of @Array@s, partitioned by equal return values of calling @block with each element
|
431
433
|
|
432
434
|
Example:
|
433
|
-
|
435
|
+
0 upto: 10 . partition_by: |x| { x < 3 } # => [[0, 1, 2], [3, 4, 5, 6, 7, 8, 9, 10]]
|
434
436
|
"""
|
435
437
|
last = block call: [first]
|
436
438
|
coll = []
|
@@ -480,7 +482,7 @@ class FancyEnumerable {
|
|
480
482
|
@return @Array@ of @Array@s with a max size of @size (grouped).
|
481
483
|
|
482
484
|
Example usage:
|
483
|
-
|
485
|
+
[1,2,3,4,5] in_groups_of: 3 # => [[1,2,3],[4,5]]
|
484
486
|
"""
|
485
487
|
|
486
488
|
groups = []
|
@@ -503,4 +505,29 @@ class FancyEnumerable {
|
|
503
505
|
|
504
506
|
groups
|
505
507
|
}
|
508
|
+
|
509
|
+
def reverse {
|
510
|
+
"""
|
511
|
+
@return @self in reverse order.
|
512
|
+
|
513
|
+
Returns @self in reverse order.
|
514
|
+
This only makes sense for collections that have an ordering.
|
515
|
+
In either case, it simply converts @self to an @Array@ and returns it in reversed order.
|
516
|
+
"""
|
517
|
+
|
518
|
+
rev = self to_a
|
519
|
+
rev reverse
|
520
|
+
}
|
521
|
+
|
522
|
+
def reverse_each: block {
|
523
|
+
"""
|
524
|
+
@block @Block@ to be called for each element in reverse order.
|
525
|
+
@return @self
|
526
|
+
|
527
|
+
Runs @block for each element on reversed version of self.
|
528
|
+
If @self is not a sorted collection, no guarantees about the reverse order can be given.
|
529
|
+
"""
|
530
|
+
|
531
|
+
reverse each: block
|
532
|
+
}
|
506
533
|
}
|
data/lib/enumerator.fy
CHANGED
@@ -31,12 +31,12 @@ class FancyEnumerator {
|
|
31
31
|
It will move the internal position forward (compared to e.g. #peek, which doesn't).
|
32
32
|
|
33
33
|
Example:
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
34
|
+
a = [1,2,3]
|
35
|
+
e = a to_enum
|
36
|
+
e next # => 1
|
37
|
+
e next # => 2
|
38
|
+
e next # => 3
|
39
|
+
e next # => raises Fancy StopIteration
|
40
40
|
"""
|
41
41
|
|
42
42
|
if: @peeked then: {
|
@@ -70,15 +70,15 @@ class FancyEnumerator {
|
|
70
70
|
raised.
|
71
71
|
|
72
72
|
Example:
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
73
|
+
a = [1,2,3]
|
74
|
+
e = a to_enum
|
75
|
+
e next p #=> 1
|
76
|
+
e peek p #=> 2
|
77
|
+
e peek p #=> 2
|
78
|
+
e peek p #=> 2
|
79
|
+
e next p #=> 2
|
80
|
+
e next p #=> 3
|
81
|
+
e next p #=> raises Fancy StopIteration
|
82
82
|
"""
|
83
83
|
|
84
84
|
unless: @peeked do: {
|
data/lib/false_class.fy
CHANGED