fancy 0.5.0 → 0.6.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.
Files changed (111) hide show
  1. data/AUTHORS +2 -0
  2. data/README.md +6 -1
  3. data/bin/fancy +6 -0
  4. data/bin/ifancy +44 -3
  5. data/boot/fancy_ext/module.rb +4 -0
  6. data/boot/fancy_ext/object.rb +4 -0
  7. data/boot/rbx-compiler/compiler/ast/block.rb +29 -1
  8. data/boot/rbx-compiler/compiler/ast/identifier.rb +6 -0
  9. data/boot/rbx-compiler/compiler/ast/message_send.rb +1 -0
  10. data/boot/rbx-compiler/parser/fancy_parser.bundle +0 -0
  11. data/boot/rbx-compiler/parser/lexer.lex +2 -0
  12. data/boot/rbx-compiler/parser/parser.rb +6 -0
  13. data/boot/rbx-compiler/parser/parser.y +14 -1
  14. data/doc/api/fancy.jsonp +1 -1
  15. data/doc/features.md +24 -0
  16. data/examples/99bottles.fy +5 -0
  17. data/examples/conditions_exceptions.fy +9 -0
  18. data/examples/conditions_parsing.fy +68 -0
  19. data/examples/greeter.fy +9 -0
  20. data/examples/html_generator.fy +59 -29
  21. data/examples/webserver/webserver.fy +8 -11
  22. data/lib/argv.fy +6 -0
  23. data/lib/array.fy +17 -35
  24. data/lib/block.fy +82 -1
  25. data/lib/boot.fy +4 -2
  26. data/lib/compiler.fy +2 -2
  27. data/lib/compiler/ast/block.fy +24 -20
  28. data/lib/compiler/ast/message_send.fy +11 -0
  29. data/lib/contracts.fy +60 -0
  30. data/lib/dynamic_slot_object.fy +61 -0
  31. data/lib/enumerable.fy +432 -394
  32. data/lib/enumerator.fy +152 -150
  33. data/lib/fdoc.fy +4 -17
  34. data/lib/fiber.fy +4 -10
  35. data/lib/file.fy +33 -25
  36. data/lib/future.fy +59 -5
  37. data/lib/hash.fy +54 -1
  38. data/lib/html.fy +107 -0
  39. data/lib/kvo.fy +173 -0
  40. data/lib/main.fy +6 -2
  41. data/lib/message_sink.fy +19 -0
  42. data/lib/number.fy +48 -0
  43. data/lib/object.fy +65 -13
  44. data/lib/package.fy +12 -2
  45. data/lib/package/dependency.fy +13 -0
  46. data/lib/package/dependency_installer.fy +27 -0
  47. data/lib/package/installer.fy +4 -10
  48. data/lib/package/uninstaller.fy +1 -3
  49. data/lib/parser/ext/lexer.lex +8 -3
  50. data/lib/parser/ext/parser.y +4 -1
  51. data/lib/parser/methods.fy +7 -3
  52. data/lib/range.fy +1 -1
  53. data/lib/rbx.fy +2 -1
  54. data/lib/rbx/array.fy +28 -12
  55. data/lib/rbx/bignum.fy +1 -1
  56. data/lib/rbx/block.fy +27 -0
  57. data/lib/rbx/console.fy +6 -6
  58. data/lib/rbx/date.fy +6 -1
  59. data/lib/rbx/documentation.fy +8 -3
  60. data/lib/rbx/exception.fy +5 -0
  61. data/lib/rbx/file.fy +40 -7
  62. data/lib/rbx/fixnum.fy +12 -1
  63. data/lib/rbx/method.fy +9 -2
  64. data/lib/rbx/module.fy +24 -0
  65. data/lib/rbx/regexp.fy +8 -0
  66. data/lib/rbx/string.fy +23 -7
  67. data/lib/rbx/tcp_server.fy +4 -2
  68. data/lib/rbx/tcp_socket.fy +14 -0
  69. data/lib/remote_object.fy +59 -0
  70. data/lib/set.fy +15 -4
  71. data/lib/string.fy +38 -5
  72. data/lib/stringio.fy +1 -0
  73. data/lib/symbol.fy +4 -0
  74. data/lib/system.fy +22 -0
  75. data/lib/thread_pool.fy +2 -2
  76. data/lib/tuple.fy +18 -1
  77. data/lib/vars.fy +17 -0
  78. data/lib/version.fy +1 -1
  79. data/ruby_lib/fancy +6 -0
  80. data/tests/array.fy +30 -0
  81. data/tests/block.fy +106 -0
  82. data/tests/class.fy +19 -0
  83. data/tests/enumerable.fy +1 -1
  84. data/tests/enumerator.fy +5 -5
  85. data/tests/file.fy +28 -0
  86. data/tests/fixnum.fy +0 -50
  87. data/tests/future.fy +9 -24
  88. data/tests/hash.fy +35 -0
  89. data/tests/html.fy +33 -0
  90. data/tests/kvo.fy +101 -0
  91. data/tests/number.fy +75 -0
  92. data/tests/object.fy +50 -3
  93. data/tests/string.fy +19 -10
  94. data/tests/symbol.fy +5 -0
  95. data/tests/tuple.fy +7 -0
  96. data/tools/fancy-mode.el +5 -1
  97. metadata +22 -21
  98. data/boot/compiler/parser/ext/fancy_parser.bundle +0 -0
  99. data/boot/rbx-compiler/parser/Makefile +0 -156
  100. data/boot/rbx-compiler/parser/lexer.c +0 -2310
  101. data/boot/rbx-compiler/parser/lexer.h +0 -315
  102. data/boot/rbx-compiler/parser/parser.c +0 -2946
  103. data/boot/rbx-compiler/parser/parser.h +0 -151
  104. data/lib/fiber_pool.fy +0 -78
  105. data/lib/method.fy +0 -6
  106. data/lib/parser/ext/Makefile +0 -156
  107. data/lib/parser/ext/fancy_parser.bundle +0 -0
  108. data/lib/parser/ext/lexer.c +0 -2392
  109. data/lib/parser/ext/lexer.h +0 -315
  110. data/lib/parser/ext/parser.c +0 -3251
  111. data/lib/parser/ext/parser.h +0 -161
