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,120 @@
|
|
1
|
+
class Fancy
|
2
|
+
class AST
|
3
|
+
|
4
|
+
class Identifier < Node
|
5
|
+
attr_reader :identifier
|
6
|
+
|
7
|
+
def initialize(line, identifier)
|
8
|
+
super(line)
|
9
|
+
@identifier = identifier
|
10
|
+
end
|
11
|
+
|
12
|
+
def constant?
|
13
|
+
@identifier =~ /^[A-Z]/
|
14
|
+
end
|
15
|
+
|
16
|
+
def instance_variable?
|
17
|
+
@identifier =~ /^@/ && !class_variable?
|
18
|
+
end
|
19
|
+
|
20
|
+
def class_variable?
|
21
|
+
@identifier =~ /^@@/
|
22
|
+
end
|
23
|
+
|
24
|
+
def local_variable?
|
25
|
+
!(constant? || instance_variable? || class_variable?)
|
26
|
+
end
|
27
|
+
|
28
|
+
def nested_classname?
|
29
|
+
constant? && @identifier.include?("::")
|
30
|
+
end
|
31
|
+
|
32
|
+
def true?
|
33
|
+
@identifier == "true"
|
34
|
+
end
|
35
|
+
|
36
|
+
def false?
|
37
|
+
@identifier == "false"
|
38
|
+
end
|
39
|
+
|
40
|
+
def nil?
|
41
|
+
@identifier == "nil"
|
42
|
+
end
|
43
|
+
|
44
|
+
def operator?
|
45
|
+
@identifier !~ /^\w/
|
46
|
+
end
|
47
|
+
|
48
|
+
def name
|
49
|
+
if constant?
|
50
|
+
@identifier.to_sym
|
51
|
+
elsif class_variable?
|
52
|
+
@identifier.to_sym
|
53
|
+
elsif instance_variable?
|
54
|
+
@identifier.to_sym
|
55
|
+
else
|
56
|
+
@identifier.to_sym
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def method_name(receiver = nil, with_ruby_args = false)
|
61
|
+
if with_ruby_args
|
62
|
+
rubyfied.to_sym
|
63
|
+
elsif @identifier !~ /:$/
|
64
|
+
# methods not ending with ':' have ':' prepended instead.
|
65
|
+
# so we dont create colissions with existing ruby methods.
|
66
|
+
# if we dont do this, whenever a ruby library tries to
|
67
|
+
# invoke (say, the print method) it will find the
|
68
|
+
# fancy version (not expecting arguments) and will fail.
|
69
|
+
":#{@identifier}".to_sym
|
70
|
+
else
|
71
|
+
@identifier.to_sym
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def rubyfied
|
76
|
+
if @identifier.split(":").size > 1
|
77
|
+
@identifier
|
78
|
+
else
|
79
|
+
if @identifier =~ /:$/
|
80
|
+
@identifier[0..-2]
|
81
|
+
else
|
82
|
+
@identifier[0..-1]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def bytecode(g)
|
88
|
+
if "__FILE__" == @identifier
|
89
|
+
Rubinius::AST::StringLiteral.new(line, Fancy::AST::Script.current.filename).
|
90
|
+
bytecode(g)
|
91
|
+
elsif "__LINE__" == @identifier
|
92
|
+
Rubinius::AST::FixnumLiteral.new(line, line).bytecode(g)
|
93
|
+
elsif nested_classname?
|
94
|
+
classnames = @identifier.split("::")
|
95
|
+
parent = Identifier.new(@line, classnames.shift)
|
96
|
+
classnames.each do |cn|
|
97
|
+
Rubinius::AST::ScopedConstant.new(@line, parent, cn.to_sym).bytecode(g)
|
98
|
+
child = Identifier.new(@line, cn)
|
99
|
+
parent = child
|
100
|
+
end
|
101
|
+
elsif constant?
|
102
|
+
Rubinius::AST::ConstantAccess.new(line, name).bytecode(g)
|
103
|
+
elsif class_variable?
|
104
|
+
Rubinius::AST::ClassVariableAccess.new(line, name).bytecode(g)
|
105
|
+
elsif instance_variable?
|
106
|
+
Rubinius::AST::InstanceVariableAccess.new(line, name).bytecode(g)
|
107
|
+
elsif true?
|
108
|
+
g.push_true
|
109
|
+
elsif false?
|
110
|
+
g.push_false
|
111
|
+
elsif nil?
|
112
|
+
g.push_nil
|
113
|
+
else
|
114
|
+
Rubinius::AST::LocalVariableAccess.new(line, name).bytecode(g)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
class Fancy
|
2
|
+
class AST
|
3
|
+
|
4
|
+
class Match < Node
|
5
|
+
def initialize(line, expr, clauses)
|
6
|
+
super(line)
|
7
|
+
@expr = expr
|
8
|
+
@clauses = clauses
|
9
|
+
end
|
10
|
+
|
11
|
+
def bytecode(g)
|
12
|
+
pos(g)
|
13
|
+
|
14
|
+
# create labels for each clause body.
|
15
|
+
clause_labels = []
|
16
|
+
@clauses.size.times do
|
17
|
+
clause_labels << g.new_label
|
18
|
+
end
|
19
|
+
end_label = g.new_label
|
20
|
+
|
21
|
+
# ok, let's emit the bytecode
|
22
|
+
@expr.bytecode(g)
|
23
|
+
|
24
|
+
@clauses.each_with_index do |c, i|
|
25
|
+
g.dup # save the @expr since we need to reuse it
|
26
|
+
c.match_expr.bytecode(g)
|
27
|
+
g.swap
|
28
|
+
g.send :":===", 1
|
29
|
+
|
30
|
+
# if match_arg is given, get a localvar slot and set the
|
31
|
+
# result of the === call to it
|
32
|
+
if c.match_arg
|
33
|
+
@match_arg_var = g.state.scope.new_local c.match_arg
|
34
|
+
g.set_local @match_arg_var.slot
|
35
|
+
end
|
36
|
+
|
37
|
+
g.git clause_labels[i]
|
38
|
+
end
|
39
|
+
g.pop
|
40
|
+
g.push_nil
|
41
|
+
g.goto end_label
|
42
|
+
|
43
|
+
clause_labels.each_with_index do |label, i|
|
44
|
+
label.set!
|
45
|
+
g.pop
|
46
|
+
@clauses[i].val_expr.bytecode(g)
|
47
|
+
|
48
|
+
# set match_arg local slot to nil, so it's only visible
|
49
|
+
# within the case body
|
50
|
+
if @match_arg_var
|
51
|
+
g.push_nil
|
52
|
+
g.set_local @match_arg_var.slot
|
53
|
+
g.pop
|
54
|
+
end
|
55
|
+
|
56
|
+
g.goto end_label
|
57
|
+
end
|
58
|
+
|
59
|
+
end_label.set!
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class MatchClause < Node
|
64
|
+
attr_reader :match_expr, :val_expr, :match_arg
|
65
|
+
def initialize(line, match_expr, val_expr, match_arg)
|
66
|
+
super(line)
|
67
|
+
if match_expr.kind_of?(Fancy::AST::Identifier) && match_expr.identifier == "_"
|
68
|
+
match_expr = Fancy::AST::Identifier.new(match_expr.line, "Object")
|
69
|
+
end
|
70
|
+
@match_expr = match_expr
|
71
|
+
@val_expr = val_expr
|
72
|
+
|
73
|
+
if match_arg
|
74
|
+
# use name so we get the identifier as a symbol
|
75
|
+
@match_arg = match_arg.name
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
class Fancy
|
2
|
+
class AST
|
3
|
+
|
4
|
+
class MessageSend < Node
|
5
|
+
def initialize(line, receiver, message_name, message_args)
|
6
|
+
super(line)
|
7
|
+
@receiver = receiver
|
8
|
+
@message_name = message_name
|
9
|
+
@message_args = message_args
|
10
|
+
end
|
11
|
+
|
12
|
+
def bytecode(g)
|
13
|
+
if @receiver.is_a? Super
|
14
|
+
SuperSend.new(@line, @message_name, @message_args).bytecode(g)
|
15
|
+
else
|
16
|
+
@receiver.bytecode(g)
|
17
|
+
@message_args.bytecode(g)
|
18
|
+
pos(g)
|
19
|
+
g.allow_private if @receiver.is_a?(Rubinius::AST::Self)
|
20
|
+
|
21
|
+
name = @message_name.method_name(@receiver, ruby_send?)
|
22
|
+
if ruby_send_block?
|
23
|
+
g.send_with_block name, @message_args.size, false
|
24
|
+
else
|
25
|
+
g.send name, @message_args.size, false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def ruby_send_block?
|
31
|
+
@message_args.ruby_block?
|
32
|
+
end
|
33
|
+
|
34
|
+
def ruby_send?
|
35
|
+
@message_args.ruby_args?
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class MessageArgs < Node
|
40
|
+
attr_reader :args
|
41
|
+
|
42
|
+
def initialize(line, *args)
|
43
|
+
super(line)
|
44
|
+
@args = args
|
45
|
+
end
|
46
|
+
|
47
|
+
def bytecode(g)
|
48
|
+
@args.each do |a|
|
49
|
+
a.bytecode(g)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def size
|
54
|
+
if ruby_args?
|
55
|
+
return @args.first.size
|
56
|
+
else
|
57
|
+
@args.size
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def ruby_args?
|
62
|
+
@args.first.is_a? RubyArgs
|
63
|
+
end
|
64
|
+
|
65
|
+
def ruby_block?
|
66
|
+
ruby_args? && @args.first.has_block?
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
class Fancy
|
2
|
+
class AST
|
3
|
+
|
4
|
+
class MethodDef < Rubinius::AST::Define
|
5
|
+
def initialize(line, method_ident, args, body, access = :public)
|
6
|
+
@line = line
|
7
|
+
@name = method_ident.method_name
|
8
|
+
@arguments = args
|
9
|
+
@body = body
|
10
|
+
@access = access
|
11
|
+
generate_ivar_assignment
|
12
|
+
|
13
|
+
if body.empty?
|
14
|
+
body.unshift_expression Rubinius::AST::NilLiteral.new(line)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def generate_ivar_assignment
|
19
|
+
@arguments.required.reverse.each do |name|
|
20
|
+
if name.to_s =~ /^@/
|
21
|
+
ident = Fancy::AST::Identifier.new(line, name.to_s)
|
22
|
+
value = Rubinius::AST::LocalVariableAccess.new(line, name)
|
23
|
+
asign = Fancy::AST::Assignment.new(line, ident, value)
|
24
|
+
body.unshift_expression(asign)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def bytecode(g)
|
30
|
+
g.push_self
|
31
|
+
g.send @access, 0
|
32
|
+
g.pop
|
33
|
+
|
34
|
+
if @name.to_s =~ /^initialize:(\S)+/
|
35
|
+
define_constructor_class_method g
|
36
|
+
end
|
37
|
+
if @name.to_s =~ /^unknown_message:with_params:$/
|
38
|
+
define_method_missing(g)
|
39
|
+
end
|
40
|
+
|
41
|
+
docstring = @body.shift_docstring
|
42
|
+
super(g)
|
43
|
+
MethodDef.set_docstring(g, docstring, @line, @arguments.names)
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
# Sets fancy documentation for the object currently
|
48
|
+
# on top of the stack
|
49
|
+
def self.set_docstring(g, docstring, line, argnames = [])
|
50
|
+
# prevent invoking documentation: when doesnt makes sense.
|
51
|
+
return unless docstring
|
52
|
+
local = StackLocal.new
|
53
|
+
local.set!(g)
|
54
|
+
ms = MessageSend.new(line,
|
55
|
+
Identifier.new(line, "Fancy::Documentation"),
|
56
|
+
Identifier.new(line, "for:is:"),
|
57
|
+
MessageArgs.new(line, local, docstring))
|
58
|
+
ms.bytecode(g)
|
59
|
+
meta = HashLiteral.new(line,
|
60
|
+
SymbolLiteral.new(line, :argnames),
|
61
|
+
ArrayLiteral.new(line, *argnames.map{|arg|StringLiteral.new(line, arg.to_s)})
|
62
|
+
)
|
63
|
+
ms = MessageSend.new(line,
|
64
|
+
Nothing.new,
|
65
|
+
Identifier.new(line, "meta:"),
|
66
|
+
MessageArgs.new(line, meta))
|
67
|
+
ms.bytecode(g)
|
68
|
+
g.pop
|
69
|
+
end
|
70
|
+
|
71
|
+
# defines a class method names "new:foo:" if we're defining a
|
72
|
+
# method named e.g. "initialize:foo:" (a constructor method).
|
73
|
+
def define_constructor_class_method(g)
|
74
|
+
method_ident = Rubinius::AST::StringLiteral.new(@line, @name.to_s[11..-1])
|
75
|
+
ms = MessageSend.new(@line,
|
76
|
+
Rubinius::AST::Self.new(@line),
|
77
|
+
Identifier.new(@line, "define_constructor_class_method:"),
|
78
|
+
MessageArgs.new(@line, method_ident))
|
79
|
+
ms.bytecode(g)
|
80
|
+
end
|
81
|
+
|
82
|
+
def define_method_missing(g)
|
83
|
+
MessageSend.new(@line,
|
84
|
+
Rubinius::AST::Self.new(@line),
|
85
|
+
Identifier.new(@line, "define_forward_method_missing"),
|
86
|
+
MessageArgs.new(@line)).bytecode(g)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
SymbolLiteral = Rubinius::AST::SymbolLiteral
|
91
|
+
|
92
|
+
class Nothing
|
93
|
+
def bytecode(g)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class StackLocal
|
98
|
+
def set!(g)
|
99
|
+
# expects value to be on top of stack
|
100
|
+
@local = g.new_stack_local
|
101
|
+
g.set_stack_local @local
|
102
|
+
end
|
103
|
+
|
104
|
+
def bytecode(g)
|
105
|
+
g.push_stack_local @local
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
class MethodArgs < Rubinius::AST::FormalArguments
|
110
|
+
def initialize(line, *args)
|
111
|
+
super(line, args.map(&:to_sym), nil, nil)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Fancy
|
2
|
+
class AST
|
3
|
+
|
4
|
+
class RangeLiteral < Node
|
5
|
+
attr_accessor :from, :to
|
6
|
+
def initialize(line, from, to)
|
7
|
+
super(line)
|
8
|
+
@from = from
|
9
|
+
@to = to
|
10
|
+
end
|
11
|
+
|
12
|
+
def bytecode(g)
|
13
|
+
ms = MessageSend.new(@line,
|
14
|
+
Identifier.new(@line, "Range"),
|
15
|
+
Identifier.new(@line, "new:to:"),
|
16
|
+
MessageArgs.new(@line, @from, @to))
|
17
|
+
ms.bytecode(g)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class Fancy
|
2
|
+
class AST
|
3
|
+
|
4
|
+
class Require < Node
|
5
|
+
def initialize(line, string)
|
6
|
+
super(line)
|
7
|
+
@string = string
|
8
|
+
end
|
9
|
+
|
10
|
+
def bytecode(g)
|
11
|
+
Rubinius::AST::Self.new(1).bytecode(g)
|
12
|
+
@string.bytecode(g)
|
13
|
+
pos(g)
|
14
|
+
g.allow_private
|
15
|
+
g.send :fancy_require, 1, false
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Fancy
|
2
|
+
class AST
|
3
|
+
|
4
|
+
class Return < Node
|
5
|
+
def initialize(line, expr)
|
6
|
+
super(line)
|
7
|
+
@expr = expr
|
8
|
+
end
|
9
|
+
|
10
|
+
def bytecode(g)
|
11
|
+
@expr.bytecode(g)
|
12
|
+
g.raise_return
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class ReturnLocal < Node
|
17
|
+
def initialize(line, expr)
|
18
|
+
super(line)
|
19
|
+
@expr = expr
|
20
|
+
end
|
21
|
+
|
22
|
+
def bytecode(g)
|
23
|
+
@expr.bytecode(g)
|
24
|
+
g.ret
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|