module Rensei::Unparser::Base

Public Instance Methods

unparse(node, opt = {}) click to toggle source
# File lib/rensei/unparser.rb, line 42
def unparse(node, opt = {})
  case node
  when RubyVM::AbstractSyntaxTree::Node, Hash, Array
    method_name = "NODE_#{node.type}"
    respond_to?(method_name, true) ? send(method_name, node, opt.dup) : node
  else
    node
  end
end

Private Instance Methods

NODE_ALIAS(node, opt = {}) click to toggle source

method alias statement format: alias [nd_1st] [nd_2nd] example: alias bar foo

# File lib/rensei/unparser.rb, line 1031
def NODE_ALIAS(node, opt = {})
  node.children.then { |nd_1st, nd_2nd|
    "alias #{unparse(nd_1st, opt)} #{unparse(nd_2nd, opt)}"
  }
end
NODE_AND(node, opt = {}) click to toggle source

&& operator format: [nd_1st] && [nd_2nd] example: foo && bar

# File lib/rensei/unparser.rb, line 348
def NODE_AND(node, opt = {})
  node.children.then { |args|
    "(#{args.map { |node| unparse(node, opt) }.join(" && ")})"
  }
end
NODE_ARGS(node, opt_ = {}) click to toggle source

method parameters format: def method_name(.., [nd_opt=some], *[nd_rest], [nd_pid], .., &[nd_body]) example: def foo(a, b, opt1=1, opt2=2, *rest, y, z, &blk); end

# File lib/rensei/unparser.rb, line 1263
def NODE_ARGS(node, opt_ = {})
  (
    _, # pre_num
    _, # pre_init
    opt,
    _, # first_post
    _, # post_num
    _, # post_init
    _, # rest
    _, # kw
    _, # kwrest
    _, # block
  ) = node.children
  "#{unparse(opt, opt_)}#{unparse(kw, opt_)}"
end
NODE_ARGSCAT(node, opt = {}) click to toggle source

splat argument following arguments format: ..(*[nd_head], [nd_body..]) example: foo(*ary, post_arg1, post_arg2)

# File lib/rensei/unparser.rb, line 936
def NODE_ARGSCAT(node, opt = {})
  node.children.then { |head, body|
    case head.type
    when :ARRAY, :LIST
      opt_flags = { expand_ARRAY: true, expand_ARGSCAT: true, expand_ARGSPUSH: false }
    when :ARGSCAT
      opt_flags = { expand_ARRAY: true, expand_ARGSCAT: true, expand_ARGSPUSH: false }
    when :ARGSPUSH
      opt_flags = { expand_ARRAY: false, expand_ARGSCAT: false, expand_ARGSPUSH: true }
    else
      opt_flags = {}
    end

    star = "*" unless %i(ARRAY LIST).include? body.type
    if opt.delete(:expand_ARGSCAT)
      "#{unparse(head, opt.merge(opt_flags))}, #{star}#{unparse(body, opt.merge(expand_ARRAY: true))}"
    else
      "[#{unparse(head, opt.merge(opt_flags))}, #{star}#{unparse(body, opt.merge(expand_ARRAY: true))}]"
    end
  }
end
NODE_ARGSPUSH(node, opt = {}) click to toggle source

splat argument following one argument format: ..(*[nd_head], [nd_body]) example: foo(*ary, post_arg)

# File lib/rensei/unparser.rb, line 961
def NODE_ARGSPUSH(node, opt = {})
  node.children.then { |head, body|
    case head.type
    when :ARRAY, :LIST
      opt_flags = { expand_ARRAY: true, expand_ARGSCAT: true, expand_ARGSPUSH: false }
    when :ARGSCAT
      opt_flags = { expand_ARRAY: false, expand_ARGSCAT: true, expand_ARGSPUSH: false }
    when :ARGSPUSH
      opt_flags = { expand_ARRAY: false, expand_ARGSCAT: false, expand_ARGSPUSH: true }
    else
      opt_flags = {}
    end

    if opt.delete(:expand_ARGSPUSH)
      "#{unparse(head, opt.merge(opt_flags))}, #{unparse(body , opt)}"
    else
      "[#{unparse(head, opt.merge(opt_flags))}, #{unparse(body , opt)}]"
    end
  }
end
NODE_ARGS_AUX(node, opt = {}) click to toggle source
# File lib/rensei/unparser.rb, line 1394
def NODE_ARGS_AUX(node, opt = {})
  ""
end
NODE_ARRAY(node, opt = {}) click to toggle source

list constructor format: [ [nd_head], [nd_next].. ] (length: [nd_alen]) example: [1, 2, 3]

# File lib/rensei/unparser.rb, line 671
def NODE_ARRAY(node, opt = {})
  node.children.then { |*args, _nil|
    if opt[:expand_ARRAY]
      "#{args.map(&_unparse(opt.except(:expand_ARRAY))).join(", ")}"
    else
      "[#{args.map(&_unparse(opt)).join(", ")}]"
    end
  }
end
NODE_ATTRASGN(node, opt = {}) click to toggle source

attr assignment format: [nd_recv]. = [nd_args] example: struct.field = foo

# File lib/rensei/unparser.rb, line 1204
def NODE_ATTRASGN(node, opt = {})
  node.children.then { |recv, mid, args|
    if opt.delete(:ignore_equal_NODE_ATTRASGN)
      "#{unparse(recv, opt)}.#{mid.to_s.delete_suffix("=")}"
    elsif mid == :[]=
      *args_, right, _ = args.children
      "#{unparse(recv, opt)}[#{args_.map(&_unparse(opt.merge(expand_ARRAY: true))).join(", ")}] = #{unparse(right, opt.merge(expand_ARRAY: true))}"
    else
      "#{unparse(recv, opt)}.#{mid}(#{unparse(args, opt.merge(expand_ARRAY: true))})"
    end
  }
end
NODE_BACK_REF(node, opt = {}) click to toggle source

