Class: Macro::CallSiteNode

Inherits:
Object show all
Defined in:
lib/macro.rb

Overview

look for macro invocations, and expand them

Instance Method Summary collapse

Instance Method Details

#macro_expand(macros, session) ⇒ Object



518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
# 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