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
@@ -0,0 +1,90 @@
1
+ class Fancy AST {
2
+
3
+ class MethodDef : Rubinius AST Define {
4
+ def initialize: @line name: @name args: @arguments body: @body access: @access {
5
+ @name = @name method_name: nil
6
+ self generate_ivar_assignment
7
+
8
+ if: (@body empty?) then: {
9
+ @body unshift_expression: $ NilLiteral new: @line
10
+ }
11
+ }
12
+
13
+ def generate_ivar_assignment {
14
+ @arguments required() reverse() each: |name| {
15
+ if: (name to_s =~ /^@/) then: {
16
+ ident = Identifier from: (name to_s) line: @line
17
+ value = Rubinius AST LocalVariableAccess new(@line, name)
18
+ asign = Assignment new: @line var: ident value: value
19
+ @body unshift_expression: asign
20
+ }
21
+ }
22
+ }
23
+
24
+ def bytecode: g {
25
+ pos(g)
26
+ g push_self()
27
+ g send(@access, 0)
28
+ g pop()
29
+
30
+ @name to_s =~ /^initialize:(\S)+/ if_do: {
31
+ define_constructor_class_method: g
32
+ }
33
+ @name to_s =~ /^unknown_message:with_params:$/ if_do: {
34
+ define_method_missing: g
35
+ }
36
+
37
+ docstring = @body shift_docstring
38
+ bytecode(g)
39
+ MethodDef set: g docstring: docstring line: @line argnames: $ @arguments names()
40
+ }
41
+
42
+ # Sets fancy documentation for the object currently
43
+ # on top of the stack
44
+ def MethodDef set: g docstring: docstring line: line argnames: argnames {
45
+ # prevent invoking documentation: when doesnt makes sense.
46
+ { return nil } unless: docstring
47
+ local = StackLocal new: line
48
+ local set: g
49
+ ms = MessageSend new: line \
50
+ message: (Identifier from: "for:is:" line: line) \
51
+ to: (Identifier from: "Fancy::Documentation" line: line) \
52
+ args: $ MessageArgs new: line args: [local, docstring]
53
+ ms bytecode: g
54
+
55
+ meta = HashLiteral new: line entries: [SymbolLiteral new: line value: 'argnames,
56
+ ArrayLiteral new: line array: $ argnames map: |arg| { StringLiteral new: line value: $ arg to_s }]
57
+ ms = MessageSend new: line \
58
+ message: (Identifier from: "meta:" line: line) \
59
+ to: (Nothing new: line) \
60
+ args: $ MessageArgs new: line args: [meta]
61
+ ms bytecode: g
62
+ g pop()
63
+ }
64
+
65
+ # defines a class method names "new:foo:" if we're defining a
66
+ # method named e.g. "initialize:foo:" (a constructor method).
67
+ def define_constructor_class_method: g {
68
+ method_ident = StringLiteral new(@line, @name to_s from: 11 to: -1)
69
+ ms = MessageSend new: @line \
70
+ message: (Identifier from: "define_constructor_class_method:" line: @line) \
71
+ to: (Self new: @line) \
72
+ args: (MessageArgs new: @line args: [method_ident])
73
+ ms bytecode: g
74
+ }
75
+
76
+ def define_method_missing: g {
77
+ ms = MessageSend new: @line \
78
+ message: (Identifier from: "define_forward_method_missing" line: @line) \
79
+ to: (Self new: @line) \
80
+ args: (MessageArgs new: @line args: [])
81
+ ms bytecode: g
82
+ }
83
+ }
84
+
85
+ class MethodArgs : Rubinius AST FormalArguments {
86
+ def initialize: @line args: @array{
87
+ initialize(@line, @array map() |a| { a to_sym() }, nil, nil)
88
+ }
89
+ }
90
+ }
@@ -0,0 +1,7 @@
1
+ class Fancy AST {
2
+
3
+ class Node : Rubinius AST Node {
4
+ define_method('bytecode) |g| { bytecode: g }
5
+ }
6
+
7
+ }
@@ -0,0 +1,16 @@
1
+ class Fancy AST {
2
+ class RangeLiteral : Node {
3
+ read_slots: ['from, 'to]
4
+ def initialize: @line from: @from to: @to {
5
+ }
6
+
7
+ def bytecode: g {
8
+ pos(g)
9
+ ms = MessageSend new: @line \
10
+ message: (Identifier from: "new:to:" line: @line) \
11
+ to: (Identifier from: "Range" line: @line) \
12
+ args: (MessageArgs new: @line args: [@from, @to])
13
+ ms bytecode: g
14
+ }
15
+ }
16
+ }
@@ -0,0 +1,15 @@
1
+ class Fancy AST {
2
+ class Require : Node {
3
+ def initialize: @line file: @string {
4
+ }
5
+
6
+ def bytecode: g {
7
+ pos(g)
8
+ ms = MessageSend new: @line \
9
+ message: (Identifier from: "require:" line: @line) \
10
+ to: (Identifier from: "Fancy::CodeLoader" line: @line) \
11
+ args: (MessageArgs new: @line args: [@string])
12
+ ms bytecode: g
13
+ }
14
+ }
15
+ }
@@ -0,0 +1,23 @@
1
+ class Fancy AST {
2
+ class Return : Node {
3
+ def initialize: @line expr: @expr {
4
+ }
5
+
6
+ def bytecode: g {
7
+ pos(g)
8
+ @expr bytecode: g
9
+ g raise_return()
10
+ }
11
+ }
12
+
13
+ class ReturnLocal : Node {
14
+ def initialize: @line expr: @expr {
15
+ }
16
+
17
+ def bytecode: g {
18
+ pos(g)
19
+ @expr bytecode: g
20
+ g ret()
21
+ }
22
+ }
23
+ }
@@ -0,0 +1,52 @@
1
+ class Fancy AST {
2
+
3
+ class Script : Node {
4
+ read_slots: ['file, 'line, 'body]
5
+
6
+ @@stack = []
7
+
8
+ def push_script {
9
+ @@stack push(self)
10
+ }
11
+
12
+ def pop_script {
13
+ @@stack pop()
14
+ }
15
+
16
+ def self current {
17
+ @@stack last()
18
+ }
19
+
20
+ def initialize: @line file: @file body: @body {
21
+ }
22
+
23
+ def bytecode: g {
24
+ pos(g)
25
+ try {
26
+ self push_script
27
+
28
+ # docs, code = body.expressions.partition do |s|
29
+ # s.kind_of?(Rubinius::AST::StringLiteral)
30
+ # end
31
+
32
+ # if code.empty?
33
+ # # only literal string found, we have to evaluate to it, not
34
+ # # use as documentation.
35
+ # docs, code = [], docs
36
+ # end
37
+
38
+ # code.each { |c| c.bytecode(g) }
39
+
40
+ @body bytecode: g
41
+
42
+ # the docs array has top-level expressions that are
43
+ # simply string literals, we can use them for file-level
44
+ # documentation.
45
+ # TODO: implement file documentation here.
46
+ } finally {
47
+ self pop_script
48
+ }
49
+ }
50
+ }
51
+
52
+ }
@@ -0,0 +1,35 @@
1
+ class Fancy AST {
2
+ class SingletonMethodDef : Rubinius AST DefineSingleton {
3
+
4
+ def initialize: @line name: @name args: @arguments body: @body access: @access owner: @receiver {
5
+ name = @name method_name: @receiver
6
+ @body = SingletonMethodDefScope new: @line name: name args: @arguments body: @body
7
+ }
8
+
9
+ def bytecode: g {
10
+ pos(g)
11
+ g push_self()
12
+ g send(@access, 0)
13
+ g pop()
14
+ bytecode(g)
15
+ }
16
+
17
+ }
18
+
19
+ class SingletonMethodDefScope : Rubinius AST DefineSingletonScope {
20
+
21
+ def initialize: @line name: @name args: @arguments body: @body { }
22
+
23
+ define_method("bytecode") |g, recv| {
24
+ bytecode: g receiver: recv
25
+ }
26
+
27
+ def bytecode: g receiver: receiver {
28
+ pos(g)
29
+ docstring = @body shift_docstring
30
+ sup = Rubinius AST DefineSingletonScope instance_method('bytecode)
31
+ sup bind(self) call(g, receiver)
32
+ MethodDef set: g docstring: docstring line: @line argnames: $ @arguments names()
33
+ }
34
+ }
35
+ }
@@ -0,0 +1,17 @@
1
+ class Fancy AST {
2
+
3
+ class Super : Node {
4
+ def initialize: @line { }
5
+ }
6
+
7
+ class SuperSend : Node {
8
+ def initialize: @line message: @name args: @args { }
9
+ def bytecode: g {
10
+ pos(g)
11
+ @args bytecode: g
12
+ name = @name method_name: nil
13
+ g send_super(name, @args size)
14
+ }
15
+ }
16
+
17
+ }
@@ -0,0 +1,176 @@
1
+ class Fancy AST {
2
+ class TryCatch : Node {
3
+
4
+ def initialize: @line body: @body handlers: @handlers ensure: @ensure {}
5
+
6
+ def bytecode: g {
7
+ pos(g)
8
+
9
+ g push_modifiers()
10
+
11
+
12
+ outer_retry = g new_label()
13
+ this_retry = g new_label()
14
+ reraise = g new_label()
15
+
16
+ # Save the current exception into a stack local
17
+ g push_exception_state()
18
+ outer_ex = g new_stack_local()
19
+ g set_stack_local(outer_ex)
20
+ g pop()
21
+
22
+ # retry label for re-entring the try body
23
+ this_retry set!()
24
+
25
+ handler = g new_label()
26
+ finally_ = g new_label()
27
+ done = g new_label()
28
+
29
+ g setup_unwind(handler, Rubinius AST RescueType)
30
+
31
+ # make a break available to use
32
+ current_break = g break()
33
+ if: current_break then: { g break=(g new_label()) }
34
+
35
+ # use lazy label to patch up prematuraly leaving a try body via retry
36
+ if: outer_retry then: { g retry=(g new_label()) }
37
+
38
+ # also handle redo unwinding through the rescue
39
+ current_redo = g redo()
40
+ if: current_redo then: { g redo=(g new_label()) }
41
+
42
+ @body bytecode(g)
43
+
44
+ g pop_unwind()
45
+ g pop()
46
+ g goto(finally_)
47
+
48
+ if: current_break then: {
49
+ if: (g break() used?()) then: {
50
+ g break() set!()
51
+ g pop_unwind()
52
+
53
+ # Reset the outer exception
54
+ g push_stack_local(outer_ex)
55
+ g restore_exception_state()
56
+
57
+ g goto(current_break)
58
+ }
59
+ g break=(current_break)
60
+ }
61
+
62
+ if: current_redo then: {
63
+ if: (g redo() used?()) then: {
64
+ g redo() set!()
65
+ g pop_unwind()
66
+
67
+ # Reset the outer exception
68
+ g push_stack_local(outer_ex)
69
+ g restore_exception_state()
70
+
71
+ g goto(current_redo)
72
+ }
73
+ g redo=(current_redo)
74
+ }
75
+
76
+ if: outer_retry then: {
77
+ if: (g retry() used?()) then: {
78
+ g retry() set!()
79
+ g pop_unwind()
80
+
81
+ # Reset the outer exception
82
+ g push_stack_local(outer_ex)
83
+ g restore_exception_state()
84
+
85
+ g goto(outer_retry)
86
+ }
87
+ g retry=(outer_retry)
88
+ }
89
+
90
+ # we jump here if an exception was thrown in the body
91
+ handler set!()
92
+
93
+ # expose the retry label here only, not before this.
94
+ g retry=(this_retry)
95
+
96
+ # save exception state to use in reraise
97
+ g push_exception_state()
98
+
99
+ raised_exc_state = g new_stack_local()
100
+ g set_stack_local(raised_exc_state)
101
+ g pop()
102
+
103
+ # save the current exception so calling #=== cant trample it.
104
+ g push_current_exception()
105
+
106
+ @handlers each: |h| { h bytecode: g final_tag: finally_ }
107
+
108
+ reraise set!()
109
+
110
+ # execte the finally block before propagating the exception
111
+ @ensure bytecode: g
112
+
113
+ # remove the exception so we have the state
114
+ g pop()
115
+ # restore the state and reraise
116
+ g push_stack_local(raised_exc_state)
117
+ g restore_exception_state()
118
+ g reraise()
119
+
120
+ finally_ set!()
121
+ @ensure bytecode: g
122
+
123
+ done set!()
124
+
125
+ g push_stack_local(outer_ex)
126
+ g restore_exception_state()
127
+ g pop_modifiers()
128
+ }
129
+ }
130
+
131
+ class ExceptionHandler : Node {
132
+ def initialize: @line condition: @condition var: @var body: @body {}
133
+
134
+ def bytecode: g final_tag: final_tag {
135
+ pos(g)
136
+ nothing = g new_label()
137
+ @condition bytecode: g
138
+ g push_current_exception()
139
+ g send('===, 1)
140
+ g gif(nothing)
141
+
142
+ if: @var then: {
143
+ Assignment new: @line var: @var value: (CurrentException new: @line) .
144
+ bytecode: g
145
+ g pop()
146
+ }
147
+
148
+ @body bytecode: g
149
+ { g pop() } unless: $ @body empty?
150
+
151
+ g clear_exception()
152
+ g pop()
153
+
154
+ g goto(final_tag)
155
+ nothing set!()
156
+ }
157
+ }
158
+
159
+ class CurrentException : Node {
160
+ def initialize: @line {}
161
+ def bytecode: g {
162
+ pos(g)
163
+ g push_current_exception()
164
+ }
165
+ }
166
+
167
+ class Retry : Node {
168
+ def initialize: @line {}
169
+ def bytecode: g {
170
+ pos(g)
171
+ g pop()
172
+ g goto(g retry())
173
+ }
174
+ }
175
+
176
+ }
@@ -0,0 +1,34 @@
1
+ class Fancy AST {
2
+ class TupleLiteral : Node {
3
+ def initialize: @line entries: @elements { }
4
+
5
+ def bytecode: g {
6
+ pos(g)
7
+ ary = ArrayLiteral new: @line array: [FixnumLiteral new: @line value: (@elements size)]
8
+
9
+ args = RubyArgs new: @line args: ary
10
+
11
+ msg_ident = Identifier from: "new" line: @line
12
+ msg_ident ruby_ident: true
13
+ ms = MessageSend new: @line \
14
+ message: (msg_ident) \
15
+ to: (Identifier from: "Rubinius::Tuple" line: @line) \
16
+ args: args
17
+
18
+ ms bytecode: g
19
+
20
+ @elements each_with_index() |e i| {
21
+ g dup()
22
+ ary = [FixnumLiteral new: @line value: i, e]
23
+
24
+ ms = MessageSend new: @line \
25
+ message: (Identifier from: "at:put:" line: @line) \
26
+ to: (Nothing new: @line) \
27
+ args: (MessageArgs new: @line args: ary)
28
+
29
+ ms bytecode: g
30
+ g pop()
31
+ }
32
+ }
33
+ }
34
+ }