fancy 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. data/README.md +1 -0
  2. data/bin/fspec +3 -1
  3. data/boot/code_loader.rb +5 -1
  4. data/boot/compiler/parser/ext/fancy_parser.bundle +0 -0
  5. data/boot/fancy_ext.rb +2 -0
  6. data/boot/fancy_ext/bootstrap.rb +6 -0
  7. data/boot/fancy_ext/symbol.rb +9 -0
  8. data/boot/fancy_ext/thread.rb +22 -1
  9. data/boot/load.rb +1 -0
  10. data/boot/rbx-compiler/parser/Makefile +156 -0
  11. data/boot/rbx-compiler/parser/fancy_parser.bundle +0 -0
  12. data/boot/rbx-compiler/parser/lexer.c +2310 -0
  13. data/boot/rbx-compiler/parser/lexer.h +315 -0
  14. data/boot/rbx-compiler/parser/parser.c +2946 -0
  15. data/boot/rbx-compiler/parser/parser.h +151 -0
  16. data/doc/api/fancy.jsonp +1 -1
  17. data/doc/features.md +8 -0
  18. data/examples/actors.fy +5 -9
  19. data/examples/actors_primitive.fy +4 -3
  20. data/examples/actors_ring.fy +15 -14
  21. data/examples/dynamic.fy +8 -0
  22. data/examples/dynamic_output.fy +15 -0
  23. data/examples/parsing.fy +1 -0
  24. data/examples/person.fy +1 -2
  25. data/lib/array.fy +49 -11
  26. data/lib/block.fy +18 -24
  27. data/lib/boot.fy +1 -1
  28. data/lib/class.fy +6 -6
  29. data/lib/compiler/ast.fy +0 -1
  30. data/lib/compiler/ast/assign.fy +25 -0
  31. data/lib/compiler/ast/block.fy +1 -0
  32. data/lib/compiler/ast/identifier.fy +16 -0
  33. data/lib/compiler/ast/literals.fy +4 -0
  34. data/lib/compiler/ast/message_send.fy +16 -1
  35. data/lib/enumerable.fy +45 -18
  36. data/lib/enumerator.fy +15 -15
  37. data/lib/false_class.fy +8 -0
  38. data/lib/fancy_spec.fy +20 -20
  39. data/lib/future.fy +35 -18
  40. data/lib/hash.fy +2 -2
  41. data/lib/integer.fy +1 -17
  42. data/lib/iteration.fy +36 -36
  43. data/lib/object.fy +65 -30
  44. data/lib/package.fy +2 -2
  45. data/lib/package/installer.fy +6 -0
  46. data/lib/parser/ext/Makefile +156 -0
  47. data/lib/parser/ext/fancy_parser.bundle +0 -0
  48. data/lib/parser/ext/lexer.c +2392 -0
  49. data/lib/parser/ext/lexer.h +315 -0
  50. data/lib/parser/ext/lexer.lex +0 -10
  51. data/lib/parser/ext/parser.c +3251 -0
  52. data/lib/parser/ext/parser.h +161 -0
  53. data/lib/parser/ext/parser.y +0 -22
  54. data/lib/parser/methods.fy +1 -13
  55. data/lib/range.fy +3 -3
  56. data/lib/rbx.fy +1 -0
  57. data/lib/rbx/actor.fy +4 -4
  58. data/lib/rbx/alpha.fy +6 -0
  59. data/lib/rbx/array.fy +5 -44
  60. data/lib/rbx/bignum.fy +1 -12
  61. data/lib/rbx/block.fy +25 -0
  62. data/lib/rbx/class.fy +1 -7
  63. data/lib/rbx/date.fy +1 -5
  64. data/lib/rbx/file.fy +1 -4
  65. data/lib/rbx/fixnum.fy +4 -16
  66. data/lib/rbx/float.fy +1 -10
  67. data/lib/rbx/integer.fy +14 -2
  68. data/lib/rbx/io.fy +1 -5
  69. data/lib/rbx/mutex.fy +30 -0
  70. data/lib/rbx/object.fy +5 -11
  71. data/lib/rbx/process.fy +13 -0
  72. data/lib/rbx/range.fy +1 -5
  73. data/lib/rbx/string.fy +4 -11
  74. data/lib/rbx/thread.fy +9 -0
  75. data/lib/rbx/time.fy +1 -7
  76. data/lib/stack.fy +1 -1
  77. data/lib/string.fy +9 -9
  78. data/lib/symbol.fy +12 -7
  79. data/lib/tuple.fy +18 -3
  80. data/lib/vars.fy +3 -0
  81. data/ruby_lib/fspec +2 -2
  82. data/ruby_lib/fyi +2 -2
  83. data/ruby_lib/ifancy +2 -2
  84. data/tests/array.fy +25 -1
  85. data/tests/assignment.fy +55 -0
  86. data/tests/future.fy +28 -0
  87. data/tests/set.fy +20 -0
  88. data/tests/stack.fy +46 -0
  89. data/tests/string.fy +1 -1
  90. data/tests/tuple.fy +22 -0
  91. data/tools/fancy-mode.el +1 -1
  92. metadata +26 -8
  93. data/lib/compiler/ast/goto.fy +0 -46
  94. 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
