PAX

 view release on metacpan or  search on metacpan

lib/PAX/CodeUnitCompiler.pm  view on Meta::CPAN

        env => $env,
        fallback => $fallback,
    };
}

sub _return_literal_from_source {
    my ($source, $sub_name) = @_;
    my $body = _extract_sub_body($source, $sub_name) or return;
    if ($body =~ /\A\s*return\s+"([^"\\]*(?:\\.[^"\\]*)*)"\s*;\s*\z/s) {
        my $value = $1;
        $value =~ s/\\"/"/g;
        $value =~ s/\\\\/\\/g;
        $value =~ s/\\n/\n/g;
        return {
            type => 'string',
            value => $value,
        };
    }
    if ($body =~ /\A\s*return\s+(-?\d+)\s*;\s*\z/s) {
        return {
            type => 'integer',
            value => 0 + $1,
        };
    }
    return;
}

sub _package_tail_is {
    my ($package, $tail) = @_;
    return 0 unless defined $package;
    return 1 if !defined $tail || $tail eq '';
    return $package =~ /(?:^|::)\Q$tail\E\z/ ? 1 : 0;
}

sub _calls_class_tail {
    my ($body, $class_tail, $method) = @_;
    return 0 unless defined $body && defined $class_tail;
    my $escaped_tail = quotemeta $class_tail;
    my $qualified_tail = qr/(?:[A-Za-z_][A-Za-z0-9_]*::)*$escaped_tail/;

    if (defined $method && $method ne '') {
        my $method_escaped = quotemeta $method;
        return $body =~ /(?:^|[^A-Za-z0-9_])$qualified_tail\s*->\s*\Q$method_escaped\E\s*\(/m ? 1 : 0;
    }
    return $body =~ /(?:^|[^A-Za-z0-9_])$qualified_tail\b/m ? 1 : 0;
}

sub _requires_class_tail {
    my ($body, $class_tail) = @_;
    return 0 unless defined $body && defined $class_tail;
    return $body =~ /^\s*require\s+(?:[A-Za-z_][A-Za-z0-9_]*::)*\Q$class_tail\E\s*;/m ? 1 : 0;
}

sub _sibling_class {
    my ($package, $class) = @_;
    return $package if !defined $class || $class eq '';
    return $package if !defined $package || $package eq '';

    my ($root) = $package =~ m{^(.*)::([^:]+)$};
    $root //= '';
    my @class_parts = split m{::}, $class;
    return join('::', grep { defined && $_ ne '' } $root, @class_parts);
}

sub _related_class_from_source {
    my ($source, $package, $body, $class, %args) = @_;
    return _sibling_class($package, $class) if !defined $class || $class eq '';

    my @methods = @{ $args{methods} || [] };
    for my $scope (grep { defined && $_ ne '' } $body, $source) {
        my $qualified = _qualified_class_in_scope($scope, $class, \@methods);
        return $qualified if defined $qualified && $qualified ne '';
    }

    for my $scope (grep { defined && $_ ne '' } $source, $body) {
        my $imported = _imported_class_in_scope($scope, $class);
        return $imported if defined $imported && $imported ne '';
    }

    return _sibling_class($package, $class);
}

sub _qualified_class_in_scope {
    my ($scope, $class, $methods) = @_;
    return if !defined $scope || !defined $class || $class eq '';
    my $qualified_tail = qr/(?:[A-Za-z_][A-Za-z0-9_]*::)+\Q$class\E/;
    if ($methods && @$methods) {
        for my $method (@$methods) {
            next if !defined $method || $method eq '';
            if ($scope =~ /($qualified_tail)\s*->\s*\Q$method\E\s*\(/m) {
                return $1;
            }
        }
    }
    return $1 if $scope =~ /($qualified_tail)\b/m;
    return;
}

sub _imported_class_in_scope {
    my ($scope, $class) = @_;
    return if !defined $scope || !defined $class || $class eq '';
    return $1 if $scope =~ /^\s*use\s+((?:[A-Za-z_][A-Za-z0-9_]*::)+\Q$class\E)\b/m;
    return $1 if $scope =~ /^\s*require\s+((?:[A-Za-z_][A-Za-z0-9_]*::)+\Q$class\E)\s*;/m;
    return;
}

sub _extract_sub_body {
    my ($source, $sub_name) = @_;
    return if $source !~ /sub\s+\Q$sub_name\E\b[^\{]*\{/g;
    my $start = pos($source);
    my $depth = 1;
    my $i = $start;
    while ($i < length($source)) {
        my $char = substr($source, $i, 1);
        $depth++ if $char eq '{';
        $depth-- if $char eq '}';
        return substr($source, $start, $i - $start) if $depth == 0;
        $i++;
    }
    return;
}



( run in 1.471 second using v1.01-cache-2.11-cpan-71847e10f99 )