@@ -548,4 +548,23 @@ FancySpec describe: Class with: {
548
548
  b to_s is: "foobar"
549
549
  b empty_method is: nil
550
550
  }
551
+
552
+ class WithConstants {
553
+ Foo = "foo"
554
+ Bar = "bar"
555
+ class Nested
556
+ }
557
+
558
+ it: "returns its nested constants" with: 'constants when: {
559
+ WithConstants constants =? ["Foo", "Bar", "Nested"] is: true
560
+ }
561
+
562
+ it: "returns a constants value" with: '[] when: {
563
+ WithConstants["Foo"] is: "foo"
564
+ WithConstants["Foo"] is: WithConstants Foo
565
+ WithConstants["Bar"] is: "bar"
566
+ WithConstants["Bar"] is: WithConstants Bar
567
+ WithConstants["Nested"] is_a?: Class . is: true
568
+ WithConstants["Nested"] is: WithConstants Nested
569
+ }
551
570
  }
@@ -1,4 +1,4 @@
1
- FancySpec describe: FancyEnumerable with: {
1
+ FancySpec describe: Fancy Enumerable with: {
2
2
  it: "selects the right element based on a comparison Block and an optional selection Block" with: 'superior_by:taking: when: {
3
3
  [1,2,3,4,5] superior_by: '> . is: 5
4
4
  [1,2,3,4,5] superior_by: '< . is: 1
@@ -1,12 +1,12 @@
1
- FancySpec describe: FancyEnumerator with: {
1
+ FancySpec describe: Fancy Enumerator with: {
2
2
  it: "iterates with 'next" with: 'new: when: {
3
- enum = FancyEnumerator new: (42..50)
3
+ enum = Fancy Enumerator new: (42..50)
4
4
  enum next is: 42
5
5
  enum next is: 43
6
6
  }
7
7
 
8
8
  it: "peeks to find next element" with: 'peek when: {
9
- enum = FancyEnumerator new: (42..50)
9
+ enum = Fancy Enumerator new: (42..50)
10
10
  enum peek is: 42
11
11
  enum peek is: 42
12
12
  enum next is: 42
@@ -16,12 +16,12 @@ FancySpec describe: FancyEnumerator with: {
16
16
  enum next is: 43
17
17
  }
18
18
 
19
- it: "turns an object with 'each: into an FancyEnumerator" with: 'to_enum when: {
19
+ it: "turns an object with 'each: into an Fancy Enumerator" with: 'to_enum when: {
20
20
  enum = (42..45) to_enum
21
21
  enum next is: 42
22
22
  }
23
23
 
24
- it: "turns an object with given method into an FancyEnumerator" with: 'to_enum: when: {
24
+ it: "turns an object with given method into an Fancy Enumerator" with: 'to_enum: when: {
25
25
  o = {}
26
26
  def o iter: block {
27
27
  1 upto: 10 do: block
@@ -5,6 +5,34 @@ FancySpec describe: File with: {
5
5
  file close
6
6
  }
7
7
 
8
+ it: "reads a file correctly" with: 'read:with: when: {
9
+ lines = File read: "README.md" . lines
10
+ idx = 0
11
+
12
+ File read: "README.md" with: |f| {
13
+ until: { f eof? } do: {
14
+ lines[idx] is: (f readline chomp)
15
+ idx = idx + 1
16
+ }
17
+ }
18
+ }
19
+
20
+ it: "writes a file correctly" with: 'write:with: when: {
21
+ dirname = "tmp"
22
+ filename = "#{dirname}/write_test.txt"
23
+
24
+ Directory create!: dirname
25
+ File write: filename with: |f| {
26
+ 10 times: |i| {
27
+ f println: i
28
+ }
29
+ }
30
+
31
+ File read: filename . lines is: $ ["0","1","2","3","4","5","6","7","8","9"]
32
+ File delete: filename
33
+ Directory delete: dirname
34
+ }
35
+
8
36
  it: "is open after opening it and closed after closing" with: 'close when: {
9
37
  file = File open: "README.md" modes: ['read]
10
38
  file open? is: true
@@ -53,26 +53,6 @@ FancySpec describe: Fixnum with: {
53
53
  2 even? is: true
54
54
  }
55
55
 
56
- it: "returns an array from 0 upto 10" with: 'upto: when: {
57
- 0 upto: 10 . is: [0,1,2,3,4,5,6,7,8,9,10]
58
- }
59
-
60
- it: "iterates from 1 upto 10" with: 'upto:do: when: {
61
- sum = 0
62
- 1 upto: 10 do: |n| { sum = sum + n }
63
- sum is: 55
64
- }
65
-
66
- it: "returns an array from 10 downto 0" with: 'downto: when: {
67
- 10 downto: 0 . is: [10,9,8,7,6,5,4,3,2,1,0]
68
- }
69
-
70
- it: "iterates from 10 downto 1" with: 'downto:do: when: {
71
- sum = 0
72
- 10 downto: 1 do: |n| { sum = sum + n }
73
- sum is: 55
74
- }
75
-
76
56
  it: "calculates the given power of itself" with: '** when: {
