fancy 0.6.0 → 0.7.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 (79) hide show
  1. data/LICENSE +1 -1
  2. data/README.md +4 -1
  3. data/Rakefile +0 -52
  4. data/bin/fspec +22 -12
  5. data/bin/ifancy +1 -1
  6. data/boot/fancy_ext/class.rb +1 -0
  7. data/boot/fancy_ext/object.rb +8 -6
  8. data/boot/rbx-compiler/compiler/ast/method_def.rb +2 -0
  9. data/boot/rbx-compiler/parser/fancy_parser.bundle +0 -0
  10. data/boot/rbx-compiler/parser/parser.y +9 -0
  11. data/doc/api/fancy.jsonp +1 -1
  12. data/examples/stupid_quicksort.fy +11 -9
  13. data/lib/array.fy +26 -58
  14. data/lib/block.fy +0 -1
  15. data/lib/boot.fy +2 -2
  16. data/lib/class.fy +85 -0
  17. data/lib/compiler/ast/class_def.fy +1 -1
  18. data/lib/compiler/ast/expression_list.fy +4 -12
  19. data/lib/compiler/ast/identifier.fy +3 -3
  20. data/lib/compiler/ast/method_def.fy +3 -1
  21. data/lib/compiler/ast/singleton_method_def.fy +4 -1
  22. data/lib/contracts.fy +53 -56
  23. data/lib/dynamic_slot_object.fy +39 -3
  24. data/lib/enumerable.fy +144 -47
  25. data/lib/fancy_spec.fy +2 -6
  26. data/lib/file.fy +67 -0
  27. data/lib/future.fy +42 -3
  28. data/lib/hash.fy +35 -29
  29. data/lib/html.fy +1 -1
  30. data/lib/integer.fy +34 -0
  31. data/lib/main.fy +13 -7
  32. data/lib/message_sink.fy +1 -1
  33. data/lib/number.fy +10 -0
  34. data/lib/object.fy +27 -1
  35. data/lib/package.fy +2 -0
  36. data/lib/package/handler.fy +56 -0
  37. data/lib/package/installer.fy +21 -51
  38. data/lib/package/specification.fy +12 -5
  39. data/lib/package/uninstaller.fy +22 -3
  40. data/lib/parser/ext/parser.y +9 -0
  41. data/lib/proxy.fy +25 -2
  42. data/lib/rbx.fy +2 -1
  43. data/lib/rbx/array.fy +16 -1
  44. data/lib/rbx/class.fy +34 -9
  45. data/lib/rbx/file.fy +2 -2
  46. data/lib/rbx/fixnum.fy +1 -11
  47. data/lib/rbx/io.fy +4 -0
  48. data/lib/rbx/module.fy +11 -0
  49. data/lib/rbx/object.fy +12 -12
  50. data/lib/rbx/proc.fy +7 -0
  51. data/lib/rbx/string.fy +5 -1
  52. data/lib/rbx/symbol.fy +9 -0
  53. data/lib/string.fy +1 -1
  54. data/lib/tuple.fy +37 -35
  55. data/lib/version.fy +6 -5
  56. data/tests/array.fy +14 -2
  57. data/tests/class.fy +79 -0
  58. data/tests/dynamic_key_hash.fy +16 -0
  59. data/tests/dynamic_slot_object.fy +28 -0
  60. data/tests/dynamic_value_array.fy +12 -0
  61. data/tests/enumerable.fy +46 -0
  62. data/tests/file.fy +38 -0
  63. data/tests/fixnum.fy +22 -0
  64. data/tests/future.fy +40 -0
  65. data/tests/hash.fy +8 -7
  66. data/tests/object.fy +31 -5
  67. data/tests/set.fy +1 -1
  68. data/tests/string.fy +18 -2
  69. data/tests/tuple.fy +7 -0
  70. data/tools/fancy-mode.el +10 -0
  71. metadata +9 -12
  72. data/examples/99bottles.fy +0 -5
  73. data/examples/conditions_exceptions.fy +0 -9
  74. data/examples/conditions_parsing.fy +0 -68
  75. data/examples/dynamic.fy +0 -8
  76. data/examples/greeter.fy +0 -9
  77. data/examples/parsing.fy +0 -1
  78. data/lib/rbx/process.fy +0 -13
  79. data/lib/remote_object.fy +0 -59
