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
@@ -8,7 +8,7 @@ class Range {
8
8
  Range new: 10 to: 100
9
9
  """
10
10
 
11
- include: FancyEnumerable
11
+ include: Fancy Enumerable
12
12
 
13
13
  def to_s {
14
14
  """
data/lib/rbx.fy CHANGED
@@ -25,8 +25,8 @@ require: "rbx/system"
25
25
  require: "rbx/exception"
26
26
  require: "rbx/io"
27
27
  require: "rbx/file"
28
- require: "rbx/tcp_server"
29
28
  require: "rbx/tcp_socket"
29
+ require: "rbx/tcp_server"
30
30
  require: "rbx/match_data"
31
31
  require: "rbx/regexp"
32
32
  require: "rbx/directory"
@@ -40,3 +40,4 @@ require: "rbx/date"
40
40
  require: "rbx/time"
41
41
  require: "rbx/actor"
42
42
  require: "rbx/mutex"
43
+ require: "rbx/module"
@@ -1,12 +1,18 @@
1
1
  class Array {
2
- ruby_aliases: [ '==, '<<, 'pop, 'last, 'shift ]
2
+ ruby_aliases: [ '==, '<<, 'pop, 'last, 'shift, 'flatten ]
3
3
 
4
4
  forwards_unary_ruby_methods
5
5
 
6
6
  def Array new: size with: default {
7
- "Creates a new Array with a given size and default-value."
7
+ """
8
+ Creates a new Array with a given size and default-value.
9
+ If @default is a @Block@, call that block for each element instead.
10
+ """
8
11
 
9
- Array new(size, default)
12
+ match default {
13
+ case Block -> Array new(size, &default)
14
+ case _ -> Array new(size, default)
15
+ }
10
16
  }
11
17
 
12
18
  def includes?: obj {
@@ -32,16 +38,14 @@ class Array {
32
38
  delete_at(index)
33
39
  return deleted
34
40
  } else: {
35
- if: (index is_a?: Array) then: {
36
- count = 0
37
- deleted_values = []
38
- index each: |idx| {
39
- deleted_values << (at: (idx - count))
40
- delete_at(idx - count)
41
- count = count + 1
42
- }
43
- return deleted_values
41
+ count = 0
42
+ deleted_values = []
43
+ index each: |idx| {
44
+ deleted_values << (at: (idx - count))
45
+ delete_at(idx - count)
46
+ count = count + 1
44
47
  }
48
+ return deleted_values
45
49
  }
46
50
  nil
47
51
  }
@@ -106,6 +110,18 @@ class Array {
106
110
  }
107
111
 
108
112
  def unshift: value {
113
+ """
114
+ @value Value to be added at the front of @self.
115
+ @return @self.
116
+
117
+ Inserts a value at the front of @self.
118
+
119
+ Example:
120
+ a = [1,2,3]
121
+ a unshift: 10
122
+ a # => [10,1,2,3]
123
+ """
124
+
109
125
  unshift(value)
110
126
  }
111
127
  }
@@ -5,7 +5,7 @@ class Bignum {
5
5
 
6
6
  include: Number
7
7
 
8
- ruby_aliases: [ '==, '-, '+, '*, '/, '<, '>, '<=, '>=, '===, '**, '& ]
8
+ ruby_aliases: [ '==, '-, '+, '*, '/, '<, '>, '<=, '>=, '===, '**, '&, '<<, '>> ]
9
9
 
10
10
  forwards_unary_ruby_methods
11
11
 
@@ -50,6 +50,19 @@ class Block {
50
50
  # Ugh. HACK.
51
51
  # Use try/catch to deal with older and latest version of rbx (method got changed)
52
52
  def call_with_receiver: receiver {
53
+ """
54
+ @receiver Receiver (value of @self) when calling the @Block@.
55
+
56
+ Calls a @Block@ with @receiver as the receiver (referenced by @self within the Block).
57
+
58
+ Example:
59
+ r1 = [1,2,3]
60
+ r2 = \"hello world\"
61
+ b = { self class }
62
+ b call_with_receiver: r1 # => Array
63
+ b call_with_receiver: r2 # => String
64
+ """
65
+
53
66
  try {
54
67
  return call_under(receiver, method() scope())
55
68
  } catch {
@@ -58,6 +71,20 @@ class Block {
58
71
  }
59
72
 
60
73
  def call: args with_receiver: receiver {
74
+ """
75
+ @args @Array@ of arguments passed to @self for invocation.
76
+ @receiver Receiver (value of @self) when calling the @Block@.
77
+
78
+ Same as @call_with_receiver: but passing along arguments to the @Block@.
79
+
80
+ Example:
81
+ r1 = [1,2,3]
82
+ r2 = \"hello world\"
83
+ b = |arg| { self to_s + arg }
84
+ b call: [\"foo\"] with_receiver: r1 # => \"123foo\"
85
+ b call: [\"foo\"] with_receiver: r2 # => \"hello worldfoo\"
86
+ """
87
+
61
88
  try {
62
89
  return call_under(receiver, method() scope(), *args)
63
90
  } catch {
@@ -38,11 +38,7 @@ class Console {
38
38
  """
39
39
 
40
40
  Console print: message
41
- if: (STDIN eof?) then: {
42
- nil
43
- } else: {
44
- STDIN gets() chomp
45
- }
41
+ Console readln
46
42
  }
47
43
 
48
44
  def Console readln {
@@ -52,7 +48,11 @@ class Console {
52
48
  Reads a line from @STDIN and returns it as a @String@.
53
49
  """
54
50
 
55
- STDIN gets() chomp
51
+ if: (STDIN eof?) then: {
52
+ nil
53
+ } else: {
54
+ STDIN gets() chomp
55
+ }
56
56
  }
57
57
 
58
58
  def Console clear {
@@ -9,9 +9,14 @@ class Date {
9
9
  metaclass forwards_unary_ruby_methods
10
10
 
11
11
  metaclass ruby_alias: 'today
12
- ruby_aliases: [ '==, '-, '+, '<, '> ]
12
+ ruby_aliases: [ '==, '-, '+, '<, '>, 'cwday, 'wday ]
13
13
 
14
14
  def != other {
15
+ """
16
+ @other Other @Date@ to compare to.
17
+ @return @true if equal, @false otherwhise.
18
+ """
19
+
15
20
  self == other not
16
21
  }
17
22
  }
@@ -2,7 +2,6 @@
2
2
  class Fancy {}
3
3
 
4
4
  class Fancy Documentation {
5
-
6
5
  def initialize: docstring {
7
6
  @docs = [docstring]
8
7
  }
@@ -42,6 +41,14 @@ class Fancy Documentation {
42
41
  doc
43
42
  }
44
43
 
44
+ def self for_method: method_name on_class: class is: docstring {
45
+ """
46
+ Similar to @Fancy::Documentation##for:is:@ but taking the method name and the @Class@ for which @Method@ to define the docstring.
47
+ """
48
+
49
+ class instance_method: method_name . documentation: docstring
50
+ }
51
+
45
52
  for: (instance_method('initialize:)) is: "Create a new documentation object."
46
53
  for: (method('for:is:)) is: "Sets the documentation for obj."
47
54
 
@@ -59,6 +66,4 @@ class Fancy Documentation {
59
66
  "Append docstring to docs."
60
67
  for: obj is: docstring
61
68
  }
62
-
63
69
  }
64
-
@@ -1,4 +1,9 @@
1
1
  class Exception {
2
+ """
3
+ Base Exception class.
4
+ All Exception classes inherit from @Exception@.
5
+ """
6
+
2
7
  forwards_unary_ruby_methods
3
8
  }
4
9
 
@@ -8,6 +8,9 @@ class File {
8
8
  'truncate => "w+"]>
9
9
 
10
10
  ruby_aliases: [ 'eof?, 'closed?, 'flush ]
11
+ metaclass alias_method: 'expand_path: for_ruby: 'expand_path
12
+
13
+ forwards_unary_ruby_methods
11
14
 
12
15
  def File open: filename modes: modes_arr with: block {
13
16
  """
@@ -46,16 +49,30 @@ class File {
46
49
  File exists?(filename)
47
50
  }
48
51
 
49
- def close {
52
+ def File read: filename {
50
53
  """
51
- Closes an opened @File@.
54
+ @filename @String@ containing the path of the File to be read.
55
+ @return Contents of the File as a @String@.
56
+
57
+ Reads all the contens (in ASCII mode) of a given file and returns
58
+ them as an Array of lines being read.
52
59
  """
53
60
 
54
- try {
55
- close()
56
- } catch Errno::ENOENT => e {
57
- IOError new: (e message) . raise!
58
- }
61
+ File read(filename)
62
+ }
63
+
64
+ def File read: filename length: length offset: offset (0) {
65
+ """
66
+ @filename @String@ containing the path of the File to be read.
67
+ @length @Fixnum@ being the maximum length to read from the File.
68
+ @offset @Fixnum@ being the offset in bytes to start reading from the File.
69
+ @return Contents of the File as a @String@.
70
+
71
+ Reads all the contens (in ASCII mode) of a given file, length and offset
72
+ and returns them as an Array of lines being read.
73
+ """
74
+
75
+ File read(filename, length, offset)
59
76
  }
60
77
 
61
78
  def File open: filename modes: modes_arr {
@@ -131,6 +148,22 @@ class File {
131
148
  File rename(old_name, new_name)
132
149
  }
133
150
 
151
+ def initialize: path {
152
+ initialize(path)
153
+ }
154
+
155
+ def close {
156
+ """
157
+ Closes an opened @File@.
158
+ """
159
+
160
+ try {
161
+ close()
162
+ } catch Errno::ENOENT => e {
163
+ IOError new: (e message) . raise!
164
+ }
165
+ }
166
+
134
167
  def modes {
135
168
  """
136
169
  @return @File@ access modes @Array@.
@@ -9,11 +9,22 @@ class Fixnum {
9
9
 
10
10
  ruby_aliases: [
11
11
  '==, '-, '+, '*, '/, '<, '>, '<=, '>=,
12
- '===, 'chr, 'to_i, 'to_f, '**, '&, '|
12
+ '===, 'chr, 'to_i, 'to_f, '**, '&, '|,
13
+ '<<, '>>
13
14
  ]
14
15
 
15
16
  alias_method: 'to_s: for: 'to_s
16
17
  alias_method: 'modulo: for: 'modulo
17
18
  alias_method: ":%" for: "modulo:" # use a : so we dont overwrite ruby's % operator
18
19
  alias_method: 'div: for: 'div
20
+
21
+ def random {
22
+ """
23
+ @return Random number between 0 and @self.
24
+
25
+ Returns a random number between 0 and @self.
26
+ """
27
+
28
+ rand(self)
29
+ }
19
30
  }
@@ -8,7 +8,7 @@ class MethodMixin {
8
8
  @return Docstring for @self.
9
9
  """
10
10
 
11
- Fancy Documentation for: (executable())
11
+ Fancy Documentation for: executable
12
12
  }
13
13
 
14
14
  def documentation: docstring {
@@ -16,7 +16,7 @@ class MethodMixin {
16
16
  @docstring New docstring for @self.
17
17
  """
18
18
 
19
- Fancy Documentation for: (executable()) is: docstring
19
+ Fancy Documentation for: executable is: docstring
20
20
  }
21
21
 
22
22
  def visibility {
@@ -66,7 +66,13 @@ class MethodMixin {
66
66
  }
67
67
 
68
68
  class Method {
69
+ """
70
+ An instance of Method represents a method on a Class.
71
+ Every method in Fancy is an instance of the Method class.
72
+ """
73
+
69
74
  ruby_alias: 'arity
75
+ ruby_alias: 'executable
70
76
  include: MethodMixin
71
77
  forwards_unary_ruby_methods
72
78
  }
@@ -77,6 +83,7 @@ class UnboundMethod {
77
83
  """
78
84
 
79
85
  ruby_alias: 'arity
86
+ ruby_alias: 'executable
80
87
  include: MethodMixin
81
88
  forwards_unary_ruby_methods
82
89
  }
@@ -0,0 +1,24 @@
1
+ class Module {
2
+ forwards_unary_ruby_methods
3
+
4
+ def [constant_name] {
5
+ """
6
+ @constant_name Name (@String@) of constant's name.
7
+ @return @constant_name's value.
8
+
9
+ Returns the value of the constant with the given name in @self.
10
+ """
11
+
12
+ const_get(constant_name)
13
+ }
14
+
15
+ def included: module {
16
+ """
17
+ @module @Module@ or @Class@ that has been included into @self.
18
+ Gets called when a @Class@ or @Module@ is included into another @Class@.
19
+ """
20
+
21
+ # do nothing by default
22
+ nil
23
+ }
24
+ }
@@ -14,6 +14,14 @@ class Regexp {
14
14
  Regexp new(source(), true)
15
15
  }
16
16
 
17
+ def m {
18
+ Regexp new(source(), Regexp MULTILINE)
19
+ }
20
+
21
+ def x {
22
+ Regexp new(source(), Regexp EXTENDED)
23
+ }
24
+
17
25
  def Regexp new: string {
18
26
  new(string)
19
27
  }
@@ -6,20 +6,25 @@ class String {
6
6
  'chomp, 'inspect, 'to_sym, '<, '>
7
7
  ]
8
8
 
9
+ alias_method: 'ruby_idx: for_ruby: '[]
9
10
  alias_method: '[]: for_ruby: '[]=
10
11
  alias_method: 'scan: for_ruby: 'scan
12
+ alias_method: 'uppercase for: 'upcase
13
+ alias_method: 'lowercase for: 'downcase
11
14
 
12
15
  forwards_unary_ruby_methods
13
16
 
14
17
  def [index] {
15
- """Given an Array of 2 Numbers, it returns the substring between the given indices.
16
- If given a Number, returns the character at that index."""
18
+ """
19
+ Given an Array of 2 Numbers, it returns the substring between the given indices.
20
+ If given a Number, returns the character at that index.
21
+ """
17
22
 
18
23
  # if given an Array, interpret it as a from:to: range substring
19
- if: (index is_a?: Array) then: {
20
- from: (index[0]) to: (index[1])
21
- } else: {
22
- ruby: '[] args: [index] . chr
24
+ match index {
25
+ case Array -> from: (index[0]) to: (index[1])
26
+ case Tuple -> ruby_idx: index
27
+ case _ -> ruby_idx: index . chr()
23
28
  }
24
29
  }
25
30
 
@@ -31,7 +36,8 @@ class String {
31
36
 
32
37
  Returns a Substring from @from to @to.
33
38
  """
34
- ruby: '[] args: [(from .. to)]
39
+
40
+ ruby_idx: (from .. to)
35
41
  }
36
42
 
37
43
  def each: block {
@@ -146,4 +152,14 @@ class String {
146
152
 
147
153
  include?(substring)
148
154
  }
155
+
156
+ def substitute: substring with: substitution {
157
+ """
158
+ @substring @String@ or @Regexp@ to be substituted.
159
+ @substitution @String@ to replace @substring with.
160
+ @return A new @String@ where @substring is substituted by @substitution.
161
+ """
162
+
163
+ gsub(substring, substitution)
164
+ }
149
165
  }