77
57
  2 ** 3 is: 8
78
58
  2 ** 0 is: 1
@@ -84,22 +64,6 @@ FancySpec describe: Fixnum with: {
84
64
  }
85
65
  }
86
66
 
87
- it: "is the square of self" with: 'squared when: {
88
- 5 squared is: 25
89
- 10 squared is: 100
90
- 20 upto: 50 do: |i| {
91
- i squared is: (i * i)
92
- }
93
- }
94
-
95
- it: "is the double value of self" with: 'doubled when: {
96
- 5 doubled is: 10
97
- 10 doubled is: 20
98
- 20 upto: 50 do: |i| {
99
- i doubled is: (i + i)
100
- }
101
- }
102
-
103
67
  it: "is the same when using underscores within the literal" when: {
104
68
  50000 is: 50_000
105
69
  100_000 is: 100000
@@ -153,18 +117,4 @@ FancySpec describe: Fixnum with: {
153
117
  times_called is: 10
154
118
  sum is: ((10..19) sum)
155
119
  }
156
-
157
- it: "returns the maximum" with: 'max: when: {
158
- 0 max: 0 . is: 0
159
- 1 max: 2 . is: 2
160
- 2 max: 1 . is: 2
161
- -2 max: -3 . is: -2
162
- }
163
-
164
- it: "returns the minimum" with: 'min: when: {
165
- 0 min: 0 . is: 0
166
- -1 min: 0 . is: -1
167
- -2 min: -3 . is: -3
168
- 2 min: 1 . is: 1
169
- }
170
120
  }