@@ -102,4 +102,42 @@ FancySpec describe: File with: {
102
102
  File directory?: "README" . is: false
103
103
  File directory?: "src/bootstrap/Makefile" . is: false
104
104
  }
105
+
106
+ it: "evals a file" with: 'eval: when: {
107
+ "/tmp/test_#{Time now to_i}.fy" tap: |filename| {
108
+ File tap: @{
109
+ write: filename with: @{ print: "2 * 3 to_s inspect" }
110
+ eval: filename . is: $ 6 to_s inspect
111
+ delete: filename
112
+ }
113
+ # File write: filename with: @{ print: "2 * 3 to_s inspect" }
114
+ # File eval: filename . is: $ 6 to_s inspect
115
+ # File delete: filename
116
+ }
117
+ }
118
+
119
+ it: "reads a config file" with: 'read_config: when: {
120
+ contents = """
121
+ {
122
+ test: 'value
123
+ other: 123
124
+ more: {
125
+ again: 'foo
126
+ yup: [1,2,3]
127
+ }
128
+ }
129
+ """
130
+
131
+ filename = "/tmp/#{Time now to_i random}_fy_test.txt"
132
+ File write: filename with: @{ write: contents }
133
+ File read_config: filename . is: <[
134
+ 'test => 'value,
135
+ 'other => 123,
136
+ 'more => <[
137
+ 'again => 'foo,
138
+ 'yup => [1,2,3]
139
+ ]>
140
+ ]>
141
+ File delete: filename
142
+ }
105
143
  }
@@ -117,4 +117,26 @@ FancySpec describe: Fixnum with: {
117
117
  times_called is: 10
118
118
  sum is: ((10..19) sum)
119
119
  }
120
+
121
+ it: "tries to run a code block self amount of times or fails" with: 'try_times: when: {
122
+ { -2 times_try: { 2 / 0 } } does_not raise: Exception
123
+ { -1 times_try: { 2 / 0 } } does_not raise: Exception
124
+ { 0 times_try: { 2 / 0 } } does_not raise: Exception
125
+ { 1 times_try: { 2 / 0 } } raises: ZeroDivisionError
126
+ { 2 times_try: { 2 / 0 } } raises: ZeroDivisionError
127
+
128
+ tries = 0
129
+ {
130
+ 2 times_try: {
131
+ tries = tries + 1
132
+ 2 / 0
133
+ }
134
+ } raises: ZeroDivisionError
135
+ tries is: 2
136
+
137
+ 2 times_try: { 2 } . is: 2
138
+
139
+ i = 0
140
+ 2 times_try: { 2 / i } retry_with: { i = 1 } . is: 2
141
+ }
120
142
  }
@@ -53,4 +53,44 @@ FancySpec describe: FutureSend with: {
53
53
  f failure message is: "error!"
54
54
  f failed? is: true
55
55
  }
56
+
57
+ it: "calls a block when done" with: 'when_done: when: {
58
+ called? = false
59
+ failed? = false
60
+ val = 0
61
+ f = { Thread sleep: 0.01; 2 } @ call
62
+ f when_done: |v| {
63
+ val = v
64
+ called? = true
65
+ }
66
+ f when_failed: |err| {
67
+ val = err
68
+ failed? = true
69
+ }
70
+
71
+ f value
72
+ called? is: true
73
+ val is: 2
74
+ }
75
+
76
+ it: "calls a block when failed" with: 'when_failed: when: {
77
+ called? = false
78
+ failed? = false
79
+ val = 0
80
+ f = { Thread sleep: 0.01; "Fail!" raise! } @ call
81
+ f when_done: |v| {
82
+ val = v
83
+ called? = true
84
+ }
85
+ f when_failed: |err| {
86
+ val = err
87
+ failed? = true
88
+ }
89
+
90
+ f value
91
+ called? is: false
92
+ failed? is: true
93
+ val message is: "Fail!"
94
+ val is_a?: Exception
95
+ }
56
96
  }
@@ -42,6 +42,14 @@ FancySpec describe: Hash with: {
42
42
  hash at: 'foo1 else: { "hello" } . is: "hello"
43
43
  }
44
44
 
45
+ it: "calls the block if it can't find the key and inserts the return value" with: 'at:else_put: when: {
46
+ hash = <['foo => "bar", 'bar => nil]>
47
+ hash at: 'foo else_put: { "hello" } . is: "bar"
48
+ hash at: 'bar else_put: { "hello" } . is: nil
49
+ hash at: 'foo1 else_put: { "hello" } . is: "hello"
50
+ hash['foo1] is: "hello"
51
+ }
52
+
45
53
  it: "returns all keys" with: 'keys when: {
46
54
  hash = <['foo => "bar", 'bar => "baz", 'foobar => 112.21]>
47
55
  hash keys is =? ['foo, 'bar, 'foobar]
@@ -123,13 +131,6 @@ FancySpec describe: Hash with: {
123
131
  h includes?: nil . is: false
124
132
  }
125
133
 
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
134
  it: "returns an object with slots based on key-value pairs in Hash" for: 'to_object when: {
134
135
  <[]> to_object slots empty? is: true
135
136
  <['name => "Chris"]> to_object tap: @{
@@ -171,9 +171,7 @@ FancySpec describe: Object with: {
171
171
  }
172
172
  MyClass new do_wacky_things is: false
173
173
 
174
- {
175
- true is: false
176
- } call_with_receiver: (MyClass new)
174
+ @{ true is: false } call: [MyClass new]
177
175
  }
178
176
 
179
177
  it: "overrides nil" with: 'nil when: {
@@ -183,7 +181,7 @@ FancySpec describe: Object with: {
183
181
  }
184
182
  }
185
183
 
186
- { nil is: true } call_with_receiver: (MyClass new)
184
+ @{ nil is: true } call: [MyClass new]
187
185
  }
188
186
 
189
187
  it: "overrides false" with: 'false when: {
@@ -193,7 +191,7 @@ FancySpec describe: Object with: {
193
191
  }
194
192
  }
195
193
 
196
- { false is: true } call_with_receiver: (MyClass2 new)
194
+ @{ false is: true } call: [MyClass2 new]
197
195
  }
198
196
 
199
197
  it: "implicitly sends a message to self if no receiver is specified" when: {
@@ -278,4 +276,32 @@ FancySpec describe: Object with: {
278
276
  bar: [1,2,3] values: v . is: 1
279
277
  v is: [1]
280
278
  }
279
+
280
+ it: "provides temporarily mutable slots" with: 'with_mutable_slots: when: {
281
+ class Student {
282
+ read_slots: ('name, 'age, 'city)
283
+ def initialize: block {
284
+ with_mutable_slots: ('name, 'age, 'city) do: block
285
+ }
286
+ }
287
+
288
+ p = Student new: @{
289
+ name: "Chris"
290
+ age: 24
291
+ city: "Osnabrück"
292
+ }
293
+
294
+ p name is: "Chris"
295
+ p age is: 24
296
+ p city is: "Osnabrück"
297
+
298
+ { p name: "New Name" } raises: NoMethodError
299
+ { p age: 25 } raises: NoMethodError
300
+ { p city: "New City" } raises: NoMethodError
301
+
302
+ # no changes
303
+ p name is: "Chris"
304
+ p age is: 24
305
+ p city is: "Osnabrück"
306
+ }
281
307
  }
@@ -16,7 +16,7 @@ FancySpec describe: Set with: {
16
16
  s << "foo"
17
17
  s << "bar"
18
18
  s << "foo"
19
- s values is: ["foo", "bar"]
19
+ s values =? ["foo", "bar"] . is: true
20
20
  }
21
21
 
22
22
  it: "only keeps unique values" with: '[] when: {
@@ -41,9 +41,9 @@ FancySpec describe: String with: {
41
41
  }
42
42
  }
43
43
 
44
- it: "behaves like a collection/sequence via each:" with: 'uniq when: {
44
+ it: "behaves like a collection/sequence via each:" with: 'unique when: {
45
45
  str = "Hello, World!"
46
- str uniq join: "" . is: "Helo, Wrd!"
46
+ str unique join: "" . is: "Helo, Wrd!"
47
47
  }
48
48
 
49
49
  it: "has all its characters as instances of String class" with: 'all?: when: {
@@ -126,6 +126,22 @@ FancySpec describe: String with: {
126
126
  s is: "Good day. Hello."
127
127
  }
128
128
 
129
+ it: "returns the character at a given index" with: '[] when: {
130
+ s = "hello"
131
+ s[0] is: "h"
132
+ s[1] is: "e"
133
+ s[2] is: "l"
134
+ s[3] is: "l"
135
+ s[4] is: "o"
136
+ # out of bounds yields nil:
137
+ s[5] is: nil
138
+ s[s size] is: nil
139
+ s[s size + 1] is: nil
140
+ "" at: 0 . is: nil
141
+ "" at: 1 . is: nil
142
+ "" at: -1 . is: nil
143
+ }
144
+
129
145
  it: "contains a substring" with: 'includes?: when: {
130
146
  "foo bar baz" includes?: "foo" . is: true
131
147
  "foo bar baz" includes?: "bar" . is: true
@@ -65,4 +65,11 @@ FancySpec describe: Tuple with: {
65
65
  sum is: 6
66
66
  vals is: [3,2,1]
67
67
  }
68
+
69
+ it: "returns an array of all elements between two indices" with: 'from:to: when: {
70
+ (1,2) from: 2 to: 3 . is: []
71
+ (1,2,3) from: 0 to: 2 . is: [1,2,3]
72
+ (4,5,6,7,8,9) from: 3 to: 5 . is: [7,8,9]
73
+ (1,2,3) from: 1 to: -1 . is: [2,3]
74
+ }
68
75
  }
