class Macro::MacroNode

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

Public Class Methods

new(macroword,header,semi,body,rescues,else_,ensure_,endword) click to toggle source
# 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

Public Instance Methods

macro_expand(macros,session) click to toggle source
# 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_ident() click to toggle source
# File lib/macro/ReduceWithsFor_RedParse_RedParse__MacroMixin_RedParse__WithMacros_1_8.rb, line 18872
def reducer_ident
  :MacroNode
end
unparse(o=default_unparse_options) click to toggle source

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

o

a list of options for unparse

# 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