@@ -16,15 +16,15 @@ FancySpec describe: FutureSend with: {
16
16
  a is: nil
17
17
  }
18
18
 
19
- it: "composes Futures to create execution pipelines" with: '&& when: {
20
- def some_computation: num {
21
- num upto: (num ** num ** num)
22
- }
19
+ # it: "composes Futures to create execution pipelines" with: '&& when: {
20
+ # def some_computation: num {
21
+ # num upto: (num ** num ** num)
22
+ # }
23
23
 
24
- f = self @ some_computation: 2 && @{select: 'even?} && @{size}
25
- f is_a?: FutureSend . is: true
26
- f value is_a?: Fixnum . is: true
27
- }
24
+ # f = self @ some_computation: 2 && @{select: 'even?} && @{size}
25
+ # f is_a?: FutureSend . is: true
26
+ # f value is_a?: Fixnum . is: true
27
+ # }
28
28
 
29
29
  it: "accesses the same future from multiple threads and blocks them until the value is computed" when: {
30
30
  def another_method {
@@ -49,23 +49,8 @@ FancySpec describe: FutureSend with: {
49
49
  "error!" raise!
50
50
  }
51
51
  f = self @ a_failing_method
52
- f failed? is: false
52
+ f value # wait for completion
53
53
  f failure message is: "error!"
54
54
  f failed? is: true
55
55
  }
56
- }
57
-
58
- FancySpec describe: FutureCollection with: {
59
- it: "executes a block for each future in the collection when it's ready" with: 'each: when: {
60
- futures = 0 upto: 10 . map: |i| {
61
- i ** i @ ** i
62
- }
63
-
64
- fc = FutureCollection new: futures
65
- fc each: |val| {
66
- val is_a?: Integer . is: true
67
- }
68
-
69
- fc await_all
70
- }
71
56
  }
@@ -35,6 +35,13 @@ FancySpec describe: Hash with: {
35
35
  hash at: 'foo . is: 'foobarbaz
36
36
  }
37
37
 
38
+ it: "calls the block if it can't find the key" with: 'at:else: when: {
39
+ hash = <['foo => "bar", 'bar => nil]>
40
+ hash at: 'foo else: { "hello" } . is: "bar"
41
+ hash at: 'bar else: { "hello" } . is: nil
42
+ hash at: 'foo1 else: { "hello" } . is: "hello"
43
+ }
44
+
38
45
  it: "returns all keys" with: 'keys when: {
