Permalink
Browse files

PCT: PAST.Compiler.wrap_handlers in Winxed

  • Loading branch information...
1 parent 52fc553 commit 0dc14b19f954bc3f241070f7b0f668420e04e8e2 @Benabik Benabik committed Apr 30, 2012
Showing with 64 additions and 89 deletions.
  1. +0 −89 compilers/pct/src/PAST/Compiler.pir
  2. +64 −0 compilers/pct/src/PAST/Compiler.winxed
View
89 compilers/pct/src/PAST/Compiler.pir
@@ -24,95 +24,6 @@ PAST::Compiler - PAST Compiler
.namespace [ 'PAST';'Compiler' ]
-.sub 'wrap_handlers' :method
- .param pmc child
- .param pmc ehs
- .param pmc options :slurpy :named
-
- .local string rtype, result
- .local int addreturn
- rtype = options['rtype']
- addreturn = options['addreturn']
- if addreturn goto wrap_no_result
- result = self.'tempreg'(rtype)
- wrap_no_result:
-
- # Probably not safe to use tempregs in an exception handler
- .local pmc tempregs
- null tempregs
- .lex '%*TEMPREGS', tempregs
-
- .local pmc it, node, ops, tail, skip
- .local int depth
- $P0 = get_hll_global ['POST'], 'Ops'
- ops = $P0.'new'('node'=>node)
- $P0 = get_hll_global ['POST'], 'Ops'
- tail = $P0.'new'('node'=>node)
- $P0 = get_hll_global ['POST'], 'Label'
- $S0 = self.'unique'('skip_handler_')
- skip = $P0.'new'('result'=>$S0)
-
- ops.'result'(result)
- unless result goto wrap_child_no_result
- child = self.'coerce'(child, result)
- wrap_child_no_result:
-
- it = iter ehs
- depth = 0
- handler_loop:
- unless it, handler_loop_done
- node = shift it
-
- .local pmc ehpir, label
- .local string exceptreg
- $P0 = get_hll_global ['POST'], 'Label'
- $S0 = self.'unique'('control_')
- label = $P0.'new'('result'=>$S0)
- self.'push_exception_handler'(node, ops, label)
- inc depth
-
- # Push the handler itself
- tail.'push'(label)
- exceptreg = self.'uniquereg'('P')
- tail.'push_pirop'('peek_exception', exceptreg)
- ehpir = self.'as_post'(node, 'rtype'=>rtype)
- unless result goto handler_loop_no_result
- ehpir = self.'coerce'(ehpir, result)
- handler_loop_no_result:
- tail.'push'(ehpir)
- tail.'push_pirop'('finalize', exceptreg)
- unless addreturn goto handler_loop_no_return
- .local pmc retval
- retval = ehpir.'result'()
- tail.'push_pirop'('return', retval)
- goto handler_loop
- handler_loop_no_return:
- tail.'push_pirop'('pop_upto_eh', exceptreg)
- $I0 = depth
- pops_loop_handler:
- tail.'push_pirop'('pop_eh')
- dec $I0
- if $I0 goto pops_loop_handler
- unless it, handler_loop_done
- tail.'push_pirop'('goto', skip)
- goto handler_loop
- handler_loop_done:
-
- ops.'push'(child)
- $I0 = depth
- unless $I0 goto pops_done
- pops_loop:
- ops.'push_pirop'('pop_eh')
- dec $I0
- if $I0 goto pops_loop
- pops_done:
- ops.'push_pirop'('goto', skip)
- ops.'push'(tail)
- ops.'push'(skip)
-
- .return (ops)
-.end
-
=back
=head3 C<PAST::Block>
View
64 compilers/pct/src/PAST/Compiler.winxed
@@ -807,6 +807,70 @@ Return the POST representation of a C<PAST::Control>.
ops.push_pirop('push_eh', ehreg);
return;
}
+
+ function wrap_handlers[method](var child, var ehs, options [slurpy, named]) {
+ string rtype = options['rtype'];
+ int addreturn = options['addreturn'];
+ string result;
+ if (!addreturn)
+ :(result) = self.tempreg(rtype);
+
+ // Probably not safe to use tempregs in an exception handler
+ var tempregs;
+ ${ .lex '%*TEMPREGS', tempregs };
+
+ using POST.Ops;
+ var node;
+ var ops = Ops.new(node:[named('node')]);
+ var tail = Ops.new(node:[named('node')]);
+ using POST.Label;
+ var skip = Label.new(string(self.unique('skip_handler_')):[named('result')]);
+
+ ops.result(result);
+ if (result)
+ child = self.coerce(child, result);
+
+ int depth = 0;
+ var it;
+ ${ iter it, ehs };
+ while (it) {
+ node = shift_var(it);
+ var label = Label.new(string(self.unique('control_')):[named('result')]);
+ self.push_exception_handler(node, ops, label);
+ ++depth;
+
+ // Push the handler itself
+ tail.push(label);
+ :(string exceptreg) = self.uniquereg('P');
+ tail.push_pirop('peek_exception', exceptreg);
+ var ehpir = self.as_post(node, rtype:[named('rtype')]);
+ if (result)
+ ehpir = self.coerce(ehpir, result);
+ tail.push(ehpir);
+ tail.push_pirop('finalize', exceptreg);
+ if (addreturn) {
+ var retval = ehpir.result();
+ tail.push_pirop('return', retval);
+ continue;
+ }
+ tail.push_pirop('pop_upto_eh', exceptreg);
+ int i = depth;
+ do {
+ tail.push_pirop('pop_eh');
+ } while(--i);
+ if (it)
+ tail.push_pirop('goto', skip);
+ }
+
+ ops.push(child);
+ for(int i = depth; i; --i)
+ ops.push_pirop('pop_eh');
+ ops.push_pirop('goto', skip);
+ ops.push(tail);
+ ops.push(skip);
+
+ return ops;
+ }
}
/*

0 comments on commit 0dc14b1

Please sign in to comment.