class Fancy class AST class BlockLiteral < Rubinius::AST::Iter def initialize(line, args, body, partial = false) @args = args body = body || Rubinius::AST::NilLiteral.new(line) if body.empty? body.unshift_expression Rubinius::AST::NilLiteral.new(line) end super(line, args, body) args.create_locals(self) if args.total_args == 0 @arguments.prelude = nil end if args.total_args > 1 @arguments.prelude = :multi end @arguments.required_args = args.required_args @partial = partial if @partial @body = ExpressionList.new @line, *@body.expressions.map{ |e| convert_to_implicit_arg_send(e) } end end def convert_to_implicit_arg_send(expr) # see self-hosted version in lib/compiler/block.fy # this is just a port of it so we can use partial blocks # in fancy's stdlib new_receiver = Identifier.new(@line, @args.args.first.to_s) case expr when Identifier expr = MessageSend.new(@line, new_receiver, expr, MessageArgs.new(@line)) when MessageSend case expr.receiver when Self expr.receiver = new_receiver when Identifier expr.receiver = MessageSend.new(@line, new_receiver, expr.receiver, MessageArgs.new(@line)) when MessageSend expr.receiver = convert_to_implicit_arg_send(expr.receiver) end end expr end def bytecode(g) #docstring = body.shift_docstring super(g) #MethodDef.set_docstring(g, docstring, line, @args.args) end end class BlockArgs < Node attr_accessor :args, :block def initialize(line, *args) super(line) @args = args.map{|a| a.name.to_sym} end def bytecode(g) if @args.size > 1 @args.each_with_index do |a, i| g.shift_array g.set_local i g.pop end else @args.each_with_index do |a, i| g.set_local i end end end def total_args @args.size end def required_args total_args end def create_locals(block) @args.each do |a| block.new_local(a) end end end end end