39
46
  hash = <['foo => "bar", 'bar => "baz", 'foobar => 112.21]>
40
47
  hash keys is =? ['foo, 'bar, 'foobar]
@@ -115,4 +122,32 @@ FancySpec describe: Hash with: {
115
122
  h includes?: "bar" . is: false
116
123
  h includes?: nil . is: false
117
124
  }
125
+
126
+ it: "fetches a value or calls a given alternative block" for: 'fetch:else: when: {
127
+ <['foo => 'bar]> fetch: 'foo else: { 42 } . is: 'bar
128
+ <['foo => 'bar]> fetch: 'unknown else: { 42 } . is: 42
129
+ <['nil => nil]> fetch: 'nil else: { 'not_found } . is: nil
130
+ <['nila => nil]> fetch: 'nil else: { 'not_found } . is: 'not_found
131
+ }
132
+
133
+ it: "returns an object with slots based on key-value pairs in Hash" for: 'to_object when: {
134
+ <[]> to_object slots empty? is: true
135
+ <['name => "Chris"]> to_object tap: @{
136
+ slots is: ['name]
137
+ name is: "Chris"
138
+ name: "New Name"
139
+ name is: "New Name"
140
+ }
141
+ <['a => "hello", 'b => "world"]> to_object tap: @{
142
+ slots size is: 2
143
+ slots includes?: 'a . is: true
144
+ slots includes?: 'b . is: true
145
+ a is: "hello"
146
+ b is: "world"
147
+ a: "world"
148
+ b: "hello"
149
+ a is: "world"
150
+ b is: "hello"
151
+ }
152
+ }
118
153
  }
@@ -0,0 +1,33 @@
1
+ require: "../lib/html"
2
+
3
+ FancySpec describe: HTML with: {
4
+ it: "generates an empty html string when initialized" when: {
5
+ HTML new to_s is: ""
6
+ }
7
+
8
+ it: "generates a simple html string" when: {
9
+ h = HTML new
10
+ h html: {
11
+ h head: {
12
+ h title: "Hello"
13
+ }
14
+ h body: {
15
+ h h1: "Hello, World!"
16
+ }
17
+ }
18
+
19
+ h to_s is: \
20
+ """<html>
21
+ <head>
22
+ <title>
23
+ Hello
24
+ </title>
25
+ </head>
26
+ <body>
27
+ <h1>
28
+ Hello, World!
29
+ </h1>
30
+ </body>
31
+ </html>"""
32
+ }
33
+ }
@@ -0,0 +1,101 @@
1
+ require: "lib/kvo"
2
+
3
+ class Person {
4
+ include: KVO
5
+ read_write_slots: ('name, 'age, 'city, 'friends)
6
+ }
7
+
8
+ FancySpec describe: KVO with: {
9
+ before_each: {
10
+ @p = Person new tap: @{
11
+ name: "Tom"
12
+ age: 42
13
+ city: "Berlin"
14
+ friends: []
15
+ }
16
+ }
17
+
18
+ it: "observes slot changes as expected" when: {
19
+ name_changed = false
20
+ new_name = nil
21
+ old_name = nil
22
+ @p observe: 'name with: |new old| {
23
+ new_name = new
24
+ old_name = old
25
+ name_changed = true
26
+ }
27
+
28
+ city_changed = false
29
+ new_city = nil
30
+ old_city = nil
31
+ @p observe: 'city with: |new old| {
32
+ new_city = new
33
+ old_city = old
34
+ city_changed = true
35
+ }
36
+
37
+ @p name: "Hello"
38
+ name_changed is: true
39
+ new_name is: "Hello"
40
+ old_name is: "Tom"
41
+ @p name is: new_name
42
+
43
+ @p age: 24
44
+ @p age is: 24
45
+
46
+ @p city: "Hamburg"
47
+ city_changed is: true
48
+ new_city is: "Hamburg"
49
+ old_city is: "Berlin"
50
+ @p city is: new_city
51
+ }
52
+
53
+ it: "observes insertions to collections correctly" when: {
54
+ friend_added = false
55
+ new_friend = nil
56
+ @p observe_insertion: 'friends with: |f| {
57
+ friend_added = true
58
+ new_friend = f
59
+ }
60
+
61
+ @p friends << "Jack"
62
+ friend_added is: true
63
+ new_friend is: "Jack"
64
+ @p friends first is: "Jack"
65
+
66
+ @p friends << "Jimmy"
67
+ new_friend is: "Jimmy"
68
+ @p friends second is: "Jimmy"
69
+ }
70
+
71
+ it: "observes removals from collections correctly" when: {
72
+ @p friends << "Jack"
73
+ @p friends << "Jimmy"
74
+
75
+ @p friends is: ["Jack", "Jimmy"]
76
+
77
+ friend_removed = false
78
+ removed_friend = nil
79
+ @p observe_removal: 'friends with: |f| {
80
+ friend_removed = true
81
+ removed_friend = f
82
+ }
83
+
84
+ @p friends remove: "Jack"
85
+ friend_removed is: true
86
+ removed_friend is: "Jack"
87
+ @p friends remove: "Jimmy"
88
+ removed_friend is: "Jimmy"
89
+
90
+ @p friends << "Jack"
91
+ @p friends << "Jimmy"
92
+ @p friends remove_at: 0
93
+ removed_friend is: "Jack"
94
+ @p friends first is: "Jimmy"
95
+
96
+ @p friends << "Jack"
97
+ @p friends << "Tom"
98
+ @p friends remove_at: (0,1)
99
+ @p friends is: ["Tom"]
100
+ }
101
+ }
@@ -0,0 +1,75 @@
1
+ FancySpec describe: Number with: {
2
+ it: "returns an array from 0 upto 10" with: 'upto: when: {
3
+ 0 upto: 10 . is: [0,1,2,3,4,5,6,7,8,9,10]
4
+ }
5
+
6
+ it: "iterates from 1 upto 10" with: 'upto:do: when: {
7
+ sum = 0
8
+ 1 upto: 10 do: |n| { sum = sum + n }
9
+ sum is: 55
10
+ }
11
+
12
+ it: "iterates from 1 upto 20 in steps of 4" when: {
13
+ sum = 0
14
+ 1 upto: 20 in_steps_of: 4 do: |n| {
15
+ sum = sum + n
16
+ }
17
+ sum is: $ [1,5,9,13,17] sum
18
+ }
19
+
20
+ it: "returns an array from 10 downto 0" with: 'downto: when: {
21
+ 10 downto: 0 . is: [10,9,8,7,6,5,4,3,2,1,0]
22
+ }
23
+
24
+ it: "iterates from 10 downto 1" with: 'downto:do: when: {
25
+ sum = 0
26
+ 10 downto: 1 do: |n| { sum = sum + n }
27
+ sum is: 55
28
+ }
29
+
30
+ it: "iterates from 20 downto 1 in steps of 4" when: {
31
+ sum = 0
32
+ 20 downto: 1 in_steps_of: 4 do: |n| {
33
+ sum = sum + n
34
+ }
35
+ sum is: $ [0,4,8,12,16,20] sum
36
+ }
37
+
38
+ it: "is the square of self" with: 'squared when: {
39
+ 5 squared is: 25
40
+ 10 squared is: 100
41
+ 20 upto: 50 do: |i| {
42
+ i squared is: (i * i)
43
+ }
44
+ }
45
+
46
+ it: "returns the cubed value of self" with: 'cubed when: {
47
+ 5 cubed is: 125
48
+ 10 cubed is: 1000
49
+ 20 upto: 50 do: |i| {
50
+ i cubed is: (i * i * i)
51
+ }
52
+ }
53
+
54
+ it: "is the double value of self" with: 'doubled when: {
55
+ 5 doubled is: 10
56
+ 10 doubled is: 20
57
+ 20 upto: 50 do: |i| {
58
+ i doubled is: (i + i)
59
+ }
60
+ }
61
+
62
+ it: "returns the maximum" with: 'max: when: {
63
+ 0 max: 0 . is: 0
64
+ 1 max: 2 . is: 2
65
+ 2 max: 1 . is: 2
66
+ -2 max: -3 . is: -2
67
+ }
68
+
69
+ it: "returns the minimum" with: 'min: when: {
70
+ 0 min: 0 . is: 0
71
+ -1 min: 0 . is: -1
72
+ -2 min: -3 . is: -3
73
+ 2 min: 1 . is: 1
74
+ }
75
+ }