Class: Macro::FormNode
- Defined in:
- lib/macro/form.rb,
lib/macro/ReduceWithsFor_RedParse_RedParse__MacroMixin_RedParse__WithMacros_1_9.rb,
lib/macro/ReduceWithsFor_RedParse_RedParse__MacroMixin_RedParse__WithMacros_1_8.rb,
lib/macro.rb
Overview
postpone macro expansion (and definition) in forms until they are evaled (or returned from a macro) but not in form parameters
Defined Under Namespace
Modules: InlineList
Class Method Summary collapse
Instance Method Summary collapse
- #_dump(depth) ⇒ Object
-
#deep_copy(transform = {}) ⇒ Object
Make a deep copy of this form.
-
#each_parameter(&block) ⇒ Object
Iterate over all the parameters in this form.
-
#formname ⇒ Object
Lazily evaluate the name of the form and return it.
-
#initialize(colon, text) ⇒ FormNode
constructor
Create a new form node.
- #initialize_copy(other) ⇒ Object
-
#initialize_ivars ⇒ Object
def _dump depth “foobarbaz” end.
- #macro_expand(macros, session) ⇒ Object
- #noinspect_instance_variables ⇒ Object
-
#parses_like ⇒ Object
Turn the form into something that is legal ruby (since :(..) is not legal ruby syntax).
-
#parsetree ⇒ Object
Transform this node into a ParseTree parse tree.
-
#rebuild_transform ⇒ Object
Initialize the transform and create all the form escapes that are used in this form.
- #reducer_ident ⇒ Object
-
#reify(transform, stars_transform) ⇒ Object
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).
-
#to_sexp(session) ⇒ Object
Convert this node to an S-expression.
-
#unparse(o = default_unparse_options) ⇒ Object
Performs the reverse of a parse operation (turns the node into a string).
Constructor Details
#initialize(colon, text) ⇒ FormNode
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
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# 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 |
Class Method Details
._load(str) ⇒ Object
82 83 84 85 86 |
# File 'lib/macro/form.rb', line 82 def self._load str result=allocate result.replace [Marshal.load(str)] result.rebuild_transform end |
Instance Method Details
#_dump(depth) ⇒ Object
78 79 80 |
# File 'lib/macro/form.rb', line 78 def _dump depth Marshal.dump text,depth end |
#deep_copy(transform = {}) ⇒ Object
Make a deep copy of this form
transform
-
TODO
162 163 164 |
# File 'lib/macro/form.rb', line 162 def deep_copy transform={} super(transform).rebuild_transform end |
#each_parameter(&block) ⇒ Object
Iterate over all the parameters in this form
block
-
the block to call for each parameter
154 155 156 |
# File 'lib/macro/form.rb', line 154 def each_parameter(&block) @parameters.each(&block) if defined? @parameters end |
#formname ⇒ Object
Lazily evaluate the name of the form and return it
265 266 267 268 269 270 271 |
# 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 |
#initialize_copy(other) ⇒ Object
70 71 72 73 74 75 76 |
# 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 |
#initialize_ivars ⇒ Object
def _dump depth
"foobarbaz"
end
def self._load str
result=allocate
end
98 99 100 101 |
# File 'lib/macro/form.rb', line 98 def initialize_ivars rebuild_transform super end |
#macro_expand(macros, session) ⇒ Object
680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 |
# File 'lib/macro.rb', line 680 def (macros,session) #return text.to_sexp({}) #maybe this doesn't allow expansion of parameters themselves... only within params? each_parameter{|param| Macro.(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 |
#noinspect_instance_variables ⇒ Object
66 67 68 |
# File 'lib/macro/form.rb', line 66 def noinspect_instance_variables %w[@stars_transform @transform] end |
#parses_like ⇒ Object
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 ]
253 254 255 256 257 258 259 260 261 262 |
# 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 |
#parsetree ⇒ Object
Transform this node into a ParseTree parse tree
221 222 223 |
# File 'lib/macro/form.rb', line 221 def parsetree parses_like.parsetree end |
#rebuild_transform ⇒ Object
Initialize the transform and create all the form escapes that are used in this form
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# 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 |
#reducer_ident ⇒ Object
19083 19084 19085 |
# File 'lib/macro/ReduceWithsFor_RedParse_RedParse__MacroMixin_RedParse__WithMacros_1_9.rb', line 19083 def reducer_ident :FormNode end |
#reify(transform, stars_transform) ⇒ Object
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
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# 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 |
#to_sexp(session) ⇒ Object
Convert this node to an S-expression
session
-
the context in which this macro is being processed
701 702 703 704 705 706 707 708 709 710 711 712 713 |
# 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 |
#unparse(o = default_unparse_options) ⇒ Object
Performs the reverse of a parse operation (turns the node into a string)
o
-
a list of options for unparse
171 172 173 |
# File 'lib/macro/form.rb', line 171 def unparse o= ":("+text.unparse(o)+")" end |