3 POST::Compiler - Compiler for POST trees
7 POST::Compiler defines a compiler that converts a POST tree into
8 PIR or an Eval PMC (bytecode).
16 .namespace [ 'POST::Compiler' ]
18 .sub '__onload' :load :init
19 .local pmc p6meta, cproto
20 p6meta = new 'P6metaclass'
21 cproto = p6meta.'new_class'('POST::Compiler', 'parent'=>'PCT::HLLCompiler', 'attr'=>'$!code')
22 cproto.'language'('POST')
23 $P1 = split ' ', 'pir evalpmc'
27 set_global '$?NAMESPACE', $P0
34 .param pmc adverbs :slurpy :named
37 newself = new 'POST::Compiler'
39 ## start with empty code
41 code = new 'CodeString'
44 ## if the root node isn't a Sub, wrap it
45 $I0 = isa post, 'POST::Sub'
47 $P0 = get_hll_global ['POST'], 'Sub'
48 post = $P0.'new'(post, 'name'=>'anon')
51 ## now generate the pir
54 ## and return whatever code was generated
55 .return newself.'code'()
61 Get/set the code generated by this compiler.
66 .param pmc code :optional
67 .param int has_code :opt_flag
69 if has_code goto set_code
70 code = getattribute self, '$!code'
73 setattribute self, '$!code', code
78 =item pir_children(node)
80 Return generated PIR for C<node> and all of its children.
84 .sub 'pir_children' :method
87 code = new 'CodeString'
88 iter = node.'iterator'()
90 unless iter goto iter_end
93 $P0 = self.'pir'(cpost)
103 Return generated pir for any POST::Node. Returns
104 the generated pir of C<node>'s children.
108 .sub 'pir' :method :multi(_,_)
110 .return self.'pir_children'(node)
114 =item pir(POST::Op node)
116 Return pir for an operation node.
120 .sub 'pir' :method :multi(_,['POST::Op'])
123 ## determine the type of operation
125 pirop = node.'pirop'()
127 ## determine if we're storing result
129 result = node.'result'()
130 unless result goto have_result
134 ## get list of arguments to operation
136 arglist = node.'list'()
138 ## get format and arguments based on pirop
139 .local string fmt, name, invocant
140 if pirop == 'call' goto pirop_call
141 if pirop == 'callmethod' goto pirop_callmethod
142 if pirop == 'return' goto pirop_return
143 if pirop == 'tailcall' goto pirop_tailcall
144 if pirop == 'inline' goto pirop_inline
159 invocant = shift arglist
163 fmt = " .return (%,)"
168 fmt = ' .return %n(%,)'
172 fmt = node.'inline'()
173 result = node.'result'()
178 code = new 'CodeString'
179 code.'emit'(fmt, arglist :flat, 'r'=>result, 'n'=>name, 'i'=>invocant, 't'=>result)
184 =item pir(POST::Label node)
190 .sub 'pir' :method :multi(_, ['POST::Label'])
192 .local string code, value
193 value = node.'result'()
201 =item pir(POST::Sub node)
203 Generate PIR for C<node>, storing the result into the compiler's
204 C<$!code> attribute and returning any code needed to look up
209 .sub 'pir' :method :multi(_, ['POST::Sub'])
213 code = new 'CodeString'
215 .local string name, pirflags
217 pirflags = node.'pirflags'()
220 $I0 = index pirflags, ':lexid('
221 if $I0 >= 0 goto pirflags_lexid_done
223 lexid = code.'unique'()
225 pirflags = concat pirflags, ' :lexid("'
231 $I0 = index pirflags, ':method'
232 if $I0 >= 0 goto pirflags_method_done
233 $S0 = node.'blocktype'()
234 if $S0 != 'method' goto pirflags_method_done
235 pirflags = concat pirflags, ' :method'
236 pirflags_method_done:
238 .local pmc outerpost, outername
239 outername = new 'Undef'
240 outerpost = node.'outer'()
241 if null outerpost goto pirflags_done
242 unless outerpost goto pirflags_done
244 ## PIR doesn't compile properly if :outer points to a sub
245 ## with :init/:load flags on it.
246 $I0 = index pirflags, ':init'
247 if $I0 >= 0 goto pirflags_done
248 $I0 = index pirflags, ':load'
249 if $I0 >= 0 goto pirflags_done
250 $S0 = outerpost.'pirflags'()
251 $I0 = index $S0, ':init'
252 if $I0 >= 0 goto pirflags_done
253 $I0 = index $S0, ':load'
254 if $I0 >= 0 goto pirflags_done
255 outername = outerpost.'lexid'()
256 $S0 = code.'escape'(outername)
257 pirflags = concat pirflags, ' :outer('
262 .local pmc outerns, ns, nskey
263 outerns = get_global '$?NAMESPACE'
265 ns = node.'namespace'()
266 unless ns goto have_ns
267 nskey = code.'key'(ns)
268 set_global '$?NAMESPACE', nskey
272 $P0 = node.'compiler'()
273 unless $P0 goto subpir_post
275 $P0 = node.'compiler_args'()
276 if $P0 goto have_compiler_args
279 $P0 = self.'hll_pir'(node, 'name'=>name, 'namespace'=>ns, 'pirflags'=>pirflags, $P0 :named :flat)
284 code.'emit'("\n.namespace %0", nskey)
285 $S0 = code.'escape'(name)
286 code.'emit'(".sub %0 %1", $S0, pirflags)
288 paramlist = node['paramlist']
289 if null paramlist goto paramlist_done
291 iter = new 'Iterator', paramlist
293 unless iter goto paramlist_done
295 if null $P0 goto param_loop
300 $P0 = self.'pir_children'(node)
302 code.'emit'(".end\n\n")
309 set_global '$?NAMESPACE', outerns
311 code = new 'CodeString'
315 .sub 'hll_pir' :method
317 .param pmc options :slurpy :named
319 options['target'] = 'pir'
320 options['grammar'] = ''
321 .local pmc source, compiler, pir
323 $S0 = node.'compiler'()
324 compiler = compreg $S0
325 $I0 = isa compiler, 'Sub'
326 if $I0 goto compiler_sub
327 .return compiler.'compile'(source, options :flat :named)
329 .return compiler(source, options :flat :named)
336 Patrick Michaud <pmichaud@pobox.com> is the author and maintainer.
337 Please send patches and suggestions to the Parrot porters or
338 Perl 6 compilers mailing lists.
342 2007-11-21 Significant refactor as part of Parrot Compiler Toolkit
346 Copyright (C) 2006-2008, The Perl Foundation.
354 # vim: expandtab shiftwidth=4 ft=pir: