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.
Files changed (242) hide show
  1. data/AUTHORS +7 -0
  2. data/LICENSE +19 -0
  3. data/README +173 -0
  4. data/Rakefile +255 -0
  5. data/bin/fancy +40 -0
  6. data/bin/fdoc +23 -0
  7. data/bin/fyi +22 -0
  8. data/bin/ifancy +46 -0
  9. data/boot/README +12 -0
  10. data/boot/code_loader.rb +165 -0
  11. data/boot/compile.fy +3 -0
  12. data/boot/fancy_ext.rb +13 -0
  13. data/boot/fancy_ext/block_env.rb +29 -0
  14. data/boot/fancy_ext/class.rb +26 -0
  15. data/boot/fancy_ext/kernel.rb +12 -0
  16. data/boot/fancy_ext/module.rb +89 -0
  17. data/boot/fancy_ext/object.rb +34 -0
  18. data/boot/fancy_ext/string_helper.rb +10 -0
  19. data/boot/load.rb +72 -0
  20. data/boot/rbx-compiler/README +12 -0
  21. data/boot/rbx-compiler/compiler.rb +24 -0
  22. data/boot/rbx-compiler/compiler/ast.rb +23 -0
  23. data/boot/rbx-compiler/compiler/ast/README +11 -0
  24. data/boot/rbx-compiler/compiler/ast/array_literal.rb +13 -0
  25. data/boot/rbx-compiler/compiler/ast/assign.rb +57 -0
  26. data/boot/rbx-compiler/compiler/ast/block.rb +70 -0
  27. data/boot/rbx-compiler/compiler/ast/class_def.rb +35 -0
  28. data/boot/rbx-compiler/compiler/ast/expression_list.rb +57 -0
  29. data/boot/rbx-compiler/compiler/ast/hash_literal.rb +11 -0
  30. data/boot/rbx-compiler/compiler/ast/identifier.rb +120 -0
  31. data/boot/rbx-compiler/compiler/ast/match.rb +81 -0
  32. data/boot/rbx-compiler/compiler/ast/message_send.rb +71 -0
  33. data/boot/rbx-compiler/compiler/ast/method_def.rb +116 -0
  34. data/boot/rbx-compiler/compiler/ast/node.rb +6 -0
  35. data/boot/rbx-compiler/compiler/ast/range_literal.rb +22 -0
  36. data/boot/rbx-compiler/compiler/ast/require.rb +20 -0
  37. data/boot/rbx-compiler/compiler/ast/return.rb +29 -0
  38. data/boot/rbx-compiler/compiler/ast/ruby_args.rb +35 -0
  39. data/boot/rbx-compiler/compiler/ast/script.rb +56 -0
  40. data/boot/rbx-compiler/compiler/ast/singleton_method_def.rb +39 -0
  41. data/boot/rbx-compiler/compiler/ast/string_literal.rb +14 -0
  42. data/boot/rbx-compiler/compiler/ast/super.rb +25 -0
  43. data/boot/rbx-compiler/compiler/ast/try_catch_block.rb +220 -0
  44. data/boot/rbx-compiler/compiler/ast/tuple_literal.rb +33 -0
  45. data/boot/rbx-compiler/compiler/command.rb +39 -0
  46. data/boot/rbx-compiler/compiler/compiler.rb +83 -0
  47. data/boot/rbx-compiler/compiler/stages.rb +99 -0
  48. data/boot/rbx-compiler/parser.rb +2 -0
  49. data/boot/rbx-compiler/parser/README +15 -0
  50. data/boot/rbx-compiler/parser/Rakefile +54 -0
  51. data/boot/rbx-compiler/parser/extconf.rb +3 -0
  52. data/boot/rbx-compiler/parser/fancy_parser.bundle +0 -0
  53. data/boot/rbx-compiler/parser/fancy_parser.c +46 -0
  54. data/boot/rbx-compiler/parser/fancy_parser.h +8 -0
  55. data/boot/rbx-compiler/parser/lexer.lex +180 -0
  56. data/boot/rbx-compiler/parser/parser.rb +356 -0
  57. data/boot/rbx-compiler/parser/parser.y +711 -0
  58. data/boot/rsexp_pretty_printer.rb +76 -0
  59. data/doc/api/fancy.css +93 -0
  60. data/doc/api/fancy.jsonp +1 -0
  61. data/doc/api/fdoc.js +187 -0
  62. data/doc/api/index.html +57 -0
  63. data/doc/api/underscore-min.js +18 -0
  64. data/doc/features.md +228 -0
  65. data/examples/argv.fy +8 -0
  66. data/examples/arithmetic.fy +7 -0
  67. data/examples/armstrong_numbers.fy +33 -0
  68. data/examples/array.fy +52 -0
  69. data/examples/blocks.fy +15 -0
  70. data/examples/boolean.fy +24 -0
  71. data/examples/call_with_receiver.fy +9 -0
  72. data/examples/class.fy +68 -0
  73. data/examples/closures.fy +24 -0
  74. data/examples/constant_access.fy +15 -0
  75. data/examples/default_args.fy +17 -0
  76. data/examples/define_methods.fy +15 -0
  77. data/examples/documentation.fy +57 -0
  78. data/examples/documentation_formatters.fy +25 -0
  79. data/examples/echo.fy +16 -0
  80. data/examples/empty_catch.fy +4 -0
  81. data/examples/exception.fy +9 -0
  82. data/examples/factorial.fy +12 -0
  83. data/examples/fibonacci.fy +16 -0
  84. data/examples/files.fy +23 -0
  85. data/examples/finally.fy +5 -0
  86. data/examples/game_of_life.fy +148 -0
  87. data/examples/hashes.fy +7 -0
  88. data/examples/hello_world.fy +6 -0
  89. data/examples/html_generator.fy +54 -0
  90. data/examples/implicit_return.fy +3 -0
  91. data/examples/matchers.fy +6 -0
  92. data/examples/methods.fy +29 -0
  93. data/examples/nested_classes.fy +27 -0
  94. data/examples/nested_try.fy +9 -0
  95. data/examples/numbers.fy +12 -0
  96. data/examples/pattern_matching.fy +40 -0
  97. data/examples/person.fy +65 -0
  98. data/examples/project-euler/01.fy +8 -0
  99. data/examples/project-euler/02.fy +21 -0
  100. data/examples/project-euler/28.fy +33 -0
  101. data/examples/rbx/and_or.fy +7 -0
  102. data/examples/rbx/blocks.fy +22 -0
  103. data/examples/rbx/classes.fy +32 -0
  104. data/examples/rbx/hello.fy +8 -0
  105. data/examples/rbx/include.fy +12 -0
  106. data/examples/rbx/inherit.fy +11 -0
  107. data/examples/rbx/methods.fy +15 -0
  108. data/examples/rbx/nested_classes.fy +9 -0
  109. data/examples/rbx/require.fy +3 -0
  110. data/examples/rbx/strings.fy +5 -0
  111. data/examples/regex.fy +7 -0
  112. data/examples/require.fy +7 -0
  113. data/examples/retry.fy +12 -0
  114. data/examples/return.fy +13 -0
  115. data/examples/ruby_require.fy +7 -0
  116. data/examples/ruby_send.fy +3 -0
  117. data/examples/singleton_methods.fy +21 -0
  118. data/examples/stupid_quicksort.fy +12 -0
  119. data/examples/threads.fy +18 -0
  120. data/examples/tuple.fy +8 -0
  121. data/examples/webserver/webserver.fy +18 -0
  122. data/lib/argv.fy +36 -0
  123. data/lib/array.fy +207 -0
  124. data/lib/block.fy +88 -0
  125. data/lib/boot.fy +41 -0
  126. data/lib/class.fy +106 -0
  127. data/lib/compiler.fy +14 -0
  128. data/lib/compiler/ast.fy +40 -0
  129. data/lib/compiler/ast/assign.fy +96 -0
  130. data/lib/compiler/ast/block.fy +84 -0
  131. data/lib/compiler/ast/class_def.fy +33 -0
  132. data/lib/compiler/ast/expression_list.fy +47 -0
  133. data/lib/compiler/ast/identifier.fy +113 -0
  134. data/lib/compiler/ast/literals.fy +122 -0
  135. data/lib/compiler/ast/match.fy +88 -0
  136. data/lib/compiler/ast/message_send.fy +110 -0
  137. data/lib/compiler/ast/method_def.fy +90 -0
  138. data/lib/compiler/ast/node.fy +7 -0
  139. data/lib/compiler/ast/range.fy +16 -0
  140. data/lib/compiler/ast/require.fy +15 -0
  141. data/lib/compiler/ast/return.fy +23 -0
  142. data/lib/compiler/ast/script.fy +52 -0
  143. data/lib/compiler/ast/singleton_method_def.fy +35 -0
  144. data/lib/compiler/ast/super.fy +17 -0
  145. data/lib/compiler/ast/try_catch.fy +176 -0
  146. data/lib/compiler/ast/tuple_literal.fy +34 -0
  147. data/lib/compiler/command.fy +51 -0
  148. data/lib/compiler/compiler.fy +73 -0
  149. data/lib/compiler/stages.fy +81 -0
  150. data/lib/directory.fy +17 -0
  151. data/lib/documentation.fy +115 -0
  152. data/lib/enumerable.fy +269 -0
  153. data/lib/eval.fy +31 -0
  154. data/lib/fancy_spec.fy +202 -0
  155. data/lib/fdoc.fy +359 -0
  156. data/lib/fdoc_hook.fy +10 -0
  157. data/lib/file.fy +54 -0
  158. data/lib/hash.fy +56 -0
  159. data/lib/main.fy +80 -0
  160. data/lib/method.fy +22 -0
  161. data/lib/nil_class.fy +56 -0
  162. data/lib/number.fy +87 -0
  163. data/lib/object.fy +170 -0
  164. data/lib/package.fy +61 -0
  165. data/lib/package/dependency.fy +24 -0
  166. data/lib/package/installer.fy +180 -0
  167. data/lib/package/specification.fy +55 -0
  168. data/lib/package/uninstaller.fy +15 -0
  169. data/lib/parser.fy +4 -0
  170. data/lib/parser/ext/README +15 -0
  171. data/lib/parser/ext/ext.c +42 -0
  172. data/lib/parser/ext/ext.h +8 -0
  173. data/lib/parser/ext/extconf.rb +3 -0
  174. data/lib/parser/ext/lexer.lex +187 -0
  175. data/lib/parser/ext/parser.y +744 -0
  176. data/lib/parser/methods.fy +297 -0
  177. data/lib/rbx.fy +37 -0
  178. data/lib/rbx/array.fy +237 -0
  179. data/lib/rbx/bignum.fy +23 -0
  180. data/lib/rbx/block.fy +9 -0
  181. data/lib/rbx/class.fy +129 -0
  182. data/lib/rbx/code_loader.fy +192 -0
  183. data/lib/rbx/console.fy +63 -0
  184. data/lib/rbx/directory.fy +46 -0
  185. data/lib/rbx/documentation.fy +64 -0
  186. data/lib/rbx/environment_variables.fy +3 -0
  187. data/lib/rbx/exception.fy +30 -0
  188. data/lib/rbx/false_class.fy +58 -0
  189. data/lib/rbx/fiber.fy +25 -0
  190. data/lib/rbx/file.fy +191 -0
  191. data/lib/rbx/fixnum.fy +25 -0
  192. data/lib/rbx/float.fy +14 -0
  193. data/lib/rbx/hash.fy +38 -0
  194. data/lib/rbx/integer.fy +15 -0
  195. data/lib/rbx/io.fy +30 -0
  196. data/lib/rbx/match_data.fy +9 -0
  197. data/lib/rbx/method.fy +22 -0
  198. data/lib/rbx/name_error.fy +3 -0
  199. data/lib/rbx/no_method_error.fy +15 -0
  200. data/lib/rbx/object.fy +117 -0
  201. data/lib/rbx/range.fy +15 -0
  202. data/lib/rbx/regexp.fy +9 -0
  203. data/lib/rbx/string.fy +63 -0
  204. data/lib/rbx/symbol.fy +12 -0
  205. data/lib/rbx/system.fy +37 -0
  206. data/lib/rbx/tcp_server.fy +6 -0
  207. data/lib/rbx/tcp_socket.fy +7 -0
  208. data/lib/rbx/thread.fy +75 -0
  209. data/lib/rbx/tuple.fy +37 -0
  210. data/lib/set.fy +61 -0
  211. data/lib/stack.fy +51 -0
  212. data/lib/string.fy +58 -0
  213. data/lib/struct.fy +13 -0
  214. data/lib/symbol.fy +23 -0
  215. data/lib/true_class.fy +43 -0
  216. data/lib/tuple.fy +68 -0
  217. data/lib/version.fy +6 -0
  218. data/tests/argv.fy +13 -0
  219. data/tests/array.fy +343 -0
  220. data/tests/assignment.fy +53 -0
  221. data/tests/block.fy +103 -0
  222. data/tests/class.fy +409 -0
  223. data/tests/control_flow.fy +79 -0
  224. data/tests/documentation.fy +24 -0
  225. data/tests/exception.fy +115 -0
  226. data/tests/file.fy +86 -0
  227. data/tests/hash.fy +101 -0
  228. data/tests/method.fy +131 -0
  229. data/tests/nil_class.fy +55 -0
  230. data/tests/number.fy +128 -0
  231. data/tests/object.fy +125 -0
  232. data/tests/parsing/sexp.fy +50 -0
  233. data/tests/pattern_matching.fy +82 -0
  234. data/tests/range.fy +11 -0
  235. data/tests/set.fy +10 -0
  236. data/tests/stack.fy +22 -0
  237. data/tests/string.fy +102 -0
  238. data/tests/symbol.fy +17 -0
  239. data/tests/true_class.fy +63 -0
  240. data/tests/tuple.fy +21 -0
  241. data/tools/fancy-mode.el +63 -0
  242. 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,13 @@
1
+ class Fancy
2
+ class AST
3
+
4
+ class ArrayLiteral < Rubinius::AST::ArrayLiteral
5
+ attr_accessor :array
6
+ def initialize(line, *array)
7
+ super(line, array)
8
+ @array = array
9
+ end
10
+ end
11
+
12
+ end
13
+ end
@@ -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
@@ -0,0 +1,11 @@
1
+ class Fancy
2
+ class AST
3
+
4
+ class HashLiteral < Rubinius::AST::HashLiteral
5
+ def initialize(line, *array)
6
+ super(line, array)
7
+ end
8
+ end
9
+
10
+ end
11
+ end