back special variable reference format: $[nd_nth] example: $&, $`, $', $+

# File lib/rensei/unparser.rb, line 808
def NODE_BACK_REF(node, opt = {})
  node.children.then { |vid,|
    vid.to_s
  }
end
NODE_BEGIN(node, opt = {}) click to toggle source

begin statement format: begin; [nd_body]; end example: begin; 1; end

# File lib/rensei/unparser.rb, line 277
      def NODE_BEGIN(node, opt = {})
        node.children.then { |body|
          if opt.delete(:pattern_match_BEGIN)
            "^(#{body.map(&_unparse(opt)).join("; ")})"
          elsif opt.delete(:without_BEGIN)
            "#{body.map(&_unparse(opt)).join("; ")}"
          elsif opt.delete(:within_BEGIN)
            "begin #{body.map(&_unparse(opt)).join("; ")} end"
          elsif body == [nil]
            ""
          else
            <<~EOS.chomp
            begin
              #{body.map(&_unparse(opt)).join("; ")}
            end
            EOS
          end
        }
      end
NODE_BLOCK(node, opt = {}) click to toggle source

statement sequence format: [nd_head]; …; [nd_next] example: foo; bar

# File lib/rensei/unparser.rb, line 61
def NODE_BLOCK(node, opt = {})
  node.children.then { |head, *nexts|
    if without_BEGIN = opt.fetch(:without_BEGIN, false)
      begin_ = proc { |str, _| str }
    else
      begin_ = proc { |str, semicolon|
        if semicolon
          "begin; #{str}; end"
        else
          "begin #{str}; end"
        end
      }
    end
    opt.merge!(within_BEGIN: !without_BEGIN)
    opt.delete(:without_BEGIN)
    if head.type == :BEGIN && head.children == [nil]
      begin_.(nexts.map(&_unparse(opt)).join("; "), true)
    elsif head.type == :BEGIN
      "BEGIN { #{unparse(head, opt)} }; #{nexts.drop(1).map(&_unparse(opt)).join("; ")}"
    else
      if nexts.empty?
        "#{unparse(head, opt)};"
      else
        begin_.([head, *nexts].map(&_unparse(opt)).join("; "), false)
      end
    end
  }
end
NODE_BLOCK_PASS(node, opt = {}) click to toggle source

arguments with block argument format: ..([nd_head], &[nd_body]) example: foo(x, &blk)

# File lib/rensei/unparser.rb, line 994
def NODE_BLOCK_PASS(node, opt = {})
  node.children.then { |head, body|
    "#{head&.then { |it| "#{unparse(it, opt)}, " }}&#{unparse(body, opt)}"
  }
end
NODE_BREAK(node, opt = {}) click to toggle source

break statement format: break [nd_stts] example: break 1

# File lib/rensei/unparser.rb, line 236
def NODE_BREAK(node, opt = {})
  node.children.then { |stts,|
    "break #{unparse(stts, opt)}"
  }
end
NODE_CALL(node, opt = {}) click to toggle source

method invocation format: [nd_recv].([nd_args]) example: obj.foo(1)

# File lib/rensei/unparser.rb, line 584
def NODE_CALL(node, opt = {})
  node.children.then { |receiver, mid, args|
    opt_flags = _expand_in_XXXCALL(args)
    "#{unparse(receiver, opt)}.#{unparse(mid, opt)}(#{unparse(args, opt.merge(_expand_in_XXXCALL(args)))})"
  }
end
NODE_CASE(node, opt) click to toggle source

case statement format: case [nd_head]; [nd_body]; end example: case x; when 1; foo; when 2; bar; else baz; end

# File lib/rensei/unparser.rb, line 119
      def NODE_CASE(node, opt)
        node.children.then { |head, body, else_|
          <<~EOS.chomp
          case #{unparse(head, opt)}
          #{unparse(body, opt)}#{else_ ? "\nelse\n#{unparse(else_, opt)}" : ""}
          end
          EOS
        }
      end
NODE_CASE2(node, opt = {}) click to toggle source

case statement with no head format: case; [nd_body]; end example: case; when 1; foo; when 2; bar; else baz; end

# File lib/rensei/unparser.rb, line 132
      def NODE_CASE2(node, opt = {})
        node.children.then { |_, body, else_|
          <<~EOS.chomp
          case
          #{unparse(body, opt)}#{else_ ? "\nelse\n#{unparse(else_, opt)}" : ""}
          end
          EOS
        }
      end
NODE_CDECL(node, opt = {}) click to toggle source

constant declaration format: [nd_else]::(constant) = [nd_value] example: X = foo

# File lib/rensei/unparser.rb, line 516
def NODE_CDECL(node, opt = {})
  node.children.then { |else_, vid, value|
    rvalue = Symbol === vid ? value : (value || vid)
    if rvalue
      "(#{unparse(else_, opt)} = #{unparse(rvalue, opt)})"
    else
      "#{unparse(else_, opt)}"
    end
  }
end
NODE_CLASS(node, opt = {}) click to toggle source

class definition format: class [nd_cpath] < [nd_super]; [nd_body]; end example: class C2 < C; ..; end

# File lib/rensei/unparser.rb, line 1058
      def NODE_CLASS(node, opt = {})
        node.children.then { |cpath, super_, body|
          <<~EOS.chomp
          class #{unparse(cpath, opt)}#{super_&.then { |it| " < #{unparse(it, opt)}" } }
            #{unparse(body, opt.merge(without_BEGIN: true))}
          end
          EOS
        }
      end
NODE_COLON2(node, opt = {}) click to toggle source

scoped constant reference format: [nd_head]:: example: M::C

# File lib/rensei/unparser.rb, line 1097
def NODE_COLON2(node, opt = {})
  node.children.then { |head, mid|
    "#{unparse(head, opt)&.then { |it| "#{unparse(head, opt)}::" }}#{mid}"
  }
end
NODE_COLON3(node, opt = {}) click to toggle source

top-level constant reference format: ::[nd_mid] example: ::object

# File lib/rensei/unparser.rb, line 1106
def NODE_COLON3(node, opt = {})
  node.children.then { |mid,|
    "::#{mid}"
  }
end
NODE_CONST(node, opt = {}) click to toggle source

constant reference format: [nd_vid](constant) example: X

# File lib/rensei/unparser.rb, line 772
def NODE_CONST(node, opt = {})
  node.children.then { |vid,|
    "#{vid}"
  }
end
NODE_CVAR(node, opt = {}) click to toggle source

class variable reference format: [nd_vid](cvar) example: @@x

# File lib/rensei/unparser.rb, line 781
def NODE_CVAR(node, opt = {})
  node.children.then { |vid,|
    vid.to_s
  }
end
NODE_CVASGN(node, opt = {}) click to toggle source

class variable assignment format: [nd_vid](cvar) = [nd_value] example: @@x = foo nd_vid, “class variable”

# File lib/rensei/unparser.rb, line 488
def NODE_CVASGN(node, opt = {})
  node.children.then { |vid, value|
    if value
      "(#{vid} = #{unparse(value, opt)})"
    else
      # Support: `hoge(@@a = 1) { @@a, b = c }`
      "#{vid}"
    end
  }
end
NODE_DASGN(node, opt = {}) click to toggle source

dynamic variable assignment (out of current scope) format: [nd_vid](dvar) = [nd_value] example: x = nil; 1.times { x = foo }

# File lib/rensei/unparser.rb, line 438
def NODE_DASGN(node, opt = {})
  node.children.then { |vid, value|
    if value
      "(#{vid} = #{unparse(value, opt)})"
    else
      # Support: `hoge(a = 1) { a, b = c }`
      "#{vid}"
    end
  }
end
NODE_DASGN_CURR(node, opt = {}) click to toggle source

dynamic variable assignment (in current scope) format: [nd_vid](current dvar) = [nd_value] example: 1.times { x = foo }

# File lib/rensei/unparser.rb, line 452
def NODE_DASGN_CURR(node, opt = {})
  node.children.then { |vid, value|
    if value == :NODE_SPECIAL_REQUIRED_KEYWORD
      "#{vid}:"
    elsif opt.delete(:KW_ARG)
      "#{vid}:#{value&.then { |it| " #{unparse(it, opt)}" }}"
    elsif value.nil?
      "#{vid}"
    elsif opt.delete(:expand_DASGN_CURR)
      "#{vid} = #{unparse(value, opt)}"
    elsif value.type == :ERRINFO
      "=> #{vid}"
    else
      "(#{vid} = #{unparse(value, opt)})"
    end
  }
end
NODE_DEFINED(node, opt = {}) click to toggle source

defined? expression format: defined?() example: defined?(foo)

# File lib/rensei/unparser.rb, line 1186
def NODE_DEFINED(node, opt = {})
  node.children.then { |head,|
    "defined?(#{unparse(head, opt)})"
  }
end
NODE_DEFN(node, opt = {}) click to toggle source

method definition format: def [nd_mid] [nd_defn]; end example: def foo; bar; end

# File lib/rensei/unparser.rb, line 1003
      def NODE_DEFN(node, opt = {})
        node.children.then { |mid, defn|
          info = unparse_NODE_SCOPE(defn, opt)
          <<~EOS.chomp
            def #{mid}(#{info[:args]})
              #{info[:body]}
            end
          EOS
        }
      end
NODE_DEFS(node, opt = {}) click to toggle source

singleton method definition format: def [nd_recv]. [nd_defn]; end example: def obj.foo; bar; end

# File lib/rensei/unparser.rb, line 1017
      def NODE_DEFS(node, opt = {})
        node.children.then { |recv, mid, defn|
          info = unparse_NODE_SCOPE(defn, opt)
          <<~EOS.chomp
            def #{unparse(recv, opt)}.#{mid}(#{info[:args]})
              #{info[:body]}
            end
          EOS
        }
      end
NODE_DOT2(node, opt = {}) click to toggle source

range constructor (incl.) format: [nd_beg].. example: 1..5

# File lib/rensei/unparser.rb, line 1115
def NODE_DOT2(node, opt = {})
  node.children.then { |beg, end_|
    "(#{unparse(beg, opt)}..#{unparse(end_, opt)})"
  }
end
NODE_DOT3(node, opt = {}) click to toggle source

range constructor (excl.) format: [nd_beg]… example: 1…5

# File lib/rensei/unparser.rb, line 1124
def NODE_DOT3(node, opt = {})
  node.children.then { |beg, end_|
    "(#{unparse(beg, opt)}...#{unparse(end_, opt)})"
  }
end
NODE_DREGX(node, opt = {}) click to toggle source

regexp literal with interpolation format: [nd_lit] example: /foo#{ bar }baz/

# File lib/rensei/unparser.rb, line 904
def NODE_DREGX(node, opt = {})
  node.children.then { |prefix, lit, suffix|
    suffix_ = suffix&.children&.compact&.map { |it|
      unparse(it, opt).then do |it|
        it.undump
      rescue
        it
      end
    }&.join
    "/#{prefix}#{unparse(lit, opt)}#{suffix_}/"
  }
end
NODE_DSTR(node, opt = {}) click to toggle source

string literal with interpolation format: [nd_lit] example: "foo#{ bar }baz"

# File lib/rensei/unparser.rb, line 878
def NODE_DSTR(node, opt = {})
  "\"#{without_DSTR_quote(node, opt)}\""
end
NODE_DSYM(node, opt = {}) click to toggle source

symbol literal with interpolation format: [nd_lit] example: :"foo#{ bar }baz"

# File lib/rensei/unparser.rb, line 920
def NODE_DSYM(node, opt = {})
  ":#{NODE_DSTR(node, opt)}"
end
NODE_DVAR(node, opt = {}) click to toggle source

dynamic variable reference format: [nd_vid](dvar) example: 1.times { x = 1; x }

# File lib/rensei/unparser.rb, line 754
def NODE_DVAR(node, opt = {})
  node.children.then { |vid, dvar|
    vid.to_s
  }
end
NODE_DXSTR(node, opt = {}) click to toggle source

xstring literal with interpolation format: [nd_lit] example: `foo#{ bar }baz`

