Class: RedParse::MethodNode

Inherits:
ValueNode show all
Includes:
HasRescue
Defined in:
lib/redparse/node.rb

Constant Summary

Constants included from FlattenedIvars

FlattenedIvars::EXCLUDED_IVARS

Instance Attribute Summary collapse

Attributes inherited from Node

#endline, #errors, #offset, #parent, #startline

Attributes included from Stackable::Meta

#boolean_identity_params, #identity_params

Class Method Summary collapse

Instance Method Summary collapse

Methods included from HasRescue

#parsetree_and_rescues, #unparse_and_rescues

Methods inherited from ValueNode

#lvalue

Methods inherited from Node

#+, #+@, #==, [], #[]=, #add_parent_links!, #begin_parsetree, create, #data, #deep_copy, #delete_extraneous_ivars!, #delete_linenums!, #depthwalk, #depthwalk_nodes, #error?, #evalable_inspect, #fixup_multiple_assignments!, #fixup_rescue_assignments!, #initialize_ivars, inline_symbols, #inspect, #lhs_unparse, #linerange, #lvalue, #lvars_defined_in, #merge_replacement_session, #negate, #original_brackets_assign, param_names, #parsetrees, #pretty_print, #prohibit_fixup, #replace_ivars_and_self, #replace_value, #rescue_parsetree, #to_parsetree, #to_parsetree_and_warnings, #unary, #walk, #xform_tree!

Methods included from Stackable::Meta

#build_exemplars, #enumerate_exemplars, #identity_param

Methods included from FlattenedIvars

#flattened_ivars, #flattened_ivars_equal?

Methods included from Stackable

#identity_name

Constructor Details

#initialize(defword, header, maybe_eq_, semi_, body, rescues, else_, ensure_, endword_) ⇒ MethodNode

Returns a new instance of MethodNode.



4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
# File 'lib/redparse/node.rb', line 4494

def initialize(defword,header,maybe_eq_,semi_,
               body,rescues,else_,ensure_,endword_)
  @offset=defword.offset
  @empty_else=@empty_ensure=nil
#        if DotCallNode===header
#          header=header.data[1]
#        end
  if CallSiteNode===header
    receiver=header.receiver
    args=header.args
    header=header.name
  end
  if MethNameToken===header
    header=header.ident 
  end
  unless String===header
    fail "unrecognized method header: #{header}"
  end
  if else_
    else_=else_.val  or @empty_else=true
  end
  if ensure_
    ensure_=ensure_.val or @empty_ensure=true
  end
  args.extend ListInNode if args
  rescues.extend ListInNode if rescues
  replace [receiver,header,args,body,rescues,else_,ensure_]
end

Instance Attribute Details

#empty_elseObject (readonly)

Returns the value of attribute empty_else.



4523
4524
4525
# File 'lib/redparse/node.rb', line 4523

def empty_else
  @empty_else
end

#empty_ensureObject (readonly)

Returns the value of attribute empty_ensure.



4523
4524
4525
# File 'lib/redparse/node.rb', line 4523

def empty_ensure
  @empty_ensure
end

Class Method Details

.namelistObject



4525
4526
4527
# File 'lib/redparse/node.rb', line 4525

def self.namelist
  %w[receiver name args body rescues elses ensures]
end

Instance Method Details

#else_=(x) ⇒ Object



4541
4542
4543
# File 'lib/redparse/node.rb', line 4541

def else_= x
  self[6]=x      
end

#ensure_=(x) ⇒ Object

def receiver= x

  self[0]=x      
end

def body= x
  self[3]=x      
end


4537
4538
4539
# File 'lib/redparse/node.rb', line 4537

def ensure_= x
  self[5]=x      
end

#imageObject



4545
4546
4547
# File 'lib/redparse/node.rb', line 4545

def image
  "(def #{receiver.image.+('.') if receiver}#{name})"
end

#parsetree(o) ⇒ Object



4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
# File 'lib/redparse/node.rb', line 4573

def parsetree(o)
  name=name()
  name=name.chop if /^[!~]@$/===name
  name=name.to_sym

  result=[name, target=[:scope, [:block, ]] ]
  if receiver
    result.unshift :defs, receiver.rescue_parsetree(o)
  else
    result.unshift :defn
  end

  goodies= (body or !rescues.empty? or elses or ensures or @empty_ensure) # or args())

  if unamp=args() and unamp=unamp.last and UnOpNode===unamp and unamp.op=="&@"
    receiver and goodies=true
  else 
    unamp=false
  end

  if receiver and !goodies
    target.delete_at 1 #omit :block
  else
    target=target[1]
  end

  target.push args=[:args,]
  target.push unamp.parsetree(o) if unamp

  if args()
    initvals=[]
    args().each{|arg| 
        case arg
            when VarNode
              args.push arg.ident.to_sym
            when UnaryStarNode
              args.push "*#{arg.val.ident}".to_sym
            when UnOpNode
              nil
            when AssignNode
              initvals << arg.parsetree(o)
              initvals[-1][-1]=arg.right.rescue_parsetree(o) #ugly
              args.push arg[0].ident.to_sym
            else 
              fail "unsupported node type in method param list: #{arg}"
        end
    }
    unless initvals.empty?
      initvals.unshift(:block) 
      args << initvals
      #args[-2][0]==:block_arg and target.push args.delete_at(-2)
    end
  end
  target.push [:nil] if !goodies && !receiver

  #it would be better to use parsetree_and_rescues for the rest of this method,
  #just to be DRYer

  target.push ensuretarget=target=[:ensure, ] if ensures or @empty_ensure
  #simple dup won't work... won't copy extend'd modules
  body=Marshal.load(Marshal.dump(body())) if body()
  elses=elses()
  if rescues.empty?
    case body
    when SequenceNode; body << elses;elses=nil
    when nil; body=elses;elses=nil
    else nil
    end if elses
  else
    target.push target=[:rescue, ] 
    elses=elses()
  end
  if body
    if BeginNode===body||RescueOpNode===body and 
      body.rescues.empty? and !body.ensure and !body.empty_ensure and body.body and body.body.size>1
        wantblock=true
    end
    body=body.parsetree(o)
    if body.first==:block and rescues.empty? and not ensures||@empty_ensure
      if wantblock
        target.push body
      else
        body.shift 
        target.concat body
      end
    else
      #body=[:block, *body] if wantblock
      target.push body
    end
  end
  target.push linked_list(rescues.map{|rescue_| rescue_.parsetree(o) }) unless rescues.empty?
  target.push elses.parsetree(o) if elses
  ensuretarget.push ensures.parsetree(o) if ensures
  ensuretarget.push [:nil] if @empty_ensure

  return result
end

#to_lispObject



4568
4569
4570
4571
# File 'lib/redparse/node.rb', line 4568

def to_lisp
  "(imethod #{name} is\n#{body.to_lisp}\n)\n"
  #no receiver, args, rescues, else_ or ensure_...
end

#unparse(o = default_unparse_options) ⇒ Object



4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
# File 'lib/redparse/node.rb', line 4549

def unparse o=default_unparse_options
  result=[
   "def ",receiver&&receiver.unparse(o)+'.',name,
     args && '('+args.map{|arg| arg.unparse o}.join(',')+')', unparse_nl(body||self,o)
  ]
  result<<unparse_and_rescues(o)
=begin
  body&&result+=body.unparse(o)

  result+=rescues.map{|resc| resc.unparse o}.to_s 
  result+="else #{else_.unparse o}\n"  if else_
  result+="else\n" if @empty_else
  result+="ensure #{ensure_.unparse o}\n"  if ensure_
  result+="ensure\n" if @empty_ensure
=end

  result<<unparse_nl(endline,o)+"end"
  result.join
end