1 # Implements methods on each Node subclass for generatng bytecode
4 require 'compiler/generator'
9 # The precursor to a CompiledMethod
11 class MethodDescription
12 def initialize(gen_class, locals)
13 @generator = gen_class.new
20 attr_reader :generator, :locals
21 attr_accessor :required, :optional, :name, :args
23 def run(container, body)
25 @required, @optional = container.argument_info
26 @name = container.name
30 desc.kind_of? MethodDescription and @generator == desc.generator
34 @generator.to_cmethod(self)
38 [:method_description, @name, @required, @optional, @generator].inspect
43 # Parent class of all AST classes used by the compiler. Contains utility
44 # classes used by nodes.
48 def show_errors(gen, &block)
49 @compiler.show_errors(gen, &block)
55 MethodDescription.new(@compiler.generator_class, self.locals)
58 def to_description(name = nil)
59 desc = new_description()
60 desc.name = name if name
74 def push_self_or_class(meth)
75 is_module = meth.new_label
78 meth.find_const :Module
86 def attach_and_call(g, name)
87 # If the body is empty, then don't bother with it.
88 return if @body.empty?
90 desc = new_description()
95 push_self_or_class(meth)
119 g.set_line orig.line, orig.file
122 # Allocate some stack to store locals.
125 g.allocate_stack @alloca
149 # REFACTOR See if there is a sane way to call 'super' here
150 # We need to call 'push_encloser' before 'sret', hence the copy-and-paste
176 g.set_line @line, @file
177 @child.bytecode(g) if @child
181 g.set_line @line, @file
182 @child.call_bytecode(g)
216 def bytecode(g, use_gif=true)
258 if @child.is? NumberLiteral
277 g.push_unique_literal @value
288 g.make_array @body.size
323 g.push_literal @string
333 g.send :`, 1, true # ` (silly vim/emacs)
341 g.send :to_s, 0, true
348 @body.reverse_each do |x|
351 g.push_literal @string
361 class DynamicExecuteString
365 g.send :`, 1, true #`
373 g.send :to_sym, 0, true
380 # A regex literal should only be converted to a Regexp the first time it
381 # is encountered. We push a literal nil here, and then overwrite the
382 # literal value with the created Regexp if it is nil, i.e. the first time
383 # only. Subsequent encounters will use the previously created Regexp
384 idx = g.add_literal(nil)
385 g.push_literal_at idx
393 g.push_literal @source
414 class DynamicOnceRegex
416 idx = g.add_literal(nil)
417 g.push_literal_at idx
432 # Implicit match against $_
434 def bytecode(generator)
435 @target.bytecode generator
436 @pattern.bytecode generator
437 generator.send :=~, 1
485 count = @body.size - 1
491 # guards for things that plugins might optimize away.
492 g.pop if g.advanced_since?(ip)
495 @body[count].bytecode(g)
517 @condition.bytecode(g)
538 # An if with no code. Sweet.
550 def bytecode(g, use_gif=true)
555 g.break = g.new_label
563 @condition.bytecode(g)
584 @condition.bytecode(g)
614 g.break = g.new_label
615 g.next = g.redo = top = g.new_label
618 if @body # Empty loop
633 [@arguments.arity, @arguments.optional.size]
637 desc = MethodDescription.new @compiler.generator_class, @locals
638 desc.name = :__block__
639 desc.required, desc.optional = argument_info
642 # Push line info down.
643 sub.set_line g.line, g.file
647 @arguments.bytecode(sub)
649 # Remove the block args.
655 sub.redo = sub.new_label
672 nil_block = g.new_label
679 g.send :__from_block__, 1
696 def jump_error(g, msg)
698 g.push_const :LocalJumpError
700 g.send :raise, 2, true
709 # Set the return value from @value above.
710 g.push_local @check_var.slot
711 g.send :break_value=, 1
715 g.push_local @check_var.slot
719 g.push_const :Compile
720 g.send :__unexpected_break__, 0
731 jump_error g, "redo used in invalid context"
748 jump_error g, "next used in invalid context"
758 jump_error g, "retry used in invalid context"
765 # The bytecode to test a when condition is different, depending on whether
766 # or not the case statement has a receiver, i.e.
770 def condition_bytecode(g, has_receiver, cond)
777 # ManyIf - no receiver
782 def bytecode(g, has_receiver, nxt, fin)
783 if @conditions.size == 1 and !@splat
784 condition_bytecode(g, has_receiver, @conditions.first)
789 @conditions.each do |c|
790 condition_bytecode(g, has_receiver, c)
795 if @splat.kind_of? Array
797 condition_bytecode(g, has_receiver, c)
804 g.send :__matches_when__, 1
807 raise Error, "encountered splat on many-if!"
816 # Remove the thing we've been testing.
817 g.pop if has_receiver
828 @receiver.bytecode(g) if has_receiver?
831 w.bytecode(g, has_receiver?, nxt, fin)
835 # The condition is still on the stack
836 g.pop if has_receiver?
848 class LocalAssignment
854 # No @value means assume that someone else put the value on the
855 # stack (ie, an masgn)
857 if @variable.on_stack?
858 if @variable.argument?
859 raise Error, "Invalid access semantics for argument: #{@name}"
862 g.set_local_fp @variable.stack_position
863 elsif @variable.created_in_block?
864 g.set_local_depth @depth, @variable.slot
866 g.set_local @variable.slot
874 if @variable.on_stack?
875 if @variable.argument?
876 g.from_fp @variable.stack_position
878 g.get_local_fp @variable.stack_position
880 elsif @variable.created_in_block?
881 g.push_local_depth @depth, @variable.slot
883 g.push_local @variable.slot
888 class BlockAsArgument
890 g.set_local @variable.slot
900 # If the array has 1 or 0 elements, grab the 0th element.
901 # otherwise, leave the array on the stack.
926 # Bytecode generation when a splat is used as a method arg
929 g.cast_array_for_args 0
936 def bytecode(g, use_gif=false)
937 if @left.is? CVar then
938 @left.check_first_bytecode(g)
964 def index_bytecode(g)
965 @index.reverse.each do |idx|
978 g.send :[], @index.size
980 if @kind == :or or @kind == :and
995 g.send :[]=, @index.size + 1
1001 g.send :[]=, @index.size + 1
1021 if @kind == :or or @kind == :and
1053 def call_bytecode(g)
1055 g.cast_array_for_args @rest.size
1058 @rest.reverse_each do |x|
1070 g.make_array @rest.size
1081 g.cast_array_for_args 1
1085 # Used for h[*x] = 3
1086 def attr_bytecode(g)
1090 g.cast_array_for_args 1
1098 g.push_my_field @index
1106 g.store_my_field @index
1120 @value.bytecode(g) if @value
1132 g.find_const :Regexp
1133 g.send :last_match, 0
1135 g.push_literal @name
1137 g.find_const :Globals
1146 @value.bytecode(g) if @value
1153 g.find_const :Regexp
1154 g.send :my_last_match=, 1
1158 g.push_literal @name
1160 g.find_const :Globals
1191 if @compiler.kernel?
1195 g.set_const @name, true
1199 g.set_const @name, true
1201 @value.bytecode(g) if @value
1205 @value.bytecode(g) if @value
1206 g.push_literal @name
1216 g.send :__const_set__, 2
1217 end # @compiler.kernel?
1234 g.send :__verify_metaclass__, 0
1238 attach_and_call g, :__metaclass_init__
1245 def superclass_bytecode(g)
1247 @superclass.bytecode(g)
1256 superclass_bytecode(g)
1257 g.open_class_under @name
1259 superclass_bytecode(g)
1263 attach_and_call g, :__class_init__
1273 g.open_module_under @name
1278 attach_and_call g, :__module_init__
1283 NODE_TYPES = {:self => "self", :nil => "nil", :true => "true", :false => "false", :gasgn => "assignment", :iasgn => "assignment", :cdecl => "assignment", :cvdecl => "assignment", :cvasgn => "assignment", :lvar => "local-variable", :str => "expression", :array => "expression", :hash => "expression", :yield => "yield", :ivar => "instance-variable", :gvar => "global-variable", :cvar => "class variable", :fcall => "method", :call => "method", :vcall => "method", :const => "constant", :colon2 => "constant", :colon3 => "constant", :lasgn => "assignment", :fixnum => "expression", :lit => "expression"}
1286 # Imported directly from compiler1 and reworked to use g.
1288 expr = @expression.dup
1290 # if something is defined, !something is too.
1291 # if !something is undefined, then so is something.
1292 expr.shift if expr[0] == :not
1294 # grouped expression == evil
1295 # TODO - Verify that this is still a sane way to detect such things
1296 if expr.flatten.include?(:newline)
1305 receiver = expr.shift
1306 msg = expr.shift # method name
1308 # Make sure there are no args.
1314 # defined?(DoesNotExist.puts) should not raise NameError
1315 if receiver.is?(ConstFind) then
1316 no_const = g.new_label
1318 g.push_literal receiver.name
1320 g.send :const_defined?, 1
1325 receiver.bytecode(g)
1326 g.send :__respond_to_eh__, 2
1335 receiver.bytecode(g)
1336 g.send :__respond_to_eh__, 2
1341 # Make sure there are no args.
1350 g.send :__respond_to_eh__, 2
1354 # class vars as symbols, not strings
1357 g.send :class_variables, 1
1360 g.push_literal expr.shift
1361 g.push_const :Globals
1367 g.send :__instance_variable_defined_eh__, 1
1371 g.push_literal expr.shift
1373 g.send :const_defined?, 1
1377 # Convert the constant parse tree into a string like ::Object::SomeClass
1378 str = const_to_string(expr, str)
1382 g.send :const_path_defined?, 1
1386 # Convert the constant parse tree into a string like ::Object::SomeClass
1387 str = const_to_string(expr, str)
1390 g.push_const :Object
1391 g.send :const_path_defined?, 1
1393 if NODE_TYPES.key?(node)
1400 push_return_value(g, node)
1403 # Return the correct string based on the node type
1404 def push_return_value(g, node)
1405 defined = g.new_label
1411 lit = NODE_TYPES[node].dup
1416 # e.g. [[:const, :Object], :Blah]
1417 # e.g. [[:colon3, :Foo], :Bar]
1418 # e.g. [[:colon2, [:colon3, :Faz], :Boo], :Batch]
1419 # e.g. [[:colon2, [:const, :Zizz], :Koom], :Yonk]
1420 # TODO - There is probably a better way, but it is late. Really late.
1421 def const_to_string(tree, str)
1422 return str if tree.empty?
1424 unless str[-2,2] == "::" || str == ""
1427 if piece.is_a?(Array)
1428 str = const_to_string(piece, str) until piece.empty?
1430 elsif [:const, :colon2].include?(piece)
1432 elsif piece == :colon3
1441 STDERR << "Passed a complex expression to 'defined?'"
1456 class RescueCondition
1457 def bytecode(g, top_if_false, if_done)
1461 @conditions.each do |x|
1473 g.send :__rescue_match__, 1
1479 if_false = g.new_label
1487 @next.bytecode(g, top_if_false, if_done)
1489 # This is the last rescue
1506 # Stupid. No body and no else.
1509 # Only an else, run it.
1513 g.retry = g.new_label
1519 g.exceptions do |ex|
1525 @rescue.bytecode(g, rr, last)
1565 g.exceptions do |ex|
1574 # Re-raise the exception
1575 if @did_return and !@outer_ensure
1577 g.push_const :ReturnException
1582 g.send :return_value, 0
1585 # Emit the special code for doing a return in a block.
1587 Return.emit_lre(g, @check_var)
1600 # Now, re-emit the code for the ensure which will run if there was no
1601 # exception generated.
1609 def bytecode(g, force=false)
1620 if !force and @in_ensure
1622 g.find_const :ReturnException
1629 Return.emit_lre(g, @check_var)
1635 def self.emit_lre(g, var)
1636 # Set the return value from @value above.
1637 g.push_local var.slot
1638 g.send :return_value=, 1
1642 g.push_local var.slot
1652 g.cast_for_multi_block_arg unless @child.splat_only?
1653 @child.in_block = true
1655 when LocalAssignment, IVarAssign, GVarAssign
1656 g.cast_for_single_block_arg
1660 g.cast_for_single_block_arg
1661 @child.bytecode(g, true)
1666 raise Error, "Unknown form of block args: #{@child.class}"
1674 # - MAsgn sexps always contain either 2 or 3 values
1675 # - If the masgn contains only 2 values:
1676 # - it means there are no lasgns, i.e. the lhs consists solely of a splat
1678 # - the first arg is the lhs splat arg, and cannot be nil; however, it
1679 # may be just the value true, in the case of a block anonymous splat arg,
1681 # - the second arg is either one of [:array, :splat, :argscat, :to_ary], or
1682 # nil if the masgn represents block arguments.
1683 # - If the masgn contains 3 values:
1684 # - the first arg is an array of lasgns with a minimum of one lasgn.
1685 # - the second arg is the lhs splat arg, or nil if there are no splats
1686 # - the third arg is either one of [:array, :splat, :argscat, :to_ary], or
1687 # nil if the masgn represents block arguments.
1688 # - An MAsgn may contain nested masgns, e.g. a,(b,c) = 1,[2,3]. The nested
1689 # masgn(s) will have nil for their @assigns, since the assigns come from
1690 # the outermost masgn.
1693 if @source.is? ArrayLiteral
1697 flip_assign_bytecode(g)
1700 statement_bytecode(g)
1703 block_arg_bytecode(g)
1705 statement_bytecode(g)
1709 # Pad stack if there are insufficient source values for the assigns
1711 diff = -@source.body.size
1713 diff += @assigns.body.size
1715 diff.times { g.push :nil }
1721 # The easiest case for a normal masgn.
1725 def flip_assign_bytecode(g)
1726 # Pad the stack with extra nils if there are more assigns
1730 @source.body.each do |x|
1734 g.rotate @source.body.size
1736 # Now all the source data is on the stack.
1738 @assigns.body.each do |x|
1747 # Clean up the stack if there was extra sources
1749 # unary - has binds strangly
1750 (-diff).times { g.pop }
1756 def array_bytecode(g)
1757 @source.body.each do |x|
1770 @splat.bytecode(g) unless @splat.kind_of? TrueClass # e.g. * = 1,2
1773 @assigns.body.reverse_each do |x|
1786 def statement_bytecode(g)
1789 elsif @source.is? Splat or @source.is? ToArray
1790 @source.child.bytecode(g)
1791 elsif @source.is? ConcatArgs
1794 raise Error, "Unknown form: #{@source.class}"
1799 @assigns.body.each do |x|
1812 @splat.bytecode(g) unless @splat.kind_of? TrueClass # HACK dup
1819 def block_arg_bytecode(g)
1821 @assigns.body.each do |x|
1828 if @splat and !@splat.kind_of? TrueClass
1837 @assigns.nil? and @splat
1847 def receiver_bytecode(g)
1855 def bytecode(g, in_masgn = false)
1862 # The dup'd rhs is on the top of the stack now
1870 @rhs_expression.bytecode(g)
1878 elsif @rhs_expression
1879 @rhs_expression.bytecode(g)
1884 # PushArgs only for this branch
1885 @arguments.attr_bytecode(g)
1898 def receiver_bytecode(g)
1905 if @arguments.kind_of? Array
1906 @arguments.reverse_each do |x|
1909 @argcount = @arguments.size
1910 elsif @arguments.is? ConcatArgs
1911 @arguments.call_bytecode(g)
1912 # ConcatArgs calls get_args on its own, so we don't need to
1915 if @arguments.is? Splat
1916 @arguments.call_bytecode(g)
1918 @arguments.bytecode(g)
1929 return if use_plugin(g, :call)
1941 receiver_bytecode(g)
1943 # @block might be BlockPass, and we don't generate the
1944 # LongReturnException detection code for that.
1945 if @block and @block.is? Iter
1950 g.send_with_register @method, allow_private?
1952 # Only BlockPass currently
1953 g.send_with_block @method, @argcount, allow_private?
1955 g.send @method, @argcount, allow_private?
1959 def block_bytecode(g)
1961 g.exceptions do |ex|
1963 # We pre-create the exception.
1965 g.find_const :LongReturnException
1967 g.set_local @check_var.slot
1973 g.send_with_register @method, allow_private?
1975 g.send_with_block @method, @argcount, allow_private?
1984 g.push_local @check_var.slot
1991 # This is also used for break in a block. If break was used,
1992 # is_return is false, so we just leave the value on the stack.
1995 g.send :is_return, 0
1998 # If this is occuring already in a block, keep it raising.
2025 g.send_with_register :call, false
2028 g.meta_send_call @argcount
2041 # Even if we're specifying new args, the original block
2049 g.send_super @method.name
2051 g.send_super @method.name, @argcount
2061 @method.arguments.required.each do |var|
2062 la = LocalAccess.new @compiler
2063 la.from_variable var
2067 @method.arguments.optional.each do |var|
2068 la = LocalAccess.new @compiler
2069 la.from_variable var
2073 if @method.arguments.splat
2074 cc = ConcatArgs.new @compiler
2075 la = LocalAccess.new @compiler
2076 la.from_variable @method.arguments.splat
2091 g.push_literal @name
2094 g.send :metaclass, 0
2096 g.send :undef_method, 1
2103 g.push_literal @current
2106 g.send :alias_method, 2, true
2113 g.push_literal @current
2115 g.find_const :Globals
2116 g.send :add_alias, 2
2120 # Represents the argument list of a method definition
2121 # See +nodes.rb+ for details.
2124 # Minimum number of arguments to be supplied
2125 min = @required.size
2127 # There is no upper bound, check is in instructions.gen
2130 # Maximum unsplatted argument count
2131 max = min + @optional.size
2134 # Check these min and max argument counts at runtime
2135 g.check_argcount min, max
2137 process_required_args(g)
2138 process_optional_args(g)
2139 process_rest_arg(g) if @splat.kind_of?(Local)
2140 process_block_arg(g) if @block_arg
2143 # Emit a local setup instruction for each required argument
2144 def process_required_args(g)
2145 @required.each do |var|
2146 g.set_local_from_fp var.slot, var.stack_position
2150 # Emit bytecode to handle any optional arguments
2151 def process_optional_args(g)
2152 @optional.each do |var|
2154 assign = @mapped_defaults[var.name]
2156 use_passed = g.new_label
2158 g.passed_arg var.stack_position
2165 g.set_local_from_fp var.slot, var.stack_position
2171 # Emit bytecode to handle a 'rest' (a.k.a. 'splat') argument
2172 def process_rest_arg(g)
2173 g.make_rest_fp @required.size + @optional.size
2174 lv = LocalAssignment.new(@compiler)
2175 lv.from_variable @splat
2180 # Emit bytecode to handle a block argument (&block syntax)
2181 def process_block_arg(g)
2190 g.send :__from_block__, 1
2194 @block_arg.bytecode(g)
2203 [@arguments.arity, @arguments.optional.size]
2207 desc = new_description()
2208 meth = desc.generator
2213 show_errors(meth) do
2214 @arguments.bytecode(meth)
2215 desc.run self, @body
2220 if @arguments.required and @arguments.required.size > 0
2221 required = Tuple.new(@arguments.required.size)
2222 @arguments.required.each_with_index {|x,i| required.put(i, x.name)}
2223 args.put(0, required)
2225 if @arguments.optional and @arguments.optional.size > 0
2226 optional = Tuple.new(@arguments.optional.size)
2227 @arguments.optional.each_with_index {|x,i| optional.put(i, x.name)}
2228 args.put(1, optional)
2230 args.put(2, @arguments.splat.name) if @arguments.splat
2236 use_plugin g, :method, desc
2242 g.push_literal compile_body(g)
2244 if @compiler.kernel?
2248 g.push_literal @name
2250 g.send :__add_method__, 2
2256 class DefineSingleton
2258 g.push_literal compile_body(g)
2259 if @compiler.kernel?
2261 g.attach_method @name
2263 g.push_literal @name
2265 g.send :metaclass, 0
2266 g.send :attach_method, 2
2298 g.push_literal @name
2304 g.send :class_variable_set, 2
2309 def prepare_receiver(g)
2318 g.push_literal @name
2320 g.send :class_variable_get, 1
2323 def check_first_bytecode(g)
2324 g.push_literal @name
2326 g.send :class_variable_defined?, 1
2328 no_cvar = g.new_label
2331 g.push_literal @name
2333 g.send :class_variable_get, 1
2350 g.send :active_path, 0