Skip to content
This repository
Browse code

Merge branch 'mls/pct_exceptionhandlers'

  • Loading branch information...
commit fad30eada4a639886548cc5e4e909805b3eb14ff 2 parents c6ed574 + b5b2038
Michael Schroeder authored October 07, 2011
125  compilers/pct/src/PAST/Compiler.pir
@@ -849,8 +849,8 @@ Return the POST representation of a C<PAST::Control>.
849 849
     .param pmc options         :slurpy :named
850 850
 
851 851
      # Probably not safe to use tempregs in an exception handler
852  
-     .local pmc tempregs
853  
-     null tempregs
  852
+    .local pmc tempregs
  853
+    null tempregs
854 854
     .lex '%*TEMPREGS', tempregs
855 855
 
856 856
     .local pmc ops, children, ishandled, nothandled
@@ -882,17 +882,61 @@ Return the POST representation of a C<PAST::Control>.
882 882
     .return (ops)
883 883
 .end
884 884
 
  885
+.sub 'push_exception_handler' :method
  886
+    .param pmc node
  887
+    .param pmc ops
  888
+    .param pmc label
  889
+
  890
+    .local string type, extype
  891
+    type = node.'handle_types'()
  892
+    extype = node.'handle_types_except'()
  893
+    if type goto handler_need_exhandler
  894
+    if extype goto handler_need_exhandler
  895
+    ops.'push_pirop'('push_eh', label)
  896
+    .return ()
  897
+
  898
+  handler_need_exhandler:
  899
+    .local pmc controltypes, subpost
  900
+    .local string ehreg
  901
+    subpost = find_dynamic_lex '$*SUB'
  902
+    ehreg = self.'uniquereg'('P')
  903
+    ops.'push_pirop'('new', ehreg, "'ExceptionHandler'")
  904
+    ops.'push_pirop'('set_label', ehreg, label)
  905
+    controltypes = get_global '%!controltypes'
  906
+    unless type, handle_types_done
  907
+    type = controltypes[type]
  908
+    unless type, handle_types_done
  909
+    $P0 = split ',', type
  910
+    ops.'push_pirop'('callmethod', '"handle_types"', ehreg, $P0 :flat)
  911
+    subpost.'add_directive'('.include "except_types.pasm"')
  912
+  handle_types_done:
  913
+    unless extype, handle_types_except_done
  914
+    extype = controltypes[extype]
  915
+    unless extype, handle_types_except_done
  916
+    $P0 = split ',', extype
  917
+    ops.'push_pirop'('callmethod', '"handle_types_except"', ehreg, $P0 :flat)
  918
+    subpost.'add_directive'('.include "except_types.pasm"')
  919
+  handle_types_except_done:
  920
+    ops.'push_pirop'('push_eh', ehreg)
  921
+    .return ()
  922
+.end
  923
+
885 924
 .sub 'wrap_handlers' :method
886 925
     .param pmc child
887 926
     .param pmc ehs
888 927
     .param pmc options         :slurpy :named
889 928
 
890  
-    .local string rtype
  929
+    .local string rtype, result
  930
+    .local int addreturn
891 931
     rtype = options['rtype']
  932
+    addreturn = options['addreturn']
  933
+    if addreturn goto wrap_no_result
  934
+    result = self.'tempreg'(rtype)
  935
+  wrap_no_result:
892 936
 
893  
-     # Probably not safe to use tempregs in an exception handler
894  
-     .local pmc tempregs
895  
-     null tempregs
  937
+    # Probably not safe to use tempregs in an exception handler
  938
+    .local pmc tempregs
  939
+    null tempregs
896 940
     .lex '%*TEMPREGS', tempregs
897 941
 
898 942
     .local pmc it, node, ops, pops, tail, skip
@@ -906,49 +950,35 @@ Return the POST representation of a C<PAST::Control>.
906 950
     $S0 = self.'unique'('skip_handler_')
907 951
     skip = $P0.'new'('result'=>$S0)
908 952
 
  953
+    ops.'result'(result)
  954
+    unless result goto wrap_child_no_result
  955
+    child = self.'coerce'(child, result)
  956
+  wrap_child_no_result:
  957
+
909 958
     it = iter ehs
910 959
   handler_loop:
911 960
     unless it, handler_loop_done
912 961
     node = shift it
913 962
 
914  
-    .local pmc ehpir, label, controltypes, subpost
915  
-    .local string ehreg, type
  963
