fancy 0.3.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 (242) hide show
  1. data/AUTHORS +7 -0
  2. data/LICENSE +19 -0
  3. data/README +173 -0
  4. data/Rakefile +255 -0
  5. data/bin/fancy +40 -0
  6. data/bin/fdoc +23 -0
  7. data/bin/fyi +22 -0
  8. data/bin/ifancy +46 -0
  9. data/boot/README +12 -0
  10. data/boot/code_loader.rb +165 -0
  11. data/boot/compile.fy +3 -0
  12. data/boot/fancy_ext.rb +13 -0
  13. data/boot/fancy_ext/block_env.rb +29 -0
  14. data/boot/fancy_ext/class.rb +26 -0
  15. data/boot/fancy_ext/kernel.rb +12 -0
  16. data/boot/fancy_ext/module.rb +89 -0
  17. data/boot/fancy_ext/object.rb +34 -0
  18. data/boot/fancy_ext/string_helper.rb +10 -0
  19. data/boot/load.rb +72 -0
  20. data/boot/rbx-compiler/README +12 -0
  21. data/boot/rbx-compiler/compiler.rb +24 -0
  22. data/boot/rbx-compiler/compiler/ast.rb +23 -0
  23. data/boot/rbx-compiler/compiler/ast/README +11 -0
  24. data/boot/rbx-compiler/compiler/ast/array_literal.rb +13 -0
  25. data/boot/rbx-compiler/compiler/ast/assign.rb +57 -0
  26. data/boot/rbx-compiler/compiler/ast/block.rb +70 -0
  27. data/boot/rbx-compiler/compiler/ast/class_def.rb +35 -0
  28. data/boot/rbx-compiler/compiler/ast/expression_list.rb +57 -0
  29. data/boot/rbx-compiler/compiler/ast/hash_literal.rb +11 -0
  30. data/boot/rbx-compiler/compiler/ast/identifier.rb +120 -0
  31. data/boot/rbx-compiler/compiler/ast/match.rb +81 -0
  32. data/boot/rbx-compiler/compiler/ast/message_send.rb +71 -0
  33. data/boot/rbx-compiler/compiler/ast/method_def.rb +116 -0
  34. data/boot/rbx-compiler/compiler/ast/node.rb +6 -0
  35. data/boot/rbx-compiler/compiler/ast/range_literal.rb +22 -0
  36. data/boot/rbx-compiler/compiler/ast/require.rb +20 -0
  37. data/boot/rbx-compiler/compiler/ast/return.rb +29 -0
  38. data/boot/rbx-compiler/compiler/ast/ruby_args.rb +35 -0
  39. data/boot/rbx-compiler/compiler/ast/script.rb +56 -0
  40. data/boot/rbx-compiler/compiler/ast/singleton_method_def.rb +39 -0
  41. data/boot/rbx-compiler/compiler/ast/string_literal.rb +14 -0
  42. data/boot/rbx-compiler/compiler/ast/super.rb +25 -0
  43. data/boot/rbx-compiler/compiler/ast/try_catch_block.rb +220 -0
  44. data/boot/rbx-compiler/compiler/ast/tuple_literal.rb +33 -0
  45. data/boot/rbx-compiler/compiler/command.rb +39 -0
  46. data/boot/rbx-compiler/compiler/compiler.rb +83 -0
  47. data/boot/rbx-compiler/compiler/stages.rb +99 -0
  48. data/boot/rbx-compiler/parser.rb +2 -0
  49. data/boot/rbx-compiler/parser/README +15 -0
  50. data/boot/rbx-compiler/parser/Rakefile +54 -0
  51. data/boot/rbx-compiler/parser/extconf.rb +3 -0
  52. data/boot/rbx-compiler/parser/fancy_parser.bundle +0 -0
  53. data/boot/rbx-compiler/parser/fancy_parser.c +46 -0
  54. data/boot/rbx-compiler/parser/fancy_parser.h +8 -0
  55. data/boot/rbx-compiler/parser/lexer.lex +180 -0
  56. data/boot/rbx-compiler/parser/parser.rb +356 -0
  57. data/boot/rbx-compiler/parser/parser.y +711 -0
  58. data/boot/rsexp_pretty_printer.rb +76 -0
  59. data/doc/api/fancy.css +93 -0
  60. data/doc/api/fancy.jsonp +1 -0
  61. data/doc/api/fdoc.js +187 -0
  62. data/doc/api/index.html +57 -0
  63. data/doc/api/underscore-min.js +18 -0
  64. data/doc/features.md +228 -0
  65. data/examples/argv.fy +8 -0
  66. data/examples/arithmetic.fy +7 -0
  67. data/examples/armstrong_numbers.fy +33 -0
  68. data/examples/array.fy +52 -0
  69. data/examples/blocks.fy +15 -0
  70. data/examples/boolean.fy +24 -0
  71. data/examples/call_with_receiver.fy +9 -0
  72. data/examples/class.fy +68 -0
  73. data/examples/closures.fy +24 -0
  74. data/examples/constant_access.fy +15 -0
  75. data/examples/default_args.fy +17 -0
  76. data/examples/define_methods.fy +15 -0
  77. data/examples/documentation.fy +57 -0
  78. data/examples/documentation_formatters.fy +25 -0
  79. data/examples/echo.fy +16 -0
  80. data/examples/empty_catch.fy +4 -0
  81. data/examples/exception.fy +9 -0
  82. data/examples/factorial.fy +12 -0
  83. data/examples/fibonacci.fy +16 -0
  84. data/examples/files.fy +23 -0
  85. data/examples/finally.fy +5 -0
  86. data/examples/game_of_life.fy +148 -0
  87. data/examples/hashes.fy +7 -0
  88. data/examples/hello_world.fy +6 -0
  89. data/examples/html_generator.fy +54 -0
  90. data/examples/implicit_return.fy +3 -0
  91. data/examples/matchers.fy +6 -0
  92. data/examples/methods.fy +29 -0
  93. data/examples/nested_classes.fy +27 -0
  94. data/examples/nested_try.fy +9 -0
  95. data/examples/numbers.fy +12 -0
  96. data/examples/pattern_matching.fy +40 -0
  97. data/examples/person.fy +65 -0
  98. data/examples/project-euler/01.fy +8 -0
  99. data/examples/project-euler/02.fy +21 -0
  100. data/examples/project-euler/28.fy +33 -0
  101. data/examples/rbx/and_or.fy +7 -0
  102. data/examples/rbx/blocks.fy +22 -0
  103. data/examples/rbx/classes.fy +32 -0
  104. data/examples/rbx/hello.fy +8 -0
  105. data/examples/rbx/include.fy +12 -0
  106. data/examples/rbx/inherit.fy +11 -0
  107. data/examples/rbx/methods.fy +15 -0
  108. data/examples/rbx/nested_classes.fy +9 -0
  109. data/examples/rbx/require.fy +3 -0
  110. data/examples/rbx/strings.fy +5 -0
  111. data/examples/regex.fy +7 -0
  112. data/examples/require.fy +7 -0
  113. data/examples/retry.fy +12 -0
  114. data/examples/return.fy +13 -0
  115. data/examples/ruby_require.fy +7 -0
  116. data/examples/ruby_send.fy +3 -0
  117. data/examples/singleton_methods.fy +21 -0
  118. data/examples/stupid_quicksort.fy +12 -0
  119. data/examples/threads.fy +18 -0
  120. data/examples/tuple.fy +8 -0
  121. data/examples/webserver/webserver.fy +18 -0
  122. data/lib/argv.fy +36 -0
  123. data/lib/array.fy +207 -0
  124. data/lib/block.fy +88 -0
  125. data/lib/boot.fy +41 -0
  126. data/lib/class.fy +106 -0
  127. data/lib/compiler.fy +14 -0
  128. data/lib/compiler/ast.fy +40 -0
  129. data/lib/compiler/ast/assign.fy +96 -0
  130. data/lib/compiler/ast/block.fy +84 -0
  131. data/lib/compiler/ast/class_def.fy +33 -0
  132. data/lib/compiler/ast/expression_list.fy +47 -0
  133. data/lib/compiler/ast/identifier.fy +113 -0
  134. data/lib/compiler/ast/literals.fy +122 -0
  135. data/lib/compiler/ast/match.fy +88 -0
  136. data/lib/compiler/ast/message_send.fy +110 -0
  137. data/lib/compiler/ast/method_def.fy +90 -0
  138. data/lib/compiler/ast/node.fy +7 -0
  139. data/lib/compiler/ast/range.fy +16 -0
  140. data/lib/compiler/ast/require.fy +15 -0
  141. data/lib/compiler/ast/return.fy +23 -0
  142. data/lib/compiler/ast/script.fy +52 -0
  143. data/lib/compiler/ast/singleton_method_def.fy +35 -0
  144. data/lib/compiler/ast/super.fy +17 -0
  145. data/lib/compiler/ast/try_catch.fy +176 -0
  146. data/lib/compiler/ast/tuple_literal.fy +34 -0
  147. data/lib/compiler/command.fy +51 -0
  148. data/lib/compiler/compiler.fy +73 -0
  149. data/lib/compiler/stages.fy +81 -0
  150. data/lib/directory.fy +17 -0
  151. data/lib/documentation.fy +115 -0
  152. data/lib/enumerable.fy +269 -0
  153. data/lib/eval.fy +31 -0
  154. data/lib/fancy_spec.fy +202 -0
  155. data/lib/fdoc.fy +359 -0
  156. data/lib/fdoc_hook.fy +10 -0
  157. data/lib/file.fy +54 -0
  158. data/lib/hash.fy +56 -0
  159. data/lib/main.fy +80 -0
  160. data/lib/method.fy +22 -0
  161. data/lib/nil_class.fy +56 -0
  162. data/lib/number.fy +87 -0
  163. data/lib/object.fy +170 -0
  164. data/lib/package.fy +61 -0
  165. data/lib/package/dependency.fy +24 -0
  166. data/lib/package/installer.fy +180 -0
  167. data/lib/package/specification.fy +55 -0
  168. data/lib/package/uninstaller.fy +15 -0
  169. data/lib/parser.fy +4 -0
  170. data/lib/parser/ext/README +15 -0
  171. data/lib/parser/ext/ext.c +42 -0
  172. data/lib/parser/ext/ext.h +8 -0
  173. data/lib/parser/ext/extconf.rb +3 -0
  174. data/lib/parser/ext/lexer.lex +187 -0
  175. data/lib/parser/ext/parser.y +744 -0
  176. data/lib/parser/methods.fy +297 -0
  177. data/lib/rbx.fy +37 -0
  178. data/lib/rbx/array.fy +237 -0
  179. data/lib/rbx/bignum.fy +23 -0
  180. data/lib/rbx/block.fy +9 -0
  181. data/lib/rbx/class.fy +129 -0
  182. data/lib/rbx/code_loader.fy +192 -0
  183. data/lib/rbx/console.fy +63 -0
  184. data/lib/rbx/directory.fy +46 -0
  185. data/lib/rbx/documentation.fy +64 -0
  186. data/lib/rbx/environment_variables.fy +3 -0
  187. data/lib/rbx/exception.fy +30 -0
  188. data/lib/rbx/false_class.fy +58 -0
  189. data/lib/rbx/fiber.fy +25 -0
  190. data/lib/rbx/file.fy +191 -0
  191. data/lib/rbx/fixnum.fy +25 -0
  192. data/lib/rbx/float.fy +14 -0
  193. data/lib/rbx/hash.fy +38 -0
  194. data/lib/rbx/integer.fy +15 -0
  195. data/lib/rbx/io.fy +30 -0
  196. data/lib/rbx/match_data.fy +9 -0
  197. data/lib/rbx/method.fy +22 -0
  198. data/lib/rbx/name_error.fy +3 -0
  199. data/lib/rbx/no_method_error.fy +15 -0
  200. data/lib/rbx/object.fy +117 -0
  201. data/lib/rbx/range.fy +15 -0
  202. data/lib/rbx/regexp.fy +9 -0
  203. data/lib/rbx/string.fy +63 -0
  204. data/lib/rbx/symbol.fy +12 -0
  205. data/lib/rbx/system.fy +37 -0
  206. data/lib/rbx/tcp_server.fy +6 -0
  207. data/lib/rbx/tcp_socket.fy +7 -0
  208. data/lib/rbx/thread.fy +75 -0
  209. data/lib/rbx/tuple.fy +37 -0
  210. data/lib/set.fy +61 -0
  211. data/lib/stack.fy +51 -0
  212. data/lib/string.fy +58 -0
  213. data/lib/struct.fy +13 -0
  214. data/lib/symbol.fy +23 -0
  215. data/lib/true_class.fy +43 -0
  216. data/lib/tuple.fy +68 -0
  217. data/lib/version.fy +6 -0
  218. data/tests/argv.fy +13 -0
  219. data/tests/array.fy +343 -0
  220. data/tests/assignment.fy +53 -0
  221. data/tests/block.fy +103 -0
  222. data/tests/class.fy +409 -0
  223. data/tests/control_flow.fy +79 -0
  224. data/tests/documentation.fy +24 -0
  225. data/tests/exception.fy +115 -0
  226. data/tests/file.fy +86 -0
  227. data/tests/hash.fy +101 -0
  228. data/tests/method.fy +131 -0
  229. data/tests/nil_class.fy +55 -0
  230. data/tests/number.fy +128 -0
  231. data/tests/object.fy +125 -0
  232. data/tests/parsing/sexp.fy +50 -0
  233. data/tests/pattern_matching.fy +82 -0
  234. data/tests/range.fy +11 -0
  235. data/tests/set.fy +10 -0
  236. data/tests/stack.fy +22 -0
  237. data/tests/string.fy +102 -0
  238. data/tests/symbol.fy +17 -0
  239. data/tests/true_class.fy +63 -0
  240. data/tests/tuple.fy +21 -0
  241. data/tools/fancy-mode.el +63 -0
  242. metadata +321 -0
data/lib/rbx/tuple.fy ADDED
@@ -0,0 +1,37 @@
1
+ Tuple = Rubinius Tuple
2
+ class Tuple {
3
+ ruby_alias: 'size
4
+
5
+ def initialize: size {
6
+ """
7
+ @size Size of the @Tuple@ (amount of values to hold).
8
+
9
+ Initializes a new @Tuple@ with a given amount of element slots.
10
+ E.g. if @size is @2, creates a 2-Tuple.
11
+ """
12
+
13
+ initialize(size)
14
+ }
15
+
16
+ def at: idx {
17
+ """
18
+ @idx Index for the element to get.
19
+ @return Element at the given index within the @Tuple@ or @nil.
20
+
21
+ Returns an element at a given indes.
22
+ Possibly throws an @Rubinius::ObjectBoundsExceededError@.
23
+ """
24
+
25
+ at(idx)
26
+ }
27
+
28
+ def at: idx put: val {
29
+ """
30
+ @idx Index of element to set.
31
+ @val Value to set at given index.
32
+
33
+ Sets a value for a given index within a @Tuple@.
34
+ """
35
+ put(idx, val)
36
+ }
37
+ }
data/lib/set.fy ADDED
@@ -0,0 +1,61 @@
1
+ class Set {
2
+ "A simple Set data structure class."
3
+
4
+ include: FancyEnumerable
5
+ read_slots: ['values]
6
+
7
+ def initialize: arr {
8
+ "Initialize a new Set with a given Array of values."
9
+ @values = arr uniq
10
+ }
11
+
12
+ def initialize {
13
+ "Initialize a new empty Set."
14
+ @values = []
15
+ }
16
+
17
+ def == other {
18
+ "Indicates, if two Sets are equal."
19
+ if: (other is_a?: Set) then: {
20
+ @values == (other values)
21
+ }
22
+ }
23
+
24
+ def Set [] arr {
25
+ "Initialize a new Array with a given Array of values."
26
+ Set new: arr
27
+ }
28
+
29
+ def << value {
30
+ "Insert a value into the Set."
31
+ { @values << value } unless: (includes?: value)
32
+ }
33
+
34
+ def includes?: value {
35
+ "Indicates, if the Set includes a given value."
36
+ @values includes?: value
37
+ }
38
+
39
+ def each: block {
40
+ "Calls a given Block for each element of the Set."
41
+ @values each: block
42
+ }
43
+
44
+ def unknown_message: msg with_params: params {
45
+ if: (params empty?) then: {
46
+ @values send: msg
47
+ } else: {
48
+ @values send: msg params: params
49
+ }
50
+ }
51
+
52
+ def to_s {
53
+ "Returns a String representation of a Set."
54
+ "Set" ++ @values to_s
55
+ }
56
+
57
+ def inspect {
58
+ "Returns a detailed String representation of a Set."
59
+ self to_s ++ " : Set"
60
+ }
61
+ }
data/lib/stack.fy ADDED
@@ -0,0 +1,51 @@
1
+ class Stack {
2
+ """
3
+ A simple Stack container class.
4
+ """
5
+
6
+ def initialize {
7
+ @arr = []
8
+ }
9
+
10
+ def initialize: size {
11
+ "Initializes a new Stack with a given size."
12
+
13
+ @arr = Array new: size
14
+ }
15
+
16
+ def push: obj {
17
+ "Pushes a value onto the Stack."
18
+
19
+ @arr << obj
20
+ }
21
+
22
+ def << obj {
23
+ "Same as Stack#push:."
24
+
25
+ @arr << obj
26
+ }
27
+
28
+ def pop {
29
+ "Pops the top-of-stack element from the Stack and returns it."
30
+
31
+ @arr remove_at: (self size - 1)
32
+ }
33
+
34
+ def top {
35
+ "Returns the top-of-stack element."
36
+
37
+ @arr last
38
+ }
39
+
40
+ def size {
41
+ "Returns the size of the Stack."
42
+
43
+ @arr size
44
+ }
45
+
46
+ def empty? {
47
+ "Indicates, if the Stack is empty."
48
+
49
+ @arr empty?
50
+ }
51
+ }
data/lib/string.fy ADDED
@@ -0,0 +1,58 @@
1
+ class String {
2
+ """
3
+ Strings are sequences of characters and behave as such.
4
+ All literal Strings within Fancy code are instances of the String
5
+ class.
6
+
7
+ They also include FancyEnumerable, which means you can use all the
8
+ common sequence methods on them, like +map:+, +select:+ etc.
9
+ """
10
+
11
+ include: FancyEnumerable
12
+
13
+ def ++ other {
14
+ "Concatenate the String with another String"
15
+
16
+ self + (other to_s)
17
+ }
18
+
19
+ def whitespace? {
20
+ "Indicates, if a String is empty or a single whitespace character."
21
+
22
+ self empty? or: (self == " ")
23
+ }
24
+
25
+ def blank? {
26
+ "Indicates, if a String consists only of whitespace."
27
+
28
+ self =~ /^\s*$/ if_do: {
29
+ true
30
+ } else: {
31
+ false
32
+ }
33
+ }
34
+
35
+ def * num {
36
+ "Returns a string that is the num-fold concatenation of itself."
37
+
38
+ str = ""
39
+ num to_i times: {
40
+ str = str ++ self
41
+ }
42
+ str
43
+ }
44
+
45
+ def words {
46
+ self split
47
+ }
48
+
49
+ def raise! {
50
+ "Raises a new StdError with self as the message."
51
+ StdError new: self . raise!
52
+ }
53
+
54
+ def rest {
55
+ "Returns a @String@ containing all but the first character."
56
+ from: 1 to: -1
57
+ }
58
+ }
data/lib/struct.fy ADDED
@@ -0,0 +1,13 @@
1
+ class Struct {
2
+ def Struct new: fields {
3
+ struct = ruby: "new" args: fields
4
+ struct read_write_slots: fields
5
+ struct define_method: "new:" with: |values| {
6
+ instance = struct new()
7
+ fields each_with_index: |f i| {
8
+ instance send: f params: [values at: i]
9
+ }
10
+ }
11
+ struct
12
+ }
13
+ }
data/lib/symbol.fy ADDED
@@ -0,0 +1,23 @@
1
+ class Symbol {
2
+ """
3
+ Symbols are unique identifiers and only created once.
4
+
5
+ If there are several occurrances of the same Symbol literal within
6
+ Fancy code, they all refer to the same Symbol object.
7
+ """
8
+
9
+ def call: arg {
10
+ """
11
+ This allows Symbols to be used like Blocks
12
+ (e.g. in all methods of Enumerable).
13
+ Example: [1, 2, 3] map: 'squared # => [1, 4, 9]
14
+ """
15
+
16
+ if: (arg is_a?: Array) then: {
17
+ arg first send: self params: $ arg rest
18
+ } else: {
19
+ arg send: self
20
+ }
21
+ }
22
+
23
+ }
data/lib/true_class.fy ADDED
@@ -0,0 +1,43 @@
1
+ class TrueClass {
2
+ "TrueClass. The class of the singleton true value."
3
+
4
+ def TrueClass new {
5
+ # always return true singleton object when trying to create a new
6
+ # TrueClass instance
7
+ true
8
+ }
9
+
10
+ def if_true: then_block else: else_block {
11
+ "Calls the then_block."
12
+ then_block call
13
+ }
14
+
15
+ def if_true: block {
16
+ "Calls the block."
17
+ block call
18
+ }
19
+
20
+ def if_false: block {
21
+ "Returns nil."
22
+ nil
23
+ }
24
+
25
+ def nil? {
26
+ "Returns nil."
27
+ false
28
+ }
29
+
30
+ def false? {
31
+ "Returns nil."
32
+ false
33
+ }
34
+
35
+ def true? {
36
+ "Returns true."
37
+ true
38
+ }
39
+
40
+ def not {
41
+ false
42
+ }
43
+ }
data/lib/tuple.fy ADDED
@@ -0,0 +1,68 @@
1
+ class Tuple {
2
+ """
3
+ Tuples are fixed-size containers providing index-based access to its
4
+ elements.
5
+ """
6
+
7
+ include: FancyEnumerable
8
+
9
+ def [] idx {
10
+ """
11
+ Forwards to @Tuple#at:@.
12
+ """
13
+
14
+ at: idx
15
+ }
16
+
17
+ def each: block {
18
+ self size times: |i| {
19
+ block call: [self at: i]
20
+ }
21
+ }
22
+
23
+ def == other {
24
+ """
25
+ @other Other @Tuple@ to compare @self with.
26
+ @return @true, if tuples are equal element-wise, @false otherwise.
27
+
28
+ Compares two @Tuple@s with each other.
29
+ """
30
+
31
+ if: (other is_a?: Tuple) then: {
32
+ if: (self size == (other size)) then: {
33
+ self size times: |i| {
34
+ unless: (self[i] == (other[i])) do: {
35
+ return false
36
+ }
37
+ }
38
+ return true
39
+ }
40
+ }
41
+ return false
42
+ }
43
+
44
+ def inspect {
45
+ str = "("
46
+ self each: |v| {
47
+ str = str ++ v
48
+ } in_between: {
49
+ str = str ++ ", "
50
+ }
51
+ str = str ++ ")"
52
+ str
53
+ }
54
+
55
+ def Tuple === obj {
56
+ """
57
+ Matches @Tuple@ class against an object.
58
+ If the given object is a Tuple instance, return a Tuple object.
59
+
60
+ @obj Object to be matched against
61
+ @return Tuple instance containing the values of @obj to be used in pattern matching.
62
+ """
63
+
64
+ if: (obj is_a?: Tuple) then: {
65
+ [obj] + (obj map: 'identity)
66
+ }
67
+ }
68
+ }
data/lib/version.fy ADDED
@@ -0,0 +1,6 @@
1
+ VERSION_MAJOR = 0
2
+ VERSION_MINOR = 3
3
+ VERSION_PATCH = 0
4
+ VERSION_SUFFIX = "alpha"
5
+
6
+ FANCY_VERSION = [VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH] join: "." ++ " " ++ VERSION_SUFFIX
data/tests/argv.fy ADDED
@@ -0,0 +1,13 @@
1
+ FancySpec describe: "ARGV & predefined values" with: {
2
+ it: "should have ARGV correctly defined" when: {
3
+ ARGV empty? should_not == true
4
+ }
5
+
6
+ it: "should have a __FILE__ variable defined" when: {
7
+ __FILE__ should_not == nil
8
+ }
9
+
10
+ it: "should have the __FILE__ value be an element in ARGV" when: {
11
+ ARGV any?: |a| { File basename(a) == (File basename(__FILE__)) } . should == true
12
+ }
13
+ }
data/tests/array.fy ADDED
@@ -0,0 +1,343 @@
1
+ FancySpec describe: Array with: {
2
+ it: "should contain three number values after adding them" for: '<< when: {
3
+ arr = []
4
+ arr << 1
5
+ arr << 2
6
+ arr << 3
7
+ arr should == [1,2,3]
8
+ arr size should == 3
9
+ }
10
+
11
+ it: "should iterate over all elements, calling a block" for: 'each: when: {
12
+ sum = 0
13
+ retval = [1,2,3,4,5] each: |x| { sum = sum + x }
14
+ retval should == sum
15
+ sum should == ([1,2,3,4,5] sum)
16
+ }
17
+
18
+ it: "should be empty after clearing it" for: 'clear when: {
19
+ arr = [1,2,3]
20
+ arr size should == 3
21
+ arr should == [1,2,3]
22
+ arr clear
23
+ arr size should == 0
24
+ arr should == []
25
+ }
26
+
27
+ it: "should be true for empty? when it's empty" for: 'empty? when: {
28
+ [] empty? should == true
29
+ [1] empty? should == false
30
+ [1,2] empty? should == false
31
+ [1,2,3] empty? should == false
32
+ }
33
+
34
+ it: "should be an empty array after initialization" for: 'new when: {
35
+ arr = Array new
36
+ arr size should == 0
37
+ }
38
+
39
+ it: "should return the correct value via index access" for: 'at: when: {
40
+ arr = ['a, 10, "hello, world"]
41
+ arr at: 2 . should == "hello, world"
42
+ arr at: 1 . should == 10
43
+ arr at: 0 . should == 'a
44
+ }
45
+
46
+ it: "should NOT include the items" for: "includes?:" when: {
47
+ arr = ['a, 10, "hello, world"]
48
+ arr includes?: "hello" . should == false
49
+ arr includes?: 11 . should == false
50
+ arr includes?: 'b . should == false
51
+ }
52
+
53
+ it: "should include the items" for: 'includes?: when: {
54
+ arr = ['a, 10, "hello, world"]
55
+ arr includes?: "hello, world" . should == true
56
+ arr includes?: 10 . should == true
57
+ arr includes?: 'a . should == true
58
+ }
59
+
60
+ it: "should return the correct index (or nil) for an element" for: 'index: when: {
61
+ arr = [1, 2, 'a, 3, 4]
62
+ arr index: 1 . should == 0
63
+ arr index: 2 . should == 1
64
+ arr index: 'a . should == 2
65
+ arr index: 3 . should == 3
66
+ arr index: 4 . should == 4
67
+ arr index: 'foo . should == nil
68
+ }
69
+
70
+ it: "should return an Array of all its indices" for: 'indices when: {
71
+ ['foo, 'bar, 'baz] indices should == [0,1,2]
72
+ [] indices should == []
73
+ ['foo] indices should == [0]
74
+ }
75
+
76
+ it: "should return all indices for an element as an Array" for: 'indices: when: {
77
+ arr = [1, 2, 'a, 3, 2, 'a]
78
+ arr indices_of: 1 . should == [0]
79
+ arr indices_of: 2 . should == [1, 4]
80
+ arr indices_of: 'a . should == [2, 5]
81
+ arr indices_of: 3. should == [3]
82
+ arr indices_of: 'foo . should == []
83
+ }
84
+
85
+ it: "should find the value" for: 'find: when: {
86
+ arr = ['foo, "bar", 'baz, 1234]
87
+
88
+ arr find: "bar" . should == "bar"
89
+
90
+ arr find: |x| {
91
+ x is_a?: String . if_true: {
92
+ x from: 0 to: 1 == "ba"
93
+ }
94
+ } . should == "bar"
95
+
96
+ arr find: "foo" . should == nil
97
+ }
98
+
99
+ it: "should NOT find the value" for: 'find: when: {
100
+ arr = ['foo, "bar", 'baz, 1234]
101
+
102
+ arr find: "ba" . should == nil
103
+
104
+ arr find: |x| {
105
+ x is_a?: String . if_true: {
106
+ x from: 0 to: 1 == "aa"
107
+ }
108
+ } . should == nil
109
+
110
+ arr find: "foobar" . should == nil
111
+ }
112
+
113
+ it: "should find the value via a block" for: 'find_by: when: {
114
+ arr = [1, 2, 'foo, "yo", nil, true]
115
+ arr find_by: |x| { x is_a?: String } . should == "yo"
116
+ arr find_by: |x| { x is_a?: Block } . should == nil
117
+ }
118
+
119
+ it: "should return the last element" for: 'last when: {
120
+ arr = [1, 2, 3, 'foo, "bar"]
121
+ arr last should == "bar"
122
+ (arr last == 'foo) should == false
123
+ }
124
+
125
+ it: "should return the last n element" for: 'last: when: {
126
+ arr = [1, 2, 3, 'foo, "bar"]
127
+ arr last: 1 . should == [arr last]
128
+ arr last: 2 . should == ['foo, "bar"]
129
+ arr last: 3 . should == [3, 'foo, "bar"]
130
+ arr last: 4 . should == [2, 3, 'foo, "bar"]
131
+ arr last: 5 . should == [1, 2, 3, 'foo, "bar"]
132
+ arr last: (arr size) . should == arr
133
+ arr last: (arr size + 1) . should == arr
134
+ }
135
+
136
+ it: "should return an array containing the values at the given indices" for: 'values_at: when: {
137
+ arr = [1, 2, 3, 'foo, "bar"]
138
+ arr values_at: [1, 3, 4, 10] . should == [2, 'foo, "bar", nil]
139
+ }
140
+
141
+ it: "should return unique values only" for: 'uniq when: {
142
+ arr = ['foo, 'bar, "baz", 'foo, "baz", "hello", 1, 0, 0, 1, 'bar, 'foo, "hello"]
143
+ arr uniq should == ['foo, 'bar, "baz", "hello", 1, 0]
144
+ }
145
+
146
+ it: "should prepend self to another array" for: '>> when: {
147
+ arr1 = ['foo, 'bar, 'baz]
148
+ arr2 = [1, 2, 3]
149
+ (arr1 >> arr2) should == ['foo, 'bar, 'baz, 1, 2, 3]
150
+ }
151
+
152
+ it: "should get an element by the []-operator" for: "[]" when: {
153
+ arr = ['foo, 'bar, 'baz]
154
+ arr[0] should == 'foo
155
+ arr[1] should == 'bar
156
+ arr[2] should == 'baz
157
+ }
158
+
159
+ it: "should get a sub-array by the []-operator" for: "[]" when: {
160
+ arr = ['foo, 'bar, 'baz]
161
+ arr[[0,2]] should == arr
162
+ arr[[0,1]] should == ['foo, 'bar]
163
+ arr[[0,1]] should == (arr from: 0 to: 1)
164
+ arr[[0,0]] should == [arr[0]]
165
+ arr[[1,1]] should == [arr[1]]
166
+ arr[[2,2]] should == [arr[2]]
167
+ arr[[0,-1]] should == arr
168
+ arr[[-1,-1]] should == [arr last]
169
+ arr[[-2,-1]] should == ['bar, 'baz]
170
+ arr[[-2,-1]] should == (arr last: 2)
171
+ }
172
+
173
+ it: "should join all elements with a string to a new string" for: 'join: when: {
174
+ arr = ['foo, 'bar, 'baz]
175
+ arr join: "," . should == "foo,bar,baz"
176
+ }
177
+
178
+ it: "should join all elements with the empty string to a new string" for: 'join when: {
179
+ arr = ['foo, 'bar, 'baz]
180
+ arr join should == "foobarbaz"
181
+ }
182
+
183
+ it: "should remove an element at a given index" for: 'remove_at: when: {
184
+ arr = [1, 'foo, 2, 'bar, 3, 'baz]
185
+ # remove_at: returns the removed element
186
+ arr remove_at: 1 . should == 'foo
187
+ arr should == [1, 2, 'bar, 3, 'baz]
188
+ arr remove_at: 3
189
+ arr should == [1, 2, 'bar, 'baz]
190
+ arr remove_at: [2, 3]
191
+ arr should == [1, 2]
192
+ arr = [1, 'hello, 2, 'world]
193
+ # remove_at: returns the removed elements as an array
194
+ # if it was passed an array of indexes
195
+ arr remove_at: [0, 2, 3] . should == [1, 2, 'world]
196
+ arr should == ['hello]
197
+ }
198
+
199
+ it: "should remove all occurances of a given object in-place" for: 'remove: when: {
200
+ arr = [1, 2, 'foo, 3, 'foo, 2, 4]
201
+ arr remove: 2
202
+ arr should == [1, 'foo, 3, 'foo, 4]
203
+ arr remove: 'foo
204
+ arr should == [1, 3, 4]
205
+ }
206
+
207
+ it: "should remove all elements with the given Array of indices" for: 'remove_at: when: {
208
+ arr = [1, 2, 'foo, 3, 'foo, 2, 4]
209
+ arr remove_at: [0, 2, 4]
210
+ arr should == [2, 3, 2, 4]
211
+ }
212
+
213
+ it: "should remove all elements that meet a given condition block" for: 'remove_if: when: {
214
+ arr = [1, 2, 3, 2, 5, 4]
215
+ arr remove_if: |x| { x < 3 }
216
+ arr should == [3, 5, 4]
217
+ }
218
+
219
+ it: "should remove all nil-value entries when calling compact" for: 'compact when: {
220
+ ['foo, nil, 'bar, nil, 'baz] compact should == ['foo, 'bar, 'baz]
221
+ [] compact should == []
222
+ [nil] compact should == []
223
+ ['foo] compact should == ['foo]
224
+ }
225
+
226
+ it: "should remove all nil-value entries in place when calling compact!" for: 'compact! when: {
227
+ arr = ['foo, nil, 'bar, nil, 'baz]
228
+ arr compact! should == ['foo, 'bar, 'baz]
229
+ arr should == ['foo, 'bar, 'baz]
230
+ [] compact! should == []
231
+ [nil] compact! should == []
232
+ ['foo] compact! should == ['foo]
233
+ }
234
+
235
+ it: "should remove all values that meet a condition" for: 'reject!: when: {
236
+ arr = ['foo, 'bar, 1, 2, 'baz, "hello"]
237
+ arr reject!: |x| { x is_a?: String } . should == ['foo, 'bar, 1, 2, 'baz]
238
+ arr should == ['foo, 'bar, 1, 2, 'baz]
239
+ arr reject!: |x| { x is_a?: Fixnum }
240
+ arr should == ['foo, 'bar, 'baz]
241
+ }
242
+
243
+ it: "should remove all values that don't meet a condition" for: 'select!: when: {
244
+ arr = ['foo, 'bar, 1, 2, 'baz, "hello"]
245
+ arr select!: |x| { x is_a?: Fixnum }
246
+ arr should == [1, 2]
247
+ }
248
+
249
+ it: "should return a new Array with all elements that meet a given condition" for: 'select: when: {
250
+ arr = [1, 2, "foo", 'bar, 120]
251
+ arr select: |x| { x is_a?: Fixnum } . should == [1,2,120]
252
+ arr should == [1, 2, "foo", 'bar, 120] # select: is non-destructive
253
+ }
254
+
255
+ it: "should print the maximum value in the list" for: 'max when: {
256
+ [1,2,3,4] max should == 4
257
+ [1,5,-3,2,6,-4,-2] max should == 6
258
+ }
259
+
260
+ it: "should print the minimum value in the list" for: 'min when: {
261
+ [1,2,3,4] min should == 1
262
+ [1,5,-3,2,6,-4,-2] min should == -4
263
+ }
264
+
265
+ it: "should return an Array containing the elements n times." for: '* when: {
266
+ [1,2,3,4,5] * 2 should == [1,2,3,4,5,1,2,3,4,5]
267
+ [1,2,3] * 2 should == ([1,2,3] + [1,2,3])
268
+ ['a,'b,'c] * 4 should == ['a,'b,'c, 'a,'b,'c, 'a,'b,'c, 'a,'b,'c]
269
+ }
270
+
271
+ it: "should return the concatenation of two Arrays" for: '+ when: {
272
+ ([1,2,3,4] + [-1,-2,-3,-4]) should == [1,2,3,4,-1,-2,-3,-4]
273
+ }
274
+
275
+ it: "should return true for all elements" for: 'all?: when: {
276
+ [1,2,3,4] all?: |x| { x < 5 } . should == true
277
+ [1,2,3,4] all?: |x| { x > 0 } . should == true
278
+ [1,2,3,4] all?: |x| { x > 4 } . should == false
279
+ }
280
+
281
+ it: "should return true for any elements" for: 'any?: when: {
282
+ [1,2,3,4] any?: |x| { x > 3 } . should == true
283
+ [1,2,3,4] any?: |x| { x < 4 } . should == true
284
+ [1,2,3,4] any?: |x| { x > 4 } . should == false
285
+ }
286
+
287
+ it: "should be selected from it with each index" for: 'select_with_index: when: {
288
+ ["yooo",2,3,1,'foo,"bar"] select_with_index: |x i| { x is_a?: Fixnum } . should == [[2,1], [3,2], [1,3]]
289
+ }
290
+
291
+ it: "should return its remaining (all but the first) elements as a new Array" for: 'rest when: {
292
+ [1,2,3,4] rest should == [2,3,4]
293
+ [] rest should == []
294
+ 100 upto: 1000 . rest should == (101 upto: 1000)
295
+ }
296
+
297
+ it: "should return itself as a string" for: 'to_s when: {
298
+ [1,2,3] to_s should == "123"
299
+ }
300
+
301
+ it: "should call a given block between calling the each block" for: 'each:in_between: when: {
302
+ arr = []
303
+ [1,2,3] each: |x| { arr << x } in_between: { arr << "-" }
304
+ arr should == [1, "-", 2, "-", 3]
305
+
306
+ str = ""
307
+ ['foo, 'bar, 'baz] each: |x| { str = str ++ (x to_s) } in_between: { str = str ++ " " }
308
+ str should == "foo bar baz"
309
+ }
310
+
311
+ it: "should return the reduced value for a given block and initial value" for: 'reduce:init_val: when: {
312
+ arr = 1 upto: 10
313
+ arr sum should == (arr reduce: '+ init_val: 0)
314
+ arr product should == (arr reduce: '* init_val: 1)
315
+ arr to_s should == (arr reduce: '++ init_val: "")
316
+ }
317
+
318
+ it: "should return the reverse of itself" for: 'reverse when: {
319
+ [1,2,3] reverse should == [3,2,1]
320
+ 1 upto: 10 . reverse should == (10 downto: 1)
321
+ }
322
+
323
+ it: "should inverse in-place" for: 'reverse! when: {
324
+ arr = [1,2,3]
325
+ arr reverse! should == [3,2,1]
326
+ arr should == [3,2,1]
327
+ }
328
+
329
+ it: "should take elements from itself as long a block yields true" for: 'take_while: when: {
330
+ 1 upto: 15 . take_while: |x| { x < 10 } . should == (1 upto: 9)
331
+ }
332
+
333
+
334
+ it: "should drop elements from itself as long a block yields true" for: 'drop_while: when: {
335
+ 1 upto: 15 . drop_while: |x| { x < 10 } . should == (10 upto: 15)
336
+ }
337
+
338
+ it: "should partition an array via a given block" for: 'partition_by: when: {
339
+ arr = [1,2,2,3,3,3,4,4,4,4,5]
340
+ arr partition_by: 'identity . should == [[1], [2,2], [3,3,3], [4,4,4,4], [5]]
341
+ arr partition_by: @{== 2} . should == [[1], [2,2], [3,3,3,4,4,4,4,5]]
342
+ }
343
+ }