- i = 0
22
- { i >= 10 } while_false: {
23
- i println
24
- i = i + 1
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: work {
34
+ def while_true: block {
34
35
  """
35
- @work @Block@ to call while @self yields @true.
36
+ @block @Block@ to call while @self yields @true.
36
37
 
37
- Calls @work while calling @self yields a @true-ish value.
38
+ Calls @block while calling @self yields a @true-ish value.
38
39
  """
39
40
 
40
41
  try {
41
- brk = { return nil }
42
- loop() {
43
- try {
44
- call if_true: work else: brk
45
- } catch Fancy NextIteration => ex {
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
- if: call then: |val| {
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
- if: obj then: self
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
- unless: obj do: self
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
- def count {
18
- get_slot: 'count
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
- def count: c {
34
- set_slot: 'count value: c
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
@@ -39,5 +39,4 @@ require: "ast/range"
39
39
  require: "ast/match"
40
40
  require: "ast/try_catch"
41
41
  require: "ast/return"
42
- require: "ast/goto"
43
42
  require: "ast/string_interpolation"
@@ -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
  }
@@ -1,5 +1,6 @@
1
1
  class Fancy AST {
2
2
  class BlockLiteral : Rubinius AST Iter {
3
+ read_slot: 'body
3
4
  def initialize: @line args: @args body: @body (NilLiteral new: line) partial: @partial (false) {
4
5
  if: (@body empty?) then: {
5
6
  @body unshift_expression: $ NilLiteral new: @line
@@ -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
  }
@@ -89,7 +89,11 @@ class Fancy AST {
89
89
  }
90
90
 
91
91
  class SymbolLiteral : Rubinius AST SymbolLiteral {
92
+ read_slot: 'value
92
93
  def initialize: line value: value { initialize(line, value) }
94
+ def string {
95
+ value
96
+ }
93
97
  def bytecode: g {
94
98
  pos(g)
95
99
  bytecode(g)
@@ -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
- g send(sym, @args size, false)
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
- \"hello, world\” join: \"-\" # => \"h-e-l-l-o-,- -w-o-r-l-d\"
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
- nil
62
+ false
63
63
  }
64
64
 
65
65
  def all?: condition {
66
66
  """
67
- Similar to @FancyEnumerable#any?:@ just checking for all elements.
68
- Indicates, if all elements meet the condition.
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
- [1,2,3,4,5] take_while: |x| { x < 4 } # => [1,2,3]
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
- [1,2,3,4,5] drop_while: |x| { x < 4 } # => [4,5]
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
- [1,2,3,4] take: 2 # => [1,2]
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
- [1,2,3,4,5] drop: 2 # => [3,4,5]
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
- [1,2,3] reduce: |sum val| { sum + val } init_val: 0 # => 6
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
- [1,2,3] inject: 0 into: |sum val| { sum + val } # => 6
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
- [1,2,1,2,3] uniq # => [1,2,3]
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
- [1,2,nil,3,nil] compact # => [1,2,3]
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
- [1,2,5,3,4] superior_by: '> # => 5
361
- [1,2,5,3,4] superior_by: '< # => 1
362
- [[1,2], [2,3,4], [], [1]] superior_by: '> taking: 'size # => [2,3,4]
363
- [[1,2], [2,3,4], [-1]] superior_by: '< taking: 'first # => [-1]
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
- 0 upto: 10 . partition_by: @{< 3} # => [[0, 1, 2], [3, 4, 5, 6, 7, 8, 9, 10]]
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
- [1,2,3,4,5] in_groups_of: 3 # => [[1,2,3],[4,5]]
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
- 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
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
- 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
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
@@ -27,6 +27,14 @@ class FalseClass {
27
27
  then_block call: [self]
28
28
  }
29
29
 
30
+ def if_nil: then_block {
31
+ nil
32
+ }
33
+
34
+ def if_nil: then_block else: else_block {
35
+ else_block call: [self]
36
+ }
37
+
30
38
  def false? {
31
39
  "Returns @true."
32
40
  true