Skip to content

Commit e58b4a5

Browse files
committed
ParseXS: refactor: add INPUT, INPUT_line nodes
This is #5 of a small series of commits to refactor INPUT keyword handling. This commit adds these two classes: ExtUtils::ParseXS::Node::INPUT ExtUtils::ParseXS::Node::INPUT_line and converts the two ExtUtils::ParseXS methods INPUT_handler() INPUT_handler_line() into parse() methods of those two classes In a very minor way, this commit also starts separating in time the parsing and the code emitting. Whereas before, each INPUT line was parsed and then C code for it immediately emitted, now *all* lines from an explicit or implicit INPUT section are parsed and stored as an INPUT node with multiple INPUT_line children, and *then* the as_code() method is called for each child. This should make no difference to the generated output code.
1 parent aeff664 commit e58b4a5

File tree

2 files changed

+85
-33
lines changed

2 files changed

+85
-33
lines changed

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1041,7 +1041,13 @@ EOF
10411041
$self->{xsub_targ_used} = 0; # TARG hasn't yet been used
10421042

10431043
# Process any implicit INPUT section.
1044-
$self->INPUT_handler($_);
1044+
{
1045+
my $input = ExtUtils::ParseXS::Node::INPUT->new();
1046+
unshift @{$self->{line}}, $_;
1047+
$input->parse($self);
1048+
$_ = shift @{$self->{line}};
1049+
$input->as_code($self);
1050+
}
10451051

10461052
# keywords which can appear anywhere in an XSUB
10471053
my $generic_xsub_keys =

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

