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,34 @@
|
|
1
|
+
class Object
|
2
|
+
define_method("ruby:with_block:") do |method, block|
|
3
|
+
self.send(method, &block)
|
4
|
+
end
|
5
|
+
|
6
|
+
define_method("ruby:args:with_block:") do |method, args, block|
|
7
|
+
self.send(method, *args, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
define_method("ruby:args:") do |method, args|
|
11
|
+
self.send(method, *args)
|
12
|
+
end
|
13
|
+
|
14
|
+
define_method(":to_s") do
|
15
|
+
return self.to_s
|
16
|
+
end
|
17
|
+
|
18
|
+
# HACK:
|
19
|
+
# When we define private/protected/public methods, we usually use
|
20
|
+
# Module#private, Module#protected & Module#public methods to set the
|
21
|
+
# access of that method.
|
22
|
+
# But in cases where we define methods not within a class
|
23
|
+
# definition, this fails. To make it work, we define these. Kinda
|
24
|
+
# stupid, i know, but oh well. Maybe need to fix this in the future.
|
25
|
+
def public
|
26
|
+
Rubinius::VariableScope.of_sender.method_visibility = nil
|
27
|
+
end
|
28
|
+
def private
|
29
|
+
Rubinius::VariableScope.of_sender.method_visibility = :private
|
30
|
+
end
|
31
|
+
def protected
|
32
|
+
Rubinius::VariableScope.of_sender.method_visibility = :protected
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class Fancy
|
2
|
+
class AST
|
3
|
+
class StringHelper
|
4
|
+
def self.unescape_string(str)
|
5
|
+
str.gsub("\\r", "\r").gsub("\\t", "\t").gsub("\\n", "\n").gsub("\\v", "\v").gsub("\\b", "\b").
|
6
|
+
gsub("\\f", "\f").gsub("\\a", "\a").gsub("\\\\", "\\").gsub("\\?", "\?").gsub("\\'", "\'").gsub('\\"', '\"').gsub("\\\"", "\"")
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
data/boot/load.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
class Fancy
|
2
|
+
# This version of Fancy::CodeLoader is used only for bootstrapping
|
3
|
+
# This constant needs to be overloaded with fancy version of this.
|
4
|
+
class BootstrapCodeLoader
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def path_stack
|
8
|
+
@path_stack ||= []
|
9
|
+
end
|
10
|
+
|
11
|
+
def file_stack
|
12
|
+
@file_stack ||= []
|
13
|
+
end
|
14
|
+
|
15
|
+
# This method may return an Fancy::Script object with source
|
16
|
+
# information.
|
17
|
+
def current_file(compiled_from)
|
18
|
+
# compiled_from is the filename captured at compile time.
|
19
|
+
# ie. the location where the fancy file was compiled from.
|
20
|
+
|
21
|
+
# file_stack.last is the filename being loaded
|
22
|
+
# possibly from a different location than it was compiled from
|
23
|
+
|
24
|
+
# Only return the current file being loaded.
|
25
|
+
file_stack.last
|
26
|
+
end
|
27
|
+
alias_method "current_file:", :current_file
|
28
|
+
|
29
|
+
def load_compiled_file(file, find_file = nil)
|
30
|
+
path_stack.push(File.expand_path(File.dirname(file), path_stack.last))
|
31
|
+
|
32
|
+
file = File.expand_path(File.basename(file), path_stack.last)
|
33
|
+
|
34
|
+
file = file + "c" if file =~ /.fy$/
|
35
|
+
file = file+".fyc" unless file =~ /\.fyc$/
|
36
|
+
raise "File not found #{file}" unless File.exist?(file)
|
37
|
+
|
38
|
+
cl = Rubinius::CodeLoader.new(file)
|
39
|
+
cm = cl.load_compiled_file(file, 0)
|
40
|
+
|
41
|
+
source = file.sub(/\.fyc/, ".fy")
|
42
|
+
|
43
|
+
file_stack.push(source)
|
44
|
+
|
45
|
+
script = cm.create_script(false)
|
46
|
+
script.file_path = source
|
47
|
+
|
48
|
+
MAIN.__send__ :__script__
|
49
|
+
|
50
|
+
file_stack.pop
|
51
|
+
path_stack.pop
|
52
|
+
end
|
53
|
+
|
54
|
+
alias_method "require:", :load_compiled_file
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
CodeLoader = BootstrapCodeLoader
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
if __FILE__ == $0
|
63
|
+
require File.expand_path("fancy_ext", File.dirname(__FILE__))
|
64
|
+
# Load files up to the --
|
65
|
+
if dash = ARGV.index("--")
|
66
|
+
load = ARGV.shift(dash + 1)
|
67
|
+
load.pop
|
68
|
+
else
|
69
|
+
load = ARGV.shift(ARGV.length)
|
70
|
+
end
|
71
|
+
load.each { |f| Fancy::CodeLoader.load_compiled_file File.expand_path(f) }
|
72
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
This directory contains all the code for compiling Fancy source files
|
2
|
+
(.fy) to Rubinius bytecode files (.fyc).
|
3
|
+
|
4
|
+
The compiler implementation is in the compiler/ directory.
|
5
|
+
|
6
|
+
The fancy_ext/ directory contains a small amount of methods defined in
|
7
|
+
Ruby to existing classes in Rubinius to allow Fancy to run on rbx. See
|
8
|
+
fancy_ext.rb for more information.
|
9
|
+
|
10
|
+
The parser/ directory contains the bison & flex written parser and
|
11
|
+
lexer which are used as a C-extension in rbx to generate the
|
12
|
+
appropriate AST node instances in parser/parser.rb.
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env rbx
|
2
|
+
|
3
|
+
# A Fancy to rbx bytecode compiler.
|
4
|
+
#
|
5
|
+
# This compiler is written in Ruby, because it's easier to start
|
6
|
+
# writing a working compiler with the given tools of Rubinius that are
|
7
|
+
# written in Ruby than porting all that code to Fancy.
|
8
|
+
#
|
9
|
+
# Once we can compile Fancy to Rubinius we will reimplement the
|
10
|
+
# compiler in Fancy and can still reuse the rubinius compiler
|
11
|
+
# toolchain for actual bytecode file generation.
|
12
|
+
#
|
13
|
+
# This program is indended to be run using rbx.
|
14
|
+
|
15
|
+
base = File.dirname(__FILE__)
|
16
|
+
require base + '/compiler/compiler'
|
17
|
+
require base + '/compiler/stages'
|
18
|
+
require base + '/compiler/ast'
|
19
|
+
require base + '/parser'
|
20
|
+
|
21
|
+
if __FILE__ == $0
|
22
|
+
require base + '/compiler/command'
|
23
|
+
Fancy::Compiler::Command.run ARGV
|
24
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
base = File.dirname(__FILE__)
|
2
|
+
|
3
|
+
require base + '/ast/node'
|
4
|
+
require base + '/ast/script'
|
5
|
+
require base + '/ast/expression_list'
|
6
|
+
require base + '/ast/message_send'
|
7
|
+
require base + '/ast/ruby_args'
|
8
|
+
require base + '/ast/identifier'
|
9
|
+
require base + '/ast/string_literal'
|
10
|
+
require base + '/ast/method_def'
|
11
|
+
require base + '/ast/singleton_method_def'
|
12
|
+
require base + '/ast/require'
|
13
|
+
require base + '/ast/class_def'
|
14
|
+
require base + '/ast/block'
|
15
|
+
require base + '/ast/assign'
|
16
|
+
require base + '/ast/array_literal'
|
17
|
+
require base + '/ast/tuple_literal'
|
18
|
+
require base + '/ast/range_literal'
|
19
|
+
require base + '/ast/hash_literal'
|
20
|
+
require base + '/ast/super'
|
21
|
+
require base + '/ast/try_catch_block'
|
22
|
+
require base + '/ast/return'
|
23
|
+
require base + '/ast/match'
|
@@ -0,0 +1,11 @@
|
|
1
|
+
This directory contains all the AST Node classes used by the
|
2
|
+
compiler. Most of them inherit from an equivalent Ruby Node class
|
3
|
+
defined in rbx's lib/compiler/ directory.
|
4
|
+
|
5
|
+
Each node class has a bytecode() method in which the actual bytecode
|
6
|
+
generation is done by calling generator methods on the generator
|
7
|
+
object, that is passed in as an argument.
|
8
|
+
|
9
|
+
If there's no bytecode() method defined in a node class, this just
|
10
|
+
means, we're simply using the bytecode() method of the superclass (the
|
11
|
+
one defined by rbx's compiler library).
|
@@ -0,0 +1,57 @@
|
|
1
|
+
class Fancy
|
2
|
+
class AST
|
3
|
+
|
4
|
+
class Assignment < Node
|
5
|
+
def initialize(line, ident, value)
|
6
|
+
super(line)
|
7
|
+
@ident = ident
|
8
|
+
@value = value
|
9
|
+
end
|
10
|
+
|
11
|
+
def bytecode(g)
|
12
|
+
if @ident.constant?
|
13
|
+
Rubinius::AST::ConstantAssignment.new(line, @ident.name, @value).bytecode(g)
|
14
|
+
elsif @ident.instance_variable?
|
15
|
+
Rubinius::AST::InstanceVariableAssignment.new(line, @ident.name, @value).
|
16
|
+
bytecode(g)
|
17
|
+
elsif @ident.class_variable?
|
18
|
+
Rubinius::AST::ClassVariableAssignment.new(line, @ident.name, @value).
|
19
|
+
bytecode(g)
|
20
|
+
else
|
21
|
+
Rubinius::AST::LocalVariableAssignment.new(line, @ident.name, @value).
|
22
|
+
bytecode(g)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class MultipleAssignment < Node
|
28
|
+
|
29
|
+
class MultipleAssignmentExpr < Node
|
30
|
+
def initialize(line)
|
31
|
+
super(line)
|
32
|
+
end
|
33
|
+
def bytecode(g)
|
34
|
+
g.shift_array
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def initialize(line, idents, values)
|
39
|
+
super(line)
|
40
|
+
@idents = idents
|
41
|
+
@values = values
|
42
|
+
end
|
43
|
+
|
44
|
+
def bytecode(g)
|
45
|
+
@values.each do |val|
|
46
|
+
val.bytecode(g)
|
47
|
+
end
|
48
|
+
g.make_array @values.size
|
49
|
+
@idents.each do |ident|
|
50
|
+
Assignment.new(@line, ident, MultipleAssignmentExpr.new(@line)).bytecode(g)
|
51
|
+
g.pop
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
class Fancy
|
2
|
+
class AST
|
3
|
+
|
4
|
+
class BlockLiteral < Rubinius::AST::Iter
|
5
|
+
def initialize(line, args, body)
|
6
|
+
@args = args
|
7
|
+
body = body || Rubinius::AST::NilLiteral.new(line)
|
8
|
+
|
9
|
+
if body.empty?
|
10
|
+
body.unshift_expression Rubinius::AST::NilLiteral.new(line)
|
11
|
+
end
|
12
|
+
|
13
|
+
super(line, args, body)
|
14
|
+
args.create_locals(self)
|
15
|
+
|
16
|
+
if args.total_args == 0
|
17
|
+
@arguments.prelude = nil
|
18
|
+
end
|
19
|
+
if args.total_args > 1
|
20
|
+
@arguments.prelude = :multi
|
21
|
+
end
|
22
|
+
@arguments.required_args = args.required_args
|
23
|
+
end
|
24
|
+
|
25
|
+
def bytecode(g)
|
26
|
+
#docstring = body.shift_docstring
|
27
|
+
super(g)
|
28
|
+
#MethodDef.set_docstring(g, docstring, line, @args.args)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class BlockArgs < Node
|
33
|
+
attr_accessor :args, :block
|
34
|
+
|
35
|
+
def initialize(line, *args)
|
36
|
+
super(line)
|
37
|
+
@args = args.map{|a| a.name.to_sym}
|
38
|
+
end
|
39
|
+
|
40
|
+
def bytecode(g)
|
41
|
+
if @args.size > 1
|
42
|
+
@args.each_with_index do |a, i|
|
43
|
+
g.shift_array
|
44
|
+
g.set_local i
|
45
|
+
g.pop
|
46
|
+
end
|
47
|
+
else
|
48
|
+
@args.each_with_index do |a, i|
|
49
|
+
g.set_local i
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def total_args
|
55
|
+
@args.size
|
56
|
+
end
|
57
|
+
|
58
|
+
def required_args
|
59
|
+
total_args
|
60
|
+
end
|
61
|
+
|
62
|
+
def create_locals(block)
|
63
|
+
@args.each do |a|
|
64
|
+
block.new_local(a)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class Fancy
|
2
|
+
class AST
|
3
|
+
|
4
|
+
class ClassDef < Rubinius::AST::Class
|
5
|
+
def initialize(line, name, parent, body)
|
6
|
+
if name.kind_of?(Fancy::AST::Identifier)
|
7
|
+
name = name.name
|
8
|
+
end
|
9
|
+
|
10
|
+
super(line, name, parent, body)
|
11
|
+
|
12
|
+
if body.empty?
|
13
|
+
body.unshift_expression Rubinius::AST::NilLiteral.new(line)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def bytecode(g)
|
18
|
+
docstring = body.body.shift_docstring
|
19
|
+
if docstring
|
20
|
+
setdoc = MessageSend.new(line,
|
21
|
+
Identifier.new(line, "Fancy::Documentation"),
|
22
|
+
Identifier.new(line, "for:append:"),
|
23
|
+
MessageArgs.new(line,
|
24
|
+
Rubinius::AST::Self.new(line),
|
25
|
+
docstring))
|
26
|
+
# Replace first string expression to set documentation.
|
27
|
+
body.body.expressions.unshift setdoc
|
28
|
+
end
|
29
|
+
super(g)
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
class Fancy
|
2
|
+
class AST
|
3
|
+
|
4
|
+
class ExpressionList < Node
|
5
|
+
attr_reader :expressions
|
6
|
+
|
7
|
+
def initialize(line, *expressions)
|
8
|
+
super(line)
|
9
|
+
@expressions = expressions
|
10
|
+
end
|
11
|
+
|
12
|
+
def unshift_expression(expression)
|
13
|
+
@expressions.unshift(expression)
|
14
|
+
end
|
15
|
+
|
16
|
+
def add_expression(expression)
|
17
|
+
@expressions << expression
|
18
|
+
end
|
19
|
+
|
20
|
+
def empty?
|
21
|
+
@expressions.empty?
|
22
|
+
end
|
23
|
+
|
24
|
+
def bytecode(g)
|
25
|
+
pos(g)
|
26
|
+
size = @expressions.size
|
27
|
+
@expressions.each do |expr|
|
28
|
+
size -= 1
|
29
|
+
expr.bytecode(g)
|
30
|
+
g.pop if size > 0
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def empty?
|
35
|
+
@expressions.size == 0
|
36
|
+
end
|
37
|
+
|
38
|
+
# This method is only used by Rubinius' compiler classes and
|
39
|
+
# defined to be able to use their bytecode generation toolchain.
|
40
|
+
def strip_arguments
|
41
|
+
[]
|
42
|
+
end
|
43
|
+
|
44
|
+
# If this expression list contains more than one expression
|
45
|
+
# and the first one is an string literal, it'll be used as doc.
|
46
|
+
# This method removes the first documentation string.
|
47
|
+
def shift_docstring
|
48
|
+
if expressions.first.kind_of?(Rubinius::AST::StringLiteral) &&
|
49
|
+
expressions.size > 1
|
50
|
+
expressions.shift
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|