+    .local pmc ehpir, label
916 964
     $P0 = get_hll_global ['POST'], 'Label'
917 965
     $S0 = self.'unique'('control_')
918 966
     label = $P0.'new'('result'=>$S0)
919  
-
920  
-    subpost = find_dynamic_lex '$*SUB'
921  
-
922  
-    ehreg = self.'uniquereg'('P')
923  
-    ops.'push_pirop'('new', ehreg, "'ExceptionHandler'")
924  
-    ops.'push_pirop'('set_label', ehreg, label)
925  
-    controltypes = get_global '%!controltypes'
926  
-    type = node.'handle_types'()
927  
-    unless type, handle_types_done
928  
-    type = controltypes[type]
929  
-    unless type, handle_types_done
930  
-    $P0 = split ',', type
931  
-    ops.'push_pirop'('callmethod', '"handle_types"', ehreg, $P0 :flat)
932  
-    subpost.'add_directive'('.include "except_types.pasm"')
933  
-  handle_types_done:
934  
-    type = node.'handle_types_except'()
935  
-    unless type, handle_types_except_done
936  
-    type = controltypes[type]
937  
-    unless type, handle_types_except_done
938  
-    $P0 = split ',', type
939  
-    ops.'push_pirop'('callmethod', '"handle_types_except"', ehreg, $P0 :flat)
940  
-    subpost.'add_directive'('.include "except_types.pasm"')
941  
-  handle_types_except_done:
942  
-    ops.'push_pirop'('push_eh', ehreg)
943  
-
  967
+    self.'push_exception_handler'(node, ops, label)
944 968
     # Add one pop_eh for every handler we push_eh
945 969
     pops.'push_pirop'('pop_eh')
946 970
 
947 971
     # Push the handler itself
948 972
     tail.'push'(label)
949 973
     ehpir = self.'as_post'(node, 'rtype'=>rtype)
  974
+    unless result goto handler_loop_no_result
  975
+    ehpir = self.'coerce'(ehpir, result)
  976
+  handler_loop_no_result:
950 977
     tail.'push'(ehpir)
951  
-
  978
+    unless addreturn goto handler_loop
  979
+    .local pmc retval
  980
+    retval = ehpir.'result'()
  981
+    tail.'push_pirop'('return', retval)
952 982
     goto handler_loop
953 983
   handler_loop_done:
954 984
 
@@ -1117,18 +1147,14 @@ Return the POST representation of a C<PAST::Block>.
1117 1147
     ##  convert children to post
1118 1148
     .local pmc ops, retval
1119 1149
     ops = self.'post_children'(node, 'signature'=>$S0)
  1150
+    ##  result of last child is return from block
  1151
+    retval = ops[-1]
1120 1152
     ##  wrap the child with appropriate exception handlers, if any
1121 1153
     .local pmc eh
1122 1154
     eh = node.'handlers'()
1123 1155
     unless eh, no_eh
1124  
-    $S0 = options['rtype']
1125  
-    retval = ops[-1]
1126  
-    ops = self.'wrap_handlers'(ops, eh, 'rtype'=>$S0)
1127  
-    goto had_eh
  1156
+    ops = self.'wrap_handlers'(ops, eh, 'rtype'=>'*', 'addreturn'=>1)
1128 1157
   no_eh:
1129  
-    ##  result of last child is return from block
1130  
-    retval = ops[-1]
1131  
-  had_eh:
1132 1158
     bpost.'push'(ops)
1133 1159
     bpost.'push_pirop'('return', retval)
1134 1160
 
@@ -1875,7 +1901,7 @@ a return value.
1875 1901
 =item try(PAST::Op node)
1876 1902
 
1877 1903
 Return the POST representation of a C<PAST::Op>
1878  
-node with a 'pasttype' of bind.  The first child
  1904
+node with a 'pasttype' of try.  The first child
1879 1905
 is the code to be surrounded by an exception handler,
1880 1906
 the second child (if any) is the code to process the
1881 1907
 handler.
@@ -1897,13 +1923,18 @@ handler.
1897 1923
     $S0 = concat $S0, '_end'
1898 1924
     endlabel = $P0.'new'('result'=>$S0)
1899 1925
 
1900  
-    .local string rtype
  1926
+    .local string rtype, result
1901 1927
     rtype = options['rtype']
  1928
+    result = self.'tempreg'(rtype)
  1929
+    ops.'result'(result)
1902 1930
 
1903 1931
     .local pmc trypast, trypost
1904 1932
     trypast = node[0]
1905 1933
     trypost = self.'as_post'(trypast, 'rtype'=>rtype)
1906  
-    ops.'push_pirop'('push_eh', catchlabel)
  1934
+    unless result goto trypost_no_result
  1935
+    trypost = self.'coerce'(trypost, result)
  1936
+  trypost_no_result:
  1937
+    self.'push_exception_handler'(node, ops, catchlabel)
1907 1938
     ops.'push'(trypost)
1908 1939
     ops.'push_pirop'('pop_eh')
1909 1940
     .local pmc elsepast, elsepost
@@ -1917,12 +1948,14 @@ handler.
1917 1948
     .local pmc catchpast, catchpost
1918 1949
     catchpast = node[1]
1919 1950
     if null catchpast goto catch_done
1920  
-    catchpost = self.'as_post'(catchpast, 'rtype'=>'v')
  1951
+    catchpost = self.'as_post'(catchpast, 'rtype'=>rtype)
  1952
+    unless result goto catchpost_no_result
  1953
+    catchpost = self.'coerce'(catchpost, result)
  1954
+  catchpost_no_result:
1921 1955
     ops.'push'(catchpost)
1922 1956
     ops.'push_pirop'('pop_eh')         # FIXME: should be before catchpost
1923 1957
   catch_done:
1924 1958
     ops.'push'(endlabel)
1925  
-    ops.'result'(trypost)
1926 1959
     .return (ops)
1927 1960
 .end
1928 1961
 
54  compilers/pct/src/PAST/Node.pir
@@ -104,6 +104,14 @@ Accessor method -- sets/returns the "flatten" flag on arguments.
104 104
     .tailcall self.'attr'('flat', value, has_value)
105 105
 .end
106 106
 
  107
+
  108
+=item handlers([node array])
  109
+
  110
+Accessor method -- sets/returns handlers associated with this node.
  111
+Handlers can be used for PAST::Block and PAST::Stmts nodes.
  112
+
  113
+=cut
  114
+
107 115
 .sub 'handlers' :method
108 116
     .param pmc value           :optional
109 117
     .param int has_value       :opt_flag
@@ -111,6 +119,37 @@ Accessor method -- sets/returns the "flatten" flag on arguments.
111 119
 .end
112 120
 
113 121
 
  122
+=item handle_types([value])
  123
+
  124
+Accessor method -- sets/returns the exception types this node
  125
+handles. This is evaluated if the node is used as a block
  126
+handler, the node is a PAST::Control node, or the node is
  127
+a PAST::Op node of type 'try'.
  128
+
  129
+=cut
  130
+
  131
+.sub 'handle_types' :method
  132
+    .param pmc value           :optional
  133
+    .param int has_value       :opt_flag
  134
+    .tailcall self.'attr'('handle_types', value, has_value)
  135
+.end
  136
+
  137
+
  138
+=item handle_types_except([value])
  139
+
  140
+Accessor method -- sets/returns the exception types this node
  141
+does not handle. Same as handle_types, but all exceptions not
  142
+matching the specified ones will be caught.
  143
+
  144
+=cut
  145
+
  146
+.sub 'handle_types_except' :method
  147
+    .param pmc value           :optional
  148
+    .param int has_value       :opt_flag
  149
+    .tailcall self.'attr'('handle_types_except', value, has_value)
  150
+.end
  151
+
  152
+
114 153
 =item lvalue([flag])
115 154
 
116 155
 Get/set the C<lvalue> attribute, which indicates whether this
@@ -842,21 +881,6 @@ outer statement.
842 881
 .end
843 882
 
844 883
 
845  
-.namespace [ 'PAST';'Control' ]
846  
-
847  
-.sub 'handle_types' :method
848  
-    .param pmc value           :optional
849  
-    .param int has_value       :opt_flag
850  
-    .tailcall self.'attr'('handle_types', value, has_value)
851  
-.end
852  
-
853  
-.sub 'handle_types_except' :method
854  
-    .param pmc value           :optional
855  
-    .param int has_value       :opt_flag
856  
-    .tailcall self.'attr'('handle_types_except', value, has_value)
857  
-.end
858  
-
859  
-
860 884
 .namespace [ 'PAST';'VarList' ]
861 885
 
862 886
 .sub 'bindvalue' :method

0 notes on commit fad30ea

Please sign in to comment.
Something went wrong with that request. Please try again.