Lines changed: 78 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2043,13 +2043,20 @@ BEGIN { $build_subclass->('', # parent
20432043
sub parse {
20442044
my __PACKAGE__ $self = shift;
20452045
my ExtUtils::ParseXS $pxs = shift;
2046+
my $do_notimplemented = shift;
20462047

20472048
$self->SUPER::parse($pxs); # set file/line_no
20482049

20492050
# Consume and process lines until the next directive.
20502051
while( @{$pxs->{line}}
20512052
&& $pxs->{line}[0] !~ /^$ExtUtils::ParseXS::BLOCK_regexp/o)
20522053
{
2054+
if ($do_notimplemented) {
2055+
# treat NOT_IMPLEMENTED_YET as another block separator, in
2056+
# addition to $BLOCK_regexp.
2057+
last if $pxs->{line}[0] =~ /^\s*NOT_IMPLEMENTED_YET/;
2058+
}
2059+
20532060
push @{$self->{lines}}, $pxs->{line}[0];
20542061
my $class = ref($self) . '_line';
20552062
my $kid = $class->new();
@@ -2062,6 +2069,20 @@ sub parse {
20622069
}
20632070

20642071

2072+
# call as_code() on any kids which have that method
2073+
2074+
sub as_code {
2075+
my __PACKAGE__ $self = shift;
2076+
my ExtUtils::ParseXS $pxs = shift;
2077+
2078+
return unless $self->{kids};
2079+
for my $kid (@{$self->{kids}}) {
2080+
next unless $kid->can('as_code');
2081+
$kid->as_code($pxs);
2082+
}
2083+
}
2084+
2085+
20652086
# ======================================================================
20662087

20672088
package ExtUtils::ParseXS::Node::keyline;
@@ -2243,42 +2264,54 @@ sub parse {
22432264

22442265
# ======================================================================
22452266

2246-
package ExtUtils::ParseXS; # XXX tmp
2267+
package ExtUtils::ParseXS::Node::INPUT;
22472268

2248-
# INPUT_handler(): handle an explicit INPUT: block, or any implicit INPUT
2269+
# Handle an explicit INPUT: block, or any implicit INPUT
22492270
# block which can follow an xsub signature or CASE keyword.
22502271

2251-
sub INPUT_handler {
2252-
my ExtUtils::ParseXS $self = shift;
2253-
my $line = shift;
2272+
BEGIN { $build_subclass->('keylines', # parent
2273+
)};
22542274

2255-
# In this loop: process each line until the next keyword or end of
2256-
# paragraph.
2275+
# The inherited parse() method will call INPUT_line->parse() for each line
22572276

2258-
for (; $line !~ /^$ExtUtils::ParseXS::BLOCK_regexp/o; $line = shift(@{ $self->{line} })) {
2259-
# treat NOT_IMPLEMENTED_YET as another block separator, in addition to
2260-
# $BLOCK_regexp.
2261-
last if $line =~ /^\s*NOT_IMPLEMENTED_YET/;
22622277

2263-
$self->INPUT_handler_line($line);
2264-
} # foreach line in INPUT block
2265-
$_ = $line;
2278+
sub parse {
2279+
my __PACKAGE__ $self = shift;
2280+
my ExtUtils::ParseXS $pxs = shift;
2281+
2282+
# Call the SUPER parse method, which will call INPUT_line->parse()
2283+
# for each lINPUT line. The '1' bool arg indicates to treat
2284+
# NOT_IMPLEMENTED_YET as another block separator, in addition to
2285+
# $BLOCK_regexp.
2286+
$self->SUPER::parse($pxs, 1);
22662287
}
22672288

22682289

22692290
# ======================================================================
22702291

2271-
package ExtUtils::ParseXS; # XXX tmp
2292+
package ExtUtils::ParseXS::Node::INPUT_line;
2293+
2294+
# Handle one line from an INPUT keyword block
2295+
2296+
BEGIN { $build_subclass->('keyline', # parent
2297+
'param', # the param object associated with this INPUT line.
2298+
)};
2299+
2300+
2301+
# Parse one line from an INPUT block
2302+
#
22722303

2273-
# process a single line from an INPUT section
2304+
sub parse {
2305+
my __PACKAGE__ $self = shift;
2306+
my ExtUtils::ParseXS $pxs = shift;
2307+
my ExtUtils::ParseXS::Node::INPUT $parent = shift; # parent INPUT node
22742308

2275-
sub INPUT_handler_line {
2276-
my ExtUtils::ParseXS $self = shift;
2277-
my $line = shift;
2309+
$self->SUPER::parse($pxs); # set file/line_no/line
2310+
my $line = $self->{line}; # line of text to be processed
22782311

22792312
return unless $line =~ /\S/; # skip blank lines
22802313

2281-
trim_whitespace($line);
2314+
ExtUtils::ParseXS::Utilities::trim_whitespace($line);
22822315
my $orig_line = $line; # keep original line for error messages
22832316

22842317
# remove any trailing semicolon, except for initialisations
@@ -2318,18 +2351,18 @@ sub INPUT_handler_line {
23182351
(\w+ | length\(\w+\)) # name or length(name)
23192352
$
23202353
/xs
2321-
or $self->blurt("Error: invalid parameter declaration '$orig_line'"), return;
2354+
or $pxs->blurt("Error: invalid parameter declaration '$orig_line'"), return;
23222355

23232356
# length(s) is only allowed in the XSUB's signature.
23242357
if ($var_name =~ /^length\((\w+)\)$/) {
2325-
$self->blurt("Error: length() not permitted in INPUT section");
2358+
$pxs->blurt("Error: length() not permitted in INPUT section");
23262359
return;
23272360
}
23282361

23292362
my ($var_num, $is_alien);
23302363

23312364
my ExtUtils::ParseXS::Node::Param $param
2332-
= $self->{xsub_sig}{names}{$var_name};
2365+
= $pxs->{xsub_sig}{names}{$var_name};
23332366

23342367

23352368
if (defined $param) {
@@ -2344,7 +2377,7 @@ sub INPUT_handler_line {
23442377
if ( $param->{in_input}
23452378
or (!$param->{is_synthetic} and defined $param->{type})
23462379
) {
2347-
$self->blurt(
2380+
$pxs->blurt(
23482381
"Error: duplicate definition of parameter '$var_name' ignored");
23492382
return;
23502383
}
@@ -2358,9 +2391,9 @@ sub INPUT_handler_line {
23582391
# type, and has already been moved to the correct position;
23592392
# otherwise, it's an alien var that didn't appear in the
23602393
# signature; move to the correct position.
2361-
@{$self->{xsub_sig}{params}} =
2362-
grep $_ != $param, @{$self->{xsub_sig}{params}};
2363-
push @{$self->{xsub_sig}{params}}, $param;
2394+
@{$pxs->{xsub_sig}{params}} =
2395+
grep $_ != $param, @{$pxs->{xsub_sig}{params}};
2396+
push @{$pxs->{xsub_sig}{params}}, $param;
23642397
$is_alien = 1;
23652398
$param->{is_alien} = 1;
23662399
}
@@ -2379,8 +2412,8 @@ sub INPUT_handler_line {
23792412
is_alien => 1,
23802413
});
23812414

2382-
push @{$self->{xsub_sig}{params}}, $param;
2383-
$self->{xsub_sig}{names}{$var_name} = $param;
2415+
push @{$pxs->{xsub_sig}{params}}, $param;
2416+
$pxs->{xsub_sig}{names}{$var_name} = $param;
23842417
}
23852418

23862419
# Parse the initialisation part of the INPUT line (if any)
@@ -2407,7 +2440,7 @@ sub INPUT_handler_line {
24072440
# "; extra code" or "+ extra code" :
24082441
# append the extra code (after passing through eval) after all the
24092442
# INPUT and PREINIT blocks have been processed, indirectly using
2410-
# the $self->{xsub_deferred_code_lines} mechanism.
2443+
# the $pxs->{xsub_deferred_code_lines} mechanism.
24112444
# In addition, for '+', also generate the normal initialisation
24122445
# code from the standard typemap - assuming that it's a real
24132446
# parameter that appears in the signature as well as the INPUT
@@ -2435,18 +2468,31 @@ sub INPUT_handler_line {
24352468
is_addr => !!$var_addr,
24362469
);
24372470

2438-
$param->check($self)
2471+
$self->{param} = $param;
2472+
2473+
$param->check($pxs)
24392474
or return;
2475+
}
2476+
2477+
2478+
sub as_code {
2479+
my __PACKAGE__ $self = shift;
2480+
my ExtUtils::ParseXS $pxs = shift;
24402481

24412482
# Emit "type var" declaration and possibly various forms of
24422483
# initialiser code.
24432484

2485+
my $param = $self->{param};
2486+
return unless $param; # might be blank line
2487+
24442488
# Synthetic params like THIS will be emitted later - they
24452489
# are treated like ANSI params, except the type can overridden
24462490
# within an INPUT statement
24472491
return if $param->{is_synthetic};
24482492

2449-
$param->as_code($self);
2493+
# The param object contains data from both the INPUT line and
2494+
# the XSUB signature.
2495+
$param->as_code($pxs);
24502496
}
24512497

24522498

0 commit comments

Comments
 (0)