# File lib/rensei/unparser.rb, line 897
def NODE_DXSTR(node, opt = {})
  "`#{without_DSTR_quote(node, opt)}`"
end
NODE_ENSURE(node, opt = {}) click to toggle source

ensure clause format: begin; [nd_head]; ensure; [nd_ensr]; end example: begin; foo; ensure; bar; end

# File lib/rensei/unparser.rb, line 333
      def NODE_ENSURE(node, opt = {})
        node.children.then { |head, ensr|
          <<~EOS.chomp
          begin
            #{unparse(head, opt)}
          ensure
            #{unparse(ensr, opt)}
          end
          EOS
        }
      end
NODE_ERRINFO(node, opt = {}) click to toggle source

virtual reference to $! format: rescue => id example: rescue => id

# File lib/rensei/unparser.rb, line 1179
def NODE_ERRINFO(node, opt = {})
  "rescue"
end
NODE_EVSTR(node, opt = {}) click to toggle source

interpolation expression format: "..#{ [nd_lit] }.." example: "foo#{ bar }baz"

# File lib/rensei/unparser.rb, line 927
def NODE_EVSTR(node, opt = {})
  node.children.then { |lit,|
    "\#{#{unparse(lit, opt)}}"
  }
end
NODE_FALSE(*) click to toggle source

false format: false example: false

# File lib/rensei/unparser.rb, line 1172
def NODE_FALSE(*)
  "false"
end
NODE_FCALL(node, opt = {}) click to toggle source

function call format: [nd_mid]() example: foo(1)

# File lib/rensei/unparser.rb, line 623
def NODE_FCALL(node, opt = {})
  node.children.then { |mid, args|
    opt_flags = _expand_in_XXXCALL(args)

    # Support `self[key]`
    if mid == :[]
      "self[#{unparse(args, opt.merge(opt_flags))}]"
    else
      "#{unparse(mid, opt)}(#{unparse(args, opt.merge(opt_flags))})"
    end
  }
end
NODE_FLIP2(node, opt = {}) click to toggle source

flip-flop condition (incl.) format: [nd_beg].. example: if (x==1)..(x==5); foo; end

# File lib/rensei/unparser.rb, line 1133
def NODE_FLIP2(node, opt = {})
  node.children.then { |beg, end_|
    "(#{unparse(beg, opt)})..(#{unparse(end_, opt)})"
  }
end
NODE_FLIP3(node, opt = {}) click to toggle source

flip-flop condition (excl.) format: [nd_beg]… example: if (x==1)…(x==5); foo; end

# File lib/rensei/unparser.rb, line 1142
def NODE_FLIP3(node, opt = {})
  node.children.then { |beg, end_|
    "(#{unparse(beg, opt)})...(#{unparse(end_, opt)})"
  }
end
NODE_FOR(node, opt = {}) click to toggle source

for statement format: for * in [nd_iter] do [nd_body] end example: for i in 1..3 do foo end

# File lib/rensei/unparser.rb, line 215
      def NODE_FOR(node, opt = {})
        node.children.then { |iter, body, var|
          scope = unparse_NODE_SCOPE(body, opt)
          <<~EOS.chomp
          for #{unparse(scope[:args], opt) || "*"} in #{unparse(iter, opt)} do
            #{scope[:body]}
          end
          EOS
        }
      end
NODE_FOR_MASGN(node, opt = {}) click to toggle source

vars of for statement with masgn format: for [nd_var] in … do … end example: for x, y in 1..3 do foo end

# File lib/rensei/unparser.rb, line 229
def NODE_FOR_MASGN(node, opt = {})
  # Support from NODE_MASGN
end
NODE_GASGN(node, opt = {}) click to toggle source

global variable assignment format: [nd_entry](gvar) = [nd_value] example: $x = foo

# File lib/rensei/unparser.rb, line 502
def NODE_GASGN(node, opt = {})
  node.children.then { |vid, value|
    if value
      "(#{vid} = #{unparse(value, opt)})"
    else
      # Support: `hoge($a = 1) { $a, b = c }`
      "#{vid}"
    end
  }
end
NODE_GVAR(node, opt = {}) click to toggle source

global variable reference format: [nd_entry](gvar) example: $x

# File lib/rensei/unparser.rb, line 790
def NODE_GVAR(node, opt = {})
  node.children.then { |vid,|
    vid.to_s
  }
end
NODE_HASH(node, opt = {}) click to toggle source

keyword arguments format: nd_head example: a: 1, b: 2 or hash constructor format: { [nd_head] } example: { 1 => 2, 3 => 4 }

# File lib/rensei/unparser.rb, line 702
def NODE_HASH(node, opt = {})
  node.children.then { |head,|
    if head.nil?
      "{}"
    # Support `foo(**kwd)`
    elsif head.children.first.nil?
      "**#{unparse(head.children[1], opt)}"
    else
      result = (head).children[0..-2].each_slice(2).map { |key, value|
        if key.nil?
          "**#{unparse(value, opt)}"
        elsif key.type == :LIT && Symbol === key.children.first
          "#{key.children.first}: #{unparse(value, opt)}"
        else
          "#{unparse(key, opt)} => #{unparse(value, opt)}"
        end
      }.join(", ")

      if opt[:expand_HASH]
        "#{result}"
      else
        "{ #{result} }"
      end
    end
  }
end
NODE_IASGN(node, opt = {}) click to toggle source

instance variable assignment format: [nd_vid](ivar) = [nd_value] example: @x = foo

# File lib/rensei/unparser.rb, line 473
def NODE_IASGN(node, opt = {})
  node.children.then { |vid, value|
    if value
      "(#{vid} = #{unparse(value, opt)})"
    else
      # Support: `hoge(@a = 1) { @a, b = c }`
      "#{vid}"
    end
  }
end
NODE_IF(node, opt = {}) click to toggle source

if statement format: if [nd_cond] then [nd_body] else [nd_else] end example: if x == 1 then foo else bar end

# File lib/rensei/unparser.rb, line 93
      def NODE_IF(node, opt = {})
        node.children.then { |cond, body, else_|
          <<~EOS.chomp
            (if #{unparse(cond, opt)}
              #{unparse(body, opt)}#{else_ ? "\nelse\n  #{unparse(else_, opt)}" : ""}
            end)
          EOS
        }
      end
NODE_ITER(node, opt = {}) click to toggle source

method call with block format: [nd_iter] { [nd_body] } example: 3.times { foo }

# File lib/rensei/unparser.rb, line 206
def NODE_ITER(node, opt = {})
  node.children.then { |iter, body|
    "#{unparse(iter, opt)} { #{unparse(body, opt)} }"
  }
end
NODE_IVAR(node, opt = {}) click to toggle source

instance variable reference format: [nd_vid](ivar) example: @x

# File lib/rensei/unparser.rb, line 763
def NODE_IVAR(node, opt = {})
  node.children.then { |vid,|
    vid.to_s
  }
end
NODE_KW_ARG(node, opt = {}) click to toggle source

keyword arguments format: def method_name(, [nd_next..]) example: def foo(a:1, b:2); end

# File lib/rensei/unparser.rb, line 1242
def NODE_KW_ARG(node, opt = {})
  node.children[0..-1].map(&_unparse(opt.merge(KW_ARG: true))).compact.join(", ")
end
NODE_LAMBDA(node, opt = {}) click to toggle source

lambda expression format: -> [nd_body] example: -> { foo }

# File lib/rensei/unparser.rb, line 1220
def NODE_LAMBDA(node, opt = {})
  node.children.then { |scope,|
    result = unparse_NODE_SCOPE(scope, opt)
    "-> (#{result[:args]}) { #{result[:body]} }"
  }
end
NODE_LASGN(node, opt = {}) click to toggle source

focal variable assignment lormat: [nd_vid](lvar) = [nd_value] example: x = foo

# File lib/rensei/unparser.rb, line 416
def NODE_LASGN(node, opt = {})
  node.children.then { |vid, value|
    _value = unparse(value, opt)
    if value == :NODE_SPECIAL_REQUIRED_KEYWORD
      "#{vid}:"
    elsif opt.delete(:KW_ARG)
      "#{vid}:#{value&.then { |it| " #{unparse(it, opt)}" }}"
    elsif value.nil? || (_value).empty?
      "#{vid}"
    elsif opt.delete(:expand_LASGN)
      "#{vid} = #{_value}"
    elsif value.type == :ERRINFO
      "=> #{vid}"
    else
      "(#{vid} = #{_value})"
    end
  }
end
NODE_LAST(node, opt = {}) click to toggle source
# File lib/rensei/unparser.rb, line 1398
def NODE_LAST(node, opt = {})
  ""
end
NODE_LIT(node, opt = {}) click to toggle source

literal format: [nd_lit] example: 1, /foo/

# File lib/rensei/unparser.rb, line 844
def NODE_LIT(node, opt = {})
  node.children.first.inspect
end
NODE_LVAR(node, opt = {}) click to toggle source

local variable reference format: [nd_vid](lvar) example: x

# File lib/rensei/unparser.rb, line 741
def NODE_LVAR(node, opt = {})
  # Support pattern match
  # in ^expr
  if opt[:pattern_match_LVAR]
    "^#{node.children.first}"
  else
    "#{node.children.first}"
  end
end
NODE_MASGN(node, opt = {}) click to toggle source

multiple assignment format: [nd_head], [nd_args] = [nd_value] example: a, b = foo

# File lib/rensei/unparser.rb, line 372
def NODE_MASGN(node, opt = {})
  node_masgn = opt[:_NODE_MASGN]
  node.children.then { |right, left, _NODE_SPECIAL_NO_NAME_REST = :dummy|
    # Support: for x, y in 1..3 do foo end
    _right = unparse(right, opt)&.then { |it|
      right.type == :FOR_MASGN || it.empty? ? ""  : " = #{it}"
    }


    # Support: (a,) = value
    if _right&.empty?
      _left = unparse(left, opt.merge(expand_ARRAY: true, ignore_equal_NODE_ATTRASGN: true)) || "*"
    elsif left
      if node_masgn && left.children.count <= 2
        _left = left.children.map(&_unparse(opt.merge(expand_ARRAY: true, ignore_equal_NODE_ATTRASGN: true))).first
      else
        _left = left.children.map(&_unparse(opt.merge(expand_ARRAY: true, ignore_equal_NODE_ATTRASGN: true))).join(", ")
      end
    end

    # Support: for * in 1..3 do foo end
    #          * = foo
    #          a, b, * = foo
    if _NODE_SPECIAL_NO_NAME_REST
      # Support `(a, *) = foo` by 2.6
      if _NODE_SPECIAL_NO_NAME_REST == :dummy
        vname = ""
      elsif _NODE_SPECIAL_NO_NAME_REST != :NODE_SPECIAL_NO_NAME_REST
        vname = unparse(_NODE_SPECIAL_NO_NAME_REST, opt)
      end
      if node_masgn
        _left = left.nil? || _left.empty? ? "*#{vname}" : "#{_left}, *#{vname}"
      else
        _left = left.nil? || _left.empty? ? "*#{vname}" : "#{_left}*#{vname}"
      end
    end

    "(#{_left})#{_right}"
  }
end
NODE_MATCH(node, opt = {}) click to toggle source

match expression (against $_ implicitly) format: [nd_lit] (in condition) example: if /foo/; foo; end

# File lib/rensei/unparser.rb, line 817
def NODE_MATCH(node, opt = {})
  node.children.then { |lit,|
    lit.inspect
  }
end
NODE_MATCH2(node, opt = {}) click to toggle source

match expression (regexp first) format: [nd_recv] =~ [nd_value] example: /foo/ =~ 'foo'

# File lib/rensei/unparser.rb, line 826
def NODE_MATCH2(node, opt = {})
  node.children.then { |recv, value|
    "#{unparse(recv, opt)} =~ #{unparse(value, opt)}"
  }
end
NODE_MATCH3(node, opt = {}) click to toggle source

match expression (regexp second) format: [nd_recv] =~ [nd_value] example: 'foo' =~ /foo/

# File lib/rensei/unparser.rb, line 835
def NODE_MATCH3(node, opt = {})
  node.children.then { |recv, value|
    "#{unparse(value, opt)} =~ #{unparse(recv, opt)}"
  }
end
NODE_MODULE(node, opt = {}) click to toggle source

module definition format: module [nd_cpath]; [nd_body]; end example: module M; ..; end

# File lib/rensei/unparser.rb, line 1071
      def NODE_MODULE(node, opt = {})
        node.children.then { |cpath, body|
          <<~EOS.chomp
          module #{unparse(cpath, opt)}
            #{unparse(body, opt.merge(without_BEGIN: true))}
          end
          EOS
        }
      end
NODE_NEXT(node, opt = {}) click to toggle source

next statement format: next [nd_stts] example: next 1

# File lib/rensei/unparser.rb, line 245
def NODE_NEXT(node, opt = {})
  node.children.then { |stts,|
    "next #{unparse(stts, opt)}"
  }
end
NODE_NIL(*) click to toggle source

nil format: nil example: nil

# File lib/rensei/unparser.rb, line 1158
def NODE_NIL(*)
  "nil"
end
NODE_NTH_REF(node, opt = {}) click to toggle source

nth special variable reference format: $[nd_nth] example: $1, $2, ..

# File lib/rensei/unparser.rb, line 799
def NODE_NTH_REF(node, opt = {})
  node.children.then { |vid,|
    vid.to_s
  }
end
NODE_ONCE(node, opt = {}) click to toggle source

once evaluation format: [nd_body] example: /foo#{ bar }baz/o

# File lib/rensei/unparser.rb, line 871
def NODE_ONCE(node, opt = {})
  "#{NODE_DREGX(node.children.first, opt)}o"
end
NODE_OPCALL(node, opt = {}) click to toggle source

method invocation format: [nd_recv] [nd_mid] [nd_args] example: foo + bar

# File lib/rensei/unparser.rb, line 594
def NODE_OPCALL(node, opt = {})
  node.children.then { |left, op, right|
    # Support !hoge
    if right == nil
      "(#{op.to_s.delete_suffix("@")}#{unparse(left, opt)})"
    else
      "(#{unparse(left, opt)} #{op} #{unparse(right, opt.merge(expand_ARRAY: true))})"
    end
  }
end
NODE_OPT_ARG(node, opt = {}) click to toggle source

optional arguments format: def method_name(, [nd_next..]) example: def foo(a, b=1, c); end

# File lib/rensei/unparser.rb, line 1230
def NODE_OPT_ARG(node, opt = {})
  node.children.map(&_unparse(opt.merge(expand_DASGN_CURR: true, expand_LASGN: true))).compact.join(", ")
end
NODE_OP_ASGN1(node, opt = {}) click to toggle source

array assignment with operator format: [nd_recv] [ [nd_args->nd_head] ] [nd_mid]= [nd_args->nd_body] example: ary += foo

# File lib/rensei/unparser.rb, line 530
def NODE_OP_ASGN1(node, opt = {})
  node.children.then { |recv, op, head, mid|
    "(#{unparse(recv, opt)}[#{unparse(head, opt.merge(expand_ARRAY: true))}] #{op}= #{unparse(mid, opt.merge(expand_ARRAY: true))})"
  }
end
NODE_OP_ASGN2(node, opt = {}) click to toggle source

attr assignment with operator format: [nd_recv]. [nd_next->nd_mid]= [nd_value]

where [attr]: [nd_next->nd_vid]

example: struct.field += foo

# File lib/rensei/unparser.rb, line 540
def NODE_OP_ASGN2(node, opt = {})
  raise NoImplemented, "Non supported `struct.field += foo`."
end
NODE_OP_ASGN_AND(node, opt = {}) click to toggle source

assignment with && operator format: [nd_head] &&= [nd_value] example: foo &&= bar

# File lib/rensei/unparser.rb, line 547
def NODE_OP_ASGN_AND(node, opt = {})
  node.children.then { |head, op, value|
    # MEMO: implement `foo &&= bar` to `(foo = (foo && bar))`
    #       but, AST is not equal
    # value_ = value.children.then { |left, right|
    #   "(#{unparse(left, opt)} && #{unparse(right, opt)})"
    # }
    # "(#{unparse(head)} = #{value_})"
    value.children.then { |left, right|
      "(#{unparse(left, opt)} &&= #{unparse(right, opt)})"
    }
  }
end
NODE_OP_ASGN_OR(node, opt = {}) click to toggle source

assignment with || operator format: [nd_head] ||= [nd_value] example: foo ||= bar

# File lib/rensei/unparser.rb, line 564
def NODE_OP_ASGN_OR(node, opt = {})
  node.children.then { |head, op, value|
    value.children.then { |left, right|
      "(#{unparse(left, opt)} ||= #{unparse(right, opt)})"
    }
  }
end
NODE_OP_CDECL(node, opt = {}) click to toggle source

constant declaration with operator format: [nd_head](constant) [nd_aid]= [nd_value] example: A::B ||= 1

# File lib/rensei/unparser.rb, line 575
def NODE_OP_CDECL(node, opt = {})
  node.children.then { |head, aid, value|
    "(#{unparse(head, opt)} #{aid}= #{unparse(value, opt)})"
  }
end
NODE_OR(node, opt = {}) click to toggle source

|| operator format: [nd_1st] || [nd_2nd] example: foo || bar

# File lib/rensei/unparser.rb, line 357
def NODE_OR(node, opt = {})
  node.children.then { |args|
    # Support pattern match
    # in String | Integer
    if opt[:pattern_match_OR]
      "#{args.map { |node| unparse(node, opt) }.join(" | ")}"
    else
      "(#{args.map { |node| unparse(node, opt) }.join(" || ")})"
    end
  }
end
NODE_POSTARG(node, opt = {}) click to toggle source

post arguments format: *[nd_1st], [nd_2nd..] = .. example: a, *rest, z = foo

# File lib/rensei/unparser.rb, line 1254
def NODE_POSTARG(node, opt = {})
  node.children.then { |_1st, _2nd|
    "#{unparse(_1st, opt)}, #{unparse(_2nd, opt.merge(expand_ARRAY: true))}"
  }
end
NODE_POSTEXE(node, opt = {}) click to toggle source

post-execution format: END { [nd_body] } example: END { foo }

# File lib/rensei/unparser.rb, line 1195
def NODE_POSTEXE(node, opt = {})
  node.children.then { |body,|
    "END { #{unparse(body, opt)} }"
  }
end
NODE_QCALL(node, opt = {}) click to toggle source

safe method invocation format: [nd_recv]&.([nd_args]) example: obj&.foo(1)

# File lib/rensei/unparser.rb, line 646
def NODE_QCALL(node, opt = {})
  node.children.then { |receiver, mid, args|
    "#{unparse(receiver, opt)}&.#{unparse(mid, opt)}(#{unparse(args, opt.merge(_expand_in_XXXCALL(args)))})"
  }
end
NODE_REDO(node, opt = {}) click to toggle source

redo statement format: redo example: redo

# File lib/rensei/unparser.rb, line 263
def NODE_REDO(node, opt = {})
  "redo"
end
NODE_RESBODY(node, opt = {}) click to toggle source

