Class: Macro::MacroNode

Inherits:
ValueNode
  • Object
show all
Defined in:
lib/macro.rb,
lib/macro/ReduceWithsFor_RedParse_RedParse__MacroMixin_RedParse__WithMacros_1_9.rb,
lib/macro/ReduceWithsFor_RedParse_RedParse__MacroMixin_RedParse__WithMacros_1_8.rb,
lib/macro.rb

Overview

look for macro definitions, save them and convert them to method definitions

Instance Method Summary collapse

Constructor Details

#initialize(macroword, header, semi, body, rescues, else_, ensure_, endword) ⇒ MacroNode

Returns a new instance of MacroNode.



743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
# File 'lib/macro.rb', line 743

def initialize(macroword,header,semi,body,rescues,else_,ensure_,endword)
    #decompose header
    if CallSiteNode===header
      receiver=header.receiver
      args=header.args
      header=header.name
    end
    if MethNameToken===header #not needed?
      header=header.ident
    end

    unless String===header
      fail "unrecognized method header: #{header}"
    end
    @data=replace [receiver,header,args,body,rescues,else_,ensure_]

=begin hmm, maybe not a good idea....
    #quote parameters to yield within macro
    walk{|cntr,i,subi,item|
      case item
      when KWCallNode;
        if item.name=="yield" 
          raise ArgumentError if item.block or item.blockparams
          if item.params
            raise ArgumentError if UnAmpNode===item.params.last
            item.params.map!{|param| FormNode.new(nil,ParenedNode[param]) }
          end
          false
        else true
        end
      else true
      end
    }
=end
end

Instance Method Details

#macro_expand(macros, session) ⇒ Object



440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
# File 'lib/macro.rb', line 440

def macro_expand(macros,session)
    fail "scoped macros are not allowed (yet)" unless session[:@modpath].empty?

    #varargs, &args and receivers are not allowed in macro definitions (yet)
    fail "macro receivers not supported yet" if receiver
    if args
      last=args
#        else
#          last=args.last
    end
    fail "macro varargs and block not supported yet" if UnOpNode===last and /\A[*&]@\Z/===last.op.ident

    name=self.name
    #macros can't be settors
    fail "macro settors are not allowed" if /=$/===name

    self.args||=[]
    args.unshift VarNode.allocate.replace(["receiver"])
    self.walk{|parent,i,subi,node| #replace self kw in body with receiver var instead
      if VarLikeNode===node and node.ident=="self"
        if subi
          parent[i][subi]=VarNode.allocate.replace(["receiver"])
        else
          parent[i]=VarNode.allocate.replace(["receiver"])
        end
      end
      true
    }

      #macro definitions need to be dealt with in 2 steps: registration and activation
#        name=self.name
    self[1]="macro_"+name unless /^macro_/===name
    node=MethodNode[*self]  #convert macro node to a method def node
    huh(node.receiver) if node.receiver
    node[0]=ParenedNode[ConstantNode[nil,"Object"]] #all macros are global for now... til we get scoped macros
    #sets receiver

    #disable postponement (delayed macros) ... i think they're not necessary
    expand=proc{|x| Node===x ? Macro.expand(x,macros,session) : x}
    node.receiver= expand[node.receiver]
    node.args.map!( &expand )if node.args
    node.body= expand[node.body]
    node.rescues.map!( &expand )if node.rescues
    node.ensure_= expand[node.ensure_]
    node.else_= expand[node.else_]
    node.eval(nil,session[:filename])
    macros[name.to_sym]=::Object.method("macro_"+name)
    return node,false
=begin was
    #node.eval #no, not here....

    newnode=Macro.postpone node, session

    #newnode=:((
    #  ^newnode
    #  Macro::GLOBALS[^name.to_sym]=Object.method ^node.name.to_sym
    #  nil
    #))
    newnode=ParenedNode[SequenceNode[
      newnode, 
      CallNode[ConstantNode[nil,"Macro", "GLOBALS"],"[]=",[
        LiteralNode[name.to_sym], 
        CallNode[ConstantNode[nil,"Object"], "method", 
             [LiteralNode[node.name.to_sym]],nil,nil]],
       nil,nil],
      VarLikeNode['nil']
    ]]


    #newnode=RedParse::VarLikeNode["nil", {:@value=>false,}]
    #subi ? parent[i][subi]=newnode : parent[i]=newnode          
    return newnode,false #dont keep recursing
=end
end

#reducer_identObject



19093
19094
19095
# File 'lib/macro/ReduceWithsFor_RedParse_RedParse__MacroMixin_RedParse__WithMacros_1_9.rb', line 19093

def reducer_ident
  :MacroNode
end

#unparse(o = default_unparse_options) ⇒ Object

Performs the reverse of a parse operation (turns the MacroNode into a string)

o

a list of options for unparse



789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
# File 'lib/macro.rb', line 789

def unparse o=default_unparse_options
  result="macro "
  result+=receiver.unparse(o)+'.' if receiver
  result+=name
  if args and !args.empty?
    result+="("
    result+=args.map{|arg| arg.unparse o}.join','
    result+=")"
  end
  result+=unparse_nl(body,o)+body.unparse(o) if body
  result+=rescues.map{|resc| resc.unparse o}.to_s if rescues
  result+=unparse_nl(else_,o)+"else "+else_.unparse( o )+"\n" if else_
  result+=unparse_nl(ensure_,o)+"ensure "+ensure_.unparse( o )+"\n" if ensure_
  result+=";end"
  return result
end