Author: pmichaud
Date: Tue May 6 10:54:31 2008
New Revision: 27351
Modified:
trunk/compilers/pct/src/PAST/Compiler.pir
Log:
[pct]:
* Fix 'call' generation of PAST nodes so that "Null PMC in invoke"
messages now read "Cannot invoke non-existent sub 'foo'".
Modified: trunk/compilers/pct/src/PAST/Compiler.pir
==============================================================================
--- trunk/compilers/pct/src/PAST/Compiler.pir (original)
+++ trunk/compilers/pct/src/PAST/Compiler.pir Tue May 6 10:54:31 2008
@@ -492,41 +492,76 @@
=item call(PAST::Op node)
-=item callmethod(PAST::Op node)
-
Return the POST representation of a C<PAST::Op> node
-with a 'pasttype' attribute of either 'call' or 'callmethod'.
+for calling a sub.
=cut
.sub 'call' :method :multi(_, ['PAST::Op'])
.param pmc node
.param pmc options :slurpy :named
+ .local pmc ops, posargs, namedargs
+ .local string name
+ name = node.'name'()
+ if name goto call_by_name
+ ## our first child is the thing to be invoked, so make sure it's a PMC
+ (ops, posargs, namedargs) = self.'post_children'(node, 'signature'=>'vP:')
+ goto children_done
+ call_by_name:
+ ## Parrot gives "Null PMC in invoke()" if we use the name
+ ## directly, so we check for it here and toss an exception
+ ## first, resolve the children arguments
+ (ops, posargs, namedargs) = self.'post_children'(node, 'signature'=>'v:')
+ ## now, check for the named sub
+ .local pmc calllabel, findop
+ $P0 = get_hll_global ['POST'], 'Label'
+ calllabel = $P0.'new'('name'=>'call_')
+ $S0 = ops.'escape'(name)
+ findop = ops.'push_pirop'('find_name', '$P10', $S0, 'result'=>'$P10')
+ ops.'push_pirop'('unless_null', findop, calllabel)
+ $S0 = concat "Cannot invoke non-existent sub '", name
+ $S0 .= "'"
+ $S0 = ops.'escape'($S0)
+ ops.'push_pirop'('die', $S0)
+ ops.'push'(calllabel)
+ ## add the named sub as the invokable sub
+ unshift posargs, findop
+ children_done:
- .local string pasttype
- pasttype = node.'pasttype'()
- if pasttype goto have_pasttype
- pasttype = 'call'
- have_pasttype:
-
- .local string signature
- signature = ':'
- unless pasttype == 'callmethod' goto have_signature
- signature = 'P:'
- have_signature:
+ ## generate the call itself
+ .local string result, rtype
+ result = ''
+ rtype = options['rtype']
+ if rtype == 'v' goto result_done
+ result = ops.'unique'('$P')
+ ops.'result'(result)
+ result_done:
+ ops.'push_pirop'('call', posargs :flat, namedargs :flat, 'result'=>result)
+ .return (ops)
+.end
+
+
+=item callmethod(PAST::Op node)
+
+Return the POST representation of a C<PAST::Op> node
+to invoke a method on a PMC.
+
+=cut
+
+.sub 'callmethod' :method :multi(_, ['PAST::Op'])
+ .param pmc node
+ .param pmc options :slurpy :named
.local pmc ops, posargs, namedargs
.local string name
name = node.'name'()
unless name goto call_first_arg
- signature = concat 'v', signature
- (ops, posargs, namedargs) = self.'post_children'(node,
'signature'=>signature)
+ (ops, posargs, namedargs) = self.'post_children'(node, 'signature'=>'vP:')
name = ops.'escape'(name)
unshift posargs, name
goto children_done
call_first_arg:
- signature = concat 'vP', signature
- (ops, posargs, namedargs) = self.'post_children'(node,
'signature'=>signature)
+ (ops, posargs, namedargs) = self.'post_children'(node, 'signature'=>'vPP:')
children_done:
.local string result, rtype
@@ -537,16 +572,10 @@
ops.'result'(result)
result_done:
- ops.'push_pirop'(pasttype, posargs :flat, namedargs :flat,
'result'=>result)
+ ops.'push_pirop'('callmethod', posargs :flat, namedargs :flat,
'result'=>result)
.return (ops)
.end
-.sub 'callmethod' :method :multi(_, ['PAST::Op'])
- .param pmc node
- .param pmc options :slurpy :named
- .return self.'call'(node, options :flat :named)
-.end
-
=item if(PAST::Op node)