CodeTools::AST << {
ArgumentAssembly < Node { node_type args field body var block # TODO: remove this unnecessary state setter body: |given_body| { given_body.last.is_a?(BlockArgument) && (self.block = given_body.pop) given_body } # All items before the first SplatValue pre_group: self.body.take_while |item| { !item.is_a?(SplatValue) } # All items after and including the first SplatValue post_group: self.body.drop_while |item| { !item.is_a?(SplatValue) } # Symbol of bytecode operation to use for send send_op: cond( self.body.detect |item| { item.is_a?(SplatValue) }, :send_with_splat, self.block, :send_with_block, :send, ) # Number of arguments to use for send operation send_count: pre_group.size splat_bytecode: |g| ArrayAssembly.new( line: self.line body: post_group ).bytecode(g) block_bytecode: |g| self.block &? self.block.bytecode(g) ?? g.push_null bytecode: |g| { pos(g) pre_group.each |item| { item.bytecode(g) } send_op == :send_with_splat && ( splat_bytecode(g) block_bytecode(g) ) send_op == :send_with_block && ( block_bytecode(g) ) } }
}