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.
- data/AUTHORS +7 -0
- data/LICENSE +19 -0
- data/README +173 -0
- data/Rakefile +255 -0
- data/bin/fancy +40 -0
- data/bin/fdoc +23 -0
- data/bin/fyi +22 -0
- data/bin/ifancy +46 -0
- data/boot/README +12 -0
- data/boot/code_loader.rb +165 -0
- data/boot/compile.fy +3 -0
- data/boot/fancy_ext.rb +13 -0
- data/boot/fancy_ext/block_env.rb +29 -0
- data/boot/fancy_ext/class.rb +26 -0
- data/boot/fancy_ext/kernel.rb +12 -0
- data/boot/fancy_ext/module.rb +89 -0
- data/boot/fancy_ext/object.rb +34 -0
- data/boot/fancy_ext/string_helper.rb +10 -0
- data/boot/load.rb +72 -0
- data/boot/rbx-compiler/README +12 -0
- data/boot/rbx-compiler/compiler.rb +24 -0
- data/boot/rbx-compiler/compiler/ast.rb +23 -0
- data/boot/rbx-compiler/compiler/ast/README +11 -0
- data/boot/rbx-compiler/compiler/ast/array_literal.rb +13 -0
- data/boot/rbx-compiler/compiler/ast/assign.rb +57 -0
- data/boot/rbx-compiler/compiler/ast/block.rb +70 -0
- data/boot/rbx-compiler/compiler/ast/class_def.rb +35 -0
- data/boot/rbx-compiler/compiler/ast/expression_list.rb +57 -0
- data/boot/rbx-compiler/compiler/ast/hash_literal.rb +11 -0
- data/boot/rbx-compiler/compiler/ast/identifier.rb +120 -0
- data/boot/rbx-compiler/compiler/ast/match.rb +81 -0
- data/boot/rbx-compiler/compiler/ast/message_send.rb +71 -0
- data/boot/rbx-compiler/compiler/ast/method_def.rb +116 -0
- data/boot/rbx-compiler/compiler/ast/node.rb +6 -0
- data/boot/rbx-compiler/compiler/ast/range_literal.rb +22 -0
- data/boot/rbx-compiler/compiler/ast/require.rb +20 -0
- data/boot/rbx-compiler/compiler/ast/return.rb +29 -0
- data/boot/rbx-compiler/compiler/ast/ruby_args.rb +35 -0
- data/boot/rbx-compiler/compiler/ast/script.rb +56 -0
- data/boot/rbx-compiler/compiler/ast/singleton_method_def.rb +39 -0
- data/boot/rbx-compiler/compiler/ast/string_literal.rb +14 -0
- data/boot/rbx-compiler/compiler/ast/super.rb +25 -0
- data/boot/rbx-compiler/compiler/ast/try_catch_block.rb +220 -0
- data/boot/rbx-compiler/compiler/ast/tuple_literal.rb +33 -0
- data/boot/rbx-compiler/compiler/command.rb +39 -0
- data/boot/rbx-compiler/compiler/compiler.rb +83 -0
- data/boot/rbx-compiler/compiler/stages.rb +99 -0
- data/boot/rbx-compiler/parser.rb +2 -0
- data/boot/rbx-compiler/parser/README +15 -0
- data/boot/rbx-compiler/parser/Rakefile +54 -0
- data/boot/rbx-compiler/parser/extconf.rb +3 -0
- data/boot/rbx-compiler/parser/fancy_parser.bundle +0 -0
- data/boot/rbx-compiler/parser/fancy_parser.c +46 -0
- data/boot/rbx-compiler/parser/fancy_parser.h +8 -0
- data/boot/rbx-compiler/parser/lexer.lex +180 -0
- data/boot/rbx-compiler/parser/parser.rb +356 -0
- data/boot/rbx-compiler/parser/parser.y +711 -0
- data/boot/rsexp_pretty_printer.rb +76 -0
- data/doc/api/fancy.css +93 -0
- data/doc/api/fancy.jsonp +1 -0
- data/doc/api/fdoc.js +187 -0
- data/doc/api/index.html +57 -0
- data/doc/api/underscore-min.js +18 -0
- data/doc/features.md +228 -0
- data/examples/argv.fy +8 -0
- data/examples/arithmetic.fy +7 -0
- data/examples/armstrong_numbers.fy +33 -0
- data/examples/array.fy +52 -0
- data/examples/blocks.fy +15 -0
- data/examples/boolean.fy +24 -0
- data/examples/call_with_receiver.fy +9 -0
- data/examples/class.fy +68 -0
- data/examples/closures.fy +24 -0
- data/examples/constant_access.fy +15 -0
- data/examples/default_args.fy +17 -0
- data/examples/define_methods.fy +15 -0
- data/examples/documentation.fy +57 -0
- data/examples/documentation_formatters.fy +25 -0
- data/examples/echo.fy +16 -0
- data/examples/empty_catch.fy +4 -0
- data/examples/exception.fy +9 -0
- data/examples/factorial.fy +12 -0
- data/examples/fibonacci.fy +16 -0
- data/examples/files.fy +23 -0
- data/examples/finally.fy +5 -0
- data/examples/game_of_life.fy +148 -0
- data/examples/hashes.fy +7 -0
- data/examples/hello_world.fy +6 -0
- data/examples/html_generator.fy +54 -0
- data/examples/implicit_return.fy +3 -0
- data/examples/matchers.fy +6 -0
- data/examples/methods.fy +29 -0
- data/examples/nested_classes.fy +27 -0
- data/examples/nested_try.fy +9 -0
- data/examples/numbers.fy +12 -0
- data/examples/pattern_matching.fy +40 -0
- data/examples/person.fy +65 -0
- data/examples/project-euler/01.fy +8 -0
- data/examples/project-euler/02.fy +21 -0
- data/examples/project-euler/28.fy +33 -0
- data/examples/rbx/and_or.fy +7 -0
- data/examples/rbx/blocks.fy +22 -0
- data/examples/rbx/classes.fy +32 -0
- data/examples/rbx/hello.fy +8 -0
- data/examples/rbx/include.fy +12 -0
- data/examples/rbx/inherit.fy +11 -0
- data/examples/rbx/methods.fy +15 -0
- data/examples/rbx/nested_classes.fy +9 -0
- data/examples/rbx/require.fy +3 -0
- data/examples/rbx/strings.fy +5 -0
- data/examples/regex.fy +7 -0
- data/examples/require.fy +7 -0
- data/examples/retry.fy +12 -0
- data/examples/return.fy +13 -0
- data/examples/ruby_require.fy +7 -0
- data/examples/ruby_send.fy +3 -0
- data/examples/singleton_methods.fy +21 -0
- data/examples/stupid_quicksort.fy +12 -0
- data/examples/threads.fy +18 -0
- data/examples/tuple.fy +8 -0
- data/examples/webserver/webserver.fy +18 -0
- data/lib/argv.fy +36 -0
- data/lib/array.fy +207 -0
- data/lib/block.fy +88 -0
- data/lib/boot.fy +41 -0
- data/lib/class.fy +106 -0
- data/lib/compiler.fy +14 -0
- data/lib/compiler/ast.fy +40 -0
- data/lib/compiler/ast/assign.fy +96 -0
- data/lib/compiler/ast/block.fy +84 -0
- data/lib/compiler/ast/class_def.fy +33 -0
- data/lib/compiler/ast/expression_list.fy +47 -0
- data/lib/compiler/ast/identifier.fy +113 -0
- data/lib/compiler/ast/literals.fy +122 -0
- data/lib/compiler/ast/match.fy +88 -0
- data/lib/compiler/ast/message_send.fy +110 -0
- data/lib/compiler/ast/method_def.fy +90 -0
- data/lib/compiler/ast/node.fy +7 -0
- data/lib/compiler/ast/range.fy +16 -0
- data/lib/compiler/ast/require.fy +15 -0
- data/lib/compiler/ast/return.fy +23 -0
- data/lib/compiler/ast/script.fy +52 -0
- data/lib/compiler/ast/singleton_method_def.fy +35 -0
- data/lib/compiler/ast/super.fy +17 -0
- data/lib/compiler/ast/try_catch.fy +176 -0
- data/lib/compiler/ast/tuple_literal.fy +34 -0
- data/lib/compiler/command.fy +51 -0
- data/lib/compiler/compiler.fy +73 -0
- data/lib/compiler/stages.fy +81 -0
- data/lib/directory.fy +17 -0
- data/lib/documentation.fy +115 -0
- data/lib/enumerable.fy +269 -0
- data/lib/eval.fy +31 -0
- data/lib/fancy_spec.fy +202 -0
- data/lib/fdoc.fy +359 -0
- data/lib/fdoc_hook.fy +10 -0
- data/lib/file.fy +54 -0
- data/lib/hash.fy +56 -0
- data/lib/main.fy +80 -0
- data/lib/method.fy +22 -0
- data/lib/nil_class.fy +56 -0
- data/lib/number.fy +87 -0
- data/lib/object.fy +170 -0
- data/lib/package.fy +61 -0
- data/lib/package/dependency.fy +24 -0
- data/lib/package/installer.fy +180 -0
- data/lib/package/specification.fy +55 -0
- data/lib/package/uninstaller.fy +15 -0
- data/lib/parser.fy +4 -0
- data/lib/parser/ext/README +15 -0
- data/lib/parser/ext/ext.c +42 -0
- data/lib/parser/ext/ext.h +8 -0
- data/lib/parser/ext/extconf.rb +3 -0
- data/lib/parser/ext/lexer.lex +187 -0
- data/lib/parser/ext/parser.y +744 -0
- data/lib/parser/methods.fy +297 -0
- data/lib/rbx.fy +37 -0
- data/lib/rbx/array.fy +237 -0
- data/lib/rbx/bignum.fy +23 -0
- data/lib/rbx/block.fy +9 -0
- data/lib/rbx/class.fy +129 -0
- data/lib/rbx/code_loader.fy +192 -0
- data/lib/rbx/console.fy +63 -0
- data/lib/rbx/directory.fy +46 -0
- data/lib/rbx/documentation.fy +64 -0
- data/lib/rbx/environment_variables.fy +3 -0
- data/lib/rbx/exception.fy +30 -0
- data/lib/rbx/false_class.fy +58 -0
- data/lib/rbx/fiber.fy +25 -0
- data/lib/rbx/file.fy +191 -0
- data/lib/rbx/fixnum.fy +25 -0
- data/lib/rbx/float.fy +14 -0
- data/lib/rbx/hash.fy +38 -0
- data/lib/rbx/integer.fy +15 -0
- data/lib/rbx/io.fy +30 -0
- data/lib/rbx/match_data.fy +9 -0
- data/lib/rbx/method.fy +22 -0
- data/lib/rbx/name_error.fy +3 -0
- data/lib/rbx/no_method_error.fy +15 -0
- data/lib/rbx/object.fy +117 -0
- data/lib/rbx/range.fy +15 -0
- data/lib/rbx/regexp.fy +9 -0
- data/lib/rbx/string.fy +63 -0
- data/lib/rbx/symbol.fy +12 -0
- data/lib/rbx/system.fy +37 -0
- data/lib/rbx/tcp_server.fy +6 -0
- data/lib/rbx/tcp_socket.fy +7 -0
- data/lib/rbx/thread.fy +75 -0
- data/lib/rbx/tuple.fy +37 -0
- data/lib/set.fy +61 -0
- data/lib/stack.fy +51 -0
- data/lib/string.fy +58 -0
- data/lib/struct.fy +13 -0
- data/lib/symbol.fy +23 -0
- data/lib/true_class.fy +43 -0
- data/lib/tuple.fy +68 -0
- data/lib/version.fy +6 -0
- data/tests/argv.fy +13 -0
- data/tests/array.fy +343 -0
- data/tests/assignment.fy +53 -0
- data/tests/block.fy +103 -0
- data/tests/class.fy +409 -0
- data/tests/control_flow.fy +79 -0
- data/tests/documentation.fy +24 -0
- data/tests/exception.fy +115 -0
- data/tests/file.fy +86 -0
- data/tests/hash.fy +101 -0
- data/tests/method.fy +131 -0
- data/tests/nil_class.fy +55 -0
- data/tests/number.fy +128 -0
- data/tests/object.fy +125 -0
- data/tests/parsing/sexp.fy +50 -0
- data/tests/pattern_matching.fy +82 -0
- data/tests/range.fy +11 -0
- data/tests/set.fy +10 -0
- data/tests/stack.fy +22 -0
- data/tests/string.fy +102 -0
- data/tests/symbol.fy +17 -0
- data/tests/true_class.fy +63 -0
- data/tests/tuple.fy +21 -0
- data/tools/fancy-mode.el +63 -0
- 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,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
|
+
}
|