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
data/bin/fancy
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/env rbx
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
base = File.dirname(__FILE__)
|
5
|
+
require File.expand_path("../boot/fancy_ext", base)
|
6
|
+
|
7
|
+
# Use the bootstrapping code loader.
|
8
|
+
require File.expand_path("../boot/load", base)
|
9
|
+
|
10
|
+
do_retry = true
|
11
|
+
begin
|
12
|
+
Fancy::CodeLoader.load_compiled_file File.expand_path("../lib/boot", base)
|
13
|
+
|
14
|
+
# Remove the bootstrapping code loader
|
15
|
+
bcl = Fancy.send :remove_const, :CodeLoader
|
16
|
+
bcl.load_compiled_file File.expand_path("../lib/rbx/code_loader", base)
|
17
|
+
|
18
|
+
# Initialize the load path
|
19
|
+
Fancy::CodeLoader.push_loadpath File.expand_path("../lib", base)
|
20
|
+
|
21
|
+
# Load compiler+eval support
|
22
|
+
Fancy::CodeLoader.load_compiled_file File.expand_path("../lib/eval", base)
|
23
|
+
|
24
|
+
# Run main
|
25
|
+
Fancy::CodeLoader.load_compiled_file File.expand_path("../lib/main", base)
|
26
|
+
|
27
|
+
rescue RuntimeError => e
|
28
|
+
if e.message =~ /File not found (.*)lib\/boot.fyc/
|
29
|
+
if do_retry
|
30
|
+
puts "Fancy hasn't been bootstrapped yet. Doing that now.\n\n"
|
31
|
+
`cd #{base} && rbx -S rake clean && rbx -S rake`
|
32
|
+
do_retry = false
|
33
|
+
retry
|
34
|
+
else
|
35
|
+
raise e
|
36
|
+
end
|
37
|
+
else
|
38
|
+
raise e
|
39
|
+
end
|
40
|
+
end
|
data/bin/fdoc
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/usr/bin/env rbx
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
class Fancy; end
|
5
|
+
class Fancy::Parser; end
|
6
|
+
|
7
|
+
# fdoc is a documentation generator for fancy.
|
8
|
+
# This is a ruby script because we need to setup a hook
|
9
|
+
# BEFORE any fancy code is loaded. So we can create
|
10
|
+
# documentation for Fancy's builtin objects as well.
|
11
|
+
# See fdoc.
|
12
|
+
base = File.expand_path("../boot", File.dirname(__FILE__))
|
13
|
+
require File.expand_path("rbx-compiler/parser/fancy_parser", base)
|
14
|
+
require File.expand_path("rbx-compiler/compiler", base)
|
15
|
+
require File.expand_path("code_loader", base)
|
16
|
+
require File.expand_path("fancy_ext", base)
|
17
|
+
|
18
|
+
Fancy::CodeLoader.load_compiled_file File.expand_path("../lib/rbx/documentation.fyc", base)
|
19
|
+
Fancy::CodeLoader.load_compiled_file File.expand_path("../lib/fdoc_hook.fyc", base)
|
20
|
+
|
21
|
+
Fancy::CodeLoader.load_compiled_file File.expand_path("../lib/rbx.fyc", base)
|
22
|
+
|
23
|
+
Fancy::CodeLoader.load_compiled_file File.expand_path("../lib/fdoc.fyc", base)
|
data/bin/fyi
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env fancy
|
2
|
+
# -*- fancy -*-
|
3
|
+
|
4
|
+
ARGV[1] if_do: |ident| {
|
5
|
+
"Documentation for: '" ++ ident ++ "' :" println;
|
6
|
+
ident includes?: "#" . if_true: {
|
7
|
+
parts = (ident split: "#");
|
8
|
+
obj = (parts[0]) eval;
|
9
|
+
method = obj method: (parts[1]);
|
10
|
+
method documentation println
|
11
|
+
} else: {
|
12
|
+
obj = ident eval;
|
13
|
+
obj documentation println
|
14
|
+
}
|
15
|
+
} else: {
|
16
|
+
["Prints the documentation string for a given object or one if its methods",
|
17
|
+
"Usage:",
|
18
|
+
"fyi [ObjectIdentifier]",
|
19
|
+
"fyi [ObjectIdentifier]#[MethodName]",
|
20
|
+
"",
|
21
|
+
"Example: fyi Array#each:"] println
|
22
|
+
}
|
data/bin/ifancy
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
#!/usr/bin/env fancy
|
2
|
+
# -*- fancy -*-
|
3
|
+
|
4
|
+
require("readline")
|
5
|
+
|
6
|
+
["Welcome to the (still very simple) Fancy REPL",
|
7
|
+
"Fancy " ++ FANCY_VERSION] println
|
8
|
+
|
9
|
+
ARGV rest each: |file| {
|
10
|
+
"LOADING: " ++ file println
|
11
|
+
require: file
|
12
|
+
}
|
13
|
+
|
14
|
+
# handle SIGINT
|
15
|
+
trap("INT") {
|
16
|
+
"Quitting." println
|
17
|
+
System exit
|
18
|
+
}
|
19
|
+
|
20
|
+
Console newline;
|
21
|
+
|
22
|
+
def double_or_empty?: line {
|
23
|
+
(line =~ /^\s*$/) or: (Readline HISTORY to_a[-2] == line)
|
24
|
+
}
|
25
|
+
|
26
|
+
|
27
|
+
try {
|
28
|
+
bnd = binding()
|
29
|
+
|
30
|
+
{ Readline readline(">> ", true) } while_do: |line| {
|
31
|
+
|
32
|
+
double_or_empty?: line . if_true: {
|
33
|
+
Readline::HISTORY pop()
|
34
|
+
}
|
35
|
+
|
36
|
+
line =~ /^\s*$/ if_false: {
|
37
|
+
try {
|
38
|
+
Fancy eval: line binding: bnd . inspect println
|
39
|
+
} catch Exception => e {
|
40
|
+
e message() println
|
41
|
+
}
|
42
|
+
}
|
43
|
+
}
|
44
|
+
} catch Interrupt => e {
|
45
|
+
System exit
|
46
|
+
}
|
data/boot/README
ADDED
@@ -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.
|
data/boot/code_loader.rb
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
#!/usr/bin/env rbx
|
2
|
+
|
3
|
+
base = File.dirname(__FILE__) + "/"
|
4
|
+
|
5
|
+
# load in fancy specific extensions
|
6
|
+
require base + "fancy_ext"
|
7
|
+
|
8
|
+
require base + "/rbx-compiler/compiler"
|
9
|
+
require base + "/rbx-compiler/compiler/command"
|
10
|
+
|
11
|
+
# only used for bin/fdoc at the moment
|
12
|
+
# this is just temporary and was copied from and old version
|
13
|
+
# of rbx/fancy_code_loader.rb
|
14
|
+
|
15
|
+
class Fancy
|
16
|
+
class CodeLoader
|
17
|
+
class << self
|
18
|
+
SOURCE_FILE_EXTENSION = "fy"
|
19
|
+
COMPILED_FILE_EXTENSION = "fyc"
|
20
|
+
|
21
|
+
@@load_path = []
|
22
|
+
@@compiled = {}
|
23
|
+
@@loaded = {}
|
24
|
+
@@current_dir = []
|
25
|
+
|
26
|
+
def push_loadpath path
|
27
|
+
@@load_path << path unless @@load_path.include? path
|
28
|
+
end
|
29
|
+
|
30
|
+
# Throws an exception for a given filename that wasn't found and
|
31
|
+
# thus could not be loaded.
|
32
|
+
def load_error(filename)
|
33
|
+
raise "LoadError: Can't find file: #{filename}"
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns the name of a file or nil, if it doesn't exist.
|
37
|
+
# Might append a ".fy" extension, if it's missing for the given
|
38
|
+
# filename.
|
39
|
+
def find_file(filename)
|
40
|
+
filename_with_ext = filename + ".#{SOURCE_FILE_EXTENSION}"
|
41
|
+
if !File.exists?(filename) || File.directory?(filename)
|
42
|
+
return filename_with_ext if File.exists? filename_with_ext
|
43
|
+
else
|
44
|
+
return filename
|
45
|
+
end
|
46
|
+
nil
|
47
|
+
end
|
48
|
+
|
49
|
+
# Finds a file in a given path and returns the filename including
|
50
|
+
# the path.
|
51
|
+
def find_file_in_path(file, path)
|
52
|
+
find_file(path + "/" + file)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Tries to find a file with a given name in the LOADPATH array
|
56
|
+
# (all paths that have been seen while loading other files so
|
57
|
+
# far), starting with the @current_dir (the directory, the current
|
58
|
+
# running fancy source file is in).
|
59
|
+
def filename_for(filename)
|
60
|
+
if f = find_file(filename)
|
61
|
+
return f
|
62
|
+
else
|
63
|
+
if @@current_dir.last && f = find_file_in_path(filename, @@current_dir.last)
|
64
|
+
return f
|
65
|
+
end
|
66
|
+
@@load_path.each do |p|
|
67
|
+
begin
|
68
|
+
if f = find_file_in_path(filename, p)
|
69
|
+
return f
|
70
|
+
end
|
71
|
+
rescue
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
load_error filename
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns the source filename for a given filename.
|
79
|
+
# E.g. "foo.fyc" => "foo.fy"
|
80
|
+
def source_filename_for(filename)
|
81
|
+
if filename =~ /.compiled.#{COMPILED_FILE_EXTENSION}$/
|
82
|
+
return filename[0..-14]
|
83
|
+
elsif filename =~ /.#{COMPILED_FILE_EXTENSION}$/
|
84
|
+
return filename[0..-2]
|
85
|
+
end
|
86
|
+
filename
|
87
|
+
end
|
88
|
+
|
89
|
+
# Returns the compiled filename for a given filename.
|
90
|
+
# E.g. "foo.fy" => "foo.fyc", "foo" => "foo.compiled.rbc"
|
91
|
+
def compiled_filename_for(filename)
|
92
|
+
if filename =~ /.#{COMPILED_FILE_EXTENSION}$/
|
93
|
+
return filename
|
94
|
+
end
|
95
|
+
if filename =~ /\.#{SOURCE_FILE_EXTENSION}$/
|
96
|
+
return filename + "c"
|
97
|
+
else
|
98
|
+
return filename + ".compiled.#{COMPILED_FILE_EXTENSION}"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# Optionally compiles a file, if not done yet and returns the
|
103
|
+
# compiled file's name.
|
104
|
+
def optionally_compile_file(f)
|
105
|
+
source_filename = source_filename_for(f)
|
106
|
+
filename = filename_for(source_filename)
|
107
|
+
compiled_file = compiled_filename_for(filename)
|
108
|
+
unless @@compiled[filename]
|
109
|
+
if !File.exists?(compiled_file) ||
|
110
|
+
File.stat(compiled_file).mtime < File.stat(filename).mtime
|
111
|
+
Compiler.compile_fancy_file filename, nil, 1, false
|
112
|
+
else
|
113
|
+
@@compiled[filename] = true
|
114
|
+
end
|
115
|
+
end
|
116
|
+
compiled_file
|
117
|
+
end
|
118
|
+
|
119
|
+
# Loads a compiled fancy bytecode file.
|
120
|
+
# If +find_file+ is set to false, it will just use the given
|
121
|
+
# filename without looking up the file in the LOADPATH.
|
122
|
+
def load_compiled_file(filename, find_file = true)
|
123
|
+
if find_file
|
124
|
+
filename = filename_for(filename)
|
125
|
+
file = compiled_filename_for(filename)
|
126
|
+
end
|
127
|
+
|
128
|
+
file = optionally_compile_file(file)
|
129
|
+
|
130
|
+
unless @@loaded[file]
|
131
|
+
unless File.exists? file
|
132
|
+
load_error file
|
133
|
+
end
|
134
|
+
|
135
|
+
dirname = File.dirname(file)
|
136
|
+
push_loadpath dirname
|
137
|
+
@@current_dir.push dirname
|
138
|
+
@@loaded[file] = true
|
139
|
+
|
140
|
+
cl = Rubinius::CodeLoader.new(file)
|
141
|
+
cm = cl.load_compiled_file(file, 0)
|
142
|
+
|
143
|
+
script = cm.create_script(false)
|
144
|
+
script.file_path = filename
|
145
|
+
|
146
|
+
MAIN.__send__ :__script__
|
147
|
+
|
148
|
+
@@current_dir.pop
|
149
|
+
end
|
150
|
+
end
|
151
|
+
alias_method "require:", :load_compiled_file
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
if $0 == __FILE__
|
157
|
+
# load & run file
|
158
|
+
file = ARGV.shift
|
159
|
+
raise "Expected a fancy file to load" unless file
|
160
|
+
if File.exists? file
|
161
|
+
Fancy::CodeLoader.load_compiled_file file
|
162
|
+
else
|
163
|
+
Fancy::CodeLoader.load_compiled_file(base + "../lib/main.fyc")
|
164
|
+
end
|
165
|
+
end
|
data/boot/compile.fy
ADDED
data/boot/fancy_ext.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# The fancy_ext directory contains Rubinius-specific code (mostly
|
2
|
+
# extension methods) for existing classes that need to be defined in
|
3
|
+
# Ruby in order for Fancy to work correctly on rbx.
|
4
|
+
# The amount of code should be kept as small as possible, as we want
|
5
|
+
# to write as much in Fancy as possible.
|
6
|
+
|
7
|
+
base = File.dirname(__FILE__) + "/fancy_ext/"
|
8
|
+
require base + "kernel"
|
9
|
+
require base + "module"
|
10
|
+
require base + "object"
|
11
|
+
require base + "block_env"
|
12
|
+
require base + "class"
|
13
|
+
require base + "string_helper"
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# in Fancy we use the BlockEnvironment as Block
|
2
|
+
Block = Rubinius::BlockEnvironment
|
3
|
+
|
4
|
+
class Block
|
5
|
+
define_method("while_true:") do |block|
|
6
|
+
while tmp = self.call
|
7
|
+
block.call(tmp)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# call without arguments
|
12
|
+
alias_method :":call", :call
|
13
|
+
|
14
|
+
define_method("call:") do |args|
|
15
|
+
if args.first.is_a?(Array) && args.size == 1
|
16
|
+
call args.first
|
17
|
+
else
|
18
|
+
call *args
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
define_method("call_with_receiver:") do |obj|
|
23
|
+
call_under obj, method.scope
|
24
|
+
end
|
25
|
+
|
26
|
+
define_method("call:with_receiver:") do |args, obj|
|
27
|
+
call_under obj, method.scope, *args
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class Class
|
2
|
+
# the define_constructor_class_method: method defines a constructor
|
3
|
+
# class method.
|
4
|
+
# e.g. for an instance method named "initialize:foo:" we'll define a class
|
5
|
+
# method named "new:foo:" which creates a new instance of the class
|
6
|
+
# (via allocate) & call the "initialize:foo:" method on it, before
|
7
|
+
# returning the new instance.
|
8
|
+
# NOTE:
|
9
|
+
# the method_name argument to "define_constructor_class_method:"
|
10
|
+
# contains only the rest of the method name, not including the
|
11
|
+
# "initialize:" or "new:", so we'll have to prepend it ourselves
|
12
|
+
define_method("define_constructor_class_method:") do |method_name|
|
13
|
+
self.metaclass.send(:define_method, "new:" + method_name) do |*args|
|
14
|
+
obj = self.allocate
|
15
|
+
obj.send("initialize:" + method_name, *args)
|
16
|
+
return obj
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
define_method(":define_forward_method_missing") do
|
21
|
+
define_method("method_missing") do |method_name, *args|
|
22
|
+
self.send("unknown_message:with_params:", method_name, args)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Kernel
|
2
|
+
|
3
|
+
alias_method :":metaclass", :metaclass
|
4
|
+
|
5
|
+
def fancy_require(file, compile = false)
|
6
|
+
if compile
|
7
|
+
file = Fancy::CodeLoader.compile_file! file
|
8
|
+
end
|
9
|
+
find_file = !compile
|
10
|
+
Fancy::CodeLoader.load_compiled_file file, find_file
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
class Module
|
2
|
+
|
3
|
+
# Fancy version does not restricts to only modules.
|
4
|
+
define_method :"include:" do |modules|
|
5
|
+
modules = [modules] unless modules.kind_of?(Array)
|
6
|
+
modules.reverse_each do |mod|
|
7
|
+
mod.send :"append_features:", self
|
8
|
+
mod.send :included, self
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# Fancy version does not restricts to only modules.
|
13
|
+
###
|
14
|
+
#
|
15
|
+
# Called when this Module is being included in another Module.
|
16
|
+
# This may be overridden for custom behaviour. The default
|
17
|
+
# is to add constants, instance methods and module variables
|
18
|
+
# of this Module and all Modules that this one includes to +klass+.
|
19
|
+
#
|
20
|
+
# See also #include.
|
21
|
+
#
|
22
|
+
define_method :"append_features:" do |klass|
|
23
|
+
# check other.frozen
|
24
|
+
# taint other from self
|
25
|
+
|
26
|
+
insert_at = klass
|
27
|
+
mod = self
|
28
|
+
changed = false
|
29
|
+
|
30
|
+
while mod
|
31
|
+
|
32
|
+
# Check for a cyclic include
|
33
|
+
if mod == klass
|
34
|
+
raise ArgumentError, "cyclic include detected"
|
35
|
+
end
|
36
|
+
|
37
|
+
# Try and detect check_mod in klass's heirarchy, and where.
|
38
|
+
#
|
39
|
+
# I (emp) tried to use Module#< here, but we need to also know
|
40
|
+
# where in the heirarchy the module is to change the insertion point.
|
41
|
+
# Since Module#< doesn't report that, we're going to just search directly.
|
42
|
+
#
|
43
|
+
superclass_seen = false
|
44
|
+
add = true
|
45
|
+
|
46
|
+
k = klass.direct_superclass
|
47
|
+
while k
|
48
|
+
if k.kind_of? Rubinius::IncludedModule
|
49
|
+
# Oh, we found it.
|
50
|
+
if k == mod
|
51
|
+
# ok, if we're still within the directly included modules
|
52
|
+
# of klass, then put future things after mod, not at the
|
53
|
+
# beginning.
|
54
|
+
insert_at = k unless superclass_seen
|
55
|
+
add = false
|
56
|
+
break
|
57
|
+
end
|
58
|
+
else
|
59
|
+
superclass_seen = true
|
60
|
+
end
|
61
|
+
|
62
|
+
k = k.direct_superclass
|
63
|
+
end
|
64
|
+
|
65
|
+
if add
|
66
|
+
if mod.kind_of? Rubinius::IncludedModule
|
67
|
+
original_mod = mod.module
|
68
|
+
else
|
69
|
+
original_mod = mod
|
70
|
+
end
|
71
|
+
|
72
|
+
im = Rubinius::IncludedModule.new(original_mod).attach_to insert_at
|
73
|
+
insert_at = im
|
74
|
+
|
75
|
+
changed = true
|
76
|
+
end
|
77
|
+
|
78
|
+
mod = mod.direct_superclass
|
79
|
+
end
|
80
|
+
|
81
|
+
if changed
|
82
|
+
method_table.each do |meth, obj, vis|
|
83
|
+
Rubinius::VM.reset_method_cache meth
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
return self
|
88
|
+
end
|
89
|
+
end
|