@@ -1,3 +1,10 @@
1
+ ;;; fancy-mode.el --- Major mode for programming with the Fancy language.
2
+ ;;
3
+ ;; URL: http://www.fancy-lang.org
4
+ ;; Version: 0.1
5
+ ;; Author: Christopher Bertels <chris@fancy-lang.org>
6
+
7
+
1
8
  (require 'generic-x)
2
9
 
3
10
  (define-generic-mode
@@ -40,6 +47,7 @@
40
47
 
41
48
  (add-to-list 'auto-mode-alist '("\\.fy\\'" . fancy-mode))
42
49
  (add-to-list 'auto-mode-alist '("\\.fancypack\\'" . fancy-mode))
50
+ (add-to-list 'auto-mode-alist '("\\Fakefile\\'" . fancy-mode))
43
51
 
44
52
  (add-to-list 'interpreter-mode-alist '("fancy" . fancy-mode))
45
53
 
@@ -65,3 +73,5 @@
65
73
  (setq indent-line-function 'fancy-indent-line)
66
74
 
67
75
  (provide 'fancy-mode)
76
+
77
+ ;;; fancy-mode.el ends here
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fancy
3
3
  version: !ruby/object:Gem::Version
4
- hash: 2770122483358164876
4
+ hash: 3845972432426844170
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 6
8
+ - 7
9
9
  - 0
10
- version: 0.6.0
10
+ version: 0.7.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Christopher Bertels
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: ruby_lib
16
16
  cert_chain: []
17
17
 
18
- date: 2012-01-25 00:00:00 Z
18
+ date: 2012-05-05 00:00:00 Z
19
19
  dependencies: []
20
20
 
21
21
  description: |
@@ -88,7 +88,6 @@ files:
88
88
  - lib/proxy.fy
89
89
  - lib/range.fy
90
90
  - lib/rbx.fy
91
- - lib/remote_object.fy
92
91
  - lib/set.fy
93
92
  - lib/stack.fy
94
93
  - lib/string.fy
@@ -107,6 +106,7 @@ files:
107
106
  - lib/compiler/stages.fy
108
107
  - lib/package/dependency.fy
109
108
  - lib/package/dependency_installer.fy
109
+ - lib/package/handler.fy
110
110
  - lib/package/installer.fy
111
111
  - lib/package/list.fy
112
112
  - lib/package/specification.fy
@@ -140,7 +140,7 @@ files:
140
140
  - lib/rbx/name_error.fy
141
141
  - lib/rbx/no_method_error.fy
142
142
  - lib/rbx/object.fy
143
- - lib/rbx/process.fy
143
+ - lib/rbx/proc.fy
144
144
  - lib/rbx/range.fy
145
145
  - lib/rbx/regexp.fy
146
146
  - lib/rbx/string.fy
@@ -185,6 +185,9 @@ files:
185
185
  - tests/class.fy
186
186
  - tests/control_flow.fy
187
187
  - tests/documentation.fy
188
+ - tests/dynamic_key_hash.fy
189
+ - tests/dynamic_slot_object.fy
190
+ - tests/dynamic_value_array.fy
188
191
  - tests/enumerable.fy
189
192
  - tests/enumerator.fy
190
193
  - tests/exception.fy
@@ -214,7 +217,6 @@ files:
214
217
  - bin/fyi
215
218
  - bin/ifancy
216
219
  - bin/fspec
217
- - examples/99bottles.fy
218
220
  - examples/actor_bunnies.fy
219
221
  - examples/actors.fy
220
222
  - examples/actors_primitive.fy
@@ -229,14 +231,11 @@ files:
229
231
  - examples/call_with_receiver.fy
230
232
  - examples/class.fy
231
233
  - examples/closures.fy
232
- - examples/conditions_exceptions.fy
233
- - examples/conditions_parsing.fy
234
234
  - examples/constant_access.fy
235
235
  - examples/default_args.fy
236
236
  - examples/define_methods.fy
237
237
  - examples/documentation.fy
238
238
  - examples/documentation_formatters.fy
239
- - examples/dynamic.fy
240
239
  - examples/dynamic_output.fy
241
240
  - examples/echo.fy
242
241
  - examples/empty_catch.fy
@@ -249,7 +248,6 @@ files:
249
248
  - examples/future_composition.fy
250
249
  - examples/futures.fy
251
250
  - examples/game_of_life.fy
252
- - examples/greeter.fy
253
251
  - examples/hashes.fy
254
252
  - examples/hello_world.fy
255
253
  - examples/html_generator.fy
@@ -259,7 +257,6 @@ files:
259
257
  - examples/nested_classes.fy
260
258
  - examples/nested_try.fy
261
259
  - examples/numbers.fy
262
- - examples/parsing.fy
263
260
  - examples/pattern_matching.fy
264
261
  - examples/person.fy
265
262
  - examples/regex.fy
@@ -1,5 +0,0 @@
1
- # see http://bottles.heroku.com/wall/99
2
- 99 downto: 2 do: |i| {
3
- "#{i} bottles of beer on the wall, #{i} bottles of beer." println
4
- "Take one down and pass it around, #{i - 1} bottles of beer on the wall.\n" println
5
- }
@@ -1,9 +0,0 @@
1
- with_handlers: @{
2
- when: ZeroDivisionError do: { restart: 'default }
3
- } do: {
4
- with_restarts: {
5
- default: { 1 }
6
- } do: {
7
- 10 / 0 inspect println println
8
- }
9
- }
@@ -1,68 +0,0 @@
1
- class MalformedLogEntry : Error {
2
- read_slot: 'text
3
- def initialize: @text
4
- }
5
-
6
- class LogEntry {
7
- read_write_slots: ('word, 'number)
8
-
9
- def LogEntry parse_entry: text {
10
- word, number = text split: "|"
11
- number = number to_i
12
- if: (word && number) then: {
13
- LogEntry new do: {
14
- word: word
15
- number: number
16
- }
17
- } else: {
18
- MalformedLogEntry new: text signal!
19
- }
20
- }
21
- }
22
-
23
- class LogFile {
24
- read_slots: ('filename, 'entries)
25
- def initialize: @filename entries: @entries ([]);
26
- def parse {
27
- @text = File read: @filename
28
- with_restarts: {
29
- skip_entry: { nil }
30
- } do: {
31
- @text lines each: |line| {
32
- @entries << (LogEntry parse_entry: line)
33
- }
34
- }
35
- }
36
- }
37
-
38
- class LogAnalyzer {
39
- read_slots: ('words, 'numbers)
40
- def initialize: @logfiles {
41
- @words = <[]>
42
- @numbers = <[]>
43
- }
44
- def analyze_all {
45
- @entries = @logfiles map: |f| {
46
- LogFile new: f . do: { parse } . entries
47
- } flatten
48
-
49
- @entries each: |e| { analyze: e }
50
- }
51
- def analyze: entry {
52
- if: (@words[entry word]) then: |val| {
53
- @words[entry word]: (val + 1)
54
- } else: {
55
- @words[entry word]: 1
56
- }
57
- if: (@numbers[entry number]) then: |val| {
58
- @numbers[entry number]: (val + 1)
59
- } else: {
60
- @numbers[entry number]: 1
61
- }
62
- }
63
- }
64
-
65
- l = LogAnalyzer new: ["examples/conditions_parsing_log.log"]
66
- l analyze_all
67
- " words: #{l words to_a sort_by: 'second reverse inspect}" println
68
- "numbers: #{l numbers to_a sort_by: 'second reverse inspect}" println