class Macro::FormNode
postpone macro expansion (and definition) in forms until they are evaled (or returned from a macro) but not in form parameters
The syntax node for forms
Public Class Methods
# File lib/macro/form.rb, line 82 def self._load str result=allocate result.replace [Marshal.load(str)] result.rebuild_transform end
Create a new form node. The user should normally not call this function. Form nodes are created by the parser.
colon
-
A colon token
text
-
A ParenedNode or VarLikeNode
# File lib/macro/form.rb, line 37 def initialize(colon,text) @startline=@endline=nil # Certain node types need to be quoted # (or rather, not unquoted) if RedParse::VarLikeNode===text #this code is dead now, I believe @transform=HashLiteralNode[] @stars_transform=HashLiteralNode[] text.startline=text.endline=0 super text return end # Sanity check - make sure this is a valid ParenedNode if ParenedNode===text && text.size==1 text=text.body #unquote the form elsif text.size==0 @transform=HashLiteralNode[] @stars_transform=HashLiteralNode[] super SequenceNode[] return end super text rebuild_transform end
Public Instance Methods
# File lib/macro/form.rb, line 78 def _dump depth Marshal.dump text,depth end
Make a deep copy of this form
transform
-
TODO
# File lib/macro/form.rb, line 162 def deep_copy transform={} super(transform).rebuild_transform end
Iterate over all the parameters in this form
block
-
the block to call for each parameter
# File lib/macro/form.rb, line 154 def each_parameter(&block) @parameters.each(&block) if defined? @parameters end
Lazily evaluate the name of the form and return it
# File lib/macro/form.rb, line 265 def formname startline=@startline if defined? @startline endline=@endline if defined? @endline ivars={:@startline=>startline, :@endline=>endline} @formname ||= ConstantNode[nil,"Macro","Names",::Macro::Names.request(self), ivars] end
# File lib/macro/form.rb, line 70 def initialize_copy other replace other other.instance_variables{|v| instance_variable_set v, other.instance_variable_get(v) } rebuild_transform end
def _dump depth
"foobarbaz"
end
def self._load str
result=allocate
end
# File lib/macro/form.rb, line 98 def initialize_ivars rebuild_transform super end
# File lib/macro.rb, line 680 def macro_expand(macros,session) #return text.to_sexp({}) #maybe this doesn't allow expansion of parameters themselves... only within params? each_parameter{|param| Macro.expand(param,macros,session) } #replace (text for) form itself with a reference which will be #looked up at runtime (and have parameters expanded at that point too) return parses_like,false #halt further recursion: already done where necessary end
# File lib/macro/form.rb, line 66 def noinspect_instance_variables %w[@stars_transform @transform] end
Turn the form into something that is legal ruby (since :(..) is not legal ruby syntax). Thus the form is changed from the syntax:
:(code)
to:
RedParse::SomeNodeType[ some transform of code ]
# File lib/macro/form.rb, line 253 def parses_like startline=@startline if defined? @startline endline=@endline if defined? @endline ivars={:@startline=>startline, :@endline=>endline} CallSiteNode[ CallSiteNode[formname, "reify", [@transform,@stars_transform], ivars], "text", ivars ] #:(^(formname).reify(^@transform,^@stars_transform).text) end
Transform this node into a ParseTree parse tree
# File lib/macro/form.rb, line 221 def parsetree parses_like.parsetree end
Initialize the transform and create all the form escapes that are used in this form
# File lib/macro/form.rb, line 105 def rebuild_transform # TODO: this method needs to be better documented/refactored @transform=HashLiteralNode[] @stars_transform=HashLiteralNode[] @parameters=[] @parameters.extend RedParse::ListInNode walkers=proc{|rcvr,wraplayers| #curry rcvr.walk{|parent,i,j,node| node.startline=node.endline=0 if node.respond_to? :startline case node when FormEscapeNode target=node.wraplevel #fail if wraplayers > target if wraplayers==target #skip this parameter if it doesn't have enough wrappers @parameters << node #remember parameter (and implicitly, location) nil# and stop further recursion else true end when FormNode #walk form with same walker we're using now, except an extra layer of form parameters #must be present for them to be considered 'our' parameters walkers[node.text,wraplayers+1] nil #don't recurse in this node again, we just did it else true end } if rcvr.respond_to? :walk } walkers[text,1] @parameters.each{|orig_escd| escd=orig_escd escd=escd.val while FormEscapeNode===escd if UnaryStarNode===escd @stars_transform.push LiteralNode[orig_escd.__id__], escd.val else @transform.push LiteralNode[orig_escd.__id__], escd end } return self end
# File lib/macro/ReduceWithsFor_RedParse_RedParse__MacroMixin_RedParse__WithMacros_1_8.rb, line 18862 def reducer_ident :FormNode end
Called when the form is evaluated to convert the abstract form of the parse tree into a concrete form that can be modified (makes a copy of the form).
transform
-
the transform to use in the deep copy
# File lib/macro/form.rb, line 181 def reify transform, stars_transform transform&&=transform.dup stars_transform&&=stars_transform.dup transform.each_pair{|k,v| case v when Node; next when Symbol; v=CallNode[nil,v.to_s] else v=Macro.quote v end transform[k]=v } stars_transform.each_pair{|k,v| case v when Symbol; v=CallNode[nil,v.to_s] else v=Macro.quote v end stars_transform[k]=v.extend InlineList } result=deep_copy(transform.merge( stars_transform )) #expand InlineLists somehow result.walk{|parent,i,j,node| if InlineList===node if j parent[i][j,1]=*node else parent[i,1]=*node end nil #halt further recursion else true end } unless stars_transform.empty? return result end
Convert this node to an S-expression
session
-
the context in which this macro is being processed
# File lib/macro.rb, line 701 def to_sexp session nest=session[:form_nest_level] session[:form_nest_level]=nest ? nest+1 : 2 result=super if nest session[:form_nest_level]-=1 else session.delete :form_nest_level end return result end
Performs the reverse of a parse operation (turns the node into a string)
o
-
a list of options for unparse
# File lib/macro/form.rb, line 171 def unparse o=default_unparse_options ":("+text.unparse(o)+")" end