Skip to content

Commit 19caf65

Browse files
committed
ParseXS: refactor: lookup typemaps at parse time
The last few commits have moved the looking-up and processing of typemap entries (but not the evalling) for parameters from Param::as_input_code() and Param::as_output_code() into their own subs, lookup_input_typemap() and lookup_output_typemap(). This commit takes that one step further, and makes those new subs be called at parse time, rather than at code-generation time. This is needed because in principle, XSUB ASTs should be completely self-contained, and the code they emit shouldn't vary depending on when their top-level as_code() methods are called. But via the TYPEMAP: <<EOF mechanism, its possible for the typemap to change between XSUBs. This commit does this in a very crude way. Formerly, at code-emitting time, as_input_code() etc would do: my ($foo, $bar, ...) = lookup_input_typemap(...); Now, the parsing code does $self->{input_typemap_vals} = [ lookup_input_typemap(...) ]; and as_input_code() etc does: my ($foo, $bar, ...) = @{$self->{input_typemap_vals}}; Note that there are both output_typemap_vals and output_typemap_vals_outlist fields, as it's possible for the same parameter to be used both for updating the original arg (OUTPUT) and for returning the current value as a new SV (OUTLIST). So potentially we save the results of *two* calls to lookup_output_typemap() for each parameter.
1 parent b713240 commit 19caf65

File tree

1 file changed

+79
-4
lines changed
  • dist/ExtUtils-ParseXS/lib/ExtUtils/ParseXS

1 file changed

+79
-4
lines changed

dist/ExtUtils-ParseXS/lib/ExtUtils/ParseXS/Node.pm

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,6 +1093,16 @@ BEGIN { $build_subclass->('Param', # parent
10931093
'in_output', # the parameter has appeared in an OUTPUT statement
10941094
'do_setmagic', # 'SETMAGIC: ENABLE' was active for this parameter
10951095
'output_code', # the optional setting-code for this parameter
1096+
1097+
# ArrayRefs: results of looking up typemaps (which are done in the
1098+
# parse phase, as the typemap definitions can in theory change
1099+
# further down in the XS file). For now these just store
1100+
# uninterpreted, the list returned by the call to
1101+
# lookup_input_typemap() etc, for later use by the as_input_code()
1102+
# etc methods.
1103+
'input_typemap_vals', # result of lookup_input_typemap()
1104+
'output_typemap_vals', # result of lookup_output_typemap(...)
1105+
'output_typemap_vals_outlist', # result of lookup_output_typemap(..., n)
10961106
)};
10971107

10981108

@@ -1561,10 +1571,15 @@ sub as_input_code {
15611571
"\t$var";
15621572
}
15631573

1564-
my ($init_template, $eval_vars, $is_template) =
1565-
$self->lookup_input_typemap($pxs, $xsub, $xbody);
1574+
# Result of parse-phase lookup of INPUT typemap for this param's type.
1575+
my $lookup = $self->{input_typemap_vals};
1576+
$pxs->death("Internal error: parameter '$var' doesn't have input_typemap_vals")
1577+
unless $lookup;
1578+
1579+
my ($init_template, $eval_vars, $is_template) = @$lookup;
15661580

15671581
return unless defined $init_template; # an error occurred
1582+
15681583
unless ($is_template) {
15691584
# template already expanded
15701585
print " = $init_template\n";
@@ -1755,9 +1770,14 @@ sub as_output_code {
17551770
# OUTPUT line should not be used.
17561771
undef $output_code if defined $out_num;
17571772

1773+
# Result of parse-phase lookup of OUTPUT typemap for this param's type.
1774+
my $lookup = defined $out_num
1775+
? $self->{output_typemap_vals_outlist}
1776+
: $self->{output_typemap_vals};
1777+
$pxs->death("Internal error: parameter '$var' doesn't have output_typemap_vals")
1778+
unless $lookup;
17581779

1759-
my ($expr, $eval_vars, $is_template, $saw_DAE) =
1760-
$self->lookup_output_typemap($pxs, $xsub, $xbody, $out_num);
1780+
my ($expr, $eval_vars, $is_template, $saw_DAE) = @$lookup;
17611781

17621782
return unless defined $expr; # error
17631783

@@ -2570,6 +2590,17 @@ sub parse {
25702590
. $ExtUtils::ParseXS::Constants::generic_xsub_keywords_alt,
25712591
);
25722592

2593+
2594+
# For each param, look up its INPUT typemap information now (at parse
2595+
# time) and save the results for use later in as_input_code().
2596+
2597+
for my $ioparam (@{$xbody->{ioparams}{kids}}) {
2598+
# might be placeholder param which doesn't get emitted
2599+
next unless defined $ioparam->{type};
2600+
$ioparam->{input_typemap_vals} =
2601+
[ $ioparam->lookup_input_typemap($pxs, $xsub, $xbody) ];
2602+
}
2603+
25732604
# Now that the type of each param is finalised, calculate its
25742605
# overridden prototype character, if any.
25752606
#
@@ -2811,6 +2842,50 @@ sub parse {
28112842
)
28122843
? 1 : 0;
28132844

2845+
# For each param, look up its OUTPUT typemap information now (at parse
2846+
# time) and save the results for use later in as_output_code_().
2847+
2848+
for my $ioparam (@{$xbody->{ioparams}{kids}}) {
2849+
# might be placeholder param which doesn't get emitted
2850+
# XXXX next unless defined $ioparam->{type};
2851+
2852+
next unless
2853+
# XXX simplify all this
2854+
( defined $ioparam->{in_out}
2855+
&& $ioparam->{in_out} =~ /OUT$/
2856+
&& !$ioparam->{in_output}
2857+
)
2858+
||
2859+
2860+
(
2861+
$ioparam->{var} eq "RETVAL"
2862+
&& ( $ioparam->{in_output}
2863+
or ( $xbody->{seen_autocall}
2864+
&& $xsub->{decl}{return_type}{type} ne "void"
2865+
&& !$xsub->{decl}{return_type}{no_output}
2866+
)
2867+
)
2868+
)
2869+
||
2870+
(
2871+
$ioparam->{in_output}
2872+
&& $ioparam->{var} ne 'RETVAL'
2873+
)
2874+
;
2875+
2876+
$ioparam->{output_typemap_vals} =
2877+
[ $ioparam->lookup_output_typemap($pxs, $xsub, $xbody) ];
2878+
}
2879+
2880+
my $out_num = $xsub->{XSRETURN_count_basic};
2881+
2882+
for my $ioparam (@{$xbody->{ioparams}{kids}}) {
2883+
next unless defined $ioparam->{in_out}
2884+
&& $ioparam->{in_out} =~ /OUTLIST$/;
2885+
$ioparam->{output_typemap_vals_outlist} =
2886+
[ $ioparam->lookup_output_typemap($pxs, $xsub, $xbody, $out_num++) ];
2887+
}
2888+
28142889
1;
28152890
}
28162891

0 commit comments

Comments
 (0)