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,33 @@
|
|
1
|
+
class Fancy AST {
|
2
|
+
class ClassDef : Rubinius AST Class {
|
3
|
+
def initialize: @line name: @name parent: @parent body: @body {
|
4
|
+
name = nil
|
5
|
+
if: (@name is_a?: NestedConstant) then: {
|
6
|
+
name = @name scoped
|
7
|
+
} else: {
|
8
|
+
name = @name string to_sym()
|
9
|
+
}
|
10
|
+
|
11
|
+
if: (@body empty?) then: {
|
12
|
+
@body unshift_expression: $ NilLiteral new: @line
|
13
|
+
}
|
14
|
+
|
15
|
+
initialize(@line, name, @parent, @body)
|
16
|
+
}
|
17
|
+
|
18
|
+
def bytecode: g {
|
19
|
+
pos(g)
|
20
|
+
docstring = body() body() shift_docstring
|
21
|
+
docstring if_do: {
|
22
|
+
setdoc = MessageSend new: @line \
|
23
|
+
message: (Identifier from: "for:append:" line: @line) \
|
24
|
+
to: (Identifier from: "Fancy::Documentation" line: @line) \
|
25
|
+
args: (MessageArgs new: @line args: [Self new: @line, docstring])
|
26
|
+
|
27
|
+
# Replace first string expression to set documentation.
|
28
|
+
body() body() unshift_expression: setdoc
|
29
|
+
}
|
30
|
+
bytecode(g)
|
31
|
+
}
|
32
|
+
}
|
33
|
+
}
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class Fancy AST {
|
2
|
+
|
3
|
+
class ExpressionList : Node {
|
4
|
+
read_slots: ['expressions]
|
5
|
+
def initialize: @line list: @expressions ([]) {}
|
6
|
+
|
7
|
+
def unshift_expression: expression {
|
8
|
+
@expressions unshift(expression)
|
9
|
+
}
|
10
|
+
|
11
|
+
def add_expression: expression {
|
12
|
+
@expressions << expression
|
13
|
+
}
|
14
|
+
|
15
|
+
def empty? {
|
16
|
+
@expressions empty?
|
17
|
+
}
|
18
|
+
|
19
|
+
def bytecode: g {
|
20
|
+
pos(g)
|
21
|
+
size = @expressions size
|
22
|
+
@expressions each: |expr| {
|
23
|
+
size = size - 1
|
24
|
+
expr bytecode: g
|
25
|
+
{ g pop() } if: (size > 0)
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
# This method is only used by Rubinius' compiler classes and
|
30
|
+
# defined to be able to use their bytecode generation toolchain.
|
31
|
+
def strip_arguments {
|
32
|
+
[]
|
33
|
+
}
|
34
|
+
|
35
|
+
# If this expression list contains more than one expression
|
36
|
+
# and the first one is an string literal, it'll be used as doc.
|
37
|
+
# This method removes the first documentation string.
|
38
|
+
def shift_docstring {
|
39
|
+
if: ((@expressions first kind_of?(Rubinius AST StringLiteral)) && \
|
40
|
+
(@expressions size > 1)) then: {
|
41
|
+
@expressions shift()
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
}
|
46
|
+
|
47
|
+
}
|
@@ -0,0 +1,113 @@
|
|
1
|
+
class Fancy AST {
|
2
|
+
|
3
|
+
class Identifier : Node {
|
4
|
+
read_slots: ['string, 'line]
|
5
|
+
read_write_slots: ['ruby_ident]
|
6
|
+
|
7
|
+
@@gen_ident_start = 0
|
8
|
+
|
9
|
+
def Identifier generate: line {
|
10
|
+
"""
|
11
|
+
@line Line to be set for generated Identifier.
|
12
|
+
@return New generated Identifier, e.g. \"______gen_ident______1\"
|
13
|
+
|
14
|
+
Generates a new Identifier using a simple counter.
|
15
|
+
"""
|
16
|
+
|
17
|
+
@@gen_ident_start = @@gen_ident_start + 1
|
18
|
+
Identifier from: ("______gen_ident______" ++ @@gen_ident_start) line: line
|
19
|
+
}
|
20
|
+
|
21
|
+
def initialize: @line string: @string ruby_ident: @ruby_ident (false) {}
|
22
|
+
|
23
|
+
def name {
|
24
|
+
@string to_sym()
|
25
|
+
}
|
26
|
+
|
27
|
+
def method_name: receiver ruby_send: ruby (false) {
|
28
|
+
ruby || @ruby_ident if_do: {
|
29
|
+
@string to_sym()
|
30
|
+
} else: {
|
31
|
+
@string =~ /:$/ . if_do: {
|
32
|
+
@string to_sym()
|
33
|
+
} else: {
|
34
|
+
":" + @string . to_sym()
|
35
|
+
}
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
def self from: string line: line filename: filename (nil) {
|
40
|
+
type = match string -> {
|
41
|
+
case "__FILE__" -> return CurrentFile new: line filename: filename
|
42
|
+
case "__LINE__" -> return CurrentLine new: line
|
43
|
+
case "self" -> return Self new: line
|
44
|
+
case /^[A-Z].*::/ -> NestedConstant
|
45
|
+
case /^[A-Z]/ -> Constant
|
46
|
+
case /^@@/ -> ClassVariable
|
47
|
+
case /^@/ -> InstanceVariable
|
48
|
+
case _ -> Identifier
|
49
|
+
}
|
50
|
+
type new: line string: string
|
51
|
+
}
|
52
|
+
|
53
|
+
def bytecode: g {
|
54
|
+
pos(g)
|
55
|
+
match @string -> {
|
56
|
+
case "true" -> g push_true()
|
57
|
+
case "false" -> g push_false()
|
58
|
+
case "nil" -> g push_nil()
|
59
|
+
case _ -> Rubinius AST LocalVariableAccess new(@line, self name) bytecode(g)
|
60
|
+
}
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
class InstanceVariable : Identifier {
|
65
|
+
def initialize: @line string: @string {}
|
66
|
+
def bytecode: g {
|
67
|
+
pos(g)
|
68
|
+
Rubinius AST InstanceVariableAccess new(@line, self name) bytecode(g)
|
69
|
+
}
|
70
|
+
}
|
71
|
+
|
72
|
+
class ClassVariable : Identifier {
|
73
|
+
def initialize: @line string: @string {}
|
74
|
+
def bytecode: g {
|
75
|
+
pos(g)
|
76
|
+
Rubinius AST ClassVariableAccess new(@line, self name) bytecode(g)
|
77
|
+
}
|
78
|
+
}
|
79
|
+
|
80
|
+
class Constant : Identifier {
|
81
|
+
def initialize: @line string: @string {}
|
82
|
+
def bytecode: g {
|
83
|
+
pos(g)
|
84
|
+
Rubinius AST ConstantAccess new(@line, self name) bytecode(g)
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
class NestedConstant : Identifier {
|
89
|
+
def initialize: @line string: @string {
|
90
|
+
}
|
91
|
+
|
92
|
+
def initialize: @line const: const parent: parent {
|
93
|
+
@string = (parent string) ++ "::" ++ (const string)
|
94
|
+
}
|
95
|
+
|
96
|
+
def scoped {
|
97
|
+
names = @string split("::")
|
98
|
+
parent = Constant new: @line string: (names shift())
|
99
|
+
scoped = nil
|
100
|
+
names each() |name| {
|
101
|
+
scoped = Rubinius AST ScopedConstant new(@line, parent, name to_sym())
|
102
|
+
parent = scoped
|
103
|
+
}
|
104
|
+
scoped
|
105
|
+
}
|
106
|
+
|
107
|
+
def bytecode: g {
|
108
|
+
pos(g)
|
109
|
+
self scoped bytecode(g)
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
}
|
@@ -0,0 +1,122 @@
|
|
1
|
+
class Fancy AST {
|
2
|
+
class NilLiteral : Rubinius AST NilLiteral {
|
3
|
+
def initialize: line { initialize(line) }
|
4
|
+
def bytecode: g {
|
5
|
+
pos(g)
|
6
|
+
bytecode(g)
|
7
|
+
}
|
8
|
+
}
|
9
|
+
|
10
|
+
class FixnumLiteral : Rubinius AST FixnumLiteral {
|
11
|
+
def initialize: line value: value { initialize(line, value) }
|
12
|
+
def bytecode: g {
|
13
|
+
pos(g)
|
14
|
+
bytecode(g)
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
class NumberLiteral : Rubinius AST NumberLiteral {
|
19
|
+
def initialize: line value: value { initialize(line, value) }
|
20
|
+
def bytecode: g {
|
21
|
+
pos(g)
|
22
|
+
bytecode(g)
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
class StringLiteral : Rubinius AST StringLiteral {
|
27
|
+
def initialize: line value: value { initialize(line, StringHelper unescape_string(value)) }
|
28
|
+
def bytecode: g {
|
29
|
+
pos(g)
|
30
|
+
bytecode(g)
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
class CurrentFile : Node {
|
35
|
+
def initialize: @line filename: @filename { }
|
36
|
+
def bytecode: g {
|
37
|
+
pos(g)
|
38
|
+
args = MessageArgs new: @line args: [StringLiteral new: @line value: @filename]
|
39
|
+
MessageSend new: @line message: (Identifier from: "current_file:" line: @line) \
|
40
|
+
to: (Identifier from: "Fancy::CodeLoader" line: @line) \
|
41
|
+
args: args .
|
42
|
+
bytecode: g
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
class CurrentLine : Node {
|
47
|
+
def initialize: @line {}
|
48
|
+
def bytecode: g {
|
49
|
+
pos(g)
|
50
|
+
FixnumLiteral new: @line value: @line . bytecode: g
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
54
|
+
class Nothing : Node {
|
55
|
+
def initialize: @line { }
|
56
|
+
def bytecode: g { pos(g) }
|
57
|
+
}
|
58
|
+
|
59
|
+
class StackTop : Node {
|
60
|
+
def initialize: @line { }
|
61
|
+
def bytecode: g {
|
62
|
+
pos(g)
|
63
|
+
g dup()
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
class StackLocal : Node {
|
68
|
+
def initialize: @line { }
|
69
|
+
def set: g { @local = g new_stack_local(); g set_stack_local(@local) }
|
70
|
+
def bytecode: g {
|
71
|
+
pos(g)
|
72
|
+
g push_stack_local(@local)
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
class Self : Rubinius AST Self {
|
77
|
+
def initialize: line { initialize(line) }
|
78
|
+
def bytecode: g {
|
79
|
+
pos(g)
|
80
|
+
bytecode(g)
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
class SymbolLiteral : Rubinius AST SymbolLiteral {
|
85
|
+
def initialize: line value: value { initialize(line, value) }
|
86
|
+
def bytecode: g {
|
87
|
+
pos(g)
|
88
|
+
bytecode(g)
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
class RegexpLiteral : Rubinius AST RegexLiteral {
|
93
|
+
def initialize: line value: value { initialize(line, value, 0) }
|
94
|
+
def bytecode: g {
|
95
|
+
pos(g)
|
96
|
+
bytecode(g)
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
class ArrayLiteral : Rubinius AST ArrayLiteral {
|
101
|
+
read_slots: ['array]
|
102
|
+
def initialize: line array: @array {
|
103
|
+
@array if_nil: { @array = [] }
|
104
|
+
initialize(line, @array)
|
105
|
+
}
|
106
|
+
def bytecode: g {
|
107
|
+
pos(g)
|
108
|
+
bytecode(g)
|
109
|
+
}
|
110
|
+
}
|
111
|
+
|
112
|
+
class HashLiteral : Rubinius AST HashLiteral {
|
113
|
+
def initialize: line entries: @key_values {
|
114
|
+
@key_values if_nil: { @key_values = [] }
|
115
|
+
initialize(line, @key_values)
|
116
|
+
}
|
117
|
+
def bytecode: g {
|
118
|
+
pos(g)
|
119
|
+
bytecode(g)
|
120
|
+
}
|
121
|
+
}
|
122
|
+
}
|
@@ -0,0 +1,88 @@
|
|
1
|
+
class Fancy AST {
|
2
|
+
|
3
|
+
class Match : Node {
|
4
|
+
def initialize: @line expr: @expr body: @clauses {
|
5
|
+
}
|
6
|
+
|
7
|
+
|
8
|
+
def bytecode: g {
|
9
|
+
pos(g)
|
10
|
+
|
11
|
+
# create labels for each clause body.
|
12
|
+
clause_labels = []
|
13
|
+
@clauses size times: {
|
14
|
+
clause_labels << (g new_label())
|
15
|
+
}
|
16
|
+
end_label = g new_label()
|
17
|
+
|
18
|
+
# ok, let's emit the bytecode
|
19
|
+
@expr bytecode: g
|
20
|
+
|
21
|
+
@match_arg_vars = []
|
22
|
+
|
23
|
+
@clauses each_with_index: |c i| {
|
24
|
+
g dup() # save the @expr since we need to reuse it
|
25
|
+
c expr bytecode: g
|
26
|
+
g swap()
|
27
|
+
g send(':===, 1)
|
28
|
+
|
29
|
+
# if match_arg is given, get a localvar slot and set the
|
30
|
+
# result of the === call to it
|
31
|
+
if: (c match_args first) then: |marg| {
|
32
|
+
match_arg_var = g state() scope() new_local(marg)
|
33
|
+
@match_arg_vars << match_arg_var
|
34
|
+
g set_local(match_arg_var slot())
|
35
|
+
}
|
36
|
+
|
37
|
+
# for any remaining match arguments, set their values to
|
38
|
+
# whatever matcher[idx] returns (should be the matched data)
|
39
|
+
c match_args rest each_with_index: |match_arg idx| {
|
40
|
+
idx = idx + 1 # we only want from index 1 onwards
|
41
|
+
g dup() # dup the matcher object
|
42
|
+
match_arg_var = g state() scope() new_local(match_arg)
|
43
|
+
@match_arg_vars << match_arg_var
|
44
|
+
FixnumLiteral new: @line value: idx . bytecode: g
|
45
|
+
g send('at:, 1)
|
46
|
+
g set_local(match_arg_var slot())
|
47
|
+
g pop()
|
48
|
+
}
|
49
|
+
|
50
|
+
g git(clause_labels[i])
|
51
|
+
}
|
52
|
+
g pop()
|
53
|
+
g push_nil()
|
54
|
+
g goto(end_label)
|
55
|
+
|
56
|
+
clause_labels each_with_index: |label i| {
|
57
|
+
label set!()
|
58
|
+
g pop()
|
59
|
+
@clauses[i] body bytecode: g
|
60
|
+
|
61
|
+
# set match_arg locals slot to nil, so they're only visible
|
62
|
+
# within the case body
|
63
|
+
@match_arg_vars each: |marg_var| {
|
64
|
+
g push_nil()
|
65
|
+
g set_local(marg_var slot())
|
66
|
+
g pop()
|
67
|
+
}
|
68
|
+
|
69
|
+
g goto(end_label)
|
70
|
+
}
|
71
|
+
|
72
|
+
end_label set!()
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
class MatchClause : Node {
|
77
|
+
read_slots: ['expr, 'body, 'match_args]
|
78
|
+
def initialize: @line expr: @expr body: @body args: @match_args {
|
79
|
+
if: (@expr kind_of?: Identifier) then: {
|
80
|
+
if: (@expr string == "_") then: {
|
81
|
+
@expr = Identifier from: "Object" line: @line
|
82
|
+
}
|
83
|
+
}
|
84
|
+
@match_args = @match_args map: 'name
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
}
|
@@ -0,0 +1,110 @@
|
|
1
|
+
class Fancy AST {
|
2
|
+
|
3
|
+
class MessageSend : Node {
|
4
|
+
read_write_slots: ['name, 'receiver, 'args]
|
5
|
+
def initialize: @line message: @name to: @receiver args: @args { }
|
6
|
+
|
7
|
+
def bytecode: g {
|
8
|
+
pos(g)
|
9
|
+
if: (@receiver is_a?: Super) then: {
|
10
|
+
SuperSend new: @line message: @name args: @args . bytecode: g
|
11
|
+
} else: {
|
12
|
+
@receiver bytecode: g
|
13
|
+
@args bytecode: g
|
14
|
+
pos(g)
|
15
|
+
{ g allow_private() } if: (@receiver is_a?: Self)
|
16
|
+
sym = @name method_name: @receiver ruby_send: (self ruby_send?)
|
17
|
+
if: (self has_splat?) then: {
|
18
|
+
{ g push_nil() } unless: $ self ruby_block?
|
19
|
+
g send_with_splat(sym, @args size, false)
|
20
|
+
return nil
|
21
|
+
}
|
22
|
+
if: (self ruby_block?) then: {
|
23
|
+
g send_with_block(sym, @args size, false)
|
24
|
+
} else: {
|
25
|
+
g send(sym, @args size, false)
|
26
|
+
}
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
def ruby_block? {
|
31
|
+
@args has_block?
|
32
|
+
}
|
33
|
+
|
34
|
+
def ruby_send? {
|
35
|
+
@args ruby_args?
|
36
|
+
}
|
37
|
+
|
38
|
+
def has_splat? {
|
39
|
+
@args has_splat?
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
class MessageArgs : Node {
|
44
|
+
read_slots: ['args]
|
45
|
+
def initialize: @line args: @args { }
|
46
|
+
|
47
|
+
def bytecode: g {
|
48
|
+
pos(g)
|
49
|
+
@args each: |a| {
|
50
|
+
a bytecode: g
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
54
|
+
def size {
|
55
|
+
@args size
|
56
|
+
}
|
57
|
+
|
58
|
+
def ruby_args? {
|
59
|
+
is_a?: RubyArgs
|
60
|
+
}
|
61
|
+
|
62
|
+
def has_block? {
|
63
|
+
false
|
64
|
+
}
|
65
|
+
|
66
|
+
def has_splat? {
|
67
|
+
false
|
68
|
+
}
|
69
|
+
}
|
70
|
+
|
71
|
+
|
72
|
+
class RubyArgs : MessageArgs {
|
73
|
+
def initialize: @line args: @args block: @block (nil) {
|
74
|
+
{ @args = @args array } unless: (@args is_a?: Array)
|
75
|
+
@block if_nil: {
|
76
|
+
if: (@args last kind_of?: Identifier) then: {
|
77
|
+
if: (@args last string =~ /^&\w/) then: {
|
78
|
+
@block = @args pop()
|
79
|
+
@block = Identifier new: (@block line) string: (@block string from: 1 to: -1)
|
80
|
+
}
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
if: (@args last kind_of?: Identifier) then: {
|
85
|
+
if: (@args last string =~ /^\*\w/) then: {
|
86
|
+
@splat = @args pop()
|
87
|
+
@splat = Identifier new: (@splat line) string: (@splat string from: 1 to: -1)
|
88
|
+
}
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
def bytecode: g {
|
93
|
+
pos(g)
|
94
|
+
@args each: |a| {
|
95
|
+
a bytecode: g
|
96
|
+
}
|
97
|
+
{ @splat bytecode: g; g cast_array() } if: @splat
|
98
|
+
{ @block bytecode: g } if: @block
|
99
|
+
}
|
100
|
+
|
101
|
+
def has_block? {
|
102
|
+
@block nil? not
|
103
|
+
}
|
104
|
+
|
105
|
+
def has_splat? {
|
106
|
+
@splat nil? not
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
}
|