fancy 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }