class Macro::CallSiteNode

look for macro invocations, and expand them

Public Instance Methods

macro_expand(macros,session) click to toggle source
# File lib/macro.rb, line 518
def macro_expand(macros,session)
  
  name=self.name
  #pp macros
  #pp Macro::GLOBALS
  macro=macros[name.to_sym]
  unless macro
    #turn off modpath surity in blocks.
    #this disables modpath surity in callsite receivers and parameters as well;
    #unnecessary, but no great loss.
    old_unsure=session[:@modpath_unsure]
    session[:@modpath_unsure]=true
    map!{|node| 
      case node
      when Node; Macro.expand node,macros,session
      when Array; node.map{|item| Macro.expand item,macros,session}
      else node
      end
    }
    session[:@modpath_unsure]=old_unsure

    return nil,false #change nothing, recursion done already
  end
  return nil,true unless macro #change nothing but keep recursing if not a macro

  Method===macro or fail

  args = args()||[]

  #if this callsite names a macro, then it is a macro
  #macro=macros[name.to_sym]=::Object.method(macro) if String===macro
  #refuse macro calls with receivers, blocks, varargs, or &args: not supported yet
  fail "macro blocky args not supported yet" if UnOpNode===args.last and args.last.ident=="&@"
  fail "macro varargs calls not supported yet" if UnaryStarNode===args.last
  fail if args.class!=Array
  args.unshift receiver||VarLikeNode.allocate.replace(["self"])
  if block
    newnode=macro.call( *args )do |*bparams|
              if !blockparams
                block
              else
                bparams=KWCallNode["nil"] if bparams.empty?
                #warning: scoping rules for lvars in blocks not enforced here
                #(rather serious violation of variable hygiene)
                ParenedNode[ AssignNode[MultiAssign[*blockparams],'=',bparams]+block ]
              end
            end
  else
    newnode=macro.call( *args )
  end
  #subi ? parent[i][subi]=newnode : parent[i]=newnode

  # and keep recursing, no matter what, by all means!!
  if newnode
    newnode=Macro.expand newnode,macros,session #just do it here
    newnode=OneLineParenedNode[newnode] #disable newlines in macro text
  else
    newnode=JustNilNode.new
  end
  return newnode,false                        #and not in caller
end