class Macro::Node

Public Instance Methods

eval(binding=nil,file=nil,line=nil) click to toggle source

just like Kernel#eval, but allows macros (and forms) and input is a RedParse parse tree (as receiver). beware: default for binding is currently broken. best practice is to pass an explicit binding (see Kernel#binding) for now.

+binding+:: the binding in which to evaluate the node
+file+::    for purpose of evaluation, the name of the file this node
            came from
+line+::    for purpose of evaluation, the line number this node came
            from
# File lib/macro.rb, line 284
def eval(binding=nil,file=nil,line=nil)
  #binding should default to Binding.of_caller, but.... that's expensive

  if String===binding
    file=binding
    binding=nil
  end
 
  #references to 'self' (implicit and explicit) within this parse tree
  #should be forced to refer to the self from binding, (if any)...

  expanded_tree=self   #Macro.expand(deep_copy,::Macro::GLOBALS)

  unparsed=expanded_tree.unparse
  #puts unparsed
  ::Kernel.eval unparsed, binding||::Object.new_binding,file||'(eval)',line||1
end
load(name='',wrap=false) click to toggle source

A helper for Macro.load and Macro.eval. The source code for the node is saved to a file so that it can be viewed in the debugger.

name

the name of the file being loaded

wrap

whether to wrap the loaded file in an anonymous module

# File lib/macro.rb, line 308
def load(name='',wrap=false)
  expanded_tree=self    #Macro.expand(deep_copy,::Macro::GLOBALS)

  #replace __FILE__ in tree with the correct file name
  #(otherwise, it will point to some tmp file)
  filenamenode=nil
  expanded_tree.walk{|parent,i,subi,node|
    if VarLikeNode===node and node.ident=="__FILE__"
      filenamenode||=Macro.quote name #StringNode[name.gsub(/['\\]/){|ch| '\\'+ch},{:@open=>"'", :@close=>"'"}]
      if parent
        subi ? parent[i][subi]=filenamenode : parent[i]=filenamenode
      else
        expanded_tree=filenamenode
      end
    end
    true
  }
  
  unparsed=expanded_tree.unparse
  #p expanded_tree
  #puts unparsed
  Tempfile.open("macroexpanded_"+name.gsub("/","__")){|tf|
    tf.write unparsed
    tf.flush
    ::Kernel::load tf.path, wrap
  }
  return true
end
to_sexp(session) click to toggle source

Convert this node to an S-expression

session

the context in which this macro is being processed

# File lib/macro.rb, line 341
def to_sexp session
  # TODO: this (and all other functions similarly named) is possibly
  # dead code
  self.class.name+"["+
    map{|param| call_to_sexp param,session }.join(", ")+
    ", {"+instance_variables.map{|iv| 
            iv=="@data" and next
            val=instance_variable_get(iv)
            val=call_to_sexp(val,session)
            ":"+iv+"=>"+val
          }.join(", ")+"}"+
  "]"
end

Private Instance Methods

call_to_sexp(param,session) click to toggle source
# File lib/macro.rb, line 356
def call_to_sexp param,session
  if param.instance_of? ::Array 
    "["+param.map{|subparam| call_to_sexp(subparam,session)}.join(", ")+"]"
  elsif param.respond_to?(:to_sexp) 
    param.to_sexp(session) 
  else
    param.inspect
  end
end