5 POST::Compiler - Compiler for POST trees
9 POST::Compiler defines a compiler that converts a POST tree into
10 PIR or an Eval PMC (bytecode).
18 .namespace [ 'POST';'Compiler' ]
20 .sub '__onload' :load :init
21 .local pmc p6meta, cproto
22 p6meta = new 'P6metaclass'
23 cproto = p6meta.'new_class'('POST::Compiler', 'parent'=>'PCT::HLLCompiler')
24 cproto.'language'('POST')
25 $P1 = split ' ', 'pir evalpmc'
29 set_global '$?HLL', $P0
31 set_global '$?NAMESPACE', $P0
36 =item C<escape(string str)>
38 Returns an escaped value of C<str> suitable for including in PIR.
39 If the string contains any non-ASCII characters, then it's
40 prefixed with 'unicode:'. (This method just delegates to
41 PAST::Compiler.escape, which does the same thing.)
47 $P0 = get_hll_global ['PAST'], 'Compiler'
48 .tailcall $P0.'escape'(str)
51 =item C<key_pir( string name1 [, string name2, ...] )>
53 Constructs a PIR key using the strings passed as arguments.
54 For example, C<key('Foo', 'Bar')> returns C<["Foo";"Bar"]>.
58 .sub 'key_pir' :method
59 .param pmc args :slurpy
60 .local string out, sep
64 unless args goto args_done
66 if null $P0 goto args_loop
67 $I0 = does $P0, 'array'
68 if $I0 goto args_array
70 $S0 = self.'escape'($P0)
76 splice args, $P0, 0, 0
86 .param pmc adverbs :slurpy :named
89 newself = new ['POST';'Compiler']
91 .local pmc innerpir, line
92 innerpir = new 'StringBuilder'
93 .lex '$CODE', innerpir
97 ## if the root node isn't a Sub, wrap it
98 $I0 = isa post, ['POST';'Sub']
100 $P0 = get_hll_global ['POST'], 'Sub'
101 post = $P0.'new'(post, 'name'=>'anon')
104 ## now generate the pir
107 ## and return whatever code was generated
112 =item pir_children(node)
114 Return generated PIR for C<node> and all of its children.
118 .sub 'pir_children' :method
121 line = find_caller_lex '$LINE'
125 iter = node.'iterator'()
127 unless iter goto iter_end
128 .local pmc cpost, pos, source
131 if null pos goto done_subline
132 source = cpost['source']
133 if null source goto done_subline
134 line = self.'lineof'(source, pos, 'cache'=>1)
145 Return generated pir for any POST::Node. Returns
146 the generated pir of C<node>'s children.
150 .sub 'pir' :method :multi(_,_)
152 self.'pir_children'(node)
156 =item pir(POST::Op node)
158 Return pir for an operation node.
162 .sub 'pir' :method :multi(_,['POST';'Op'])
165 ## determine the type of operation
167 pirop = node.'pirop'()
169 ## determine if we're storing result
171 result = node.'result'()
172 unless result goto have_result
176 ## get list of arguments to operation
178 arglist = node.'list'()
180 ## get format and arguments based on pirop
181 .local string fmt, name, invocant
182 if pirop == 'call' goto pirop_call
183 if pirop == 'callmethod' goto pirop_callmethod
184 if pirop == 'return' goto pirop_return
185 if pirop == 'yield' goto pirop_yield
186 if pirop == 'tailcall' goto pirop_tailcall
187 if pirop == 'inline' goto pirop_inline
200 fmt = " %r%i.%n(%,)\n"
202 invocant = shift arglist
206 fmt = " .return (%,)\n"
210 fmt = " .yield (%,)\n"
215 fmt = " .tailcall %n(%,)\n"
219 fmt = node.'inline'()
221 result = node.'result'()
225 .local pmc subpir, subline, line
226 subpir = find_caller_lex '$SUBPIR'
227 subline = find_caller_lex '$SUBLINE'
228 line = find_caller_lex '$LINE'
229 if subline == line goto done_line
230 subpir.'append_format'(".annotate 'line', %0\n", line)
233 subpir.'append_format'(fmt, arglist :flat, 'r'=>result, 'n'=>name, 'i'=>invocant, 't'=>result)
237 =item pir(POST::Label node)
243 .sub 'pir' :method :multi(_, ['POST';'Label'])
245 .local pmc subpir, value
246 value = node.'result'()
247 subpir = find_caller_lex '$SUBPIR'
248 subpir.'append_format'(" %0:\n", value)
252 =item pir(POST::Sub node)
254 Generate PIR for C<node>, storing the result into the compiler's
255 C<$!code> attribute and returning any code needed to look up
260 .sub 'pir' :method :multi(_, ['POST';'Sub'])
263 .local pmc subpir, subline, innerpir
264 subpir = new 'StringBuilder'
265 .lex '$SUBPIR', subpir
267 .lex '$SUBLINE', subline
268 innerpir = new 'StringBuilder'
269 .lex '$CODE', innerpir
271 .local string name, pirflags
273 pirflags = node.'pirflags'()
276 $I0 = index pirflags, ':subid('
277 if $I0 >= 0 goto pirflags_subid_done
279 subid = node.'subid'()
280 pirflags = concat pirflags, ' :subid("'
286 $I0 = index pirflags, ':method'
287 if $I0 >= 0 goto pirflags_method_done
288 $S0 = node.'blocktype'()
289 if $S0 != 'method' goto pirflags_method_done
290 pirflags = concat pirflags, ' :method'
291 pirflags_method_done:
293 .local pmc outerpost, outername
294 outername = new 'Undef'
295 outerpost = node.'outer'()
296 if null outerpost goto pirflags_done
297 unless outerpost goto pirflags_done
298 outername = outerpost.'subid'()
299 $S0 = self.'escape'(outername)
300 pirflags = concat pirflags, ' :outer('
305 .local pmc outerhll, hll
306 outerhll = get_global '$?HLL'
311 set_global '$?HLL', hll
313 .local pmc outerns, ns, nskey
314 outerns = get_global '$?NAMESPACE'
316 $P0 = node.'namespace'()
317 unless $P0 goto have_ns
320 set_global '$?NAMESPACE', ns
321 nskey = self.'key_pir'(ns)
324 multi = node.'multi'()
325 unless multi goto no_multi
327 .local pmc parts, m_iter
328 parts = new ['ResizableStringArray']
331 unless m_iter goto multi_iter_done
334 if $S0 == "_" goto push_part
335 $S0 = self.'key_pir'($P0)
341 pirflags = concat pirflags, ' :multi('
342 $S0 = join ',', parts
343 pirflags = concat pirflags, $S0
344 pirflags = concat pirflags, ')'
348 $P0 = node['loadinit']
349 if null $P0 goto loadinit_done
353 $P0 = node.'compiler'()
354 unless $P0 goto subpir_post
356 $P0 = node.'compiler_args'()
357 if $P0 goto have_compiler_args
360 $P0 = self.'hll_pir'(node, 'name'=>name, 'namespace'=>ns, 'pirflags'=>pirflags, $P0 :named :flat)
365 unless hll goto subpir_ns
366 $P0 = self.'escape'(hll)
367 subpir.'append_format'("\n.HLL %0\n", $P0)
369 subpir.'append_format'("\n.namespace %0\n", nskey)
371 $S0 = node['directives']
372 unless $S0 goto subpir_decl
373 subpir.'append_format'("%0", $S0)
375 $S0 = self.'escape'(name)
376 subpir.'append_format'(".sub %0 %1\n", $S0, pirflags)
378 paramlist = node['paramlist']
379 if null paramlist goto paramlist_done
383 unless it goto paramlist_done
385 if null $P0 goto param_loop
390 self.'pir_children'(node)
391 subpir.'append_format'(".end\n\n")
395 outerpir = find_caller_lex '$CODE'
399 set_global '$?NAMESPACE', outerns
400 set_global '$?HLL', outerhll
404 .sub 'hll_pir' :method
406 .param pmc options :slurpy :named
408 options['target'] = 'pir'
410 options['subid'] = $P0
411 .local pmc source, compiler, pir
413 $S0 = node.'compiler'()
414 compiler = compreg $S0
415 $I0 = isa compiler, 'Sub'
416 if $I0 goto compiler_sub
417 .tailcall compiler.'compile'(source, options :flat :named)
419 .tailcall compiler(source, options :flat :named)
426 Patrick Michaud <pmichaud@pobox.com> is the author and maintainer.
427 Please send patches and suggestions to the Parrot porters or
428 Perl 6 compilers mailing lists.
432 2007-11-21 Significant refactor as part of Parrot Compiler Toolkit
436 Copyright (C) 2006-2008, Parrot Foundation.
444 # vim: expandtab shiftwidth=4 ft=pir: