Front page | perl.cvs.parrot |
Postings from December 2008
[svn:parrot] r34304 - trunk/compilers/pct/src/PAST
From:
pmichaud
Date:
December 23, 2008 17:12
Subject:
[svn:parrot] r34304 - trunk/compilers/pct/src/PAST
Message ID:
20081224011217.22101CBA12@x12.develooper.com
Author: pmichaud
Date: Tue Dec 23 17:12:14 2008
New Revision: 34304
Modified:
trunk/compilers/pct/src/PAST/Compiler.pir
Log:
[pct]: Merge pctloop2 branch into trunk.
This allows all loops to handle last/next/redo exceptions.
Modified: trunk/compilers/pct/src/PAST/Compiler.pir
==============================================================================
--- trunk/compilers/pct/src/PAST/Compiler.pir (original)
+++ trunk/compilers/pct/src/PAST/Compiler.pir Tue Dec 23 17:12:14 2008
@@ -1242,137 +1242,142 @@
.end
-=item while(PAST::Op node)
-
-=item until(PAST::Op node)
+=item loop_gen(...)
-Return the POST representation of a C<while> or C<until> loop.
+Generate a standard loop with NEXT/LAST/REDO exception handling.
=cut
-.sub 'while' :method :multi(_, ['PAST';'Op'])
- .param pmc node
+.sub 'loop_gen' :method
.param pmc options :slurpy :named
- .local string pasttype
- pasttype = node.'pasttype'()
+ .local pmc testlabel, prelabel, redolabel, nextlabel, donelabel, handlabel
+ $P0 = get_hll_global ['POST'], 'Label'
+ .local string loopname
+ loopname = self.'unique'('loop')
+ $S0 = concat loopname, '_test'
+ testlabel = $P0.'new'('result'=>$S0)
+ $S0 = concat loopname, '_redo'
+ redolabel = $P0.'new'('result'=>$S0)
+ $S0 = concat loopname, '_next'
+ nextlabel = $P0.'new'('result'=>$S0)
+ $S0 = concat loopname, '_done'
+ donelabel = $P0.'new'('result'=>$S0)
+ $S0 = concat loopname, '_handler'
+ handlabel = $P0.'new'('result'=>$S0)
+
+ .local pmc testpost, prepost, bodypost
+ .local string testop
+ .local int bodyfirst
+ testop = options['testop']
+ testpost = options['test']
+ prepost = options['pre']
+ bodypost = options['body']
+ bodyfirst = options['bodyfirst']
+
+ if testop goto have_testop
+ testop = 'unless'
+ have_testop:
.local pmc ops
$P0 = get_hll_global ['POST'], 'Ops'
- ops = $P0.'new'('node'=>node)
+ ops = $P0.'new'()
- .local pmc exprpast, exprpost
- .local pmc bodypast, bodypost
- exprpast = node[0]
- bodypast = node[1]
+ .local string handreg
+ handreg = self.'uniquereg'('P')
+ ops.'push_pirop'('new', handreg, "'ExceptionHandler'")
+ ops.'push_pirop'('set_addr', handreg, handlabel)
+ ops.'push_pirop'('callmethod', '"handle_types"', handreg, .CONTROL_LOOP_NEXT, .CONTROL_LOOP_REDO, .CONTROL_LOOP_LAST)
+ ops.'push_pirop'('push_eh', handreg)
+
+ unless bodyfirst goto bodyfirst_done
+ ops.'push_pirop'('goto', redolabel)
+ bodyfirst_done:
+ ops.'push'(testlabel)
+ if null testpost goto test_done
+ ops.'push'(testpost)
+ ops.'push_pirop'(testop, testpost, donelabel)
+ test_done:
+ if null prepost goto pre_done
+ ops.'push'(prepost)
+ pre_done:
+ ops.'push'(redolabel)
+ if null bodypost goto body_done
+ ops.'push'(bodypost)
+ body_done:
+ ops.'push'(nextlabel)
+ ops.'push_pirop'('goto', testlabel)
+ ops.'push'(handlabel)
+ ops.'push_pirop'('.local pmc exception')
+ ops.'push_pirop'('.get_results (exception)')
+ $S0 = self.'uniquereg'('P')
+ ops.'push_pirop'('getattribute', $S0, 'exception', "'type'")
+ ops.'push_pirop'('eq', $S0, .CONTROL_LOOP_NEXT, nextlabel)
+ ops.'push_pirop'('eq', $S0, .CONTROL_LOOP_REDO, redolabel)
+ ops.'push'(donelabel)
+ ops.'push_pirop'('pop_eh')
+ .return (ops)
+.end
+
- .local pmc looplabel, endlabel
- $P0 = get_hll_global ['POST'], 'Label'
- $S0 = concat pasttype, '_'
- $S0 = self.'unique'($S0)
- looplabel = $P0.'new'('result'=>$S0)
- $S0 = concat $S0, '_end'
- endlabel = $P0.'new'('result'=>$S0)
+=item while(PAST::Op node)
- ## determine if we need an 'if' or an 'unless'
- ## on the conditional (while => if, until => unless)
- .local string iftype
- iftype = 'if'
- if pasttype == 'until' goto have_iftype
- iftype = 'unless'
- have_iftype:
+=item until(PAST::Op node)
- .local string rtype, exprrtype
- rtype = options['rtype']
- exprrtype = 'r'
- if rtype != 'v' goto have_exprrtype
- exprrtype = '*'
- have_exprrtype:
+=item repeat_while(PAST::Op node)
- exprpost = self.'as_post'(exprpast, 'rtype'=>exprrtype)
+=item repeat_until(PAST::Op node)
+
+Return the POST representation of a C<while> or C<until> loop.
+
+=cut
+
+.sub 'while' :method :multi(_, ['PAST';'Op'])
+ .param pmc node
+ .param pmc options :slurpy :named
+ .local pmc exprpast, bodypast
+ exprpast = node[0]
+ bodypast = node[1]
+
+ .local pmc exprpost, bodypost
+ exprpost = self.'as_post'(exprpast, 'rtype'=>'r')
.local pmc arglist
arglist = new 'ResizablePMCArray'
$I0 = bodypast.'arity'()
- unless $I0 goto have_arglist
+ if $I0 < 1 goto have_arglist
push arglist, exprpost
have_arglist:
-
- ops.'push'(looplabel)
- ops.'push'(exprpost)
- ops.'push_pirop'(iftype, exprpost, endlabel)
bodypost = self.'as_post'(bodypast, 'rtype'=>'v', 'arglist'=>arglist)
- ops.'push'(bodypost)
- ops.'push_pirop'('goto', looplabel)
- ops.'push'(endlabel)
+
+ .local string testop
+ testop = options['testop']
+ .local int bodyfirst
+ bodyfirst = options['bodyfirst']
+
+ .local pmc ops
+ ops = self.'loop_gen'('testop'=>testop, 'test'=>exprpost, 'body'=>bodypost, 'bodyfirst'=>bodyfirst)
ops.'result'(exprpost)
+ ops.'node'(node)
.return (ops)
.end
.sub 'until' :method :multi(_, ['PAST';'Op'])
.param pmc node
.param pmc options :slurpy :named
- .tailcall self.'while'(node, options :flat :named)
+ .tailcall self.'while'(node, options :flat :named, 'testop'=>'if')
.end
-=item repeat_while(PAST::Op node)
-
-=item repeat_until(PAST::Op node)
-
-Return the POST representation of a C<repeat_while> or C<repeat_until> loop.
-
-=cut
-
.sub 'repeat_while' :method :multi(_, ['PAST';'Op'])
.param pmc node
.param pmc options :slurpy :named
-
- .local string pasttype
- pasttype = node.'pasttype'()
-
- .local pmc ops
- $P0 = get_hll_global ['POST'], 'Ops'
- ops = $P0.'new'('node'=>node)
-
- .local pmc exprpast, exprpost
- .local pmc bodypast, bodypost
- exprpast = node[0]
- bodypast = node[1]
-
- .local pmc looplabel
- $P0 = get_hll_global ['POST'], 'Label'
- $S0 = concat pasttype, '_'
- looplabel = $P0.'new'('name'=>$S0)
-
- ## determine if we need an 'if' or an 'unless'
- ## on the conditional (repeat_while => if, repeat_until => unless)
- .local string iftype
- iftype = 'if'
- if pasttype != 'repeat_until' goto have_iftype
- iftype = 'unless'
- have_iftype:
-
- .local string rtype, exprrtype
- rtype = options['rtype']
- exprrtype = 'r'
- if rtype != 'v' goto have_exprrtype
- exprrtype = '*'
- have_exprrtype:
-
- ops.'push'(looplabel)
- bodypost = self.'as_post'(bodypast, 'rtype'=>'v')
- ops.'push'(bodypost)
- exprpost = self.'as_post'(exprpast, 'rtype'=>exprrtype)
- ops.'push'(exprpost)
- ops.'push_pirop'(iftype, exprpost, looplabel)
- ops.'result'(exprpost)
- .return (ops)
+ .tailcall self.'while'(node, options :flat :named, 'bodyfirst'=>1)
.end
.sub 'repeat_until' :method :multi(_, ['PAST';'Op'])
.param pmc node
.param pmc options :slurpy :named
- .tailcall self.'repeat_while'(node, options :flat :named)
+ .tailcall self.'while'(node, options :flat :named, 'testop'=>'if', 'bodyfirst'=>1)
.end
@@ -1387,45 +1392,33 @@
.param pmc node
.param pmc options :slurpy :named
- .local pmc ops
+ .local pmc ops, prepost, testpost
$P0 = get_hll_global ['POST'], 'Ops'
- ops = $P0.'new'('node'=>node)
+ ops = $P0.'new'('node'=>node)
+ prepost = $P0.'new'()
+ $S0 = self.'uniquereg'('P')
+ testpost = $P0.'new'('result'=>$S0)
- .local pmc looplabel, nextlabel, endlabel, undeflabel
- $P0 = get_hll_global ['POST'], 'Label'
- $S0 = self.'unique'('for_')
- looplabel = $P0.'new'('result'=>$S0)
- $S1 = concat $S0, '_next'
- nextlabel = $P0.'new'('result'=>$S1)
- $S2 = concat $S0, '_end'
- endlabel = $P0.'new'('result'=>$S2)
- $S3 = concat $S0, '_undef_iter'
- undeflabel = $P0.'new'('result'=>$S3)
-
- .local pmc collpast, collpost
+ .local pmc collpast, bodypast
collpast = node[0]
+ bodypast = node[1]
+
+ .local pmc collpost, testpost
collpost = self.'as_post'(collpast, 'rtype'=>'P')
ops.'push'(collpost)
- .local string iter, next_handler
- iter = self.'uniquereg'('P')
- ops.'result'(iter)
+ ## don't try to iterate undefined values
+ .local pmc undeflabel
+ $P0 = get_hll_global ['POST'], 'Label'
+ undeflabel = $P0.'new'('name'=>'for_undef_')
$S0 = self.'uniquereg'('I')
ops.'push_pirop'('defined', $S0, collpost)
ops.'push_pirop'('unless', $S0, undeflabel)
- next_handler = self.'uniquereg'('P')
- ops.'push_pirop'('new', next_handler, "'ExceptionHandler'")
- ops.'push_pirop'('set_addr', next_handler, nextlabel)
- ops.'push_pirop'('callmethod', '"handle_types"', next_handler, .CONTROL_LOOP_NEXT)
- ops.'push_pirop'('push_eh', next_handler)
- ops.'push_pirop'('iter', iter, collpost)
- ops.'push'(looplabel)
- ops.'push_pirop'('unless', iter, endlabel)
- .local pmc subpast
- subpast = node[1]
+ ops.'push_pirop'('iter', testpost, collpost)
- ## determine the number of elements to take at each iteration
+ ## determine the arity of the loop. We check arity of the 'for'
+ ## node itself, and if not set we use the arity of the body.
.local int arity
arity = 1
$P0 = node.'arity'()
@@ -1434,37 +1427,34 @@
arity = $P0
goto have_arity
arity_child:
- $P0 = subpast.'arity'()
+ $P0 = bodypast.'arity'()
$I0 = defined $P0
unless $I0 goto have_arity
arity = $P0
have_arity:
+ ## build the argument list to pass to the body
.local pmc arglist
arglist = new 'ResizablePMCArray'
arity_loop:
- .local string nextval
- nextval = self.'uniquereg'('P')
- ops.'push_pirop'('shift', nextval, iter)
+ .local string nextarg
+ nextarg = self.'uniquereg'('P')
+ prepost.'push_pirop'('shift', nextarg, testpost)
if arity < 1 goto arity_end
- push arglist, nextval
+ push arglist, nextarg
dec arity
if arity > 0 goto arity_loop
arity_end:
- .local pmc subpost
- subpast.'blocktype'('immediate') # FIXME
- subpost = self.'as_post'(subpast, 'rtype'=>'P', 'arglist'=>arglist)
- ops.'push'(subpost)
- ops.'push_pirop'('goto', looplabel)
- ops.'push'(nextlabel)
- ops.'push_pirop'('.local pmc exception')
- ops.'push_pirop'('.get_results (exception)')
- ops.'push_pirop'('set', next_handler, 0)
- ops.'push_pirop'('goto', looplabel)
- ops.'push'(endlabel)
- ops.'push_pirop'('pop_eh')
+ ## now build the body itself
+ .local pmc bodypost
+ bodypost = self.'as_post'(bodypast, 'rtype'=>'v', 'arglist'=>arglist)
+
+ ## generate the loop and return
+ $P0 = self.'loop_gen'('test'=>testpost, 'pre'=>prepost, 'body'=>bodypost)
+ ops.'push'($P0)
ops.'push'(undeflabel)
+ ops.'result'(testpost)
.return (ops)
.end
-
[svn:parrot] r34304 - trunk/compilers/pct/src/PAST
by pmichaud