fancy 0.3.2 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. data/README.md +4 -1
  2. data/Rakefile +8 -0
  3. data/bin/fyi +25 -20
  4. data/bin/ifancy +39 -5
  5. data/{extconf.rb → boot/extconf.rb} +1 -1
  6. data/boot/fancy_ext/block_env.rb +0 -14
  7. data/boot/fancy_ext/kernel.rb +6 -2
  8. data/boot/rbx-compiler/parser/fancy_parser.bundle +0 -0
  9. data/examples/actor.fy +37 -0
  10. data/examples/armstrong_numbers.fy +1 -1
  11. data/examples/curl_async.fy +37 -0
  12. data/examples/echo.fy +1 -1
  13. data/examples/factorial.fy +1 -1
  14. data/examples/future_composition.fy +20 -0
  15. data/examples/game_of_life.fy +2 -2
  16. data/examples/person.fy +4 -8
  17. data/examples/rbx/blocks.fy +1 -1
  18. data/examples/return.fy +1 -1
  19. data/examples/struct.fy +9 -0
  20. data/lib/argv.fy +2 -2
  21. data/lib/array.fy +157 -0
  22. data/lib/block.fy +18 -1
  23. data/lib/boot.fy +5 -1
  24. data/lib/compiler/ast/class_def.fy +1 -1
  25. data/lib/compiler/ast/identifier.fy +2 -2
  26. data/lib/compiler/ast/message_send.fy +2 -2
  27. data/lib/compiler/ast/method_def.fy +2 -2
  28. data/lib/compiler/ast/try_catch.fy +5 -1
  29. data/lib/documentation.fy +1 -1
  30. data/lib/enumerable.fy +3 -7
  31. data/lib/enumerator.fy +77 -0
  32. data/lib/false_class.fy +52 -0
  33. data/lib/fancy_spec.fy +40 -12
  34. data/lib/fdoc.fy +2 -2
  35. data/lib/file.fy +8 -1
  36. data/lib/future.fy +23 -2
  37. data/lib/iteration.fy +60 -0
  38. data/lib/main.fy +4 -4
  39. data/lib/nil_class.fy +14 -22
  40. data/lib/number.fy +51 -0
  41. data/lib/object.fy +126 -43
  42. data/lib/package/installer.fy +1 -1
  43. data/lib/parser/ext/lexer.lex +6 -1
  44. data/lib/parser/ext/parser.y +18 -0
  45. data/lib/parser/methods.fy +20 -2
  46. data/lib/proxy.fy +20 -3
  47. data/lib/rbx.fy +0 -1
  48. data/lib/rbx/array.fy +4 -138
  49. data/lib/rbx/block.fy +25 -1
  50. data/lib/rbx/class.fy +21 -0
  51. data/lib/rbx/exception.fy +1 -0
  52. data/lib/rbx/fiber.fy +1 -0
  53. data/lib/rbx/file.fy +8 -0
  54. data/lib/rbx/integer.fy +0 -8
  55. data/lib/rbx/method.fy +34 -7
  56. data/lib/rbx/no_method_error.fy +8 -1
  57. data/lib/rbx/object.fy +3 -32
  58. data/lib/rbx/range.fy +13 -1
  59. data/lib/rbx/regexp.fy +3 -0
  60. data/lib/rbx/string.fy +6 -1
  61. data/lib/rbx/system.fy +20 -2
  62. data/lib/set.fy +2 -2
  63. data/lib/string.fy +1 -1
  64. data/lib/struct.fy +15 -12
  65. data/lib/symbol.fy +2 -2
  66. data/lib/true_class.fy +16 -20
  67. data/lib/version.fy +1 -1
  68. data/tests/argv.fy +1 -0
  69. data/tests/array.fy +33 -2
  70. data/tests/block.fy +44 -0
  71. data/tests/class.fy +102 -88
  72. data/tests/control_flow.fy +131 -8
  73. data/tests/enumerator.fy +85 -0
  74. data/tests/exception.fy +13 -13
  75. data/tests/file.fy +4 -13
  76. data/tests/future.fy +26 -0
  77. data/tests/method.fy +83 -72
  78. data/tests/nil_class.fy +20 -13
  79. data/tests/number.fy +16 -9
  80. data/tests/object.fy +39 -20
  81. data/tests/string.fy +7 -0
  82. data/tests/true_class.fy +4 -4
  83. data/tools/fancy-mode.el +1 -1
  84. metadata +15 -20
  85. data/boot/compiler/parser/ext/fancy_parser.bundle +0 -0
  86. data/boot/rbx-compiler/parser/Makefile +0 -162
  87. data/boot/rbx-compiler/parser/lexer.c +0 -2316
  88. data/boot/rbx-compiler/parser/lexer.h +0 -315
  89. data/boot/rbx-compiler/parser/parser.c +0 -3105
  90. data/boot/rbx-compiler/parser/parser.h +0 -114
  91. data/lib/lazy_array.fy +0 -23
  92. data/lib/parser/ext/Makefile +0 -162
  93. data/lib/parser/ext/fancy_parser.bundle +0 -0
  94. data/lib/parser/ext/lexer.c +0 -2360
  95. data/lib/parser/ext/lexer.h +0 -315
  96. data/lib/parser/ext/parser.c +0 -3382
  97. data/lib/parser/ext/parser.h +0 -118
  98. data/lib/rbx/false_class.fy +0 -58
data/lib/rbx/exception.fy CHANGED
@@ -1,5 +1,6 @@
1
1
  class StandardError {
2
2
  ruby_alias: 'message
3
+ ruby_alias: 'backtrace
3
4
 
4
5
  def initialize {
5
6
  "Creates a new Exception with an empty message."
data/lib/rbx/fiber.fy CHANGED
@@ -4,6 +4,7 @@ Fiber = Rubinius Fiber
4
4
 
5
5
  class Fiber {
6
6
  metaclass ruby_alias: 'yield
7
+ metaclass ruby_alias: 'current
7
8
  ruby_alias: 'resume
8
9
  ruby_alias: 'alive?
9
10
 
data/lib/rbx/file.fy CHANGED
@@ -174,6 +174,14 @@ class File {
174
174
  print(str)
175
175
  }
176
176
 
177
+ def read: bytes {
178
+ """
179
+ @bytes Integer the amount of bytes to read from a @File@.
180
+ """
181
+
182
+ read(bytes)
183
+ }
184
+
177
185
  def newline {
178
186
  "Writes a newline character to the @File@."
179
187
 
data/lib/rbx/integer.fy CHANGED
@@ -4,12 +4,4 @@ class Integer {
4
4
  def times: block {
5
5
  times(&block)
6
6
  }
7
-
8
- def upto: num do_each: block {
9
- upto(num, &block)
10
- }
11
-
12
- def downto: num do_each: block {
13
- downto(num, &block)
14
- }
15
7
  }
data/lib/rbx/method.fy CHANGED
@@ -1,4 +1,4 @@
1
- class Method {
1
+ class MethodMixin {
2
2
  def documentation {
3
3
  Fancy Documentation for: (executable())
4
4
  }
@@ -6,17 +6,44 @@ class Method {
6
6
  def documentation: str {
7
7
  Fancy Documentation for: (executable()) is: str
8
8
  }
9
- }
10
9
 
11
- class UnboundMethod {
10
+ def visibility {
11
+ """
12
+ Returns the visibility ('private, 'protected, 'public) of a @Method@ in its defined context, if any.
13
+ """
14
+ entry = @defined_in method_table() lookup(@name)
15
+ { entry visibility() } if: entry
16
+ }
12
17
 
13
- def documentation {
14
- Fancy Documentation for: (executable())
18
+ def public? {
19
+ """
20
+ Returns true, if the @Method@ is public in its defined context.
21
+ """
22
+ visibility == 'public
15
23
  }
16
24
 
17
- def documentation: str {
18
- Fancy Documentation for: (executable()) is: str
25
+ def protected? {
26
+ """
27
+ Returns true, if the @Method@ is protected in its defined context.
28
+ """
29
+ visibility == 'protected
19
30
  }
20
31
 
32
+ def private? {
33
+ """
34
+ Returns true, if the @Method@ is private in its defined context.
35
+ """
36
+ visibility == 'private
37
+ }
38
+ }
39
+
40
+ class Method {
41
+ ruby_alias: 'arity
42
+ include: MethodMixin
43
+ }
44
+
45
+ class UnboundMethod {
46
+ ruby_alias: 'arity
47
+ include: MethodMixin
21
48
  }
22
49
 
@@ -10,6 +10,13 @@ class NoMethodError {
10
10
  Returns the name of the method that was not found as a @String@.
11
11
  """
12
12
 
13
- name to_s from: 1 to: -1
13
+ match name to_s {
14
+ case /^:/ -> name to_s from: 1 to: -1 . to_sym
15
+ case _ -> name
16
+ }
17
+ }
18
+
19
+ def self inspect {
20
+ "NoMethodError"
14
21
  }
15
22
  }
data/lib/rbx/object.fy CHANGED
@@ -40,35 +40,6 @@ class Object {
40
40
  instance_variable_get("@" ++ slotname)
41
41
  }
42
42
 
43
- def and: other {
44
- """
45
- Boolean conjunction.
46
- Returns true if self and other are true, otherwise nil.
47
- """
48
-
49
- self if_do: {
50
- other if_do: {
51
- return true
52
- }
53
- }
54
- return false
55
- }
56
-
57
- def or: other {
58
- """
59
- Boolean disjunction.
60
- Returns true if either self or other is true, otherwise nil.
61
- """
62
- self if_do: {
63
- return true
64
- } else: {
65
- other if_do: {
66
- return true
67
- }
68
- }
69
- return false
70
- }
71
-
72
43
  def define_singleton_method: name with: block {
73
44
  metaclass define_method: name with: block
74
45
  }
@@ -87,17 +58,17 @@ class Object {
87
58
  kind_of?(class)
88
59
  }
89
60
 
90
- def send: message {
61
+ def send_message: message {
91
62
  send(message_name: message)
92
63
  }
93
64
 
94
- def send: message params: params {
65
+ def send_message: message with_params: params {
95
66
  ruby: (message_name: message) args: params
96
67
  }
97
68
 
98
69
  def message_name: symbol {
99
70
  symbol = symbol to_s
100
- if: (symbol includes?: ":") then: {
71
+ if: (symbol =~ /:/) then: {
101
72
  symbol
102
73
  } else: {
103
74
  ":" ++ symbol
data/lib/rbx/range.fy CHANGED
@@ -10,6 +10,18 @@ class Range {
10
10
  }
11
11
 
12
12
  def each: block {
13
- each(&block)
13
+ try {
14
+ val = nil
15
+ each() |x| {
16
+ try {
17
+ val = block call: [x]
18
+ } catch (Fancy NextIteration) => ex {
19
+ val = ex return_value
20
+ }
21
+ }
22
+ val
23
+ } catch (Fancy BreakIteration) => ex {
24
+ ex return_value
25
+ }
14
26
  }
15
27
  }
data/lib/rbx/regexp.fy CHANGED
@@ -1,4 +1,7 @@
1
1
  class Regexp {
2
+ ruby_alias: 'inspect
3
+ ruby_alias: 'to_s
4
+
2
5
  def === string {
3
6
  ruby: 'match args: [string]
4
7
  }
data/lib/rbx/string.fy CHANGED
@@ -9,6 +9,7 @@ class String {
9
9
  ruby_alias: 'to_f
10
10
  ruby_alias: 'chomp
11
11
  ruby_alias: 'inspect
12
+ ruby_alias: 'to_sym
12
13
 
13
14
  def [] index {
14
15
  """Given an Array of 2 Numbers, it returns the substring between the given indices.
@@ -39,7 +40,7 @@ class String {
39
40
 
40
41
  Calls a given @Block with each character in a @String.
41
42
  """
42
- split("") each(&block)
43
+ split("") each: block
43
44
  }
44
45
 
45
46
  def at: idx {
@@ -98,4 +99,8 @@ class String {
98
99
  def % values {
99
100
  ruby: '% args: [values to_a]
100
101
  }
102
+
103
+ def unpack: format {
104
+ unpack(format)
105
+ }
101
106
  }
data/lib/rbx/system.fy CHANGED
@@ -1,3 +1,5 @@
1
+ require("open3")
2
+
1
3
  class System {
2
4
  def System exit {
3
5
  "Exit the running Fancy process."
@@ -22,10 +24,26 @@ class System {
22
24
 
23
25
  def System pipe: command_str {
24
26
  """
25
- Runs the given string as a popen() call and returns a IO handle
27
+ @command_str String to run as a command via popen3()
28
+ @return @IO@ object representing the command's @STDOUT IO stream.
29
+
30
+ Runs the given string as a popen3() call and returns a IO handle
26
31
  that can be read from
27
32
  """
28
33
 
29
- IO popen(command_str)
34
+ in, out, err = Open3 popen3(command_str)
35
+ return out
36
+ }
37
+
38
+ def System pipe: command_str do: block {
39
+ """
40
+ @command_str String to run as a command via popen3()
41
+ @block @Block@ to be called with @STDIN, @STDOUT and @STDERR.
42
+
43
+ Runs the given string as a popen3() call, passing in a given @Block@.
44
+ The @Block@ is expected to take 3 arguments for @STDIN, @STDOUT and @STDERR.
45
+ """
46
+
47
+ Open3 popen3(command_str, &block)
30
48
  }
31
49
  }
data/lib/set.fy CHANGED
@@ -43,9 +43,9 @@ class Set {
43
43
 
44
44
  def unknown_message: msg with_params: params {
45
45
  if: (params empty?) then: {
46
- @values send: msg
46
+ @values send_message: msg
47
47
  } else: {
48
- @values send: msg params: params
48
+ @values send_message: msg with_params: params
49
49
  }
50
50
  }
51
51
 
data/lib/string.fy CHANGED
@@ -25,7 +25,7 @@ class String {
25
25
  def blank? {
26
26
  "Indicates, if a String consists only of whitespace."
27
27
 
28
- self =~ /^\s*$/ if_do: {
28
+ self =~ /^\s*$/ if_true: {
29
29
  true
30
30
  } else: {
31
31
  false
data/lib/struct.fy CHANGED
@@ -1,13 +1,16 @@
1
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
- }
2
+ def Struct new: fields {
3
+ struct = new(*fields)
4
+ struct read_write_slots: fields
5
+
6
+ def struct new: values {
7
+ new(*values)
8
+ }
9
+
10
+ def struct new {
11
+ new()
12
+ }
13
+
14
+ struct
15
+ }
16
+ }
data/lib/symbol.fy CHANGED
@@ -14,9 +14,9 @@ class Symbol {
14
14
  """
15
15
 
16
16
  if: (arg is_a?: Array) then: {
17
- arg first send: self params: $ arg rest
17
+ arg first send_message: self with_params: $ arg rest
18
18
  } else: {
19
- arg send: self
19
+ arg send_message: self
20
20
  }
21
21
  }
22
22
 
data/lib/true_class.fy CHANGED
@@ -1,5 +1,5 @@
1
1
  class TrueClass {
2
- "TrueClass. The class of the singleton true value."
2
+ "TrueClass. The class of the singleton @true value."
3
3
 
4
4
  def TrueClass new {
5
5
  # always return true singleton object when trying to create a new
@@ -7,37 +7,33 @@ class TrueClass {
7
7
  true
8
8
  }
9
9
 
10
- def if_true: then_block else: else_block {
11
- "Calls the then_block."
12
- then_block call
13
- }
14
-
15
10
  def if_true: block {
16
- "Calls the block."
17
- block call
11
+ "Calls @block."
12
+ block call: [self]
18
13
  }
19
14
 
20
- def if_false: block {
21
- "Returns nil."
22
- nil
15
+ def if_true: then_block else: else_block {
16
+ "Calls @then_block."
17
+ then_block call: [self]
23
18
  }
24
19
 
25
- def nil? {
26
- "Returns nil."
27
- false
20
+ def true? {
21
+ "Returns @true."
22
+ true
28
23
  }
29
24
 
30
- def false? {
31
- "Returns nil."
32
- false
25
+ def to_s {
26
+ "Returns @true as a @String@."
27
+ "true"
33
28
  }
34
29
 
35
- def true? {
36
- "Returns true."
37
- true
30
+ def to_a {
31
+ "Returns an empty @Array@."
32
+ []
38
33
  }
39
34
 
40
35
  def not {
36
+ "Returns @false."
41
37
  false
42
38
  }
43
39
  }
data/lib/version.fy CHANGED
@@ -1,6 +1,6 @@
1
1
  VERSION_MAJOR = 0
2
2
  VERSION_MINOR = 3
3
- VERSION_PATCH = 0
3
+ VERSION_PATCH = 3
4
4
  VERSION_SUFFIX = "alpha"
5
5
 
6
6
  FANCY_VERSION = [VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH] join: "." ++ " " ++ VERSION_SUFFIX
data/tests/argv.fy CHANGED
@@ -5,6 +5,7 @@ FancySpec describe: "ARGV & predefined values" with: {
5
5
 
6
6
  it: "should have a __FILE__ variable defined" when: {
7
7
  __FILE__ should_not == nil
8
+ __FILE__ should =~ /\/argv.fy$/
8
9
  }
9
10
 
10
11
  it: "should have the __FILE__ value be an element in ARGV" when: {
data/tests/array.fy CHANGED
@@ -10,8 +10,7 @@ FancySpec describe: Array with: {
10
10
 
11
11
  it: "should iterate over all elements, calling a block" for: 'each: when: {
12
12
  sum = 0
13
- retval = [1,2,3,4,5] each: |x| { sum = sum + x }
14
- retval should == sum
13
+ [1,2,3,4,5] each: |x| { sum = sum + x }
15
14
  sum should == ([1,2,3,4,5] sum)
16
15
  }
17
16
 
@@ -43,6 +42,18 @@ FancySpec describe: Array with: {
43
42
  arr at: 0 . should == 'a
44
43
  }
45
44
 
45
+ it: "should set the value for a given index" for: 'at:put: when: {
46
+ arr = [1,2,3]
47
+ arr at: 0 put: 10
48
+ arr should == [10, 2, 3]
49
+ arr at: -1 put: 30
50
+ arr should == [10, 2, 30]
51
+ arr at: 1 put: 20
52
+ arr should == [10,20,30]
53
+ arr at: 3 put: 40
54
+ arr should == [10,20,30,40]
55
+ }
56
+
46
57
  it: "should NOT include the items" for: "includes?:" when: {
47
58
  arr = ['a, 10, "hello, world"]
48
59
  arr includes?: "hello" . should == false
@@ -340,4 +351,24 @@ FancySpec describe: Array with: {
340
351
  arr partition_by: 'identity . should == [[1], [2,2], [3,3,3], [4,4,4,4], [5]]
341
352
  arr partition_by: @{== 2} . should == [[1], [2,2], [3,3,3,4,4,4,4,5]]
342
353
  }
354
+
355
+ it: "should remove the first value" for: 'shift when: {
356
+ a = [1,2,3]
357
+ a shift should == 1
358
+ a should == [2,3]
359
+
360
+ a = []
361
+ a shift should == nil
362
+ a should == []
363
+ }
364
+
365
+ it: "should append a value at the front" for: 'unshift: when: {
366
+ a = []
367
+ a unshift: 1 . should == a # should return self
368
+ a should == [1]
369
+
370
+ a = [1,2,3]
371
+ a unshift: (a shift) . should == a
372
+ a should == [1,2,3]
373
+ }
343
374
  }