rescue clause (cont'd) format: rescue [nd_args]; [nd_body]; (rescue) [nd_head] example: begin; foo; rescue; bar; else; baz; end

# File lib/rensei/unparser.rb, line 314
def NODE_RESBODY(node, opt = {})
  node.children.then { |args, body|
    args_ = args&.then { |it| unparse(it, opt.merge(expand_ARRAY: true)) }
    if body.type == :BLOCK
      if body.children.first&.children[1]&.type == :ERRINFO
        "rescue #{args_} #{unparse(body, opt.merge(without_BEGIN: true))}"
      else
        "rescue #{args_}; #{unparse(body, opt)}"
      end
    else
      # MEMO: Support by `begin; foo; rescue; bar; else; baz; end`
      "rescue #{args_}; #{unparse(body, opt)}"
    end
  }
end
NODE_RESCUE(node, opt = {}) click to toggle source

rescue clause format: begin; [nd_body]; (rescue) [nd_resq]; else [nd_else]; end example: begin; foo; rescue; bar; else; baz; end

# File lib/rensei/unparser.rb, line 300
      def NODE_RESCUE(node, opt = {})
        node.children.then { |body, resq, else_|
          <<~EOS.chomp
          begin
            #{unparse(body, opt)}
          #{unparse(resq, opt)}#{else_ ? "\nelse\n  #{unparse(else_)}" : ""}
          end
          EOS
        }
      end
NODE_RETRY(node, opt = {}) click to toggle source

retry statement format: retry example: retry

# File lib/rensei/unparser.rb, line 270
def NODE_RETRY(node, opt = {})
  "retry"
end
NODE_RETURN(node, opt = {}) click to toggle source

return statement format: return [nd_stts] example: return 1

# File lib/rensei/unparser.rb, line 254
def NODE_RETURN(node, opt = {})
  node.children.then { |stts,|
    "(return #{unparse(stts, opt)})"
  }
end
NODE_SCLASS(node, opt = {}) click to toggle source

singleton class definition format: class << [nd_recv]; [nd_body]; end example: class << obj; ..; end

# File lib/rensei/unparser.rb, line 1084
      def NODE_SCLASS(node, opt = {})
        node.children.then { |recv, body|
          <<~EOS.chomp
          class << #{unparse(recv, opt)}
            #{unparse(body, opt.merge(without_BEGIN: true))}
          end
          EOS
        }
      end
NODE_SCOPE(node, opt = {}) click to toggle source

new scope format: [nd_tbl]: local table, [nd_args]: arguments, [nd_body]: body

# File lib/rensei/unparser.rb, line 1314
def NODE_SCOPE(node, opt = {})
  result = unparse_NODE_SCOPE(node, opt)
  if result[:args].empty?
    "#{result[:body]}"
  elsif opt[:ITER]
    "|#{result[:args]}| #{result[:body]}"
  else
    "|#{result[:args]}| #{result[:body]}"
  end
end
NODE_SELF(*) click to toggle source

self format: self example: self

# File lib/rensei/unparser.rb, line 1151
def NODE_SELF(*)
  "self"
end
NODE_SPLAT(node, opt = {}) click to toggle source

splat argument format: *[nd_head] example: foo(*ary)

# File lib/rensei/unparser.rb, line 985
def NODE_SPLAT(node, opt = {})
  node.children.then { |head,|
    "*#{unparse(head, opt.merge(expand_ARRAY: false))}"
  }
end
NODE_STR(node, opt = {}) click to toggle source

string literal format: [nd_lit] example: 'foo'

# File lib/rensei/unparser.rb, line 851
def NODE_STR(node, opt = {})
  if opt.delete(:ignore_quote_STR)
    node.children.first.to_s.escape
  else
    node.children.first.inspect
  end
end
NODE_SUPER(node, opt = {}) click to toggle source

super invocation format: super [nd_args] example: super 1

# File lib/rensei/unparser.rb, line 655
def NODE_SUPER(node, opt = {})
  node.children.then { |args, |
    "super(#{unparse(args, opt.merge(expand_ARRAY: true))})"
  }
end
NODE_TRUE(*) click to toggle source

true format: true example: true

# File lib/rensei/unparser.rb, line 1165
def NODE_TRUE(*)
  "true"
end
NODE_UNDEF(node, opt = {}) click to toggle source

method undef statement format: undef [nd_undef] example: undef foo

# File lib/rensei/unparser.rb, line 1049
def NODE_UNDEF(node, opt = {})
  node.children.then { |nd_undef,|
    "undef #{unparse(nd_undef, opt)}"
  }
end
NODE_UNLESS(node, opt = {}) click to toggle source

unless statement format: unless [nd_cond] then [nd_body] else [nd_else] end example: unless x == 1 then foo else bar end

# File lib/rensei/unparser.rb, line 106
      def NODE_UNLESS(node, opt = {})
        node.children.then { |cond, body, else_|
          <<~EOS.chomp
            (unless #{unparse(cond, opt)}
              #{unparse(body, opt)}#{else_ ? "\nelse\n  #{unparse(else_, opt)}" : ""}
            end)
          EOS
        }
      end
NODE_UNTIL(node, opt = {}) click to toggle source

until statement format: until [nd_cond]; [nd_body]; end example: until x == 1; foo; end

# File lib/rensei/unparser.rb, line 182
      def NODE_UNTIL(node, opt = {})
        node.children.then { |cond, body, state|
          # MEMO: state is not supported Ruby 2.6
          state = true if state.nil?
          if state
            <<~EOS.chomp
            until #{unparse(cond, opt)}
              #{unparse(body, opt)}
            end
            EOS
          # state: begin-end-until
          else
            <<~EOS.chomp
            begin
              #{unparse(body, opt)}
            end until #{unparse(cond, opt)}
            EOS
          end
        }
      end
NODE_VALIAS(node, opt = {}) click to toggle source

global variable alias statement format: alias [nd_alias](gvar) [nd_orig](gvar) example: alias $y $x

# File lib/rensei/unparser.rb, line 1040
def NODE_VALIAS(node, opt = {})
  node.children.then { |nd_1st, nd_2nd|
    "alias #{nd_1st} #{nd_2nd}"
  }
end
NODE_VALUES(node, opt = {}) click to toggle source

return arguments format: [ [nd_head], [nd_next].. ] (length: [nd_alen]) example: return 1, 2, 3

# File lib/rensei/unparser.rb, line 684
def NODE_VALUES(node, opt = {})
  node.children[0..-2].map(&_unparse(opt)).join(", ")
end
NODE_VCALL(node, opt = {}) click to toggle source

function call with no argument format: [nd_mid] example: foo

# File lib/rensei/unparser.rb, line 639
def NODE_VCALL(node, opt = {})
  node.children.first.to_s
end
NODE_WHEN(node, opt = {}) click to toggle source

when clause format: when [nd_head]; [nd_body]; (when or else) [nd_next] example: case x; when 1; foo; when 2; bar; else baz; end

# File lib/rensei/unparser.rb, line 145
      def NODE_WHEN(node, opt = {})
        node.children.then { |head, body, next_|
          <<~EOS.chomp
          when #{unparse(head, opt.merge(expand_ARRAY: true))}
            #{unparse(body, opt)}
          #{next_&.type == :WHEN || next_.nil? ? unparse(next_, opt) : "else\n  #{unparse(next_, opt)}"}
          EOS
        }
      end
NODE_WHILE(node, opt = {}) click to toggle source

while statement format: while [nd_cond]; [nd_body]; end example: while x == 1; foo; end

# File lib/rensei/unparser.rb, line 158
      def NODE_WHILE(node, opt = {})
        node.children.then { |cond, body, state|
          # MEMO: state is not supported Ruby 2.6
          state = true if state.nil?
          if state
            <<~EOS.chomp
            while #{unparse(cond, opt)}
              #{unparse(body, opt)}
            end
            EOS
          # state: begin-end-while
          else
            <<~EOS.chomp
            begin
              #{unparse(body, opt)}
            end while #{unparse(cond, opt)}
            EOS
          end
        }
      end
NODE_XSTR(node, opt = {}) click to toggle source

xstring literal format: [nd_lit] example: `foo`

# File lib/rensei/unparser.rb, line 862
def NODE_XSTR(node, opt = {})
  node.children.then { |lit,|
    "`#{lit.to_s}`"
  }
end
NODE_YIELD(node, opt = {}) click to toggle source

yield invocation format: yield [nd_head] example: yield 1

# File lib/rensei/unparser.rb, line 732
def NODE_YIELD(node, opt = {})
  node.children.then { |head,|
    "yield(#{unparse(head, opt.merge(expand_ARRAY: true))})"
  }
end
NODE_ZARRAY(node, opt = {}) click to toggle source

empty list constructor format: [] example: []

# File lib/rensei/unparser.rb, line 691
def NODE_ZARRAY(node, opt = {})
  "[]"
end
NODE_ZSUPER(node, opt = {}) click to toggle source

super invocation with no argument format: super example: super

# File lib/rensei/unparser.rb, line 664
def NODE_ZSUPER(node, opt = {})
  "super"
end
_expand_in_XXXCALL(node) click to toggle source
# File lib/rensei/unparser.rb, line 605
def _expand_in_XXXCALL(node)
  case node&.type
  when :ARRAY, :LIST
    opt_flags = { expand_ARRAY: true }
  when :ARGSCAT
    opt_flags = { expand_ARGSCAT: true }
  when :ARGSPUSH
    opt_flags = { expand_ARGSPUSH: true }
  when :BLOCK_PASS
    _expand_in_XXXCALL(node.children.first)
  else
    opt_flags = { expand_ARRAY: true }
  end
end
_unparse(opt = {}) click to toggle source
# File lib/rensei/unparser.rb, line 54
def _unparse(opt = {})
  proc { |node| unparse(node, opt.dup) }
end
unparse_NODE_ARGS(node, opt = {}) click to toggle source
# File lib/rensei/unparser.rb, line 1278
def unparse_NODE_ARGS(node, opt = {})
  %i(
    pre_num
    pre_init
    opt
    first_post
    post_num
    post_init
    rest
    kw
    kwrest
    block
  ).map.with_index { |key, i| [key, node.children[i]] }.to_h.then { |info|
    info.merge(
      unparsed_pre_init: info[:pre_init]&.then { |node|
        node.type == :BLOCK ? node.children.map(&_unparse(opt)) : [unparse(node, opt)]
      } || [],
      unparsed_post_init: info[:post_init]&.then { |node|
        node.type == :BLOCK ? node.children.map(&_unparse(opt)) : [unparse(node, opt)]
      } || [],
      unparsed_opt: info[:opt]&.then { |it| unparse_NODE_OPT_ARG(it, opt.merge(expand_DASGN_CURR: true, expand_LASGN: true)) } || [],
      unparsed_rest: unparse(info[:rest], opt)&.then { |it|
        if it == :NODE_SPECIAL_EXCESSIVE_COMMA
          [" "]
        else
          ["*#{it}"]
        end
      } || [],
      unparsed_kw: info[:kw]&.then { |it| unparse_NODE_KW_ARG(it, opt.merge(expand_DASGN_CURR: true, expand_LASGN: true, KW_ARG: true)) } || [],
      unparsed_kwrest: info[:kwrest]&.then { |it| "**#{unparse(it, opt)}" },
    )
  }
end
unparse_NODE_KW_ARG(node, opt = {}) click to toggle source
# File lib/rensei/unparser.rb, line 1245
def unparse_NODE_KW_ARG(node, opt = {})
  node.children.then { |head, children|
    [unparse(head, opt)] + (children ? unparse_NODE_KW_ARG(children, opt) : [])
  }
end
unparse_NODE_OPT_ARG(node, opt = {}) click to toggle source
# File lib/rensei/unparser.rb, line 1233
def unparse_NODE_OPT_ARG(node, opt = {})
  node.children.then { |head, children|
    [unparse(head, opt)] + (children ? unparse_NODE_OPT_ARG(children, opt) : [])
  }
end
unparse_NODE_SCOPE(node, opt = {}) click to toggle source
# File lib/rensei/unparser.rb, line 1324
def unparse_NODE_SCOPE(node, opt = {})
  node.children.then { |tbl, args, body|
    break { args: "", body: unparse(body, opt) } if args.nil?

    info = unparse_NODE_ARGS(args, opt.merge(_NODE_MASGN: true))

    # Support proc { |**| }
    break { args: "**", body: unparse(body, opt) } if tbl == [nil] && info[:kwrest]

    tbl_ = tbl.dup
    pre_args = []
    [info[:pre_num], info[:unparsed_pre_init]&.size || 0].max.times {
      tbl_.shift.then { |it|
        pre_args << (it ? it : info[:unparsed_pre_init].shift)
      }
    }

    # skip to opt args
    # e.g. a = 1, b = 2
    tbl_ = tbl_.drop(info[:unparsed_opt].count)

    # skip to rest args
    # e.g. *a
    tbl_ = tbl_.drop(info[:unparsed_rest].count)

    star = nil
    tbl_.take_while(&:nil?).tap { |nils|
      if info[:unparsed_post_init].count < nils.count
        star = "*"
        tbl_ = tbl_.drop(1)
      end
    }

    post_args = []
    [info[:post_num], info[:unparsed_post_init]&.size || 0].max.times {
      tbl_.shift.then { |it|
        post_args << (it ? it : info[:unparsed_post_init].shift)
      }
    }

    # skip to kw args
    # e.g. a:, b: c: 1
    tbl_ = tbl_.drop(info[:unparsed_kw].count.tap { |count| break count + 1 if count != 0 })

    if info[:unparsed_kwrest] == "**" && tbl_.fetch(0, 1) != nil
      kwrest = ""
    else
      kwrest = info[:unparsed_kwrest]
    end

    if opt.delete(:ignore_numbered_paramters)
      pre_args -= [:_1, :_2, :_3, :_4, :_5, :_6, :_7, :_8, :_9]
    end

    params = [
      pre_args,
      info[:unparsed_opt].join(", "),
      info[:unparsed_rest].join(", "),
      star,
      post_args,
      info[:unparsed_post_init].join(", "),
      info[:unparsed_kw].join(", "),
      kwrest,
      info[:block]&.then { |str| "&#{str}" },
    ].compact.reject(&:empty?).join(", ")

    { args: params, body: unparse(body, opt) }
  }
end
without_DSTR_quote(node, opt) click to toggle source
# File lib/rensei/unparser.rb, line 881
def without_DSTR_quote(node, opt)
  node.children.then { |prefix, lit, suffix|
    suffix_ = suffix&.children&.compact&.map { |it|
      if it.type == :STR
        unparse(it, opt.merge(ignore_quote_STR: true))
      else
        unparse(it, opt.merge(ignore_quote_STR: false))
      end
    }&.join
    "#{prefix&.escape}#{unparse(lit, opt)}#{suffix_}"
  }
end